Merged PR 427: 画面実装(テンプレートファイル一覧画面)

## 概要
[Task2651: 画面実装(テンプレートファイル一覧画面)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2651)

- テンプレートファイル一覧画面を実装

## レビューポイント
- 取得方法やstoreの構成は問題ないか

## 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/Task2651?csf=1&web=1&e=MAaOJd

## 動作確認状況
- ローカルで確認

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
saito.k 2023-09-22 07:36:23 +00:00
parent f120f4f7e5
commit 3f4d4ec436
16 changed files with 695 additions and 9 deletions

View File

@ -20,6 +20,7 @@ import WorkflowPage from "pages/WorkflowPage";
import TypistGroupSettingPage from "pages/TypistGroupSettingPage";
import WorktypeIdSettingPage from "pages/WorkTypeIdSettingPage";
import AccountPage from "pages/AccountPage";
import { TemplateFilePage } from "pages/TemplateFilePage";
const AppRouter: React.FC = () => (
<Routes>
@ -72,6 +73,10 @@ const AppRouter: React.FC = () => (
path="/workflow/worktype-id"
element={<RouteAuthGuard component={<WorktypeIdSettingPage />} />}
/>
<Route
path="/workflow/template"
element={<RouteAuthGuard component={<TemplateFilePage />} />}
/>
<Route
path="/partners"
element={<RouteAuthGuard component={<PartnerPage />} />}

View File

@ -561,6 +561,19 @@ export interface DeallocateLicenseRequest {
*/
'userId': number;
}
/**
*
* @export
* @interface DeleteAccountRequest
*/
export interface DeleteAccountRequest {
/**
* ID
* @type {number}
* @memberof DeleteAccountRequest
*/
'accountId': number;
}
/**
*
* @export
@ -905,6 +918,19 @@ export interface GetSortCriteriaResponse {
*/
'paramName': string;
}
/**
*
* @export
* @interface GetTemplatesResponse
*/
export interface GetTemplatesResponse {
/**
*
* @type {Array<TemplateFile>}
* @memberof GetTemplatesResponse
*/
'templates': Array<TemplateFile>;
}
/**
*
* @export
@ -1631,6 +1657,57 @@ export interface TemplateDownloadLocationResponse {
*/
'url': string;
}
/**
*
* @export
* @interface TemplateFile
*/
export interface TemplateFile {
/**
* ID
* @type {number}
* @memberof TemplateFile
*/
'id': number;
/**
*
* @type {string}
* @memberof TemplateFile
*/
'name': string;
}
/**
*
* @export
* @interface TemplateUploadFinishedRequest
*/
export interface TemplateUploadFinishedRequest {
/**
*
* @type {string}
* @memberof TemplateUploadFinishedRequest
*/
'name': string;
/**
* URL
* @type {string}
* @memberof TemplateUploadFinishedRequest
*/
'url': string;
}
/**
*
* @export
* @interface TemplateUploadLocationResponse
*/
export interface TemplateUploadLocationResponse {
/**
*
* @type {string}
* @memberof TemplateUploadLocationResponse
*/
'url': string;
}
/**
*
* @export
@ -2154,6 +2231,46 @@ export const AccountsApiAxiosParamCreator = function (configuration?: Configurat
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {DeleteAccountRequest} deleteAccountRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteAccount: async (deleteAccountRequest: DeleteAccountRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'deleteAccountRequest' is not null or undefined
assertParamExists('deleteAccount', 'deleteAccountRequest', deleteAccountRequest)
const localVarPath = `/accounts/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(deleteAccountRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
@ -2611,9 +2728,9 @@ export const AccountsApiAxiosParamCreator = function (configuration?: Configurat
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
me: async (updateAccountInfoRequest: UpdateAccountInfoRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
updateAccountInfo: async (updateAccountInfoRequest: UpdateAccountInfoRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'updateAccountInfoRequest' is not null or undefined
assertParamExists('me', 'updateAccountInfoRequest', updateAccountInfoRequest)
assertParamExists('updateAccountInfo', 'updateAccountInfoRequest', updateAccountInfoRequest)
const localVarPath = `/accounts/me`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -2852,6 +2969,17 @@ export const AccountsApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.createWorktype(createWorktypesRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
* @param {DeleteAccountRequest} deleteAccountRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async deleteAccount(deleteAccountRequest: DeleteAccountRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteAccount(deleteAccountRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
@ -2987,8 +3115,8 @@ export const AccountsApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async me(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.me(updateAccountInfoRequest, options);
async updateAccountInfo(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.updateAccountInfo(updateAccountInfoRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -3097,6 +3225,16 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP
createWorktype(createWorktypesRequest: CreateWorktypesRequest, options?: any): AxiosPromise<object> {
return localVarFp.createWorktype(createWorktypesRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {DeleteAccountRequest} deleteAccountRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteAccount(deleteAccountRequest: DeleteAccountRequest, options?: any): AxiosPromise<object> {
return localVarFp.deleteAccount(deleteAccountRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
@ -3220,8 +3358,8 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
me(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: any): AxiosPromise<object> {
return localVarFp.me(updateAccountInfoRequest, options).then((request) => request(axios, basePath));
updateAccountInfo(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: any): AxiosPromise<object> {
return localVarFp.updateAccountInfo(updateAccountInfoRequest, options).then((request) => request(axios, basePath));
},
/**
*
@ -3338,6 +3476,18 @@ export class AccountsApi extends BaseAPI {
return AccountsApiFp(this.configuration).createWorktype(createWorktypesRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {DeleteAccountRequest} deleteAccountRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AccountsApi
*/
public deleteAccount(deleteAccountRequest: DeleteAccountRequest, options?: AxiosRequestConfig) {
return AccountsApiFp(this.configuration).deleteAccount(deleteAccountRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
@ -3486,8 +3636,8 @@ export class AccountsApi extends BaseAPI {
* @throws {RequiredError}
* @memberof AccountsApi
*/
public me(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: AxiosRequestConfig) {
return AccountsApiFp(this.configuration).me(updateAccountInfoRequest, options).then((request) => request(this.axios, this.basePath));
public updateAccountInfo(updateAccountInfoRequest: UpdateAccountInfoRequest, options?: AxiosRequestConfig) {
return AccountsApiFp(this.configuration).updateAccountInfo(updateAccountInfoRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
@ -3956,6 +4106,80 @@ export const FilesApiAxiosParamCreator = function (configuration?: Configuration
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {TemplateUploadFinishedRequest} templateUploadFinishedRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadTemplateFinished: async (templateUploadFinishedRequest: TemplateUploadFinishedRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'templateUploadFinishedRequest' is not null or undefined
assertParamExists('uploadTemplateFinished', 'templateUploadFinishedRequest', templateUploadFinishedRequest)
const localVarPath = `/files/template/upload-finished`;
// 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(templateUploadFinishedRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Blob Storage上のテンプレートファイルのアップロード先アクセスURLを取得します
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadTemplateLocation: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/files/template/upload-location`;
// 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: 'GET', ...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};
@ -4018,6 +4242,27 @@ export const FilesApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadLocation(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
* @param {TemplateUploadFinishedRequest} templateUploadFinishedRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async uploadTemplateFinished(templateUploadFinishedRequest: TemplateUploadFinishedRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadTemplateFinished(templateUploadFinishedRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
* Blob Storage上のテンプレートファイルのアップロード先アクセスURLを取得します
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async uploadTemplateLocation(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<TemplateUploadLocationResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadTemplateLocation(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
}
};
@ -4067,6 +4312,25 @@ export const FilesApiFactory = function (configuration?: Configuration, basePath
uploadLocation(options?: any): AxiosPromise<AudioUploadLocationResponse> {
return localVarFp.uploadLocation(options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {TemplateUploadFinishedRequest} templateUploadFinishedRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadTemplateFinished(templateUploadFinishedRequest: TemplateUploadFinishedRequest, options?: any): AxiosPromise<object> {
return localVarFp.uploadTemplateFinished(templateUploadFinishedRequest, options).then((request) => request(axios, basePath));
},
/**
* Blob Storage上のテンプレートファイルのアップロード先アクセスURLを取得します
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
uploadTemplateLocation(options?: any): AxiosPromise<TemplateUploadLocationResponse> {
return localVarFp.uploadTemplateLocation(options).then((request) => request(axios, basePath));
},
};
};
@ -4123,6 +4387,29 @@ export class FilesApi extends BaseAPI {
public uploadLocation(options?: AxiosRequestConfig) {
return FilesApiFp(this.configuration).uploadLocation(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {TemplateUploadFinishedRequest} templateUploadFinishedRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof FilesApi
*/
public uploadTemplateFinished(templateUploadFinishedRequest: TemplateUploadFinishedRequest, options?: AxiosRequestConfig) {
return FilesApiFp(this.configuration).uploadTemplateFinished(templateUploadFinishedRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
* Blob Storage上のテンプレートファイルのアップロード先アクセスURLを取得します
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof FilesApi
*/
public uploadTemplateLocation(options?: AxiosRequestConfig) {
return FilesApiFp(this.configuration).uploadTemplateLocation(options).then((request) => request(this.axios, this.basePath));
}
}
@ -5357,6 +5644,109 @@ export class TasksApi extends BaseAPI {
/**
* TemplatesApi - axios parameter creator
* @export
*/
export const TemplatesApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getTemplates: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/templates`;
// 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: 'GET', ...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,
};
},
}
};
/**
* TemplatesApi - functional programming interface
* @export
*/
export const TemplatesApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = TemplatesApiAxiosParamCreator(configuration)
return {
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getTemplates(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetTemplatesResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getTemplates(options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
}
};
/**
* TemplatesApi - factory interface
* @export
*/
export const TemplatesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = TemplatesApiFp(configuration)
return {
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getTemplates(options?: any): AxiosPromise<GetTemplatesResponse> {
return localVarFp.getTemplates(options).then((request) => request(axios, basePath));
},
};
};
/**
* TemplatesApi - object-oriented interface
* @export
* @class TemplatesApi
* @extends {BaseAPI}
*/
export class TemplatesApi extends BaseAPI {
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof TemplatesApi
*/
public getTemplates(options?: AxiosRequestConfig) {
return TemplatesApiFp(this.configuration).getTemplates(options).then((request) => request(this.axios, this.basePath));
}
}
/**
* UsersApi - axios parameter creator
* @export

View File

@ -16,6 +16,7 @@ import licenseOrderHistory from "features/license/licenseOrderHistory/licenseOrd
import typistGroup from "features/workflow/typistGroup/typistGroupSlice";
import worktype from "features/workflow/worktype/worktypeSlice";
import account from "features/account/accountSlice";
import template from "features/workflow/template/templateSlice";
export const store = configureStore({
reducer: {
@ -36,6 +37,7 @@ export const store = configureStore({
typistGroup,
worktype,
account,
template,
},
});

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.7.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<style type="text/css">
.st0{fill:#282828;}
</style>
<path class="st0" d="M11,44c-0.8,0-1.5-0.3-2.1-0.9C8.3,42.5,8,41.8,8,41V7c0-0.8,0.3-1.5,0.9-2.1C9.5,4.3,10.2,4,11,4h17l12,12v5.8
h-3V18H26V7H11v34h13v3H11z M11,41V7V41z M33.1,43.9v-6.5h-6.5v-3.9h6.5V27H37v6.5h6.5v3.9H37v6.5H33.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 647 B

View File

@ -72,7 +72,7 @@ export const updateAccountInfoAsync = createAsyncThunk<
const accountApi = new AccountsApi(config);
try {
await accountApi.me(args, {
await accountApi.updateAccountInfo(args, {
headers: { authorization: `Bearer ${accessToken}` },
});
thunkApi.dispatch(

View File

@ -0,0 +1,4 @@
export * from "./templateSlice";
export * from "./state";
export * from "./operations";
export * from "./selectors";

View File

@ -0,0 +1,42 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { Configuration, GetTemplatesResponse, TemplatesApi } from "api";
import type { RootState } from "app/store";
import { ErrorObject, createErrorObject } from "common/errors";
import { openSnackbar } from "features/ui/uiSlice";
import { getTranslationID } from "translation";
export const listTemplateAsync = createAsyncThunk<
GetTemplatesResponse,
void,
{
// rejectした時の返却値の型
rejectValue: {
error: ErrorObject;
};
}
>("workflow/listTemplateAsync", async (args, thunkApi) => {
// apiのConfigurationを取得する
const { getState } = thunkApi;
const state = getState() as RootState;
const { configuration, accessToken } = state.auth;
const config = new Configuration(configuration);
const templateApi = new TemplatesApi(config);
try {
const { data } = await templateApi.getTemplates({
headers: { authorization: `Bearer ${accessToken}` },
});
return data;
} catch (e) {
// e ⇒ errorObjectに変換"
const error = createErrorObject(e);
thunkApi.dispatch(
openSnackbar({
level: "error",
message: getTranslationID("common.message.internalServerError"),
})
);
return thunkApi.rejectWithValue({ error });
}
});

View File

@ -0,0 +1,7 @@
import { RootState } from "app/store";
export const selectTemplates = (state: RootState) =>
state.template.domain.templates;
export const selectIsLoading = (state: RootState) =>
state.template.apps.isLoading;

View File

@ -0,0 +1,14 @@
import { TemplateFile } from "api";
export interface TemplateState {
apps: Apps;
domain: Domain;
}
export interface Apps {
isLoading: boolean;
}
export interface Domain {
templates?: TemplateFile[];
}

View File

@ -0,0 +1,34 @@
import { createSlice } from "@reduxjs/toolkit";
import { TemplateState } from "./state";
import { listTemplateAsync } from "./operations";
const initialState: TemplateState = {
apps: {
isLoading: false,
},
domain: {
templates: undefined,
},
};
export const templateSlice = createSlice({
name: "template",
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(listTemplateAsync.pending, (state) => {
state.apps.isLoading = true;
});
builder.addCase(listTemplateAsync.fulfilled, (state, action) => {
const { templates } = action.payload;
state.domain.templates = templates;
state.apps.isLoading = false;
});
builder.addCase(listTemplateAsync.rejected, (state) => {
state.apps.isLoading = false;
});
},
});
export default templateSlice.reducer;

View File

@ -0,0 +1,109 @@
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch } from "app/store";
import Header from "components/header";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation";
import undo from "assets/images/undo.svg";
import styles from "styles/app.module.scss";
import {
listTemplateAsync,
selectIsLoading,
selectTemplates,
} from "features/workflow/template";
import addTemplate from "assets/images/template_add.svg";
import progress_activit from "assets/images/progress_activit.svg";
export const TemplateFilePage: React.FC = () => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
const templates = useSelector(selectTemplates);
const isLoading = useSelector(selectIsLoading);
useEffect(() => {
dispatch(listTemplateAsync());
}, [dispatch]);
return (
<div className={styles.wrap}>
<Header userName="XXXXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>
<div>
<div className={styles.pageHeader}>
<h1 className={styles.pageTitle}>
{t(getTranslationID("workflowPage.label.title"))}
</h1>
<p className={styles.pageTx}>
{t(getTranslationID("templateFilePage.label.title"))}
</p>
</div>
</div>
<section className={styles.workflow}>
<div>
<ul className={`${styles.menuAction} ${styles.worktype}`}>
<li>
<a
href="/workflow"
className={`${styles.menuLink} ${styles.isActive}`}
>
<img src={undo} alt="" className={styles.menuIcon} />
{t(getTranslationID("common.label.return"))}
</a>
</li>
<li>
<a className={`${styles.menuLink} ${styles.isActive}`}>
<img src={addTemplate} alt="" className={styles.menuIcon} />
{t(getTranslationID("templateFilePage.label.addTemplate"))}
</a>
</li>
</ul>
<table className={`${styles.table} ${styles.template}`}>
<tr className={styles.tableHeader}>
<th className={styles.noLine}>
{t(getTranslationID("templateFilePage.label.fileName"))}
</th>
<th>{/** empty th */}</th>
</tr>
{templates?.map((template) => (
<tr key={template.id}>
<td>{template.name}</td>
<td>
<ul className={`${styles.menuAction} ${styles.inTable}`}>
<li>
<a
href=""
className={`${styles.menuLink} ${styles.isActive}`}
>
{t(getTranslationID("common.label.delete"))}
</a>
</li>
</ul>
</td>
</tr>
))}
{!isLoading && templates?.length === 0 && (
<p
style={{
margin: "10px",
textAlign: "center",
}}
>
{t(getTranslationID("common.message.listEmpty"))}
</p>
)}
{isLoading && (
<img
src={progress_activit}
className={styles.icLoading}
alt="Loading"
/>
)}
</table>
</div>
</section>
</main>
</div>
);
};

View File

@ -20,6 +20,11 @@ const WorkflowPage: React.FC = (): JSX.Element => (
Worktype ID Setting
</a>
</span>
<span>
<a style={{ margin: 20 }} href="/workflow/template">
Template File
</a>
</span>
</div>
</main>
<Footer />

View File

@ -413,6 +413,13 @@
"updateActiveWorktypeFailedError": "(de)Active WorktypeIDの保存に失敗しました。画面を更新し、再度実行してください"
}
},
"templateFilePage": {
"label": {
"title": "(de)Template List",
"addTemplate": "(de)Add Template",
"fileName": "(de)Flie Name"
}
},
"partnerPage": {
"label": {
"title": "(de)Partners",
@ -451,5 +458,14 @@
"message": {
"updateAccountFailedError": "(de)アカウント情報の保存に失敗しました。画面を更新し、再度実行してください"
}
},
"deleteAccountPopup": {
"label": {
"title": "(de)Delete Account",
"subTitle": "(de)Delete your account",
"cautionOfDeleteingAccountData": "(de)Deleting your account will remove all of your audio files and\nlicenses from system. and you'll cannot use ODMS Cloud.\nThis cannot be undone.",
"deleteButton": "(de)Delete account",
"cancelButton": "(de)Cancel"
}
}
}

