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) {
|
||||
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
|
||||
@ -6774,6 +6812,19 @@ export const TemplatesApiAxiosParamCreator = function (configuration?: Configura
|
||||
export const TemplatesApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosParamCreator = TemplatesApiAxiosParamCreator(configuration)
|
||||
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
|
||||
@ -6796,6 +6847,16 @@ export const TemplatesApiFp = function(configuration?: Configuration) {
|
||||
export const TemplatesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||
const localVarFp = TemplatesApiFp(configuration)
|
||||
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
|
||||
@ -6815,6 +6876,18 @@ export const TemplatesApiFactory = function (configuration?: Configuration, base
|
||||
* @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
|
||||
|
||||
@ -73,4 +73,7 @@ export const errorCodes = [
|
||||
"E015001", // タイピストグループ削除済みエラー
|
||||
"E015002", // タイピストグループがワークフローに紐づいているエラー
|
||||
"E015003", // タイピストグループがルーティングされているエラー
|
||||
"E016001", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルがすでに削除済みだった)
|
||||
"E016002", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルがWorkflowに指定されていた)
|
||||
"E016003", // テンプレートファイル削除エラー(削除しようとしたテンプレートファイルが未完了のタスクに紐づいていた)
|
||||
] as const;
|
||||
|
||||
@ -115,3 +115,78 @@ export const uploadTemplateAsync = createAsyncThunk<
|
||||
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 { TemplateState } from "./state";
|
||||
import { listTemplateAsync, uploadTemplateAsync } from "./operations";
|
||||
import {
|
||||
deleteTemplateAsync,
|
||||
listTemplateAsync,
|
||||
uploadTemplateAsync,
|
||||
} from "./operations";
|
||||
|
||||
const initialState: TemplateState = {
|
||||
apps: {
|
||||
@ -45,6 +49,15 @@ export const templateSlice = createSlice({
|
||||
builder.addCase(uploadTemplateAsync.rejected, (state) => {
|
||||
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 { AppDispatch } from "app/store";
|
||||
import Header from "components/header";
|
||||
@ -13,6 +13,7 @@ import {
|
||||
selectTemplates,
|
||||
listTemplateAsync,
|
||||
selectIsLoading,
|
||||
deleteTemplateAsync,
|
||||
} from "features/workflow/template";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
@ -35,6 +36,23 @@ export const TemplateFilePage: React.FC = () => {
|
||||
dispatch(listTemplateAsync());
|
||||
}, [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 (
|
||||
<>
|
||||
{isShowAddPopup && (
|
||||
@ -101,16 +119,17 @@ export const TemplateFilePage: React.FC = () => {
|
||||
<td>{template.name}</td>
|
||||
<td>
|
||||
<ul className={`${styles.menuAction} ${styles.inTable}`}>
|
||||
{/* テンプレートファイル削除はCCB後回し分なので非表示
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href=""
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
onClick={() => {
|
||||
onDeleteTemplate(template.id);
|
||||
}}
|
||||
>
|
||||
{t(getTranslationID("common.label.delete"))}
|
||||
</a>
|
||||
</li>
|
||||
*/}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -475,6 +475,10 @@
|
||||
"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.",
|
||||
"fileEmptyError": "Dateiauswahl ist erforderlich. Bitte wählen Sie eine Datei aus."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(de)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(de)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
|
||||
@ -475,6 +475,10 @@
|
||||
"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.",
|
||||
"fileEmptyError": "File selection is required. Please select a file."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
|
||||
@ -475,6 +475,10 @@
|
||||
"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.",
|
||||
"fileEmptyError": "Se requiere selección de archivos. Por favor seleccione un archivo."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(es)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(es)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
|
||||
@ -475,6 +475,10 @@
|
||||
"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.",
|
||||
"fileEmptyError": "La sélection de fichiers est requise. Veuillez sélectionner un fichier."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(fr)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(fr)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user