Merged PR 588: 画面実装(タスク一覧画面:タスクキャンセル操作追加)

## 概要
[Task3131: 画面実装(タスク一覧画面:タスクキャンセル操作追加)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3131)

- タスク 3131: 画面実装(タスク一覧画面:タスクキャンセル操作追加)
- タスク一覧に対してCancel Dictationボタンを実装しました

## レビューポイント
- タスク関連のほかの処理で実施しているものについて、キャンセルで実施必要か確認いただきたいです。
  - キャンセル後のデスクトップアプリ起動
    - 不要の認識
  - キャンセル前のソート条件保存
    - ステータスが変わるため、必要な認識
- ログイン名を取得するためにloginのselectorを使用していますが問題ないか確認いただきたいです
(他フィーチャと余計な関連を作るのはあまりよくないと思いつつ、同じような取得処理を作るのも嫌だと思いつつ。。)

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

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

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
masaaki 2023-11-22 01:13:03 +00:00
parent f38733f9b2
commit 501fc5a15d
7 changed files with 179 additions and 8 deletions

View File

@ -9,6 +9,7 @@ import {
listTypistsAsync, listTypistsAsync,
playbackAsync, playbackAsync,
updateAssigneeAsync, updateAssigneeAsync,
cancelAsync,
} from "./operations"; } from "./operations";
import { import {
SORTABLE_COLUMN, SORTABLE_COLUMN,
@ -176,6 +177,15 @@ export const dictationSlice = createSlice({
builder.addCase(playbackAsync.rejected, (state) => { builder.addCase(playbackAsync.rejected, (state) => {
state.apps.isLoading = false; state.apps.isLoading = false;
}); });
builder.addCase(cancelAsync.pending, (state) => {
state.apps.isLoading = true;
});
builder.addCase(cancelAsync.fulfilled, (state) => {
state.apps.isLoading = false;
});
builder.addCase(cancelAsync.rejected, (state) => {
state.apps.isLoading = false;
});
builder.addCase(listBackupPopupTasksAsync.pending, (state) => { builder.addCase(listBackupPopupTasksAsync.pending, (state) => {
state.apps.isBackupListLoading = true; state.apps.isBackupListLoading = true;
}); });

View File

@ -355,6 +355,78 @@ export const playbackAsync = createAsyncThunk<
} }
}); });
export const cancelAsync = createAsyncThunk<
{
/** empty */
},
{
direction: DirectionType;
paramName: SortableColumnType;
audioFileId: number;
isTypist: boolean;
},
{
// rejectした時の返却値の型
rejectValue: {
error: ErrorObject;
};
}
>("dictations/cancelAsync", async (args, thunkApi) => {
const { audioFileId, direction, paramName, isTypist } = 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);
const usersApi = new UsersApi(config);
try {
// ユーザーがタイピストである場合に、ソート条件を保存する
if (isTypist) {
await usersApi.updateSortCriteria(
{ direction, paramName },
{
headers: { authorization: `Bearer ${accessToken}` },
}
);
}
await tasksApi.cancel(audioFileId, {
headers: { authorization: `Bearer ${accessToken}` },
});
thunkApi.dispatch(
openSnackbar({
level: "info",
message: getTranslationID("common.message.success"),
})
);
return {};
} catch (e) {
// e ⇒ errorObjectに変換"
const error = createErrorObject(e);
// ステータスが[Inprogress,Pending]以外、またはタスクが存在しない場合、またはtypistで自分のタスクでない場合
if (error.code === "E010601" || error.code === "E010603") {
thunkApi.dispatch(
openSnackbar({
level: "error",
message: getTranslationID("dictationPage.message.cancelFailedError"),
})
);
return thunkApi.rejectWithValue({ error });
}
thunkApi.dispatch(
openSnackbar({
level: "error",
message: getTranslationID("common.message.internalServerError"),
})
);
return thunkApi.rejectWithValue({ error });
}
});
export const listBackupPopupTasksAsync = createAsyncThunk< export const listBackupPopupTasksAsync = createAsyncThunk<
TasksResponse, TasksResponse,
{ {

View File

@ -30,7 +30,9 @@ import {
DirectionType, DirectionType,
selectIsLoading, selectIsLoading,
playbackAsync, playbackAsync,
cancelAsync,
} from "features/dictation"; } from "features/dictation";
import { selectUserName } from "features/login/index";
import { getTranslationID } from "translation"; import { getTranslationID } from "translation";
import { Task } from "api/api"; import { Task } from "api/api";
import { isAdminUser, isAuthorUser, isTypistUser } from "features/auth"; import { isAdminUser, isAuthorUser, isTypistUser } from "features/auth";
@ -73,6 +75,9 @@ const DictationPage: React.FC = (): JSX.Element => {
[dispatch, setIsChangeTranscriptionistPopupOpen] [dispatch, setIsChangeTranscriptionistPopupOpen]
); );
// ログイン中のユーザ名
const myName = useSelector(selectUserName);
// 各カラムの表示/非表示 // 各カラムの表示/非表示
const displayColumn = useSelector(selectDisplayInfo); const displayColumn = useSelector(selectDisplayInfo);
@ -417,6 +422,57 @@ const DictationPage: React.FC = (): JSX.Element => {
] ]
); );
const onCancel = useCallback(
async (audioFileId: number) => {
if (
/* eslint-disable-next-line no-alert */
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
) {
return;
}
const { meta } = await dispatch(
cancelAsync({
audioFileId,
direction: sortDirection,
paramName: sortableParamName,
isTypist,
})
);
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,
isTypist,
sortDirection,
sortableParamName,
t,
]
);
const onCloseBackupPopup = useCallback(() => { const onCloseBackupPopup = useCallback(() => {
setIsBackupPopupOpen(false); setIsBackupPopupOpen(false);
}, []); }, []);
@ -1056,6 +1112,27 @@ const DictationPage: React.FC = (): JSX.Element => {
)} )}
</a> </a>
</li> </li>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={
(x.status === STATUS.INPROGRESS ||
x.status === STATUS.PENDING) &&
(isAdmin || isTypist)
? ""
: styles.isDisable
}
onClick={() => {
onCancel(x.audioFileId);
}}
>
{t(
getTranslationID(
"dictationPage.label.cancelDictation"
)
)}
</a>
</li>
<li> <li>
<a> <a>
{t( {t(

View File

@ -203,7 +203,9 @@
"message": { "message": {
"noPlaybackAuthorization": "Sie haben keine Berechtigung zum Abspielen dieser Datei.", "noPlaybackAuthorization": "Sie haben keine Berechtigung zum Abspielen dieser Datei.",
"taskToPlaybackNoExists": "Die Datei kann nicht abgespielt werden, da sie bereits transkribiert wurde oder nicht existiert.", "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." "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)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
}, },
"label": { "label": {
"title": "Diktate", "title": "Diktate",
@ -247,7 +249,8 @@
"selectedTranscriptionist": "Ausgewählter transkriptionist", "selectedTranscriptionist": "Ausgewählter transkriptionist",
"poolTranscriptionist": "Transkriptionsliste", "poolTranscriptionist": "Transkriptionsliste",
"fileBackup": "(de)File Backup", "fileBackup": "(de)File Backup",
"downloadForBackup": "(de)Download for backup" "downloadForBackup": "(de)Download for backup",
"cancelDictation": "(de)Cancel Dictation"
} }
}, },
"cardLicenseIssuePopupPage": { "cardLicenseIssuePopupPage": {

View File

@ -203,7 +203,9 @@
"message": { "message": {
"noPlaybackAuthorization": "You do not have permission to playback this file.", "noPlaybackAuthorization": "You do not have permission to playback this file.",
"taskToPlaybackNoExists": "The file cannot be played because it has already been transcribed or does not exist.", "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." "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": "タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
}, },
"label": { "label": {
"title": "Dictations", "title": "Dictations",
@ -247,7 +249,8 @@
"selectedTranscriptionist": "Selected Transcriptionist", "selectedTranscriptionist": "Selected Transcriptionist",
"poolTranscriptionist": "Transcription List", "poolTranscriptionist": "Transcription List",
"fileBackup": "File Backup", "fileBackup": "File Backup",
"downloadForBackup": "Download for backup" "downloadForBackup": "Download for backup",
"cancelDictation": "Cancel Dictation"
} }
}, },
"cardLicenseIssuePopupPage": { "cardLicenseIssuePopupPage": {

View File

@ -203,7 +203,9 @@
"message": { "message": {
"noPlaybackAuthorization": "No tienes permiso para reproducir este archivo.", "noPlaybackAuthorization": "No tienes permiso para reproducir este archivo.",
"taskToPlaybackNoExists": "El archivo no se puede reproducir porque ya ha sido transcrito o no existe.", "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." "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)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
}, },
"label": { "label": {
"title": "Dictado", "title": "Dictado",
@ -247,7 +249,8 @@
"selectedTranscriptionist": "Transcriptor seleccionado", "selectedTranscriptionist": "Transcriptor seleccionado",
"poolTranscriptionist": "Lista de transcriptor", "poolTranscriptionist": "Lista de transcriptor",
"fileBackup": "(es)File Backup", "fileBackup": "(es)File Backup",
"downloadForBackup": "(es)Download for backup" "downloadForBackup": "(es)Download for backup",
"cancelDictation": "(es)Cancel Dictation"
} }
}, },
"cardLicenseIssuePopupPage": { "cardLicenseIssuePopupPage": {

View File

@ -203,7 +203,9 @@
"message": { "message": {
"noPlaybackAuthorization": "Vous n'êtes pas autorisé à lire ce fichier.", "noPlaybackAuthorization": "Vous n'êtes pas autorisé à lire ce fichier.",
"taskToPlaybackNoExists": "Le fichier ne peut pas être lu car il a déjà été transcrit ou n'existe pas.", "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." "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)タスクのキャンセルに失敗しました。画面を更新し、再度ご確認ください。"
}, },
"label": { "label": {
"title": "Dictées", "title": "Dictées",
@ -247,7 +249,8 @@
"selectedTranscriptionist": "Transcriptionniste sélectionné", "selectedTranscriptionist": "Transcriptionniste sélectionné",
"poolTranscriptionist": "Liste de transcriptionniste", "poolTranscriptionist": "Liste de transcriptionniste",
"fileBackup": "(fr)File Backup", "fileBackup": "(fr)File Backup",
"downloadForBackup": "(fr)Download for backup" "downloadForBackup": "(fr)Download for backup",
"cancelDictation": "(fr)Cancel Dictation"
} }
}, },
"cardLicenseIssuePopupPage": { "cardLicenseIssuePopupPage": {