Merged PR 462: ワークフロー追加ポップアップ実装
## 概要 [Task2740: ワークフロー追加ポップアップ実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2740) - ワークフロー追加Popupを実装 - 多言語対応 ## レビューポイント - タイピスト・タイピストグループの変更処理 - 選択・除外で処理を分けたが一緒にしたほうが良い? - 各パラメータの変更処理 - 値のチェックは足りているか ## UIの変更 - https://ndstokyo.sharepoint.com/:f:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88/Task2740?csf=1&web=1&e=UHGFtv ## 動作確認状況 - ローカルで確認 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
aef6a35a7d
commit
7682c41ba5
@ -55,4 +55,5 @@ export const errorCodes = [
|
|||||||
"E011001", // ワークタイプ重複エラー
|
"E011001", // ワークタイプ重複エラー
|
||||||
"E011002", // ワークタイプ登録上限超過エラー
|
"E011002", // ワークタイプ登録上限超過エラー
|
||||||
"E011003", // ワークタイプ不在エラー
|
"E011003", // ワークタイプ不在エラー
|
||||||
|
"E013001", // ワークフローのAuthorIDとWorktypeIDのペア重複エラー
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
@ -1,9 +1,22 @@
|
|||||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||||
import { Configuration, GetWorkflowsResponse, WorkflowsApi } from "api";
|
import {
|
||||||
|
AccountsApi,
|
||||||
|
Author,
|
||||||
|
Configuration,
|
||||||
|
GetWorkflowsResponse,
|
||||||
|
TemplateFile,
|
||||||
|
TemplatesApi,
|
||||||
|
Typist,
|
||||||
|
TypistGroup,
|
||||||
|
WorkflowTypist,
|
||||||
|
WorkflowsApi,
|
||||||
|
Worktype,
|
||||||
|
} from "api";
|
||||||
import type { RootState } from "app/store";
|
import type { RootState } from "app/store";
|
||||||
import { ErrorObject, createErrorObject } from "common/errors";
|
import { ErrorObject, createErrorObject } from "common/errors";
|
||||||
import { openSnackbar } from "features/ui/uiSlice";
|
import { openSnackbar } from "features/ui/uiSlice";
|
||||||
import { getTranslationID } from "translation";
|
import { getTranslationID } from "translation";
|
||||||
|
import { WorkflowRelations } from "./state";
|
||||||
|
|
||||||
export const listWorkflowAsync = createAsyncThunk<
|
export const listWorkflowAsync = createAsyncThunk<
|
||||||
GetWorkflowsResponse,
|
GetWorkflowsResponse,
|
||||||
@ -40,3 +53,161 @@ export const listWorkflowAsync = createAsyncThunk<
|
|||||||
return thunkApi.rejectWithValue({ error });
|
return thunkApi.rejectWithValue({ error });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const createWorkflowAsync = createAsyncThunk<
|
||||||
|
{
|
||||||
|
/* Empty Object */
|
||||||
|
},
|
||||||
|
void,
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("workflow/createWorkflowAsync", async (args, thunkApi) => {
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const workflowsApi = new WorkflowsApi(config);
|
||||||
|
const { selectedAssignees, authorId, templateId, worktypeId } =
|
||||||
|
state.workflow.apps;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (authorId === undefined) {
|
||||||
|
throw new Error("authorId is not found");
|
||||||
|
}
|
||||||
|
// 選択されたタイピストを取得し、リクエスト用の型に変換する
|
||||||
|
const typists = selectedAssignees.map(
|
||||||
|
(item): WorkflowTypist => ({
|
||||||
|
typistId: item.typistUserId,
|
||||||
|
typistGroupId: item.typistGroupId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
await workflowsApi.createWorkflows(
|
||||||
|
{
|
||||||
|
authorId,
|
||||||
|
typists,
|
||||||
|
templateId,
|
||||||
|
worktypeId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "info",
|
||||||
|
message: getTranslationID("common.message.success"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
} catch (e) {
|
||||||
|
// e ⇒ errorObjectに変換"
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
const { code, statusCode } = error;
|
||||||
|
// AuthorIDとWorktypeIDが一致するものが既に存在する場合
|
||||||
|
if (code === "E013001") {
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID(
|
||||||
|
"workflowPage.message.workflowConflictError"
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
// パラメータが存在しない場合
|
||||||
|
if (statusCode === 400) {
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("workflowPage.message.saveFailedError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
// その他のエラー
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("common.message.internalServerError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getworkflowRelationsAsync = createAsyncThunk<
|
||||||
|
{
|
||||||
|
authors: Author[];
|
||||||
|
typists: Typist[];
|
||||||
|
typistGroups: TypistGroup[];
|
||||||
|
templates: TemplateFile[];
|
||||||
|
worktypes: Worktype[];
|
||||||
|
},
|
||||||
|
void,
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("workflow/getworkflowRelationsAsync", async (args, thunkApi) => {
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const accountsApi = new AccountsApi(config);
|
||||||
|
const templatesApi = new TemplatesApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { authors } = (
|
||||||
|
await accountsApi.getAuthors({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
const { typists } = (
|
||||||
|
await accountsApi.getTypists({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
const { typistGroups } = (
|
||||||
|
await accountsApi.getTypistGroups({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
const { templates } = (
|
||||||
|
await templatesApi.getTemplates({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
const { worktypes } = (
|
||||||
|
await accountsApi.getWorktypes({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
authors,
|
||||||
|
typists,
|
||||||
|
typistGroups,
|
||||||
|
templates,
|
||||||
|
worktypes,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
// e ⇒ errorObjectに変換"
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("common.message.internalServerError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Assignee } from "api";
|
||||||
import { RootState } from "app/store";
|
import { RootState } from "app/store";
|
||||||
|
|
||||||
export const selectWorkflows = (state: RootState) =>
|
export const selectWorkflows = (state: RootState) =>
|
||||||
@ -5,3 +6,47 @@ export const selectWorkflows = (state: RootState) =>
|
|||||||
|
|
||||||
export const selectIsLoading = (state: RootState) =>
|
export const selectIsLoading = (state: RootState) =>
|
||||||
state.workflow.apps.isLoading;
|
state.workflow.apps.isLoading;
|
||||||
|
|
||||||
|
export const selectWorkflowRelations = (state: RootState) =>
|
||||||
|
state.workflow.domain.workflowRelations;
|
||||||
|
|
||||||
|
export const selectWorkflowAssinee = (state: RootState) => {
|
||||||
|
// 選択されたassigneeを取得
|
||||||
|
const { selectedAssignees } = state.workflow.apps;
|
||||||
|
// すべてのassigneeを取得
|
||||||
|
const assignees = state.workflow.domain.workflowRelations?.assignees ?? [];
|
||||||
|
// assigneeが選択されているかどうかを判定する
|
||||||
|
const isAssigneeSelected = (assignee: Assignee) =>
|
||||||
|
selectedAssignees.some(
|
||||||
|
(sa) =>
|
||||||
|
sa.typistUserId === assignee.typistUserId &&
|
||||||
|
sa.typistGroupId === assignee.typistGroupId
|
||||||
|
);
|
||||||
|
// 未選択のassigneeを取得する
|
||||||
|
const poolAssignees = assignees.filter(
|
||||||
|
(assignee) => !isAssigneeSelected(assignee)
|
||||||
|
);
|
||||||
|
// selectedAssigneesとpoolAssigneesをtypistNameでソートして返す
|
||||||
|
return {
|
||||||
|
selectedAssignees: [...selectedAssignees].sort((a, b) =>
|
||||||
|
a.typistName.localeCompare(b.typistName)
|
||||||
|
),
|
||||||
|
poolAssignees: poolAssignees.sort((a, b) =>
|
||||||
|
a.typistName.localeCompare(b.typistName)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export const selectIsAddLoading = (state: RootState) =>
|
||||||
|
state.workflow.apps.isAddLoading;
|
||||||
|
|
||||||
|
export const selectWorkflowError = (state: RootState) => {
|
||||||
|
// authorIdがundefinedの場合はエラーを返す
|
||||||
|
const hasAuthorIdEmptyError = state.workflow.apps.authorId === undefined;
|
||||||
|
// workflowAssineeのselectedが空の場合はエラーを返す
|
||||||
|
const hasSelectedWorkflowAssineeEmptyError =
|
||||||
|
state.workflow.apps.selectedAssignees.length === 0;
|
||||||
|
return {
|
||||||
|
hasAuthorIdEmptyError,
|
||||||
|
hasSelectedWorkflowAssineeEmptyError,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Workflow } from "api";
|
import { Assignee, Author, TemplateFile, Workflow, Worktype } from "api";
|
||||||
|
|
||||||
export interface WorkflowState {
|
export interface WorkflowState {
|
||||||
apps: Apps;
|
apps: Apps;
|
||||||
@ -7,8 +7,21 @@ export interface WorkflowState {
|
|||||||
|
|
||||||
export interface Apps {
|
export interface Apps {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
isAddLoading: boolean;
|
||||||
|
selectedAssignees: Assignee[];
|
||||||
|
authorId?: number;
|
||||||
|
worktypeId?: number;
|
||||||
|
templateId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Domain {
|
export interface Domain {
|
||||||
workflows?: Workflow[];
|
workflows?: Workflow[];
|
||||||
|
workflowRelations?: WorkflowRelations;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkflowRelations {
|
||||||
|
authors: Author[];
|
||||||
|
assignees: Assignee[];
|
||||||
|
templates: TemplateFile[];
|
||||||
|
worktypes: Worktype[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import { createSlice } from "@reduxjs/toolkit";
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
|
import { Assignee } from "api";
|
||||||
|
import {
|
||||||
|
createWorkflowAsync,
|
||||||
|
getworkflowRelationsAsync,
|
||||||
|
listWorkflowAsync,
|
||||||
|
} from "./operations";
|
||||||
import { WorkflowState } from "./state";
|
import { WorkflowState } from "./state";
|
||||||
import { listWorkflowAsync } from "./operations";
|
|
||||||
|
|
||||||
const initialState: WorkflowState = {
|
const initialState: WorkflowState = {
|
||||||
apps: {
|
apps: {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
isAddLoading: false,
|
||||||
|
selectedAssignees: [],
|
||||||
},
|
},
|
||||||
domain: {},
|
domain: {},
|
||||||
};
|
};
|
||||||
@ -12,7 +19,55 @@ const initialState: WorkflowState = {
|
|||||||
export const workflowSlice = createSlice({
|
export const workflowSlice = createSlice({
|
||||||
name: "workflow",
|
name: "workflow",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {},
|
reducers: {
|
||||||
|
clearWorkflow: (state) => {
|
||||||
|
state.apps.selectedAssignees = [];
|
||||||
|
state.apps.authorId = undefined;
|
||||||
|
state.apps.worktypeId = undefined;
|
||||||
|
state.apps.templateId = undefined;
|
||||||
|
state.domain.workflowRelations = undefined;
|
||||||
|
},
|
||||||
|
addAssignee: (state, action: PayloadAction<{ assignee: Assignee }>) => {
|
||||||
|
const { assignee } = action.payload;
|
||||||
|
const { selectedAssignees } = state.apps;
|
||||||
|
|
||||||
|
// assigneeがselectedAssigneesに存在するか確認する
|
||||||
|
const isDuplicate = selectedAssignees.some(
|
||||||
|
(x) =>
|
||||||
|
x.typistUserId === assignee.typistUserId &&
|
||||||
|
x.typistGroupId === assignee.typistGroupId
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重複していなければ追加する
|
||||||
|
if (!isDuplicate) {
|
||||||
|
const newSelectedAssignees = [...selectedAssignees, assignee];
|
||||||
|
// stateに保存する
|
||||||
|
state.apps.selectedAssignees = newSelectedAssignees;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeAssignee: (state, action: PayloadAction<{ assignee: Assignee }>) => {
|
||||||
|
const { assignee } = action.payload;
|
||||||
|
const { selectedAssignees } = state.apps;
|
||||||
|
// selectedAssigneeの要素からassigneeを削除する
|
||||||
|
state.apps.selectedAssignees = selectedAssignees.filter(
|
||||||
|
(x) =>
|
||||||
|
x.typistUserId !== assignee.typistUserId ||
|
||||||
|
x.typistGroupId !== assignee.typistGroupId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
changeAuthor: (state, action: PayloadAction<{ authorId: number }>) => {
|
||||||
|
const { authorId } = action.payload;
|
||||||
|
state.apps.authorId = authorId;
|
||||||
|
},
|
||||||
|
changeWorktype: (state, action: PayloadAction<{ worktypeId?: number }>) => {
|
||||||
|
const { worktypeId } = action.payload;
|
||||||
|
state.apps.worktypeId = worktypeId;
|
||||||
|
},
|
||||||
|
changeTemplate: (state, action: PayloadAction<{ templateId?: number }>) => {
|
||||||
|
const { templateId } = action.payload;
|
||||||
|
state.apps.templateId = templateId;
|
||||||
|
},
|
||||||
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder.addCase(listWorkflowAsync.pending, (state) => {
|
builder.addCase(listWorkflowAsync.pending, (state) => {
|
||||||
state.apps.isLoading = true;
|
state.apps.isLoading = true;
|
||||||
@ -26,7 +81,62 @@ export const workflowSlice = createSlice({
|
|||||||
builder.addCase(listWorkflowAsync.rejected, (state) => {
|
builder.addCase(listWorkflowAsync.rejected, (state) => {
|
||||||
state.apps.isLoading = false;
|
state.apps.isLoading = false;
|
||||||
});
|
});
|
||||||
|
builder.addCase(getworkflowRelationsAsync.pending, (state) => {
|
||||||
|
state.apps.isAddLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(getworkflowRelationsAsync.fulfilled, (state, action) => {
|
||||||
|
const { authors, typistGroups, typists, templates, worktypes } =
|
||||||
|
action.payload;
|
||||||
|
|
||||||
|
// 取得したtypistsとtypistGroupsを型変換
|
||||||
|
const assineeTypists = typists.map(
|
||||||
|
(typist): Assignee => ({
|
||||||
|
typistUserId: typist.id,
|
||||||
|
typistGroupId: undefined,
|
||||||
|
typistName: typist.name,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const assineeTypistGroups = typistGroups.map(
|
||||||
|
(typistGroup): Assignee => ({
|
||||||
|
typistUserId: undefined,
|
||||||
|
typistGroupId: typistGroup.id,
|
||||||
|
typistName: typistGroup.name,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
// 取得したtypistsとtypistGroupsを結合
|
||||||
|
const assinees = [...assineeTypists, ...assineeTypistGroups];
|
||||||
|
// storeに保存
|
||||||
|
state.domain.workflowRelations = {
|
||||||
|
authors,
|
||||||
|
assignees: assinees,
|
||||||
|
templates,
|
||||||
|
worktypes,
|
||||||
|
};
|
||||||
|
|
||||||
|
state.apps.isAddLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(getworkflowRelationsAsync.rejected, (state) => {
|
||||||
|
state.apps.isAddLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(createWorkflowAsync.pending, (state) => {
|
||||||
|
state.apps.isAddLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(createWorkflowAsync.fulfilled, (state) => {
|
||||||
|
state.apps.isAddLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(createWorkflowAsync.rejected, (state) => {
|
||||||
|
state.apps.isAddLoading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const {
|
||||||
|
addAssignee,
|
||||||
|
removeAssignee,
|
||||||
|
changeAuthor,
|
||||||
|
changeWorktype,
|
||||||
|
changeTemplate,
|
||||||
|
clearWorkflow,
|
||||||
|
} = workflowSlice.actions;
|
||||||
|
|
||||||
export default workflowSlice.reducer;
|
export default workflowSlice.reducer;
|
||||||
|
|||||||
293
dictation_client/src/pages/WorkflowPage/addworkflowPopup.tsx
Normal file
293
dictation_client/src/pages/WorkflowPage/addworkflowPopup.tsx
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
|
import { AppDispatch } from "app/store";
|
||||||
|
import progress_activit from "assets/images/progress_activit.svg";
|
||||||
|
import {
|
||||||
|
addAssignee,
|
||||||
|
removeAssignee,
|
||||||
|
changeAuthor,
|
||||||
|
changeTemplate,
|
||||||
|
changeWorktype,
|
||||||
|
clearWorkflow,
|
||||||
|
selectIsAddLoading,
|
||||||
|
selectWorkflowAssinee,
|
||||||
|
selectWorkflowError,
|
||||||
|
selectWorkflowRelations,
|
||||||
|
} from "features/workflow";
|
||||||
|
import {
|
||||||
|
createWorkflowAsync,
|
||||||
|
getworkflowRelationsAsync,
|
||||||
|
listWorkflowAsync,
|
||||||
|
} from "features/workflow/operations";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import styles from "styles/app.module.scss";
|
||||||
|
import { getTranslationID } from "translation";
|
||||||
|
import close from "../../assets/images/close.svg";
|
||||||
|
|
||||||
|
interface AddWorkflowPopupProps {
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AddWorkflowPopup: React.FC<AddWorkflowPopupProps> = (
|
||||||
|
props
|
||||||
|
): JSX.Element => {
|
||||||
|
const { onClose } = props;
|
||||||
|
const dispatch: AppDispatch = useDispatch();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
// 保存ボタンを押したかどうか
|
||||||
|
const [isPushAddButton, setIsPushAddButton] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const workflowRelations = useSelector(selectWorkflowRelations);
|
||||||
|
const { poolAssignees, selectedAssignees } = useSelector(
|
||||||
|
selectWorkflowAssinee
|
||||||
|
);
|
||||||
|
const isLoading = useSelector(selectIsAddLoading);
|
||||||
|
const { hasAuthorIdEmptyError, hasSelectedWorkflowAssineeEmptyError } =
|
||||||
|
useSelector(selectWorkflowError);
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(getworkflowRelationsAsync());
|
||||||
|
// ポップアップのアンマウント時に初期化を行う
|
||||||
|
return () => {
|
||||||
|
dispatch(clearWorkflow());
|
||||||
|
setIsPushAddButton(false);
|
||||||
|
};
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const changeWorktypeId = useCallback(
|
||||||
|
(target: string) => {
|
||||||
|
// 空文字の場合はundefinedをdispatchする
|
||||||
|
if (target === "") {
|
||||||
|
dispatch(changeWorktype({ worktypeId: undefined }));
|
||||||
|
} else if (!Number.isNaN(Number(target))) {
|
||||||
|
dispatch(changeWorktype({ worktypeId: Number(target) }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeTemplateId = useCallback(
|
||||||
|
(target: string) => {
|
||||||
|
// 空文字の場合はundefinedをdispatchする
|
||||||
|
if (target === "") {
|
||||||
|
dispatch(changeTemplate({ templateId: undefined }));
|
||||||
|
} else if (!Number.isNaN(Number(target))) {
|
||||||
|
dispatch(changeTemplate({ templateId: Number(target) }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeAuthorId = useCallback(
|
||||||
|
(target: string) => {
|
||||||
|
if (!Number.isNaN(target)) {
|
||||||
|
dispatch(changeAuthor({ authorId: Number(target) }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 追加ボタン押下時の処理
|
||||||
|
const handleAdd = useCallback(async () => {
|
||||||
|
setIsPushAddButton(true);
|
||||||
|
// エラーチェック
|
||||||
|
if (hasAuthorIdEmptyError || hasSelectedWorkflowAssineeEmptyError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { meta } = await dispatch(createWorkflowAsync());
|
||||||
|
if (meta.requestStatus === "fulfilled") {
|
||||||
|
onClose();
|
||||||
|
dispatch(listWorkflowAsync());
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
dispatch,
|
||||||
|
hasAuthorIdEmptyError,
|
||||||
|
hasSelectedWorkflowAssineeEmptyError,
|
||||||
|
onClose,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${styles.modal} ${styles.isShow}`}>
|
||||||
|
<div className={styles.modalBox}>
|
||||||
|
<p className={styles.modalTitle}>
|
||||||
|
{t(getTranslationID("worktypeIdSetting.label.addWorktypeId"))}
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */}
|
||||||
|
<img
|
||||||
|
src={close}
|
||||||
|
className={styles.modalTitleIcon}
|
||||||
|
alt="close"
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<form className={styles.form}>
|
||||||
|
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||||
|
<dt className={styles.formTitle} />
|
||||||
|
<dt>{t(getTranslationID("workflowPage.label.authorID"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<select
|
||||||
|
className={styles.formInput}
|
||||||
|
onChange={(e) => {
|
||||||
|
changeAuthorId(e.target.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="" hidden>
|
||||||
|
{`-- ${t(
|
||||||
|
getTranslationID("workflowPage.label.selectAuthor")
|
||||||
|
)} --`}
|
||||||
|
</option>
|
||||||
|
{workflowRelations?.authors.map((author) => (
|
||||||
|
<option key={author.authorId} value={author.id}>
|
||||||
|
{author.authorId}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{isPushAddButton && hasAuthorIdEmptyError && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{t(getTranslationID("workflowPage.message.inputEmptyError"))}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
<dt className={styles.overLine}>
|
||||||
|
{t(getTranslationID("workflowPage.label.worktypeOptional"))}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<select
|
||||||
|
className={styles.formInput}
|
||||||
|
onChange={(e) => {
|
||||||
|
changeWorktypeId(e.target.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="" hidden>
|
||||||
|
{`-- ${t(
|
||||||
|
getTranslationID("workflowPage.label.selectWorktypeId")
|
||||||
|
)} --`}
|
||||||
|
</option>
|
||||||
|
<option value="">
|
||||||
|
{`-- ${t(getTranslationID("common.label.notSelected"))} --`}
|
||||||
|
</option>
|
||||||
|
{workflowRelations?.worktypes.map((worktype) => (
|
||||||
|
<option key={worktype.id} value={worktype.id}>
|
||||||
|
{worktype.worktypeId}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
<dt className={styles.formTitle}>
|
||||||
|
{t(getTranslationID("typistGroupSetting.label.transcriptionist"))}
|
||||||
|
</dt>
|
||||||
|
<dd className={`${styles.formChange} ${styles.last}`}>
|
||||||
|
<ul className={styles.chooseMember}>
|
||||||
|
<li className={styles.changeTitle}>
|
||||||
|
{t(getTranslationID("workflowPage.label.selected"))}
|
||||||
|
</li>
|
||||||
|
{selectedAssignees?.map((x) => {
|
||||||
|
const key = `${x.typistName}_${
|
||||||
|
x.typistUserId ?? x.typistGroupId
|
||||||
|
}`;
|
||||||
|
return (
|
||||||
|
<li key={key}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className={styles.formCheck}
|
||||||
|
value={x.typistName}
|
||||||
|
id={key}
|
||||||
|
checked
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(removeAssignee({ assignee: x }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor={key} title="Remove">
|
||||||
|
{x.typistName}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
<p />
|
||||||
|
<ul className={styles.holdMember}>
|
||||||
|
<li className={styles.changeTitle}>
|
||||||
|
{t(getTranslationID("workflowPage.label.pool"))}
|
||||||
|
</li>
|
||||||
|
{poolAssignees?.map((x) => {
|
||||||
|
const key = `${x.typistName}_${
|
||||||
|
x.typistUserId ?? x.typistGroupId
|
||||||
|
}`;
|
||||||
|
return (
|
||||||
|
<li key={key}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className={styles.formCheck}
|
||||||
|
value={x.typistName}
|
||||||
|
id={key}
|
||||||
|
onClick={() => dispatch(addAssignee({ assignee: x }))}
|
||||||
|
/>
|
||||||
|
<label htmlFor={key} title="Add">
|
||||||
|
{x.typistName}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
{isPushAddButton && hasSelectedWorkflowAssineeEmptyError && (
|
||||||
|
<span
|
||||||
|
className={styles.formError}
|
||||||
|
style={{ margin: "0px 30px 0px 30px" }}
|
||||||
|
>
|
||||||
|
{t(
|
||||||
|
getTranslationID(
|
||||||
|
"workflowPage.message.selectedTypistEmptyError"
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
<dt className={styles.overLine}>
|
||||||
|
{t(getTranslationID("workflowPage.label.templateOptional"))}
|
||||||
|
</dt>
|
||||||
|
<dd className={styles.last}>
|
||||||
|
<select
|
||||||
|
className={styles.formInput}
|
||||||
|
onChange={(e) => {
|
||||||
|
changeTemplateId(e.target.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="" hidden>
|
||||||
|
{`-- ${t(
|
||||||
|
getTranslationID("workflowPage.label.selectTemplate")
|
||||||
|
)} --`}
|
||||||
|
</option>
|
||||||
|
<option value="">
|
||||||
|
{`-- ${t(getTranslationID("common.label.notSelected"))} --`}
|
||||||
|
</option>
|
||||||
|
{workflowRelations?.templates.map((template) => (
|
||||||
|
<option
|
||||||
|
key={`${template.name}_${template.id}`}
|
||||||
|
value={template.id}
|
||||||
|
>
|
||||||
|
{template.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<input
|
||||||
|
type="button"
|
||||||
|
value={t(getTranslationID("common.label.save"))}
|
||||||
|
className={`${styles.formSubmit} ${styles.marginBtm1} ${
|
||||||
|
!isLoading ? styles.isActive : ""
|
||||||
|
}`}
|
||||||
|
onClick={handleAdd}
|
||||||
|
/>
|
||||||
|
{isLoading && (
|
||||||
|
<img
|
||||||
|
src={progress_activit}
|
||||||
|
className={styles.icLoading}
|
||||||
|
alt="Loading"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Header from "components/header";
|
import Header from "components/header";
|
||||||
import Footer from "components/footer";
|
import Footer from "components/footer";
|
||||||
import styles from "styles/app.module.scss";
|
import styles from "styles/app.module.scss";
|
||||||
@ -14,10 +14,13 @@ import { listWorkflowAsync } from "features/workflow/operations";
|
|||||||
import { selectIsLoading, selectWorkflows } from "features/workflow";
|
import { selectIsLoading, selectWorkflows } from "features/workflow";
|
||||||
import progress_activit from "assets/images/progress_activit.svg";
|
import progress_activit from "assets/images/progress_activit.svg";
|
||||||
import { getTranslationID } from "translation";
|
import { getTranslationID } from "translation";
|
||||||
|
import { AddWorkflowPopup } from "./addworkflowPopup";
|
||||||
|
|
||||||
const WorkflowPage: React.FC = (): JSX.Element => {
|
const WorkflowPage: React.FC = (): JSX.Element => {
|
||||||
const dispatch: AppDispatch = useDispatch();
|
const dispatch: AppDispatch = useDispatch();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
// 追加Popupの表示制御
|
||||||
|
const [isShowAddPopup, setIsShowAddPopup] = useState<boolean>(false);
|
||||||
const workflows = useSelector(selectWorkflows);
|
const workflows = useSelector(selectWorkflows);
|
||||||
const isLoading = useSelector(selectIsLoading);
|
const isLoading = useSelector(selectIsLoading);
|
||||||
|
|
||||||
@ -25,138 +28,166 @@ const WorkflowPage: React.FC = (): JSX.Element => {
|
|||||||
dispatch(listWorkflowAsync());
|
dispatch(listWorkflowAsync());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrap}>
|
<>
|
||||||
<Header userName="XXXXXX" />
|
{isShowAddPopup && (
|
||||||
<UpdateTokenTimer />
|
<AddWorkflowPopup
|
||||||
<main className={styles.main}>
|
onClose={() => {
|
||||||
<div className="">
|
setIsShowAddPopup(false);
|
||||||
<div className={styles.pageHeader}>
|
}}
|
||||||
<h1 className={styles.pageTitle}>
|
/>
|
||||||
{t(getTranslationID("workflowPage.label.title"))}
|
)}
|
||||||
</h1>
|
<div className={styles.wrap}>
|
||||||
</div>
|
<Header userName="XXXXXX" />
|
||||||
<section className={styles.workflow}>
|
<UpdateTokenTimer />
|
||||||
<div>
|
<main className={styles.main}>
|
||||||
<ul className={`${styles.menuAction} ${styles.alignRight}`}>
|
<div className="">
|
||||||
<li className={styles.floatLeft}>
|
<div className={styles.pageHeader}>
|
||||||
<a className={`${styles.menuLink} ${styles.isActive}`}>
|
<h1 className={styles.pageTitle}>
|
||||||
<img
|
{t(getTranslationID("workflowPage.label.title"))}
|
||||||
src={ruleAddImg}
|
</h1>
|
||||||
alt="addRoutingRule"
|
|
||||||
className={styles.menuIcon}
|
|
||||||
/>
|
|
||||||
{t(getTranslationID("workflowPage.label.addRoutingRule"))}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="/workflow/template"
|
|
||||||
className={`${styles.menuLink} ${styles.isActive}`}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={templateSettingImg}
|
|
||||||
alt="templateSetting"
|
|
||||||
className={styles.menuIcon}
|
|
||||||
/>
|
|
||||||
{t(getTranslationID("workflowPage.label.templateSetting"))}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="/workflow/worktype-id"
|
|
||||||
className={`${styles.menuLink} ${styles.isActive}`}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={worktypeSettingImg}
|
|
||||||
alt="worktypeIdSetting"
|
|
||||||
className={styles.menuIcon}
|
|
||||||
/>
|
|
||||||
{t(
|
|
||||||
getTranslationID("workflowPage.label.worktypeIdSetting")
|
|
||||||
)}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="/workflow/typist-group"
|
|
||||||
className={`${styles.menuLink} ${styles.isActive}`}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={groupSettingImg}
|
|
||||||
alt="typistGroupSetting"
|
|
||||||
className={styles.menuIcon}
|
|
||||||
/>
|
|
||||||
{t(
|
|
||||||
getTranslationID("workflowPage.label.typistGroupSetting")
|
|
||||||
)}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<table className={`${styles.table} ${styles.workflow}`}>
|
|
||||||
<tr className={styles.tableHeader}>
|
|
||||||
<th className={styles.clm0}>{/** empty th */}</th>
|
|
||||||
<th>{t(getTranslationID("workflowPage.label.authorID"))}</th>
|
|
||||||
<th>{t(getTranslationID("workflowPage.label.worktype"))}</th>
|
|
||||||
<th>
|
|
||||||
{t(getTranslationID("workflowPage.label.transcriptionist"))}
|
|
||||||
</th>
|
|
||||||
<th>{t(getTranslationID("workflowPage.label.template"))}</th>
|
|
||||||
</tr>
|
|
||||||
{workflows?.map((workflow) => (
|
|
||||||
<tr key={workflow.id}>
|
|
||||||
<td className={styles.clm0}>
|
|
||||||
<ul className={styles.menuInTable}>
|
|
||||||
<li>
|
|
||||||
<a href="">
|
|
||||||
{t(getTranslationID("workflowPage.label.editRule"))}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="">
|
|
||||||
{t(getTranslationID("common.label.delete"))}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>{workflow.author.authorId}</td>
|
|
||||||
<td>{workflow.worktype?.worktypeId ?? "-"}</td>
|
|
||||||
|
|
||||||
<td className={styles.txWsline}>
|
|
||||||
{workflow.typists.map((typist, i) => (
|
|
||||||
<>
|
|
||||||
{typist.typistName}
|
|
||||||
{i !== workflow.typists.length - 1 && <br />}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</td>
|
|
||||||
<td>{workflow.template?.fileName ?? "-"}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</table>
|
|
||||||
{!isLoading && workflows?.length === 0 && (
|
|
||||||
<p
|
|
||||||
style={{
|
|
||||||
margin: "10px",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t(getTranslationID("common.message.listEmpty"))}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{isLoading && (
|
|
||||||
<img
|
|
||||||
src={progress_activit}
|
|
||||||
className={styles.icLoading}
|
|
||||||
alt="Loading"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<section className={styles.workflow}>
|
||||||
</div>
|
<div>
|
||||||
</main>
|
<ul className={`${styles.menuAction} ${styles.alignRight}`}>
|
||||||
<Footer />
|
<li className={styles.floatLeft}>
|
||||||
</div>
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||||
|
<a
|
||||||
|
className={`${styles.menuLink} ${styles.isActive}`}
|
||||||
|
onClick={() => {
|
||||||
|
setIsShowAddPopup(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={ruleAddImg}
|
||||||
|
alt="addRoutingRule"
|
||||||
|
className={styles.menuIcon}
|
||||||
|
/>
|
||||||
|
{t(getTranslationID("workflowPage.label.addRoutingRule"))}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/workflow/template"
|
||||||
|
className={`${styles.menuLink} ${styles.isActive}`}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={templateSettingImg}
|
||||||
|
alt="templateSetting"
|
||||||
|
className={styles.menuIcon}
|
||||||
|
/>
|
||||||
|
{t(
|
||||||
|
getTranslationID("workflowPage.label.templateSetting")
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/workflow/worktype-id"
|
||||||
|
className={`${styles.menuLink} ${styles.isActive}`}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={worktypeSettingImg}
|
||||||
|
alt="worktypeIdSetting"
|
||||||
|
className={styles.menuIcon}
|
||||||
|
/>
|
||||||
|
{t(
|
||||||
|
getTranslationID("workflowPage.label.worktypeIdSetting")
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/workflow/typist-group"
|
||||||
|
className={`${styles.menuLink} ${styles.isActive}`}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={groupSettingImg}
|
||||||
|
alt="typistGroupSetting"
|
||||||
|
className={styles.menuIcon}
|
||||||
|
/>
|
||||||
|
{t(
|
||||||
|
getTranslationID(
|
||||||
|
"workflowPage.label.typistGroupSetting"
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<table className={`${styles.table} ${styles.workflow}`}>
|
||||||
|
<tr className={styles.tableHeader}>
|
||||||
|
<th className={styles.clm0}>{/** empty th */}</th>
|
||||||
|
<th>
|
||||||
|
{t(getTranslationID("workflowPage.label.authorID"))}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{t(getTranslationID("workflowPage.label.worktype"))}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{t(
|
||||||
|
getTranslationID("workflowPage.label.transcriptionist")
|
||||||
|
)}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{t(getTranslationID("workflowPage.label.template"))}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{workflows?.map((workflow) => (
|
||||||
|
<tr key={workflow.id}>
|
||||||
|
<td className={styles.clm0}>
|
||||||
|
<ul className={styles.menuInTable}>
|
||||||
|
<li>
|
||||||
|
<a href="">
|
||||||
|
{t(
|
||||||
|
getTranslationID("workflowPage.label.editRule")
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="">
|
||||||
|
{t(getTranslationID("common.label.delete"))}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>{workflow.author.authorId}</td>
|
||||||
|
<td>{workflow.worktype?.worktypeId ?? "-"}</td>
|
||||||
|
|
||||||
|
<td className={styles.txWsline}>
|
||||||
|
{workflow.typists.map((typist, i) => (
|
||||||
|
<>
|
||||||
|
{typist.typistName}
|
||||||
|
{i !== workflow.typists.length - 1 && <br />}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</td>
|
||||||
|
<td>{workflow.template?.fileName ?? "-"}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</table>
|
||||||
|
{!isLoading && workflows?.length === 0 && (
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
margin: "10px",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t(getTranslationID("common.message.listEmpty"))}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{isLoading && (
|
||||||
|
<img
|
||||||
|
src={progress_activit}
|
||||||
|
className={styles.icLoading}
|
||||||
|
alt="Loading"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -363,9 +363,22 @@
|
|||||||
"typistGroupSetting": "(de)Transcriptionist Group Setting",
|
"typistGroupSetting": "(de)Transcriptionist Group Setting",
|
||||||
"authorID": "Autoren-ID",
|
"authorID": "Autoren-ID",
|
||||||
"worktype": "Aufgabentypkennung",
|
"worktype": "Aufgabentypkennung",
|
||||||
|
"worktypeOptional": "(de)Worktype ID (Optional)",
|
||||||
"transcriptionist": "Transkriptionist",
|
"transcriptionist": "Transkriptionist",
|
||||||
"template": "(de)Template",
|
"template": "(de)Template",
|
||||||
"editRule": "(de)Edit Rule"
|
"templateOptional": "(de)Template (Optional)",
|
||||||
|
"editRule": "(de)Edit Rule",
|
||||||
|
"selected": "Ausgewählter transkriptionist",
|
||||||
|
"pool": "Transkriptionsliste",
|
||||||
|
"selectAuthor": "(de)Select Author",
|
||||||
|
"selectWorktypeId": "(de)Select Worktype ID",
|
||||||
|
"selectTemplate": "(de)Select Template"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"selectedTypistEmptyError": "(de)Transcriptionist,TranscriptionistGroupがいないルーティングルールは保存できません。ルーティング先を1つ以上選択してください。",
|
||||||
|
"workflowConflictError": "(de)指定したAuthorIDとWorktypeIDの組み合わせで既にルーティングルールが登録されています。他の組み合わせで登録してください。",
|
||||||
|
"inputEmptyError": "Pflichtfeld",
|
||||||
|
"saveFailedError": "(de)ルーティングルールの保存に失敗しました。画面を更新し、再度実行してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typistGroupSetting": {
|
"typistGroupSetting": {
|
||||||
@ -485,4 +498,4 @@
|
|||||||
"backToTopPageLink": "(de)Back to TOP Page"
|
"backToTopPageLink": "(de)Back to TOP Page"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,9 +363,22 @@
|
|||||||
"typistGroupSetting": "Transcriptionist Group Setting",
|
"typistGroupSetting": "Transcriptionist Group Setting",
|
||||||
"authorID": "Author ID",
|
"authorID": "Author ID",
|
||||||
"worktype": "Worktype ID",
|
"worktype": "Worktype ID",
|
||||||
|
"worktypeOptional": "Worktype ID (Optional)",
|
||||||
"transcriptionist": "Transcriptionist",
|
"transcriptionist": "Transcriptionist",
|
||||||
"template": "Template",
|
"template": "Template",
|
||||||
"editRule": "Edit Rule"
|
"templateOptional": "Template (Optional)",
|
||||||
|
"editRule": "Edit Rule",
|
||||||
|
"selected": "Selected Transcriptionist",
|
||||||
|
"pool": "Transcription List",
|
||||||
|
"selectAuthor": "Select Author",
|
||||||
|
"selectWorktypeId": "Select Worktype ID",
|
||||||
|
"selectTemplate": "Select Template"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"selectedTypistEmptyError": "Transcriptionist,TranscriptionistGroupがいないルーティングルールは保存できません。ルーティング先を1つ以上選択してください。",
|
||||||
|
"workflowConflictError": "指定したAuthorIDとWorktypeIDの組み合わせで既にルーティングルールが登録されています。他の組み合わせで登録してください。",
|
||||||
|
"inputEmptyError": "Mandatory Field",
|
||||||
|
"saveFailedError": "ルーティングルールの保存に失敗しました。画面を更新し、再度実行してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typistGroupSetting": {
|
"typistGroupSetting": {
|
||||||
@ -485,4 +498,4 @@
|
|||||||
"backToTopPageLink": "Back to TOP Page"
|
"backToTopPageLink": "Back to TOP Page"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,9 +363,22 @@
|
|||||||
"typistGroupSetting": "(es)Transcriptionist Group Setting",
|
"typistGroupSetting": "(es)Transcriptionist Group Setting",
|
||||||
"authorID": "ID de autor",
|
"authorID": "ID de autor",
|
||||||
"worktype": "ID de tipo de trabajo",
|
"worktype": "ID de tipo de trabajo",
|
||||||
|
"worktypeOptional": "(es)Worktype ID (Optional)",
|
||||||
"transcriptionist": "Transcriptor",
|
"transcriptionist": "Transcriptor",
|
||||||
"template": "(es)Template",
|
"template": "(es)Template",
|
||||||
"editRule": "(es)Edit Rule"
|
"templateOptional": "(es)Template (Optional)",
|
||||||
|
"editRule": "(es)Edit Rule",
|
||||||
|
"selected": "Transcriptor seleccionado",
|
||||||
|
"pool": "Lista de transcriptor",
|
||||||
|
"selectAuthor": "(es)Select Author",
|
||||||
|
"selectWorktypeId": "(es)Select Worktype ID",
|
||||||
|
"selectTemplate": "(es)Select Template"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"selectedTypistEmptyError": "(es)Transcriptionist,TranscriptionistGroupがいないルーティングルールは保存できません。ルーティング先を1つ以上選択してください。",
|
||||||
|
"workflowConflictError": "(es)指定したAuthorIDとWorktypeIDの組み合わせで既にルーティングルールが登録されています。他の組み合わせで登録してください。",
|
||||||
|
"inputEmptyError": "Campo obligatorio",
|
||||||
|
"saveFailedError": "(es)ルーティングルールの保存に失敗しました。画面を更新し、再度実行してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typistGroupSetting": {
|
"typistGroupSetting": {
|
||||||
@ -485,4 +498,4 @@
|
|||||||
"backToTopPageLink": "(es)Back to TOP Page"
|
"backToTopPageLink": "(es)Back to TOP Page"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,9 +363,22 @@
|
|||||||
"typistGroupSetting": "(fr)Transcriptionist Group Setting",
|
"typistGroupSetting": "(fr)Transcriptionist Group Setting",
|
||||||
"authorID": "Identifiant Auteur",
|
"authorID": "Identifiant Auteur",
|
||||||
"worktype": "Identifiant du Type de travail",
|
"worktype": "Identifiant du Type de travail",
|
||||||
|
"worktypeOptional": "(fr)Worktype ID (Optional)",
|
||||||
"transcriptionist": "Transcriptionniste",
|
"transcriptionist": "Transcriptionniste",
|
||||||
"template": "(fr)Template",
|
"template": "(fr)Template",
|
||||||
"editRule": "(fr)Edit Rule"
|
"templateOptional": "(fr)Template (Optional)",
|
||||||
|
"editRule": "(fr)Edit Rule",
|
||||||
|
"selected": "Transcriptionniste sélectionné",
|
||||||
|
"pool": "Liste de transcriptionniste",
|
||||||
|
"selectAuthor": "(fr)Select Author",
|
||||||
|
"selectWorktypeId": "(fr)Select Worktype ID",
|
||||||
|
"selectTemplate": "(fr)Select Template"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"selectedTypistEmptyError": "(fr)Transcriptionist,TranscriptionistGroupがいないルーティングルールは保存できません。ルーティング先を1つ以上選択してください。",
|
||||||
|
"workflowConflictError": "(fr)指定したAuthorIDとWorktypeIDの組み合わせで既にルーティングルールが登録されています。他の組み合わせで登録してください。",
|
||||||
|
"inputEmptyError": "Champ obligatoire",
|
||||||
|
"saveFailedError": "(fr)ルーティングルールの保存に失敗しました。画面を更新し、再度実行してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typistGroupSetting": {
|
"typistGroupSetting": {
|
||||||
@ -485,4 +498,4 @@
|
|||||||
"backToTopPageLink": "(fr)Back to TOP Page"
|
"backToTopPageLink": "(fr)Back to TOP Page"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user