Merged PR 729: 画面実装(ファイル削除設定ポップアップ画面)

## 概要
[Task3547: 画面実装(ファイル削除設定ポップアップ画面)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3547)

- ファイル削除設定ポップアップの新規実装をしました。

## レビューポイント
- reduxとの連携部分の設計でNGな部分ないか?
- 処理の抜け漏れないか?

## 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/Task3547?csf=1&web=1&e=0pu92Q

## 動作確認状況
- ローカルで一通りの動作確認しました。

## 補足
- とくになし
This commit is contained in:
Kentaro Fukunaga 2024-02-06 12:58:55 +00:00 committed by saito.k
parent eaf1b3c8b8
commit 548c7a05e9
13 changed files with 474 additions and 113 deletions

View File

@ -78,6 +78,18 @@ export interface Account {
* @memberof Account
*/
'delegationPermission': boolean;
/**
*
* @type {boolean}
* @memberof Account
*/
'autoFileDelete': boolean;
/**
*
* @type {number}
* @memberof Account
*/
'fileRetentionDays': number;
/**
*
* @type {number}
@ -2077,6 +2089,25 @@ export interface UpdateAccountInfoRequest {
*/
'secondryAdminUserId'?: number;
}
/**
*
* @export
* @interface UpdateFileDeleteSettingRequest
*/
export interface UpdateFileDeleteSettingRequest {
/**
*
* @type {boolean}
* @memberof UpdateFileDeleteSettingRequest
*/
'autoFileDelete': boolean;
/**
*
* @type {number}
* @memberof UpdateFileDeleteSettingRequest
*/
'retentionDays': number;
}
/**
*
* @export
@ -3328,6 +3359,46 @@ export const AccountsApiAxiosParamCreator = function (configuration?: Configurat
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {UpdateFileDeleteSettingRequest} updateFileDeleteSettingRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updateFileDeleteSetting: async (updateFileDeleteSettingRequest: UpdateFileDeleteSettingRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'updateFileDeleteSettingRequest' is not null or undefined
assertParamExists('updateFileDeleteSetting', 'updateFileDeleteSettingRequest', updateFileDeleteSettingRequest)
const localVarPath = `/accounts/me/file-delete-setting`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication bearer required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(updateFileDeleteSettingRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
@ -3790,6 +3861,19 @@ export const AccountsApiFp = function(configuration?: Configuration) {
const operationBasePath = operationServerMap['AccountsApi.updateAccountInfo']?.[index]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
},
/**
*
* @summary
* @param {UpdateFileDeleteSettingRequest} updateFileDeleteSettingRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async updateFileDeleteSetting(updateFileDeleteSettingRequest: UpdateFileDeleteSettingRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.updateFileDeleteSetting(updateFileDeleteSettingRequest, options);
const index = configuration?.serverIndex ?? 0;
const operationBasePath = operationServerMap['AccountsApi.updateFileDeleteSetting']?.[index]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
},
/**
*
* @summary
@ -4087,6 +4171,16 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP
updateAccountInfo(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: any): AxiosPromise<object> {
return localVarFp.updateAccountInfo(updateAccountInfoRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {UpdateFileDeleteSettingRequest} updateFileDeleteSettingRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updateFileDeleteSetting(updateFileDeleteSettingRequest: UpdateFileDeleteSettingRequest, options?: any): AxiosPromise<object> {
return localVarFp.updateFileDeleteSetting(updateFileDeleteSettingRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
@ -4425,6 +4519,18 @@ export class AccountsApi extends BaseAPI {
return AccountsApiFp(this.configuration).updateAccountInfo(updateAccountInfoRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {UpdateFileDeleteSettingRequest} updateFileDeleteSettingRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AccountsApi
*/
public updateFileDeleteSetting(updateFileDeleteSettingRequest: UpdateFileDeleteSettingRequest, options?: AxiosRequestConfig) {
return AccountsApiFp(this.configuration).updateFileDeleteSetting(updateFileDeleteSettingRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
@ -7309,46 +7415,6 @@ export const UsersApiAxiosParamCreator = function (configuration?: Configuration
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(postUpdateUserRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {PostDeleteUserRequest} postDeleteUserRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updeateUser: async (postDeleteUserRequest: PostDeleteUserRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'postDeleteUserRequest' is not null or undefined
assertParamExists('updeateUser', 'postDeleteUserRequest', postDeleteUserRequest)
const localVarPath = `/users/delete`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication bearer required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(postDeleteUserRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
@ -7529,19 +7595,6 @@ export const UsersApiFp = function(configuration?: Configuration) {
const operationBasePath = operationServerMap['UsersApi.updateUser']?.[index]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
},
/**
*
* @summary
* @param {PostDeleteUserRequest} postDeleteUserRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async updeateUser(postDeleteUserRequest: PostDeleteUserRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.updeateUser(postDeleteUserRequest, options);
const index = configuration?.serverIndex ?? 0;
const operationBasePath = operationServerMap['UsersApi.updeateUser']?.[index]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
},
}
};
@ -7678,16 +7731,6 @@ export const UsersApiFactory = function (configuration?: Configuration, basePath
updateUser(postUpdateUserRequest: PostUpdateUserRequest, options?: any): AxiosPromise<object> {
return localVarFp.updateUser(postUpdateUserRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {PostDeleteUserRequest} postDeleteUserRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updeateUser(postDeleteUserRequest: PostDeleteUserRequest, options?: any): AxiosPromise<object> {
return localVarFp.updeateUser(postDeleteUserRequest, options).then((request) => request(axios, basePath));
},
};
};
@ -7849,18 +7892,6 @@ export class UsersApi extends BaseAPI {
public updateUser(postUpdateUserRequest: PostUpdateUserRequest, options?: AxiosRequestConfig) {
return UsersApiFp(this.configuration).updateUser(postUpdateUserRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {PostDeleteUserRequest} postDeleteUserRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof UsersApi
*/
public updeateUser(postDeleteUserRequest: PostDeleteUserRequest, options?: AxiosRequestConfig) {
return UsersApiFp(this.configuration).updeateUser(postDeleteUserRequest, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -4,6 +4,7 @@ import {
updateAccountInfoAsync,
getAccountRelationsAsync,
deleteAccountAsync,
updateFileDeleteSettingAsync,
} from "./operations";
const initialState: AccountState = {
@ -15,6 +16,8 @@ const initialState: AccountState = {
tier: 0,
country: "",
delegationPermission: false,
autoFileDelete: false,
fileRetentionDays: 0,
},
},
dealers: [],
@ -29,6 +32,8 @@ const initialState: AccountState = {
secondryAdminUserId: undefined,
},
isLoading: false,
autoFileDelete: false,
fileRetentionDays: 0,
},
};
@ -64,6 +69,20 @@ export const accountSlice = createSlice({
const { secondryAdminUserId } = action.payload;
state.apps.updateAccountInfo.secondryAdminUserId = secondryAdminUserId;
},
changeAutoFileDelete: (
state,
action: PayloadAction<{ autoFileDelete: boolean }>
) => {
const { autoFileDelete } = action.payload;
state.apps.autoFileDelete = autoFileDelete;
},
changeFileRetentionDays: (
state,
action: PayloadAction<{ fileRetentionDays: number }>
) => {
const { fileRetentionDays } = action.payload;
state.apps.fileRetentionDays = fileRetentionDays;
},
cleanupApps: (state) => {
state.domain = initialState.domain;
},
@ -85,6 +104,10 @@ export const accountSlice = createSlice({
action.payload.accountInfo.account.primaryAdminUserId;
state.apps.updateAccountInfo.secondryAdminUserId =
action.payload.accountInfo.account.secondryAdminUserId;
state.apps.autoFileDelete =
action.payload.accountInfo.account.autoFileDelete;
state.apps.fileRetentionDays =
action.payload.accountInfo.account.fileRetentionDays;
state.apps.isLoading = false;
});
builder.addCase(getAccountRelationsAsync.rejected, (state) => {
@ -99,6 +122,15 @@ export const accountSlice = createSlice({
builder.addCase(updateAccountInfoAsync.rejected, (state) => {
state.apps.isLoading = false;
});
builder.addCase(updateFileDeleteSettingAsync.pending, (state) => {
state.apps.isLoading = true;
});
builder.addCase(updateFileDeleteSettingAsync.fulfilled, (state) => {
state.apps.isLoading = false;
});
builder.addCase(updateFileDeleteSettingAsync.rejected, (state) => {
state.apps.isLoading = false;
});
builder.addCase(deleteAccountAsync.pending, (state) => {
state.apps.isLoading = true;
});
@ -115,6 +147,8 @@ export const {
changeDealerPermission,
changePrimaryAdministrator,
changeSecondryAdministrator,
changeAutoFileDelete,
changeFileRetentionDays,
cleanupApps,
} = accountSlice.actions;
export default accountSlice.reducer;

View File

@ -9,6 +9,7 @@ import {
UpdateAccountInfoRequest,
UsersApi,
DeleteAccountRequest,
UpdateFileDeleteSettingRequest,
} from "../../api/api";
import { Configuration } from "../../api/configuration";
import { ViewAccountRelationsInfo } from "./types";
@ -112,6 +113,58 @@ export const updateAccountInfoAsync = createAsyncThunk<
}
});
export const updateFileDeleteSettingAsync = createAsyncThunk<
{
/* Empty Object */
},
{ autoFileDelete: boolean; fileRetentionDays: number },
{
// rejectした時の返却値の型
rejectValue: {
error: ErrorObject;
};
}
>("accounts/updateFileDeleteSettingAsync", async (args, thunkApi) => {
// apiのConfigurationを取得する
const { getState } = thunkApi;
const state = getState() as RootState;
const { configuration } = state.auth;
const accessToken = getAccessToken(state.auth);
const config = new Configuration(configuration);
const accountApi = new AccountsApi(config);
const requestParam: UpdateFileDeleteSettingRequest = {
autoFileDelete: args.autoFileDelete,
retentionDays: args.fileRetentionDays,
};
try {
await accountApi.updateFileDeleteSetting(requestParam, {
headers: { authorization: `Bearer ${accessToken}` },
});
thunkApi.dispatch(
openSnackbar({
level: "info",
message: getTranslationID("common.message.success"),
})
);
return {};
} catch (e) {
const error = createErrorObject(e);
const errorMessage = getTranslationID("common.message.internalServerError");
thunkApi.dispatch(
openSnackbar({
level: "error",
message: errorMessage,
})
);
return thunkApi.rejectWithValue({ error });
}
});
export const deleteAccountAsync = createAsyncThunk<
{
/* Empty Object */

View File

@ -16,3 +16,18 @@ export const selectIsLoading = (state: RootState) =>
state.account.apps.isLoading;
export const selectUpdateAccountInfo = (state: RootState) =>
state.account.apps.updateAccountInfo;
export const selectFileDeleteSetting = (state: RootState) => {
const { autoFileDelete, fileRetentionDays } = state.account.apps;
return {
autoFileDelete,
fileRetentionDays,
};
};
export const selectInputValidationErrors = (state: RootState) => {
const { fileRetentionDays } = state.account.apps;
const hasFileRetentionDaysError =
fileRetentionDays <= 0 || fileRetentionDays >= 1000;
return {
hasFileRetentionDaysError,
};
};

View File

@ -19,4 +19,6 @@ export interface Domain {
export interface Apps {
updateAccountInfo: UpdateAccountInfoRequest;
isLoading: boolean;
autoFileDelete: boolean;
fileRetentionDays: number;
}

View File

@ -12,6 +12,8 @@ const initialState: PartnerLicensesState = {
tier: 0,
country: "",
delegationPermission: false,
autoFileDelete: false,
fileRetentionDays: 0,
},
total: 0,
ownPartnerLicense: {

View File

@ -448,43 +448,43 @@ export const deleteUserAsync = createAsyncThunk<
// ユーザーに有効なライセンスが割り当たっているため削除不可
if (error.code === "E014007") {
errorMessage = getTranslationID(
"userListPage.message.UserDeletionLicenseActiveError"
"userListPage.message.userDeletionLicenseActiveError"
);
}
// 管理者ユーザーため削除不可
if (error.code === "E014002") {
errorMessage = getTranslationID(
"userListPage.message.AdminUserDeletionError"
"userListPage.message.adminUserDeletionError"
);
}
// タイピストユーザーで担当タスクがあるため削除不可
if (error.code === "E014009") {
errorMessage = getTranslationID(
"userListPage.message.TypistUserDeletionTranscriptionTaskError"
"userListPage.message.typistUserDeletionTranscriptionTaskError"
);
}
// タイピストユーザーでルーティングルールに設定されているため削除不可
if (error.code === "E014004") {
errorMessage = getTranslationID(
"userListPage.message.TypistDeletionRoutingRuleError"
"userListPage.message.typistDeletionRoutingRuleError"
);
}
// タイピストユーザーでTranscriptionistGroupに所属しているため削除不可
if (error.code === "E014005") {
errorMessage = getTranslationID(
"userListPage.message.TypistUserDeletionTranscriptionistGroupError"
"userListPage.message.typistUserDeletionTranscriptionistGroupError"
);
}
// Authorユーザーで同一AuthorIDのタスクがあるため削除不可
if (error.code === "E014006") {
errorMessage = getTranslationID(
"userListPage.message.AuthorUserDeletionTranscriptionTaskError"
"userListPage.message.authorUserDeletionTranscriptionTaskError"
);
}
// Authorユーザーで同一AuthorIDがルーティングルールに設定されているため削除不可
if (error.code === "E014003") {
errorMessage = getTranslationID(
"userListPage.message.AuthorDeletionRoutingRuleError"
"userListPage.message.authorDeletionRoutingRuleError"
);
}

View File

@ -0,0 +1,169 @@
import React, { useCallback, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
selectInputValidationErrors,
selectFileDeleteSetting,
updateFileDeleteSettingAsync,
selectIsLoading,
getAccountRelationsAsync,
} from "features/account";
import { AppDispatch } from "app/store";
import { useTranslation } from "react-i18next";
import styles from "../../styles/app.module.scss";
import { getTranslationID } from "../../translation";
import close from "../../assets/images/close.svg";
import {
changeAutoFileDelete,
changeFileRetentionDays,
} from "../../features/account/accountSlice";
import progress_activit from "../../assets/images/progress_activit.svg";
interface FileDeleteSettingPopupProps {
// eslint-disable-next-line react/no-unused-prop-types
onClose: () => void;
}
export const FileDeleteSettingPopup: React.FC<FileDeleteSettingPopupProps> = (
props
) => {
const { onClose } = props;
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
const isLoading = useSelector(selectIsLoading);
const fileDeleteSetting = useSelector(selectFileDeleteSetting);
const { hasFileRetentionDaysError } = useSelector(
selectInputValidationErrors
);
const closePopup = useCallback(() => {
if (isLoading) return;
onClose();
}, [isLoading, onClose]);
const [isPushSubmitButton, setIsPushSubmitButton] = useState<boolean>(false);
const onUpdateFileDeleteSetting = useCallback(async () => {
if (isLoading) return;
setIsPushSubmitButton(true);
if (hasFileRetentionDaysError) {
return;
}
const { meta } = await dispatch(
updateFileDeleteSettingAsync({
autoFileDelete: fileDeleteSetting.autoFileDelete,
fileRetentionDays: fileDeleteSetting.fileRetentionDays,
})
);
setIsPushSubmitButton(false);
if (meta.requestStatus === "fulfilled") {
closePopup();
dispatch(getAccountRelationsAsync());
}
}, [
closePopup,
dispatch,
fileDeleteSetting.autoFileDelete,
fileDeleteSetting.fileRetentionDays,
hasFileRetentionDaysError,
isLoading,
]);
return (
<div className={`${styles.modal} ${styles.isShow}`}>
<div className={styles.modalBox}>
<p className={styles.modalTitle}>
{t(getTranslationID("fileDeleteSettingPopup.label.title"))}
<button type="button" onClick={closePopup}>
<img src={close} className={styles.modalTitleIcon} alt="close" />
</button>
</p>
<form className={styles.form}>
<dl className={`${styles.formList} ${styles.hasbg}`}>
<dt className={styles.formTitle} />
<dt>
{t(
getTranslationID(
"fileDeleteSettingPopup.label.autoFileDeleteCheck"
)
)}
</dt>
<dd className={styles.last}>
<p>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label>
<input
type="checkbox"
className={styles.formCheck}
checked={fileDeleteSetting.autoFileDelete}
onChange={(e) => {
dispatch(
changeAutoFileDelete({
autoFileDelete: e.target.checked,
})
);
}}
/>
</label>
</p>
<p className={styles.txWsline}>
{t(
getTranslationID(
"fileDeleteSettingPopup.label.daysAnnotation"
)
)}
</p>
<input
type="number"
min={1}
max={999}
value={fileDeleteSetting.fileRetentionDays}
className={`${styles.formInput} ${styles.short}`}
disabled={!fileDeleteSetting.autoFileDelete}
onChange={(e) => {
dispatch(
changeFileRetentionDays({
fileRetentionDays: Number(e.target.value),
})
);
}}
/>{" "}
{t(getTranslationID("fileDeleteSettingPopup.label.days"))}
{isPushSubmitButton && hasFileRetentionDaysError && (
<span className={styles.formError}>
{t(
getTranslationID(
"fileDeleteSettingPopup.label.daysValidationError"
)
)}
</span>
)}
</dd>
<dd className={`${styles.full} ${styles.alignCenter}`}>
<input
type="button"
name="submit"
value={t(
getTranslationID("fileDeleteSettingPopup.label.saveButton")
)}
className={`${styles.formSubmit} ${styles.marginBtm1} ${
!isLoading ? styles.isActive : ""
}`}
onClick={onUpdateFileDeleteSetting}
disabled={isLoading}
/>
</dd>
<img
style={{ display: isLoading ? "inline" : "none" }}
src={progress_activit}
className={styles.icLoading}
alt="Loading"
/>
</dl>
</form>
</div>
</div>
);
};

View File

@ -23,6 +23,7 @@ import { getTranslationID } from "translation";
import { TIERS } from "components/auth/constants";
import { isApproveTier } from "features/auth";
import { DeleteAccountPopup } from "./deleteAccountPopup";
import { FileDeleteSettingPopup } from "./fileDeleteSettingPopup";
import progress_activit from "../../assets/images/progress_activit.svg";
const AccountPage: React.FC = (): JSX.Element => {
@ -40,10 +41,17 @@ const AccountPage: React.FC = (): JSX.Element => {
const [isDeleteAccountPopupOpen, setIsDeleteAccountPopupOpen] =
useState(false);
const [isFileDeleteSettingPopupOpen, setIsFileDeleteSettingPopupOpen] =
useState(false);
const onDeleteAccountOpen = useCallback(() => {
setIsDeleteAccountPopupOpen(true);
}, [setIsDeleteAccountPopupOpen]);
const onDeleteFileDeleteSettingOpen = useCallback(() => {
setIsFileDeleteSettingPopupOpen(true);
}, [setIsFileDeleteSettingPopupOpen]);
// 階層表示用
const tierNames: { [key: number]: string } = {
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -89,6 +97,13 @@ const AccountPage: React.FC = (): JSX.Element => {
}}
/>
)}
{isFileDeleteSettingPopupOpen && (
<FileDeleteSettingPopup
onClose={() => {
setIsFileDeleteSettingPopupOpen(false);
}}
/>
)}
<div className={styles.wrap}>
<Header />
<UpdateTokenTimer />
@ -102,12 +117,13 @@ const AccountPage: React.FC = (): JSX.Element => {
<section className={styles.account}>
<div className={styles.boxFlex}>
{/* File Delete Setting
<ul className={`${styles.menuAction} ${styles.box100}`}>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<a
href="account_setting.html"
className={`${styles.menuLink} ${styles.isActive}`}
onClick={onDeleteFileDeleteSettingOpen}
data-tag="open-file-delete-setting-popup"
>
<img
src="images/file_delete.svg"
@ -120,7 +136,6 @@ const AccountPage: React.FC = (): JSX.Element => {
</a>
</li>
</ul>
*/}
<div className={styles.marginRgt3}>
<dl className={styles.listVertical}>

View File

@ -129,13 +129,13 @@
"roleChangeError": "Die Benutzerrolle kann nicht geändert werden. Die angezeigten Informationen sind möglicherweise veraltet. Aktualisieren Sie daher bitte den Bildschirm, um den neuesten Status anzuzeigen.",
"encryptionPasswordCorrectError": "Das Verschlüsselungskennwort entspricht nicht den Regeln.",
"alreadyLicenseDeallocatedError": "Die zugewiesene Lizenz wurde bereits storniert. Die angezeigten Informationen sind möglicherweise veraltet. Aktualisieren Sie daher bitte den Bildschirm, um den neuesten Status anzuzeigen.",
"UserDeletionLicenseActiveError": "(de)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"TypistDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"AdminUserDeletionError": "(de)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"TypistUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"AuthorUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"TypistUserDeletionTranscriptionistGroupError": "(de)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"AuthorDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
"userDeletionLicenseActiveError": "(de)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"typistDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"adminUserDeletionError": "(de)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"typistUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"authorUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"typistUserDeletionTranscriptionistGroupError": "(de)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"authorDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
},
"label": {
"title": "Benutzer",
@ -570,5 +570,15 @@
"job": "Aufgabe",
"close": "Schließen"
}
},
"fileDeleteSettingPopup": {
"label": {
"title": "(de)Auto File Delete Setting",
"autoFileDeleteCheck": "(de)Auto file delete",
"daysAnnotation": "(de)Number of days from transcription finished to delete the files.",
"days": "(de)Days",
"saveButton": "(de)Save Settings",
"daysValidationError": "(de)Daysには1999の数字を入力してください。"
}
}
}

View File

@ -129,13 +129,13 @@
"roleChangeError": "Unable to change the User Role. The displayed information may be outdated, so please refresh the screen to see the latest status.",
"encryptionPasswordCorrectError": "Encryption password does not meet the rules.",
"alreadyLicenseDeallocatedError": "Assigned license has already been canceled. The displayed information may be outdated, so please refresh the screen to see the latest status.",
"UserDeletionLicenseActiveError": "ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"TypistDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"AdminUserDeletionError": "ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"TypistUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"AuthorUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"TypistUserDeletionTranscriptionistGroupError": "ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"AuthorDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
"userDeletionLicenseActiveError": "ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"typistDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"adminUserDeletionError": "ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"typistUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"authorUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"typistUserDeletionTranscriptionistGroupError": "ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"authorDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
},
"label": {
"title": "User",
@ -570,5 +570,15 @@
"job": "Job",
"close": "Close"
}
},
"fileDeleteSettingPopup": {
"label": {
"title": "Auto File Delete Setting",
"autoFileDeleteCheck": "Auto file delete",
"daysAnnotation": "Number of days from transcription finished to delete the files.",
"days": "Days",
"saveButton": "Save Settings",
"daysValidationError": "Daysには1999の数字を入力してください。"
}
}
}

View File

@ -129,13 +129,13 @@
"roleChangeError": "No se puede cambiar la función de usuario. La información mostrada puede estar desactualizada, así que actualice la pantalla para ver el estado más reciente.",
"encryptionPasswordCorrectError": "La contraseña de cifrado no cumple con las reglas.",
"alreadyLicenseDeallocatedError": "La licencia asignada ya ha sido cancelada. La información mostrada puede estar desactualizada, así que actualice la pantalla para ver el estado más reciente.",
"UserDeletionLicenseActiveError": "(es)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"TypistDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"AdminUserDeletionError": "(es)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"TypistUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"AuthorUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"TypistUserDeletionTranscriptionistGroupError": "(es)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"AuthorDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
"userDeletionLicenseActiveError": "(es)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"typistDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"adminUserDeletionError": "(es)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"typistUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"authorUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"typistUserDeletionTranscriptionistGroupError": "(es)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"authorDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
},
"label": {
"title": "Usuario",
@ -570,5 +570,15 @@
"job": "Trabajo",
"close": "Cerrar"
}
},
"fileDeleteSettingPopup": {
"label": {
"title": "(es)Auto File Delete Setting",
"autoFileDeleteCheck": "(es)Auto file delete",
"daysAnnotation": "(es)Number of days from transcription finished to delete the files.",
"days": "(es)Days",
"saveButton": "(es)Save Settings",
"daysValidationError": "(es)Daysには1999の数字を入力してください。"
}
}
}

View File

@ -129,13 +129,13 @@
"roleChangeError": "Impossible de modifier le rôle de l'utilisateur. Les informations affichées peuvent être obsolètes, veuillez donc actualiser l'écran pour voir le dernier statut.",
"encryptionPasswordCorrectError": "Le mot de passe de cryptage n'est pas conforme aux règles.",
"alreadyLicenseDeallocatedError": "La licence attribuée a déjà été annulée. Les informations affichées peuvent être obsolètes, veuillez donc actualiser l'écran pour voir le dernier statut.",
"UserDeletionLicenseActiveError": "(fr)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"TypistDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"AdminUserDeletionError": "(fr)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"TypistUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"AuthorUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"TypistUserDeletionTranscriptionistGroupError": "(fr)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"AuthorDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
"userDeletionLicenseActiveError": "(fr)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
"typistDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
"adminUserDeletionError": "(fr)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
"typistUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
"authorUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
"typistUserDeletionTranscriptionistGroupError": "(fr)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
"authorDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
},
"label": {
"title": "Utilisateur",
@ -570,5 +570,15 @@
"job": "Tâches",
"close": "Fermer"
}
},
"fileDeleteSettingPopup": {
"label": {
"title": "(fr)Auto File Delete Setting",
"autoFileDeleteCheck": "(fr)Auto file delete",
"daysAnnotation": "(fr)Number of days from transcription finished to delete the files.",
"days": "(fr)Days",
"saveButton": "(fr)Save Settings",
"daysValidationError": "(fr)Daysには1999の数字を入力してください。"
}
}
}