View File

@ -413,6 +413,13 @@
"updateActiveWorktypeFailedError": "Active WorktypeIDの保存に失敗しました。画面を更新し、再度実行してください"
}
},
"templateFilePage": {
"label": {
"title": "Template List",
"addTemplate": "Add Template",
"fileName": "Flie Name"
}
},
"partnerPage": {
"label": {
"title": "Partners",
@ -451,5 +458,14 @@
"message": {
"updateAccountFailedError": "アカウント情報の保存に失敗しました。画面を更新し、再度実行してください"
}
},
"deleteAccountPopup": {
"label": {
"title": "Delete Account",
"subTitle": "Delete your account",
"cautionOfDeleteingAccountData": "Deleting your account will remove all of your audio files and\nlicenses from system. and you'll cannot use ODMS Cloud.\nThis cannot be undone.",
"deleteButton": "Delete account",
"cancelButton": "Cancel"
}
}
}

View File

@ -413,6 +413,13 @@
"updateActiveWorktypeFailedError": "(es)Active WorktypeIDの保存に失敗しました。画面を更新し、再度実行してください"
}
},
"templateFilePage": {
"label": {
"title": "(es)Template List",
"addTemplate": "(es)Add Template",
"fileName": "(es)Flie Name"
}
},
"partnerPage": {
"label": {
"title": "(es)Partners",
@ -451,5 +458,14 @@
"message": {
"updateAccountFailedError": "(es)アカウント情報の保存に失敗しました。画面を更新し、再度実行してください"
}
},
"deleteAccountPopup": {
"label": {
"title": "(es)Delete Account",
"subTitle": "(es)Delete your account",
"cautionOfDeleteingAccountData": "(es)Deleting your account will remove all of your audio files and\nlicenses from system. and you'll cannot use ODMS Cloud.\nThis cannot be undone.",
"deleteButton": "(es)Delete account",
"cancelButton": "(es)Cancel"
}
}
}

View File

@ -413,6 +413,13 @@
"updateActiveWorktypeFailedError": "(fr)Active WorktypeIDの保存に失敗しました。画面を更新し、再度実行してください"
}
},
"templateFilePage": {
"label": {
"title": "(fr)Template List",
"addTemplate": "(fr)Add Template",
"fileName": "(fr)Flie Name"
}
},
"partnerPage": {
"label": {
"title": "(fr)Partners",
@ -451,5 +458,14 @@
"message": {
"updateAccountFailedError": "(fr)アカウント情報の保存に失敗しました。画面を更新し、再度実行してください"
}
},
"deleteAccountPopup": {
"label": {
"title": "(fr)Delete Account",
"subTitle": "(fr)Delete your account",
"cautionOfDeleteingAccountData": "(fr)Deleting your account will remove all of your audio files and\nlicenses from system. and you'll cannot use ODMS Cloud.\nThis cannot be undone.",
"deleteButton": "(fr)Delete account",
"cancelButton": "(fr)Cancel"
}
}
}