Merged PR 156: タイピスト割り当てポップアップ実装&画面修正
## 概要 [Task1933: タイピスト割り当てポップアップ実装&画面修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1933) - タイピスト割り当てポップアップを実装しました。 - ポップアップをタスクがUploaded時のみ開けるようにしています。 - タイピスト割り当てを変更・保存できるようにしています。 ## レビューポイント - 画面実装のデザインは適切か - データの保持方法は適切か ## UIの変更 - [Task1933](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/Task1933?csf=1&web=1&e=4ghlqe) ## 動作確認状況 - ローカルで確認 - API連携は未確認
This commit is contained in:
parent
6a1226c62e
commit
33fc741eee
@ -361,72 +361,72 @@ export interface GetLicenseSummaryRequest {
|
||||
* @interface GetLicenseSummaryResponse
|
||||
*/
|
||||
export interface GetLicenseSummaryResponse {
|
||||
/**
|
||||
*
|
||||
* @type {LicenseSummaryInfo}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
totalLicense: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
allocatedLicense: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
reusableLicense: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
freeLicense: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
expiringWithin14daysLicense: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
issueRequesting: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
numberOfRequesting: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
shortage: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
storageSize: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
usedSize: number;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
isAccountLock: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'totalLicense': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'allocatedLicense': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'reusableLicense': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'freeLicense': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'expiringWithin14daysLicense': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'issueRequesting': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'numberOfRequesting': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'shortage': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'storageSize': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'usedSize': number;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof GetLicenseSummaryResponse
|
||||
*/
|
||||
'isAccountLock': boolean;
|
||||
}
|
||||
/**
|
||||
*
|
||||
|
||||
@ -25,4 +25,5 @@ export const errorCodes = [
|
||||
"E010301", // メールアドレス登録済みエラー
|
||||
"E010302", // authorId重複エラー
|
||||
"E010401", // PONumber重複エラー
|
||||
"E010601", // タスク変更不可エラー
|
||||
] as const;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ConfigurationParameters } from "api";
|
||||
import { decodeToken } from "../../common/decodeToken";
|
||||
import { ADMIN_ROLES } from "../../components/auth/constants";
|
||||
import { ADMIN_ROLES, USER_ROLES } from "../../components/auth/constants";
|
||||
|
||||
/**
|
||||
* Get access token
|
||||
@ -66,3 +66,16 @@ export const isAdminUser = (): boolean => {
|
||||
}
|
||||
return token.role.includes(ADMIN_ROLES.ADMIN);
|
||||
};
|
||||
|
||||
/**
|
||||
* is author user ログインしているユーザがAuthorかどうかを返す
|
||||
* @returns bool
|
||||
*/
|
||||
export const isAuthorUser = (): boolean => {
|
||||
const jwt = loadAccessToken();
|
||||
const token = jwt ? decodeToken(jwt) : null;
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
return token.role.includes(USER_ROLES.AUTHOR);
|
||||
};
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||
import { Assignee, Task } from "api/api";
|
||||
import { DictationState } from "./state";
|
||||
import { getSortColumnAsync, listTasksAsync } from "./operations";
|
||||
import {
|
||||
getSortColumnAsync,
|
||||
listTasksAsync,
|
||||
listTypistGroupsAsync,
|
||||
listTypistsAsync,
|
||||
} from "./operations";
|
||||
import {
|
||||
SORTABLE_COLUMN,
|
||||
DIRECTION,
|
||||
@ -17,11 +23,18 @@ const initialState: DictationState = {
|
||||
offset: 0,
|
||||
total: 0,
|
||||
tasks: [],
|
||||
typists: [],
|
||||
typistGroups: [],
|
||||
},
|
||||
apps: {
|
||||
displayInfo: INIT_DISPLAY_INFO,
|
||||
direction: DIRECTION.ASC,
|
||||
paramName: SORTABLE_COLUMN.JobNumber,
|
||||
selectedTask: undefined,
|
||||
assignee: {
|
||||
selected: [],
|
||||
pool: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -50,6 +63,37 @@ export const dictationSlice = createSlice({
|
||||
const { paramName } = action.payload;
|
||||
state.apps.paramName = paramName;
|
||||
},
|
||||
changeSelectedTask: (state, action: PayloadAction<{ task: Task }>) => {
|
||||
const { task } = action.payload;
|
||||
state.apps.selectedTask = task;
|
||||
},
|
||||
changeAssignee: (
|
||||
state,
|
||||
action: PayloadAction<{ selected: Assignee[] }>
|
||||
) => {
|
||||
const { selected } = action.payload;
|
||||
|
||||
const typists = state.domain.typists.map(
|
||||
(x) => ({ typistUserId: x.id, typistName: x.name } as Assignee)
|
||||
);
|
||||
const typistGroups = state.domain.typistGroups.map(
|
||||
(x) => ({ typistGroupId: x.id, typistName: x.name } as Assignee)
|
||||
);
|
||||
|
||||
const transcriptionists = [...typists, ...typistGroups];
|
||||
|
||||
const pool = transcriptionists.filter(
|
||||
(x) =>
|
||||
selected.find(
|
||||
(assign) =>
|
||||
assign.typistGroupId === x.typistGroupId &&
|
||||
assign.typistUserId === x.typistUserId
|
||||
) === undefined
|
||||
);
|
||||
|
||||
state.apps.assignee.selected = selected;
|
||||
state.apps.assignee.pool = pool;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(listTasksAsync.fulfilled, (state, action) => {
|
||||
@ -62,10 +106,21 @@ export const dictationSlice = createSlice({
|
||||
state.apps.direction = action.payload.direction;
|
||||
state.apps.paramName = action.payload.paramName;
|
||||
});
|
||||
builder.addCase(listTypistsAsync.fulfilled, (state, action) => {
|
||||
state.domain.typists = action.payload.typists;
|
||||
});
|
||||
builder.addCase(listTypistGroupsAsync.fulfilled, (state, action) => {
|
||||
state.domain.typistGroups = action.payload.typistGroups;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const { changeDisplayInfo, changeDirection, changeParamName } =
|
||||
dictationSlice.actions;
|
||||
export const {
|
||||
changeDisplayInfo,
|
||||
changeDirection,
|
||||
changeParamName,
|
||||
changeSelectedTask,
|
||||
changeAssignee,
|
||||
} = dictationSlice.actions;
|
||||
|
||||
export default dictationSlice.reducer;
|
||||
|
||||
@ -2,7 +2,15 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { TasksResponse, TasksApi, UsersApi } from "../../api/api";
|
||||
import {
|
||||
TasksResponse,
|
||||
TasksApi,
|
||||
UsersApi,
|
||||
AccountsApi,
|
||||
GetTypistsResponse,
|
||||
GetTypistGroupsResponse,
|
||||
Assignee,
|
||||
} from "../../api/api";
|
||||
import { Configuration } from "../../api/configuration";
|
||||
import { ErrorObject, createErrorObject } from "../../common/errors";
|
||||
import {
|
||||
@ -162,3 +170,133 @@ export const updateSortColumnAsync = createAsyncThunk<
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
export const listTypistsAsync = createAsyncThunk<
|
||||
GetTypistsResponse,
|
||||
void,
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("dictations/listTypistsAsync", 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);
|
||||
|
||||
try {
|
||||
const typists = await accountsApi.getTypists({
|
||||
headers: { authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
|
||||
return typists.data;
|
||||
} catch (e) {
|
||||
// e ⇒ errorObjectに変換"
|
||||
const error = createErrorObject(e);
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID("common.message.internalServerError"),
|
||||
})
|
||||
);
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
export const listTypistGroupsAsync = createAsyncThunk<
|
||||
GetTypistGroupsResponse,
|
||||
void,
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("dictations/listTypistGroupsAsync", 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);
|
||||
|
||||
try {
|
||||
const typistGroup = await accountsApi.getTypistGroups({
|
||||
headers: { authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
|
||||
return typistGroup.data;
|
||||
} catch (e) {
|
||||
// e ⇒ errorObjectに変換"
|
||||
const error = createErrorObject(e);
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID("common.message.internalServerError"),
|
||||
})
|
||||
);
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
export const updateAssigneeAsync = createAsyncThunk<
|
||||
{
|
||||
/** empty */
|
||||
},
|
||||
{
|
||||
audioFileId: number;
|
||||
assignees: Assignee[];
|
||||
},
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("dictations/updateAssigneeAsync", async (args, thunkApi) => {
|
||||
const { audioFileId, assignees } = args;
|
||||
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const config = new Configuration(configuration);
|
||||
const tasksApi = new TasksApi(config);
|
||||
|
||||
try {
|
||||
await tasksApi.changeCheckoutPermission(
|
||||
audioFileId,
|
||||
{ assignees },
|
||||
{
|
||||
headers: { authorization: `Bearer ${accessToken}` },
|
||||
}
|
||||
);
|
||||
return {};
|
||||
} catch (e) {
|
||||
// e ⇒ errorObjectに変換"
|
||||
const error = createErrorObject(e);
|
||||
|
||||
// ステータスがUploaded以外、タスクが存在しない場合
|
||||
if (error.code === "E010601") {
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID("dictationPage.message.taskNotEditable"),
|
||||
})
|
||||
);
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID("common.message.internalServerError"),
|
||||
})
|
||||
);
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
@ -29,3 +29,12 @@ export const selectDirection = (state: RootState) =>
|
||||
|
||||
export const selectParamName = (state: RootState) =>
|
||||
state.dictation.apps.paramName;
|
||||
|
||||
export const selectSelectedTask = (state: RootState) =>
|
||||
state.dictation.apps.selectedTask;
|
||||
|
||||
export const selectSelectedTranscriptionists = (state: RootState) =>
|
||||
state.dictation.apps.assignee.selected;
|
||||
|
||||
export const selectPoolTranscriptionists = (state: RootState) =>
|
||||
state.dictation.apps.assignee.pool;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Task } from "../../api/api";
|
||||
import { Task, Assignee, Typist, TypistGroup } from "../../api/api";
|
||||
import {
|
||||
DirectionType,
|
||||
DisplayInfoType,
|
||||
@ -15,10 +15,17 @@ export interface Domain {
|
||||
offset: number;
|
||||
total: number;
|
||||
tasks: Task[];
|
||||
typists: Typist[];
|
||||
typistGroups: TypistGroup[];
|
||||
}
|
||||
|
||||
export interface Apps {
|
||||
displayInfo: DisplayInfoType;
|
||||
direction: DirectionType;
|
||||
paramName: SortableColumnType;
|
||||
selectedTask?: Task;
|
||||
assignee: {
|
||||
selected: Assignee[];
|
||||
pool: Assignee[];
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,194 @@
|
||||
import React, { useCallback } from "react";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
changeAssignee,
|
||||
selectPoolTranscriptionists,
|
||||
selectSelectedTask,
|
||||
selectSelectedTranscriptionists,
|
||||
updateAssigneeAsync,
|
||||
} from "features/dictation";
|
||||
import { Assignee } from "api";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import close from "../../assets/images/close.svg";
|
||||
|
||||
interface ChangeTranscriptionistPopupProps {
|
||||
onClose: (isChanged: boolean) => void;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
export const ChangeTranscriptionistPopup: React.FC<
|
||||
ChangeTranscriptionistPopupProps
|
||||
> = (props) => {
|
||||
const { onClose, isOpen } = props;
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
|
||||
// ポップアップを閉じる処理
|
||||
const closePopup = useCallback(() => {
|
||||
onClose(false);
|
||||
}, [onClose]);
|
||||
|
||||
const selectedTask = useSelector(selectSelectedTask);
|
||||
const selectedTranscriptionists = useSelector(
|
||||
selectSelectedTranscriptionists
|
||||
);
|
||||
const poolTranscriptionists = useSelector(selectPoolTranscriptionists);
|
||||
|
||||
const removeAssignee = useCallback(
|
||||
(assignee: Assignee) => {
|
||||
dispatch(
|
||||
changeAssignee({
|
||||
selected: selectedTranscriptionists.filter(
|
||||
(x) =>
|
||||
x.typistGroupId !== assignee.typistGroupId ||
|
||||
x.typistUserId !== assignee.typistUserId
|
||||
),
|
||||
})
|
||||
);
|
||||
},
|
||||
[dispatch, selectedTranscriptionists]
|
||||
);
|
||||
|
||||
const addAssignee = useCallback(
|
||||
(assignee: Assignee) => {
|
||||
dispatch(
|
||||
changeAssignee({ selected: [...selectedTranscriptionists, assignee] })
|
||||
);
|
||||
},
|
||||
[dispatch, selectedTranscriptionists]
|
||||
);
|
||||
|
||||
const onChangeTranscriptionist = useCallback(async () => {
|
||||
// ダイアログ確認
|
||||
if (
|
||||
!selectedTask ||
|
||||
/* eslint-disable-next-line no-alert */
|
||||
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const { meta } = await dispatch(
|
||||
updateAssigneeAsync({
|
||||
audioFileId: selectedTask.audioFileId,
|
||||
assignees: selectedTranscriptionists,
|
||||
})
|
||||
);
|
||||
|
||||
if (meta.requestStatus === "fulfilled") {
|
||||
onClose(true);
|
||||
}
|
||||
}, [dispatch, selectedTranscriptionists, selectedTask, onClose, t]);
|
||||
|
||||
return (
|
||||
<div className={`${styles.modal} ${isOpen ? styles.isShow : ""}`}>
|
||||
<div className={styles.modalBox}>
|
||||
<p className={styles.modalTitle}>
|
||||
{t(getTranslationID("dictationPage.label.changeTranscriptionist"))}
|
||||
{/* 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={closePopup}
|
||||
/>
|
||||
</p>
|
||||
<form action="" name="" method="" className={styles.form}>
|
||||
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||
<dt className={styles.formTitle} />
|
||||
<dt>{t(getTranslationID("dictationPage.label.jobNumber"))}</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={40}
|
||||
value={selectedTask?.jobNumber ?? ""}
|
||||
className={styles.formInput}
|
||||
readOnly
|
||||
/>
|
||||
</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.authorId"))}</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={40}
|
||||
value={selectedTask?.authorId ?? ""}
|
||||
className={styles.formInput}
|
||||
readOnly
|
||||
/>
|
||||
</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.workType"))}</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={40}
|
||||
value={selectedTask?.workType ?? ""}
|
||||
className={styles.formInput}
|
||||
readOnly
|
||||
/>
|
||||
</dd>
|
||||
<dt className={styles.formTitle}>Transcriptionist</dt>
|
||||
<dd className={`${styles.formChange} ${styles.last}`}>
|
||||
<ul className={styles.chooseMember}>
|
||||
<li className={styles.changeTitle}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"dictationPage.label.selectedTranscriptionist"
|
||||
)
|
||||
)}
|
||||
</li>
|
||||
{selectedTranscriptionists?.map((x) => (
|
||||
<li key={`${x.typistGroupId ?? 0}_${x.typistUserId ?? 0}`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={styles.formCheck}
|
||||
value={x.typistName}
|
||||
id={x.typistName}
|
||||
checked
|
||||
onClick={() => removeAssignee(x)}
|
||||
/>
|
||||
<label htmlFor={x.typistName} title="Remove">
|
||||
{x.typistName}
|
||||
</label>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<p />
|
||||
<ul className={styles.holdMember}>
|
||||
<li className={styles.changeTitle}>
|
||||
{t(
|
||||
getTranslationID("dictationPage.label.poolTranscriptionist")
|
||||
)}
|
||||
</li>
|
||||
{poolTranscriptionists?.map((x) => (
|
||||
<li key={`${x.typistGroupId ?? 0}_${x.typistUserId ?? 0}`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={styles.formCheck}
|
||||
value={x.typistName}
|
||||
id={x.typistName}
|
||||
onClick={() => addAssignee(x)}
|
||||
/>
|
||||
<label htmlFor={x.typistName} title="Add">
|
||||
{x.typistName}
|
||||
</label>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</dd>
|
||||
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||
<input
|
||||
type="button"
|
||||
name="submit"
|
||||
value={t(getTranslationID("dictationPage.label.saveChanges"))}
|
||||
className={`${styles.formSubmit} ${styles.marginBtm1} ${styles.isActive}`}
|
||||
onClick={onChangeTranscriptionist}
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,8 @@
|
||||
"passwordIncorrectError": "(de)Error Message",
|
||||
"emailIncorrectError": "(de)Error Message",
|
||||
"internalServerError": "(de)処理に失敗しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"listEmpty": "(de)検索結果が0件です。"
|
||||
"listEmpty": "(de)検索結果が0件です。",
|
||||
"dialogConfirm": "(de)操作を実行しますか?"
|
||||
},
|
||||
"label": {
|
||||
"cancel": "(de)Cancel",
|
||||
@ -171,6 +172,9 @@
|
||||
}
|
||||
},
|
||||
"dictationPage": {
|
||||
"message": {
|
||||
"taskNotEditable": "(de)すでに文字起こし作業着手中またはタスクが存在しないため、タイピストを変更できません。"
|
||||
},
|
||||
"label": {
|
||||
"title": "(de)Dictations",
|
||||
"displayInfomation": "(de)Display Information",
|
||||
@ -209,7 +213,10 @@
|
||||
"playback": "(de)Playback",
|
||||
"fileProperty": "(de)File Property",
|
||||
"changeTranscriptionist": "(de)Change Transcriptionist",
|
||||
"deleteDictation": "(de)Delete Dictation"
|
||||
"deleteDictation": "(de)Delete Dictation",
|
||||
"selectedTranscriptionist": "(de)Selected",
|
||||
"poolTranscriptionist": "(de)Pool",
|
||||
"saveChanges": "(de)Save changes"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@
|
||||
"passwordIncorrectError": "Error Message",
|
||||
"emailIncorrectError": "Error Message",
|
||||
"internalServerError": "処理に失敗しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"listEmpty": "検索結果が0件です。"
|
||||
"listEmpty": "検索結果が0件です。",
|
||||
"dialogConfirm": "操作を実行しますか?"
|
||||
},
|
||||
"label": {
|
||||
"cancel": "Cancel",
|
||||
@ -171,6 +172,9 @@
|
||||
}
|
||||
},
|
||||
"dictationPage": {
|
||||
"message": {
|
||||
"taskNotEditable": "すでに文字起こし作業着手中またはタスクが存在しないため、タイピストを変更できません。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Dictations",
|
||||
"displayInfomation": "Display Information",
|
||||
@ -209,7 +213,10 @@
|
||||
"playback": "Playback",
|
||||
"fileProperty": "File Property",
|
||||
"changeTranscriptionist": "Change Transcriptionist",
|
||||
"deleteDictation": "Delete Dictation"
|
||||
"deleteDictation": "Delete Dictation",
|
||||
"selectedTranscriptionist": "Selected",
|
||||
"poolTranscriptionist": "Pool",
|
||||
"saveChanges": "Save changes"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@
|
||||
"passwordIncorrectError": "(es)Error Message",
|
||||
"emailIncorrectError": "(es)Error Message",
|
||||
"internalServerError": "(es)処理に失敗しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"listEmpty": "(es)検索結果が0件です。"
|
||||
"listEmpty": "(es)検索結果が0件です。",
|
||||
"dialogConfirm": "(es)操作を実行しますか?"
|
||||
},
|
||||
"label": {
|
||||
"cancel": "(es)Cancel",
|
||||
@ -171,6 +172,9 @@
|
||||
}
|
||||
},
|
||||
"dictationPage": {
|
||||
"message": {
|
||||
"taskNotEditable": "(es)すでに文字起こし作業着手中またはタスクが存在しないため、タイピストを変更できません。"
|
||||
},
|
||||
"label": {
|
||||
"title": "(es)Dictations",
|
||||
"displayInfomation": "(es)Display Information",
|
||||
@ -209,7 +213,10 @@
|
||||
"playback": "(es)Playback",
|
||||
"fileProperty": "(es)File Property",
|
||||
"changeTranscriptionist": "(es)Change Transcriptionist",
|
||||
"deleteDictation": "(es)Delete Dictation"
|
||||
"deleteDictation": "(es)Delete Dictation",
|
||||
"selectedTranscriptionist": "(es)Selected",
|
||||
"poolTranscriptionist": "(es)Pool",
|
||||
"saveChanges": "(es)Save changes"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@
|
||||
"passwordIncorrectError": "(fr)Error Message",
|
||||
"emailIncorrectError": "(fr)Error Message",
|
||||
"internalServerError": "(fr)処理に失敗しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"listEmpty": "(fr)検索結果が0件です。"
|
||||
"listEmpty": "(fr)検索結果が0件です。",
|
||||
"dialogConfirm": "(fr)操作を実行しますか?"
|
||||
},
|
||||
"label": {
|
||||
"cancel": "(fr)Cancel",
|
||||
@ -171,6 +172,9 @@
|
||||
}
|
||||
},
|
||||
"dictationPage": {
|
||||
"message": {
|
||||
"taskNotEditable": "(fr)すでに文字起こし作業着手中またはタスクが存在しないため、タイピストを変更できません。"
|
||||
},
|
||||
"label": {
|
||||
"title": "(fr)Dictations",
|
||||
"displayInfomation": "(fr)Display Information",
|
||||
@ -209,7 +213,10 @@
|
||||
"playback": "(fr)Playback",
|
||||
"fileProperty": "(fr)File Property",
|
||||
"changeTranscriptionist": "(fr)Change Transcriptionist",
|
||||
"deleteDictation": "(fr)Delete Dictation"
|
||||
"deleteDictation": "(fr)Delete Dictation",
|
||||
"selectedTranscriptionist": "(fr)Selected",
|
||||
"poolTranscriptionist": "(fr)Pool",
|
||||
"saveChanges": "(fr)Save changes"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user