Merged PR 743: テンプレートファイル削除画面修正
## 概要 [Task3600: テンプレートファイル削除画面修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3600) - テンプレートファイル削除の画面を実装しました。 ## レビューポイント - エラー処理は適切でしょうか? ## UIの変更 - [Task3600](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/Task3600?csf=1&web=1&e=E25Kf7) ## 動作確認状況 - ローカルで確認
This commit is contained in:
parent
83efd97bdf
commit
bbbd3e757b
@ -6730,6 +6730,44 @@ export class TasksApi extends BaseAPI {
|
|||||||
*/
|
*/
|
||||||
export const TemplatesApiAxiosParamCreator = function (configuration?: Configuration) {
|
export const TemplatesApiAxiosParamCreator = function (configuration?: Configuration) {
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* ログインしているユーザーのアカウント配下でIDで指定されたテンプレートファイルを削除します
|
||||||
|
* @summary
|
||||||
|
* @param {number} templateFileId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
deleteTemplateFile: async (templateFileId: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'templateFileId' is not null or undefined
|
||||||
|
assertParamExists('deleteTemplateFile', 'templateFileId', templateFileId)
|
||||||
|
const localVarPath = `/templates/{templateFileId}/delete`
|
||||||
|
.replace(`{${"templateFileId"}}`, encodeURIComponent(String(templateFileId)));
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* アカウント内のテンプレートファイルの一覧を取得します
|
* アカウント内のテンプレートファイルの一覧を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -6774,6 +6812,19 @@ export const TemplatesApiAxiosParamCreator = function (configuration?: Configura
|
|||||||
export const TemplatesApiFp = function(configuration?: Configuration) {
|
export const TemplatesApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosParamCreator = TemplatesApiAxiosParamCreator(configuration)
|
const localVarAxiosParamCreator = TemplatesApiAxiosParamCreator(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* ログインしているユーザーのアカウント配下でIDで指定されたテンプレートファイルを削除します
|
||||||
|
* @summary
|
||||||
|
* @param {number} templateFileId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async deleteTemplateFile(templateFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteTemplateFile(templateFileId, options);
|
||||||
|
const index = configuration?.serverIndex ?? 0;
|
||||||
|
const operationBasePath = operationServerMap['TemplatesApi.deleteTemplateFile']?.[index]?.url;
|
||||||
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* アカウント内のテンプレートファイルの一覧を取得します
|
* アカウント内のテンプレートファイルの一覧を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -6796,6 +6847,16 @@ export const TemplatesApiFp = function(configuration?: Configuration) {
|
|||||||
export const TemplatesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
export const TemplatesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||||
const localVarFp = TemplatesApiFp(configuration)
|
const localVarFp = TemplatesApiFp(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* ログインしているユーザーのアカウント配下でIDで指定されたテンプレートファイルを削除します
|
||||||
|
* @summary
|
||||||
|
* @param {number} templateFileId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
deleteTemplateFile(templateFileId: number, options?: any): AxiosPromise<object> {
|
||||||
|
return localVarFp.deleteTemplateFile(templateFileId, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* アカウント内のテンプレートファイルの一覧を取得します
|
* アカウント内のテンプレートファイルの一覧を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -6815,6 +6876,18 @@ export const TemplatesApiFactory = function (configuration?: Configuration, base
|
|||||||
* @extends {BaseAPI}
|
* @extends {BaseAPI}
|
||||||
*/
|
*/
|
||||||
export class TemplatesApi extends BaseAPI {
|
export class TemplatesApi extends BaseAPI {
|
||||||
|
/**
|
||||||
|
* ログインしているユーザーのアカウント配下でIDで指定されたテンプレートファイルを削除します
|
||||||
|
* @summary
|
||||||
|
* @param {number} templateFileId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof TemplatesApi
|
||||||
|
*/
|
||||||
|
public deleteTemplateFile(templateFileId: number, options?: AxiosRequestConfig) {
|
||||||
|
return TemplatesApiFp(this.configuration).deleteTemplateFile(templateFileId, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* アカウント内のテンプレートファイルの一覧を取得します
|
* アカウント内のテンプレートファイルの一覧を取得します
|
||||||
* @summary
|
* @summary
|
||||||
|
|||||||
@ -73,4 +73,7 @@ export const errorCodes = [
|
|||||||
"E015001", // タイピストグループ削除済みエラー
|
"E015001", // タイピストグループ削除済みエラー
|
||||||
"E015002", // タイピストグループがワークフローに紐づいているエラー
|
"E015002", // タイピストグループがワークフローに紐づいているエラー
|
||||||
"E015003", // タイピストグループがルーティングされているエラー
|
"E015003", // タイピストグループがルーティングされているエラー
|
||||||
|
"E016001", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルがすでに削除済みだった)
|
||||||
|
"E016002", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルがWorkflowに指定されていた)
|
||||||
|
"E016003", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルが未完了のタスクに紐づいていた)
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
@ -115,3 +115,78 @@ export const uploadTemplateAsync = createAsyncThunk<
|
|||||||
return thunkApi.rejectWithValue({ error });
|
return thunkApi.rejectWithValue({ error });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const deleteTemplateAsync = createAsyncThunk<
|
||||||
|
{
|
||||||
|
/* Empty Object */
|
||||||
|
},
|
||||||
|
{ templateFileId: number },
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("workflow/deleteTemplateAsync", async (args, thunkApi) => {
|
||||||
|
const { templateFileId } = args;
|
||||||
|
// 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 templateApi = new TemplatesApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// ファイルを削除する
|
||||||
|
await templateApi.deleteTemplateFile(templateFileId, {
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "info",
|
||||||
|
message: getTranslationID("common.message.success"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
} catch (e) {
|
||||||
|
// e ⇒ errorObjectに変換"
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
|
||||||
|
if (error.code === "E016001") {
|
||||||
|
// テンプレートファイルが削除済みの場合は成功扱いとする
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "info",
|
||||||
|
message: getTranslationID("common.message.success"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = getTranslationID("common.message.internalServerError");
|
||||||
|
|
||||||
|
// テンプレートファイルがルーティングルールに紐づく場合はエラー
|
||||||
|
if (error.code === "E016002") {
|
||||||
|
message = getTranslationID(
|
||||||
|
"templateFilePage.message.deleteFailedWorkflowAssigned"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// テンプレートファイルが未完了のタスクに紐づく場合はエラー
|
||||||
|
if (error.code === "E016003") {
|
||||||
|
message = getTranslationID(
|
||||||
|
"templateFilePage.message.deleteFailedTaskAssigned"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
import { TemplateState } from "./state";
|
import { TemplateState } from "./state";
|
||||||
import { listTemplateAsync, uploadTemplateAsync } from "./operations";
|
import {
|
||||||
|
deleteTemplateAsync,
|
||||||
|
listTemplateAsync,
|
||||||
|
uploadTemplateAsync,
|
||||||
|
} from "./operations";
|
||||||
|
|
||||||
const initialState: TemplateState = {
|
const initialState: TemplateState = {
|
||||||
apps: {
|
apps: {
|
||||||
@ -45,6 +49,15 @@ export const templateSlice = createSlice({
|
|||||||
builder.addCase(uploadTemplateAsync.rejected, (state) => {
|
builder.addCase(uploadTemplateAsync.rejected, (state) => {
|
||||||
state.apps.isUploading = false;
|
state.apps.isUploading = false;
|
||||||
});
|
});
|
||||||
|
builder.addCase(deleteTemplateAsync.pending, (state) => {
|
||||||
|
state.apps.isLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(deleteTemplateAsync.fulfilled, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(deleteTemplateAsync.rejected, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { AppDispatch } from "app/store";
|
import { AppDispatch } from "app/store";
|
||||||
import Header from "components/header";
|
import Header from "components/header";
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
selectTemplates,
|
selectTemplates,
|
||||||
listTemplateAsync,
|
listTemplateAsync,
|
||||||
selectIsLoading,
|
selectIsLoading,
|
||||||
|
deleteTemplateAsync,
|
||||||
} from "features/workflow/template";
|
} from "features/workflow/template";
|
||||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||||
import { DelegationBar } from "components/delegate";
|
import { DelegationBar } from "components/delegate";
|
||||||
@ -35,6 +36,23 @@ export const TemplateFilePage: React.FC = () => {
|
|||||||
dispatch(listTemplateAsync());
|
dispatch(listTemplateAsync());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const onDeleteTemplate = useCallback(
|
||||||
|
async (templateFileId: number) => {
|
||||||
|
if (
|
||||||
|
/* eslint-disable-next-line no-alert */
|
||||||
|
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { meta } = await dispatch(deleteTemplateAsync({ templateFileId }));
|
||||||
|
if (meta.requestStatus === "fulfilled") {
|
||||||
|
dispatch(listTemplateAsync());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch, t]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isShowAddPopup && (
|
{isShowAddPopup && (
|
||||||
@ -101,16 +119,17 @@ export const TemplateFilePage: React.FC = () => {
|
|||||||
<td>{template.name}</td>
|
<td>{template.name}</td>
|
||||||
<td>
|
<td>
|
||||||
<ul className={`${styles.menuAction} ${styles.inTable}`}>
|
<ul className={`${styles.menuAction} ${styles.inTable}`}>
|
||||||
{/* テンプレートファイル削除はCCB後回し分なので非表示
|
|
||||||
<li>
|
<li>
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||||
<a
|
<a
|
||||||
href=""
|
|
||||||
className={`${styles.menuLink} ${styles.isActive}`}
|
className={`${styles.menuLink} ${styles.isActive}`}
|
||||||
|
onClick={() => {
|
||||||
|
onDeleteTemplate(template.id);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t(getTranslationID("common.label.delete"))}
|
{t(getTranslationID("common.label.delete"))}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
*/}
|
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -475,6 +475,10 @@
|
|||||||
"fileSizeTerms": "Die maximale Dateigröße, die gespeichert werden kann, beträgt 5 MB.",
|
"fileSizeTerms": "Die maximale Dateigröße, die gespeichert werden kann, beträgt 5 MB.",
|
||||||
"fileSizeError": "Die ausgewählte Dateigröße ist zu groß. Bitte wählen Sie eine Datei mit einer Größe von 5 MB oder weniger aus.",
|
"fileSizeError": "Die ausgewählte Dateigröße ist zu groß. Bitte wählen Sie eine Datei mit einer Größe von 5 MB oder weniger aus.",
|
||||||
"fileEmptyError": "Dateiauswahl ist erforderlich. Bitte wählen Sie eine Datei aus."
|
"fileEmptyError": "Dateiauswahl ist erforderlich. Bitte wählen Sie eine Datei aus."
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"deleteFailedWorkflowAssigned": "(de)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||||
|
"deleteFailedTaskAssigned": "(de)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"partnerPage": {
|
"partnerPage": {
|
||||||
|
|||||||
@ -475,6 +475,10 @@
|
|||||||
"fileSizeTerms": "The maximum file size that can be saved is 5MB.",
|
"fileSizeTerms": "The maximum file size that can be saved is 5MB.",
|
||||||
"fileSizeError": "The selected file size is too large. Please select a file that is 5MB or less in size.",
|
"fileSizeError": "The selected file size is too large. Please select a file that is 5MB or less in size.",
|
||||||
"fileEmptyError": "File selection is required. Please select a file."
|
"fileEmptyError": "File selection is required. Please select a file."
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"deleteFailedWorkflowAssigned": "テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||||
|
"deleteFailedTaskAssigned": "テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"partnerPage": {
|
"partnerPage": {
|
||||||
|
|||||||
@ -475,6 +475,10 @@
|
|||||||
"fileSizeTerms": "El tamaño máximo de archivo que se puede guardar es de 5 MB.",
|
"fileSizeTerms": "El tamaño máximo de archivo que se puede guardar es de 5 MB.",
|
||||||
"fileSizeError": "El tamaño del archivo seleccionado es demasiado grande. Seleccione un archivo que tenga un tamaño de 5 MB o menos.",
|
"fileSizeError": "El tamaño del archivo seleccionado es demasiado grande. Seleccione un archivo que tenga un tamaño de 5 MB o menos.",
|
||||||
"fileEmptyError": "Se requiere selección de archivos. Por favor seleccione un archivo."
|
"fileEmptyError": "Se requiere selección de archivos. Por favor seleccione un archivo."
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"deleteFailedWorkflowAssigned": "(es)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||||
|
"deleteFailedTaskAssigned": "(es)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"partnerPage": {
|
"partnerPage": {
|
||||||
|
|||||||
@ -475,6 +475,10 @@
|
|||||||
"fileSizeTerms": "La taille maximale du fichier pouvant être enregistré est de 5 Mo.",
|
"fileSizeTerms": "La taille maximale du fichier pouvant être enregistré est de 5 Mo.",
|
||||||
"fileSizeError": "La taille du fichier sélectionné est trop grande. Veuillez sélectionner un fichier d'une taille maximale de 5 Mo.",
|
"fileSizeError": "La taille du fichier sélectionné est trop grande. Veuillez sélectionner un fichier d'une taille maximale de 5 Mo.",
|
||||||
"fileEmptyError": "La sélection de fichiers est requise. Veuillez sélectionner un fichier."
|
"fileEmptyError": "La sélection de fichiers est requise. Veuillez sélectionner un fichier."
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"deleteFailedWorkflowAssigned": "(fr)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||||
|
"deleteFailedTaskAssigned": "(fr)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"partnerPage": {
|
"partnerPage": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user