diff --git a/dictation_client/.eslintignore b/dictation_client/.eslintignore
index 2646704..1fbf4c4 100644
--- a/dictation_client/.eslintignore
+++ b/dictation_client/.eslintignore
@@ -5,5 +5,3 @@ jest.config.js
vite.config.ts
.env.local
-# デザイナのcssから生成するため除外
-src/styles/app.module.scss.d.ts
diff --git a/dictation_client/src/features/dictation/dictationSlice.ts b/dictation_client/src/features/dictation/dictationSlice.ts
index 009d47f..3c467ec 100644
--- a/dictation_client/src/features/dictation/dictationSlice.ts
+++ b/dictation_client/src/features/dictation/dictationSlice.ts
@@ -6,6 +6,7 @@ import {
listTasksAsync,
listTypistGroupsAsync,
listTypistsAsync,
+ updateAssigneeAsync,
} from "./operations";
import {
SORTABLE_COLUMN,
@@ -35,6 +36,7 @@ const initialState: DictationState = {
selected: [],
pool: [],
},
+ isLoading: true,
},
};
@@ -96,11 +98,19 @@ export const dictationSlice = createSlice({
},
},
extraReducers: (builder) => {
+ builder.addCase(listTasksAsync.pending, (state) => {
+ state.apps.isLoading = true;
+ });
builder.addCase(listTasksAsync.fulfilled, (state, action) => {
state.domain.limit = action.payload.limit;
state.domain.offset = action.payload.offset;
state.domain.total = action.payload.total;
state.domain.tasks = action.payload.tasks;
+
+ state.apps.isLoading = false;
+ });
+ builder.addCase(listTasksAsync.rejected, (state) => {
+ state.apps.isLoading = false;
});
builder.addCase(getSortColumnAsync.fulfilled, (state, action) => {
state.apps.direction = action.payload.direction;
@@ -112,6 +122,15 @@ export const dictationSlice = createSlice({
builder.addCase(listTypistGroupsAsync.fulfilled, (state, action) => {
state.domain.typistGroups = action.payload.typistGroups;
});
+ builder.addCase(updateAssigneeAsync.pending, (state) => {
+ state.apps.isLoading = true;
+ });
+ builder.addCase(updateAssigneeAsync.fulfilled, (state) => {
+ state.apps.isLoading = false;
+ });
+ builder.addCase(updateAssigneeAsync.rejected, (state) => {
+ state.apps.isLoading = false;
+ });
},
});
diff --git a/dictation_client/src/features/dictation/operations.ts b/dictation_client/src/features/dictation/operations.ts
index 4dccf91..18963cc 100644
--- a/dictation_client/src/features/dictation/operations.ts
+++ b/dictation_client/src/features/dictation/operations.ts
@@ -275,13 +275,6 @@ export const updateAssigneeAsync = createAsyncThunk<
headers: { authorization: `Bearer ${accessToken}` },
}
);
-
- thunkApi.dispatch(
- openSnackbar({
- level: "info",
- message: getTranslationID("common.message.success"),
- })
- );
return {};
} catch (e) {
// e ⇒ errorObjectに変換"
diff --git a/dictation_client/src/features/dictation/selectors.ts b/dictation_client/src/features/dictation/selectors.ts
index 455edd0..6461175 100644
--- a/dictation_client/src/features/dictation/selectors.ts
+++ b/dictation_client/src/features/dictation/selectors.ts
@@ -38,3 +38,6 @@ export const selectSelectedTranscriptionists = (state: RootState) =>
export const selectPoolTranscriptionists = (state: RootState) =>
state.dictation.apps.assignee.pool;
+
+export const selectIsLoading = (state: RootState) =>
+ state.dictation.apps.isLoading;
diff --git a/dictation_client/src/features/dictation/state.ts b/dictation_client/src/features/dictation/state.ts
index 244b2ad..0d383f7 100644
--- a/dictation_client/src/features/dictation/state.ts
+++ b/dictation_client/src/features/dictation/state.ts
@@ -28,4 +28,5 @@ export interface Apps {
selected: Assignee[];
pool: Assignee[];
};
+ isLoading: boolean;
}
diff --git a/dictation_client/src/features/license/licenseOrder/licenseSlice.ts b/dictation_client/src/features/license/licenseOrder/licenseSlice.ts
index 583f992..6332532 100644
--- a/dictation_client/src/features/license/licenseOrder/licenseSlice.ts
+++ b/dictation_client/src/features/license/licenseOrder/licenseSlice.ts
@@ -1,10 +1,12 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
import { LicenseOrdersState } from "./state";
+import { orderLicenseAsync } from "./operations";
const initialState: LicenseOrdersState = {
apps: {
poNumber: "",
newOrder: 0,
+ isLoading: false,
},
};
export const licenseSlice = createSlice({
@@ -23,6 +25,17 @@ export const licenseSlice = createSlice({
state.apps = initialState.apps;
},
},
+ extraReducers: (builder) => {
+ builder.addCase(orderLicenseAsync.pending, (state) => {
+ state.apps.isLoading = true;
+ });
+ builder.addCase(orderLicenseAsync.fulfilled, (state) => {
+ state.apps.isLoading = false;
+ });
+ builder.addCase(orderLicenseAsync.rejected, (state) => {
+ state.apps.isLoading = false;
+ });
+ },
});
export const { changePoNumber, changeNewOrder, cleanupApps } =
diff --git a/dictation_client/src/features/license/licenseOrder/operations.ts b/dictation_client/src/features/license/licenseOrder/operations.ts
index 0d39ee5..77d97d9 100644
--- a/dictation_client/src/features/license/licenseOrder/operations.ts
+++ b/dictation_client/src/features/license/licenseOrder/operations.ts
@@ -44,7 +44,9 @@ export const orderLicenseAsync = createAsyncThunk<
thunkApi.dispatch(
openSnackbar({
level: "info",
- message: getTranslationID("common.message.success"),
+ message: getTranslationID(
+ "licenseOrderPage.message.createOrderSuccess"
+ ),
})
);
return {};
diff --git a/dictation_client/src/features/license/licenseOrder/selectors.ts b/dictation_client/src/features/license/licenseOrder/selectors.ts
index 78d3cbb..9b7a0e6 100644
--- a/dictation_client/src/features/license/licenseOrder/selectors.ts
+++ b/dictation_client/src/features/license/licenseOrder/selectors.ts
@@ -34,3 +34,6 @@ export const checkErrorIncorrectNewOrder = (newOrder: number): boolean => {
export const selectPoNumber = (state: RootState) => state.license.apps.poNumber;
export const selectNewOrder = (state: RootState) => state.license.apps.newOrder;
+
+export const selectIsLoading = (state: RootState) =>
+ state.license.apps.isLoading;
diff --git a/dictation_client/src/features/license/licenseOrder/state.ts b/dictation_client/src/features/license/licenseOrder/state.ts
index 2a1f7c3..b5fe233 100644
--- a/dictation_client/src/features/license/licenseOrder/state.ts
+++ b/dictation_client/src/features/license/licenseOrder/state.ts
@@ -5,4 +5,5 @@ export interface LicenseOrdersState {
export interface Apps {
poNumber: string;
newOrder: number;
+ isLoading: boolean;
}
diff --git a/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts b/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts
index 2b5b746..82cfadf 100644
--- a/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts
+++ b/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts
@@ -16,6 +16,9 @@ const initialState: LicenseSummaryState = {
usedSize: 0,
isAccountLock: false,
},
+ apps: {
+ isLoading: false,
+ },
};
export const licenseSummarySlice = createSlice({
diff --git a/dictation_client/src/features/license/licenseSummary/selectors.ts b/dictation_client/src/features/license/licenseSummary/selectors.ts
index e4eceee..87df71f 100644
--- a/dictation_client/src/features/license/licenseSummary/selectors.ts
+++ b/dictation_client/src/features/license/licenseSummary/selectors.ts
@@ -3,3 +3,5 @@ import { RootState } from "app/store";
// 各値はそのまま画面に表示するので、licenseSummaryInfoとして値を取得する
export const selecLicenseSummaryInfo = (state: RootState) =>
state.licenseSummary.domain;
+
+export const selectIsLoading = (state: RootState) => state.license;
diff --git a/dictation_client/src/features/license/licenseSummary/state.ts b/dictation_client/src/features/license/licenseSummary/state.ts
index d7145e6..4a0d07f 100644
--- a/dictation_client/src/features/license/licenseSummary/state.ts
+++ b/dictation_client/src/features/license/licenseSummary/state.ts
@@ -1,5 +1,6 @@
export interface LicenseSummaryState {
domain: Domain;
+ apps: Apps;
}
export interface Domain {
@@ -15,3 +16,7 @@ export interface Domain {
usedSize: number;
isAccountLock: boolean;
}
+
+export interface Apps {
+ isLoading: boolean;
+}
diff --git a/dictation_client/src/features/user/selectors.ts b/dictation_client/src/features/user/selectors.ts
index ad726e4..725206e 100644
--- a/dictation_client/src/features/user/selectors.ts
+++ b/dictation_client/src/features/user/selectors.ts
@@ -53,3 +53,4 @@ export const selectLicenseAlert = (state: RootState) =>
export const selectNtotification = (state: RootState) =>
state.user.apps.addUser.notification;
export const selectDomain = (state: RootState) => state.user.domain;
+export const selectIsLoading = (state: RootState) => state.user.apps.isLoading;
diff --git a/dictation_client/src/features/user/state.ts b/dictation_client/src/features/user/state.ts
index 760c0e5..00dac8e 100644
--- a/dictation_client/src/features/user/state.ts
+++ b/dictation_client/src/features/user/state.ts
@@ -11,6 +11,7 @@ export interface Domain {
export interface Apps {
addUser: AddUser;
+ isLoading: boolean;
}
export interface AddUser extends User {
diff --git a/dictation_client/src/features/user/userSlice.ts b/dictation_client/src/features/user/userSlice.ts
index a178060..25fcc89 100644
--- a/dictation_client/src/features/user/userSlice.ts
+++ b/dictation_client/src/features/user/userSlice.ts
@@ -1,6 +1,6 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
import { UsersState } from "./state";
-import { listUsersAsync } from "./operations";
+import { addUserAsync, listUsersAsync } from "./operations";
import { ROLE, RoleType } from "./constants";
const initialState: UsersState = {
@@ -17,6 +17,7 @@ const initialState: UsersState = {
licenseAlert: true,
notification: true,
},
+ isLoading: false,
},
};
@@ -73,8 +74,24 @@ export const userSlice = createSlice({
},
},
extraReducers: (builder) => {
+ builder.addCase(listUsersAsync.pending, (state) => {
+ state.apps.isLoading = true;
+ });
builder.addCase(listUsersAsync.fulfilled, (state, action) => {
state.domain.users = action.payload.users;
+ state.apps.isLoading = false;
+ });
+ builder.addCase(listUsersAsync.rejected, (state) => {
+ state.apps.isLoading = false;
+ });
+ builder.addCase(addUserAsync.pending, (state) => {
+ state.apps.isLoading = true;
+ });
+ builder.addCase(addUserAsync.fulfilled, (state) => {
+ state.apps.isLoading = false;
+ });
+ builder.addCase(addUserAsync.rejected, (state) => {
+ state.apps.isLoading = false;
});
},
});
diff --git a/dictation_client/src/pages/DictationPage/changeTranscriptionistPopup.tsx b/dictation_client/src/pages/DictationPage/changeTranscriptionistPopup.tsx
index 3ebc642..e13e8dd 100644
--- a/dictation_client/src/pages/DictationPage/changeTranscriptionistPopup.tsx
+++ b/dictation_client/src/pages/DictationPage/changeTranscriptionistPopup.tsx
@@ -3,6 +3,7 @@ import styles from "styles/app.module.scss";
import { useDispatch, useSelector } from "react-redux";
import {
changeAssignee,
+ selectIsLoading,
selectPoolTranscriptionists,
selectSelectedTask,
selectSelectedTranscriptionists,
@@ -13,6 +14,7 @@ import { AppDispatch } from "app/store";
import { getTranslationID } from "translation";
import { useTranslation } from "react-i18next";
import close from "../../assets/images/close.svg";
+import progress_activit from "../../assets/images/progress_activit.svg";
interface ChangeTranscriptionistPopupProps {
onClose: (isChanged: boolean) => void;
@@ -26,6 +28,8 @@ export const ChangeTranscriptionistPopup: React.FC<
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
+ const isLoading = useSelector(selectIsLoading);
+
// ポップアップを閉じる処理
const closePopup = useCallback(() => {
onClose(false);
@@ -182,9 +186,17 @@ export const ChangeTranscriptionistPopup: React.FC<
type="button"
name="submit"
value={t(getTranslationID("dictationPage.label.saveChanges"))}
- className={`${styles.formSubmit} ${styles.marginBtm1} ${styles.isActive}`}
+ className={`${styles.formSubmit} ${styles.marginBtm1} ${
+ !isLoading ? styles.isActive : ""
+ }`}
onClick={onChangeTranscriptionist}
/>
+
diff --git a/dictation_client/src/pages/DictationPage/index.tsx b/dictation_client/src/pages/DictationPage/index.tsx
index cd7a285..cb449b2 100644
--- a/dictation_client/src/pages/DictationPage/index.tsx
+++ b/dictation_client/src/pages/DictationPage/index.tsx
@@ -28,6 +28,7 @@ import {
changeAssignee,
listTypistsAsync,
listTypistGroupsAsync,
+ selectIsLoading,
} from "features/dictation";
import { getTranslationID } from "translation";
import { Task } from "api/api";
@@ -39,6 +40,7 @@ import inprogress from "../../assets/images/inprogress.svg";
import finished from "../../assets/images/finished.svg";
import backup from "../../assets/images/backup.svg";
import lock from "../../assets/images/lock.svg";
+import progress_activit from "../../assets/images/progress_activit.svg";
import { DisPlayInfo } from "./displayInfo";
import { ChangeTranscriptionistPopup } from "./changeTranscriptionistPopup";
@@ -82,6 +84,8 @@ const DictationPage: React.FC = (): JSX.Element => {
const totalPage = useSelector(selectTotalPage);
const currentPage = useSelector(selectCurrentPage);
+ const isLoading = useSelector(selectIsLoading);
+
// ページネーションのボタンクリック時のアクション
const getFirstPage = useCallback(() => {
const filter = getFilter(
@@ -421,6 +425,7 @@ const DictationPage: React.FC = (): JSX.Element => {
value="flUploaded"
className={styles.formCheck}
checked={filterUploaded}
+ disabled={isLoading}
onChange={(e) => {
setFilterUploaded(e.target.checked);
updateFilter(
@@ -443,6 +448,7 @@ const DictationPage: React.FC = (): JSX.Element => {
value="flInProgress"
className={styles.formCheck}
checked={filterInProgress}
+ disabled={isLoading}
onChange={(e) => {
setFilterInProgress(e.target.checked);
updateFilter(
@@ -465,6 +471,7 @@ const DictationPage: React.FC = (): JSX.Element => {
value="flPending"
className={styles.formCheck}
checked={filterPending}
+ disabled={isLoading}
onChange={(e) => {
setFilterPending(e.target.checked);
updateFilter(
@@ -487,6 +494,7 @@ const DictationPage: React.FC = (): JSX.Element => {
value="flFinished"
className={styles.formCheck}
checked={filterFinished}
+ disabled={isLoading}
onChange={(e) => {
setFilterFinished(e.target.checked);
updateFilter(
@@ -509,6 +517,7 @@ const DictationPage: React.FC = (): JSX.Element => {
value="flBackup"
className={styles.formCheck}
checked={filterBackup}
+ disabled={isLoading}
onChange={(e) => {
setFilterBackup(e.target.checked);
updateFilter(
@@ -537,6 +546,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.JobNumber)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.jobNumber")
@@ -552,6 +564,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.Status)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(getTranslationID("dictationPage.label.status"))}
@@ -568,6 +583,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.Encryption)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.encryption")
@@ -583,6 +601,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.AuthorId)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.authorId")
@@ -598,6 +619,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.WorkType)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.workType")
@@ -613,6 +637,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileName)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.fileName")
@@ -628,6 +655,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileLength)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.fileLength")
@@ -643,6 +673,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileSize)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.fileSize")
@@ -660,6 +693,9 @@ const DictationPage: React.FC = (): JSX.Element => {
SORTABLE_COLUMN.RecordingStartedDate
)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID(
@@ -679,6 +715,9 @@ const DictationPage: React.FC = (): JSX.Element => {
SORTABLE_COLUMN.RecordingFinishedDate
)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID(
@@ -696,6 +735,9 @@ const DictationPage: React.FC = (): JSX.Element => {
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.UploadDate)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID("dictationPage.label.uploadDate")
@@ -713,6 +755,9 @@ const DictationPage: React.FC = (): JSX.Element => {
SORTABLE_COLUMN.TranscriptionStartedDate
)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID(
@@ -732,6 +777,9 @@ const DictationPage: React.FC = (): JSX.Element => {
SORTABLE_COLUMN.TranscriptionFinishedDate
)
}
+ style={{
+ pointerEvents: isLoading ? "none" : "auto",
+ }}
>
{t(
getTranslationID(
@@ -826,7 +874,8 @@ const DictationPage: React.FC = (): JSX.Element => {
)}
- {tasks.length !== 0 &&
+ {(isChangeTranscriptionistPopupOpen || !isLoading) &&
+ tasks.length !== 0 &&
tasks.map((x) => (
- {t(getTranslationID("common.message.listEmpty"))} -
- )} + {(isChangeTranscriptionistPopupOpen || !isLoading) && + tasks.length === 0 && ( ++ {t(getTranslationID("common.message.listEmpty"))} +
+ )} - + {isLoading && ( +