Merged PR 682: タスク一覧画面修正
## 概要 [Task3458: タスク一覧画面修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3458) - タスク一覧画面のタスク削除ボタンからタスクを削除する処理を実装しました。 - タスクがInProgress、ユーザーがTypistの場合にはボタンを非活性となるようにしています。 ## レビューポイント - エラーごとの処理内容は適切でしょうか? - ボタンの活性制御は適切でしょうか? ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
This commit is contained in:
parent
81c299dd99
commit
8793606070
@ -5984,6 +5984,44 @@ export const TasksApiAxiosParamCreator = 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 {number} audioFileId ODMS Cloud上の音声ファイルID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
deleteTask: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'audioFileId' is not null or undefined
|
||||
assertParamExists('deleteTask', 'audioFileId', audioFileId)
|
||||
const localVarPath = `/tasks/{audioFileId}/delete`
|
||||
.replace(`{${"audioFileId"}}`, encodeURIComponent(String(audioFileId)));
|
||||
// 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};
|
||||
@ -6207,6 +6245,19 @@ export const TasksApiFp = function(configuration?: Configuration) {
|
||||
const operationBasePath = operationServerMap['TasksApi.checkout']?.[index]?.url;
|
||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||
},
|
||||
/**
|
||||
* 指定した文字起こしタスクを削除します。
|
||||
* @summary
|
||||
* @param {number} audioFileId ODMS Cloud上の音声ファイルID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async deleteTask(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteTask(audioFileId, options);
|
||||
const index = configuration?.serverIndex ?? 0;
|
||||
const operationBasePath = operationServerMap['TasksApi.deleteTask']?.[index]?.url;
|
||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||
},
|
||||
/**
|
||||
* 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します
|
||||
* @summary
|
||||
@ -6311,6 +6362,16 @@ export const TasksApiFactory = function (configuration?: Configuration, basePath
|
||||
checkout(audioFileId: number, options?: any): AxiosPromise<object> {
|
||||
return localVarFp.checkout(audioFileId, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
* 指定した文字起こしタスクを削除します。
|
||||
* @summary
|
||||
* @param {number} audioFileId ODMS Cloud上の音声ファイルID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
deleteTask(audioFileId: number, options?: any): AxiosPromise<object> {
|
||||
return localVarFp.deleteTask(audioFileId, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
* 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します
|
||||
* @summary
|
||||
@ -6416,6 +6477,18 @@ export class TasksApi extends BaseAPI {
|
||||
return TasksApiFp(this.configuration).checkout(audioFileId, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定した文字起こしタスクを削除します。
|
||||
* @summary
|
||||
* @param {number} audioFileId ODMS Cloud上の音声ファイルID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof TasksApi
|
||||
*/
|
||||
public deleteTask(audioFileId: number, options?: AxiosRequestConfig) {
|
||||
return TasksApiFp(this.configuration).deleteTask(audioFileId, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します
|
||||
* @summary
|
||||
|
||||
@ -8,7 +8,7 @@ export const STATUS = {
|
||||
|
||||
export type StatusType = typeof STATUS[keyof typeof STATUS];
|
||||
|
||||
export const LIMIT_TASK_NUM = 20;
|
||||
export const LIMIT_TASK_NUM = 100;
|
||||
|
||||
export const SORTABLE_COLUMN = {
|
||||
JobNumber: "JOB_NUMBER",
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
playbackAsync,
|
||||
updateAssigneeAsync,
|
||||
cancelAsync,
|
||||
deleteTaskAsync,
|
||||
} from "./operations";
|
||||
import {
|
||||
SORTABLE_COLUMN,
|
||||
@ -218,6 +219,15 @@ export const dictationSlice = createSlice({
|
||||
builder.addCase(backupTasksAsync.rejected, (state) => {
|
||||
state.apps.isDownloading = false;
|
||||
});
|
||||
builder.addCase(deleteTaskAsync.pending, (state) => {
|
||||
state.apps.isLoading = true;
|
||||
});
|
||||
builder.addCase(deleteTaskAsync.fulfilled, (state) => {
|
||||
state.apps.isLoading = false;
|
||||
});
|
||||
builder.addCase(deleteTaskAsync.rejected, (state) => {
|
||||
state.apps.isLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -572,3 +572,75 @@ export const backupTasksAsync = createAsyncThunk<
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteTaskAsync = createAsyncThunk<
|
||||
{
|
||||
// empty
|
||||
},
|
||||
{
|
||||
// パラメータ
|
||||
audioFileId: number;
|
||||
},
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("dictations/deleteTaskAsync", async (args, thunkApi) => {
|
||||
const { audioFileId } = 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 tasksApi = new TasksApi(config);
|
||||
|
||||
try {
|
||||
await tasksApi.deleteTask(audioFileId, {
|
||||
headers: { authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "info",
|
||||
message: getTranslationID("common.message.success"),
|
||||
})
|
||||
);
|
||||
return {};
|
||||
} catch (e) {
|
||||
// e ⇒ errorObjectに変換"
|
||||
const error = createErrorObject(e);
|
||||
|
||||
let message = getTranslationID("dictationPage.message.backupFailedError");
|
||||
|
||||
if (error.statusCode === 400) {
|
||||
if (error.code === "E010603") {
|
||||
// タスクが削除済みの場合は成功扱いとする
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "info",
|
||||
message: getTranslationID("common.message.success"),
|
||||
})
|
||||
);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (error.code === "E010601") {
|
||||
// タスクがInprogressの場合はエラー
|
||||
message = getTranslationID("dictationPage.message.deleteFailedError");
|
||||
}
|
||||
}
|
||||
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message,
|
||||
})
|
||||
);
|
||||
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
@ -33,6 +33,7 @@ import {
|
||||
playbackAsync,
|
||||
cancelAsync,
|
||||
PRIORITY,
|
||||
deleteTaskAsync,
|
||||
} from "features/dictation";
|
||||
import { getTranslationID } from "translation";
|
||||
import { Task } from "api/api";
|
||||
@ -61,6 +62,8 @@ const DictationPage: React.FC = (): JSX.Element => {
|
||||
const isTypist = isTypistUser();
|
||||
const isNone = !isAuthor && !isTypist;
|
||||
|
||||
const isDeletableRole = isAdmin || isAuthor;
|
||||
|
||||
// popup制御関係
|
||||
const [
|
||||
isChangeTranscriptionistPopupOpen,
|
||||
@ -506,6 +509,53 @@ const DictationPage: React.FC = (): JSX.Element => {
|
||||
return styles.isActiveAz;
|
||||
};
|
||||
|
||||
const onDeleteTask = useCallback(
|
||||
async (audioFileId: number) => {
|
||||
if (
|
||||
/* eslint-disable-next-line no-alert */
|
||||
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const { meta } = await dispatch(
|
||||
deleteTaskAsync({
|
||||
audioFileId,
|
||||
})
|
||||
);
|
||||
if (meta.requestStatus === "fulfilled") {
|
||||
const filter = getFilter(
|
||||
filterUploaded,
|
||||
filterInProgress,
|
||||
filterPending,
|
||||
filterFinished,
|
||||
filterBackup
|
||||
);
|
||||
dispatch(
|
||||
listTasksAsync({
|
||||
limit: LIMIT_TASK_NUM,
|
||||
offset: 0,
|
||||
filter,
|
||||
direction: sortDirection,
|
||||
paramName: sortableParamName,
|
||||
})
|
||||
);
|
||||
dispatch(listTypistsAsync());
|
||||
dispatch(listTypistGroupsAsync());
|
||||
}
|
||||
},
|
||||
[
|
||||
dispatch,
|
||||
filterBackup,
|
||||
filterFinished,
|
||||
filterInProgress,
|
||||
filterPending,
|
||||
filterUploaded,
|
||||
sortDirection,
|
||||
sortableParamName,
|
||||
t,
|
||||
]
|
||||
);
|
||||
|
||||
// 初回読み込み処理
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@ -1150,7 +1200,16 @@ const DictationPage: React.FC = (): JSX.Element => {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
className={
|
||||
isDeletableRole &&
|
||||
x.status !== STATUS.INPROGRESS
|
||||
? ""
|
||||
: styles.isDisable
|
||||
}
|
||||
onClick={() => onDeleteTask(x.audioFileId)}
|
||||
>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"dictationPage.label.deleteDictation"
|
||||
|
||||
@ -2047,7 +2047,7 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: #282828;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
}
|
||||
.dictation .table.dictation tr.tableHeader th.clm0 {
|
||||
width: 0px;
|
||||
@ -2482,8 +2482,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
}
|
||||
.formChange ul.chooseMember li input:checked + label:hover,
|
||||
.formChange ul.holdMember li input:checked + label:hover {
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat
|
||||
right center;
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat right
|
||||
center;
|
||||
background-size: 1.3rem;
|
||||
}
|
||||
.formChange > p {
|
||||
|
||||
@ -206,7 +206,8 @@
|
||||
"taskToPlaybackNoExists": "Die Datei kann nicht abgespielt werden, da sie bereits transkribiert wurde oder nicht existiert.",
|
||||
"taskNotEditable": "Der Transkriptionist kann nicht geändert werden, da die Transkription bereits ausgeführt wird oder die Datei nicht vorhanden ist. Bitte aktualisieren Sie den Bildschirm und prüfen Sie den aktuellen Status.",
|
||||
"backupFailedError": "(de)ファイルのバックアップに失敗したため処理を中断しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"cancelFailedError": "(de)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
|
||||
"cancelFailedError": "(de)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(de)タスクの削除に失敗しました。画面を更新し、再度ご確認ください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Diktate",
|
||||
@ -555,4 +556,4 @@
|
||||
"close": "(de)Close"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +206,8 @@
|
||||
"taskToPlaybackNoExists": "The file cannot be played because it has already been transcribed or does not exist.",
|
||||
"taskNotEditable": "The transcriptionist cannot be changed because the transcription is already in progress or the file does not exist. Please refresh the screen and check the latest status.",
|
||||
"backupFailedError": "ファイルのバックアップに失敗したため処理を中断しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"cancelFailedError": "タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
|
||||
"cancelFailedError": "タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "タスクの削除に失敗しました。画面を更新し、再度ご確認ください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Dictations",
|
||||
@ -555,4 +556,4 @@
|
||||
"close": "Close"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +206,8 @@
|
||||
"taskToPlaybackNoExists": "El archivo no se puede reproducir porque ya ha sido transcrito o no existe.",
|
||||
"taskNotEditable": "No se puede cambiar el transcriptor porque la transcripción ya está en curso o el archivo no existe. Actualice la pantalla y verifique el estado más reciente.",
|
||||
"backupFailedError": "(es)ファイルのバックアップに失敗したため処理を中断しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"cancelFailedError": "(es)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
|
||||
"cancelFailedError": "(es)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(es)タスクの削除に失敗しました。画面を更新し、再度ご確認ください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Dictado",
|
||||
@ -555,4 +556,4 @@
|
||||
"close": "(es)Close"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +206,8 @@
|
||||
"taskToPlaybackNoExists": "Le fichier ne peut pas être lu car il a déjà été transcrit ou n'existe pas.",
|
||||
"taskNotEditable": "Le transcripteur ne peut pas être changé car la transcription est déjà en cours ou le fichier n'existe pas. Veuillez actualiser l'écran et vérifier le dernier statut.",
|
||||
"backupFailedError": "(fr)ファイルのバックアップに失敗したため処理を中断しました。時間をおいて再実行しても解決しない場合はシステム管理者にお問い合わせください。",
|
||||
"cancelFailedError": "(fr)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
|
||||
"cancelFailedError": "(fr)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(fr)タスクの削除に失敗しました。画面を更新し、再度ご確認ください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Dictées",
|
||||
@ -555,4 +556,4 @@
|
||||
"close": "(fr)Close"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
-- +migrate Up
|
||||
ALTER TABLE `users` DROP COLUMN `license_alert`;
|
||||
|
||||
|
||||
-- +migrate Down
|
||||
ALTER TABLE `users` ADD COLUMN `license_alert` BOOLEAN DEFAULT TRUE NOT NULL COMMENT 'ライセンスの期限切れ通知をするかどうか';
|
||||
Loading…
x
Reference in New Issue
Block a user