SAITO-PC-3\saito.k 3877a4670d Merge branch 'develop' into ccb
# Conflicts:
#	dictation_client/src/pages/UserListPage/index.tsx
2024-02-14 11:33:11 +09:00

1520 lines
56 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useCallback, useEffect, useState } from "react";
import { AppDispatch } from "app/store";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import styles from "styles/app.module.scss";
import Footer from "components/footer";
import Header from "components/header";
import {
listTasksAsync,
selectCurrentPage,
selectTasks,
selectTotal,
selectTotalPage,
DIRECTION,
DisplayInfoType,
INIT_DISPLAY_INFO,
SORTABLE_COLUMN,
selectDisplayInfo,
changeDisplayInfo,
getSortColumnAsync,
selectParamName,
selectDirection,
changeParamName,
changeDirection,
changeSelectedTask,
openFilePropertyInfo,
SortableColumnType,
changeAssignee,
listTypistsAsync,
listTypistGroupsAsync,
DirectionType,
selectIsLoading,
playbackAsync,
cancelAsync,
PRIORITY,
deleteTaskAsync,
isSortableColumnType,
isDirectionType,
} from "features/dictation";
import { getTranslationID } from "translation";
import { Task } from "api/api";
import { isAdminUser, isAuthorUser, isTypistUser } from "features/auth";
import { STATUS, LIMIT_TASK_NUM } from "../../features/dictation";
import uploaded from "../../assets/images/uploaded.svg";
import pending from "../../assets/images/pending.svg";
import inprogress from "../../assets/images/inprogress.svg";
import finished from "../../assets/images/finished.svg";
import backup from "../../assets/images/backup.svg";
import lock from "../../assets/images/lock.svg";
import progress_activit from "../../assets/images/progress_activit.svg";
import download from "../../assets/images/download.svg";
import open_in_new from "../../assets/images/open_in_new.svg";
import { DisPlayInfo } from "./displayInfo";
import { ChangeTranscriptionistPopup } from "./changeTranscriptionistPopup";
import { BackupPopup } from "./backupPopup";
import { FilePropertyPopup } from "./filePropertyPopup";
const DictationPage: React.FC = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
const isAdmin = isAdminUser();
const isAuthor = isAuthorUser();
const isTypist = isTypistUser();
const isNone = !isAuthor && !isTypist;
const isDeletableRole = isAdmin || isAuthor;
// popup制御関係
const [
isChangeTranscriptionistPopupOpen,
setIsChangeTranscriptionistPopupOpen,
] = useState(false);
const [isFilePropertyPopupOpen, setIsFilePropertyPopupOpen] = useState(false);
const [isBackupPopupOpen, setIsBackupPopupOpen] = useState(false);
const onChangeTranscriptionistPopupOpen = useCallback(
(task: Task) => {
dispatch(changeAssignee({ selected: task.assignees }));
dispatch(changeSelectedTask({ task }));
setIsChangeTranscriptionistPopupOpen(true);
},
[dispatch, setIsChangeTranscriptionistPopupOpen]
);
const onClickFileProperty = useCallback(
(task: Task) => {
dispatch(openFilePropertyInfo({ task }));
setIsFilePropertyPopupOpen(true);
},
[dispatch, setIsFilePropertyPopupOpen]
);
// 各カラムの表示/非表示
const displayColumn = useSelector(selectDisplayInfo);
// フィルターするステータス
const [filterUploaded, setFilterUploaded] = useState(true);
const [filterPending, setFilterPending] = useState(true);
const [filterInProgress, setFilterInProgress] = useState(true);
const [filterFinished, setFilterFinished] = useState(true);
const [filterBackup, setFilterBackup] = useState(false);
// ソート対象カラム
const sortableParamName = useSelector(selectParamName);
const sortDirection = useSelector(selectDirection);
const tasks = useSelector(selectTasks);
const total = useSelector(selectTotal);
const totalPage = useSelector(selectTotalPage);
const currentPage = useSelector(selectCurrentPage);
const isLoading = useSelector(selectIsLoading);
// ページネーションのボタンクリック時のアクション
const getFirstPage = useCallback(() => {
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,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
sortDirection,
sortableParamName,
]);
const getLastPage = useCallback(() => {
const filter = getFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
const lastPageOffset = (totalPage - 1) * LIMIT_TASK_NUM;
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: lastPageOffset,
filter,
direction: sortDirection,
paramName: sortableParamName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
}, [
dispatch,
totalPage,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
sortDirection,
sortableParamName,
]);
const getPrevPage = useCallback(() => {
const filter = getFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
const prevPageOffset = (currentPage - 2) * LIMIT_TASK_NUM;
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: prevPageOffset,
filter,
direction: sortDirection,
paramName: sortableParamName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
}, [
dispatch,
currentPage,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
sortDirection,
sortableParamName,
]);
const getNextPage = useCallback(() => {
const filter = getFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
const nextPageOffset = currentPage * LIMIT_TASK_NUM;
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: nextPageOffset,
filter,
direction: sortDirection,
paramName: sortableParamName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
}, [
dispatch,
currentPage,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
sortDirection,
sortableParamName,
]);
const updateSortColumn = useCallback(
(paramName: SortableColumnType) => {
const currentDirection =
sortableParamName === paramName && sortDirection === DIRECTION.ASC
? DIRECTION.DESC
: DIRECTION.ASC;
dispatch(changeDirection({ direction: currentDirection }));
dispatch(changeParamName({ paramName }));
// ローカルストレージにソート情報を保存する
localStorage.setItem(
"sortCriteria",
`direction:${currentDirection},paramName:${paramName}`
);
const filter = getFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: 0,
filter,
direction: currentDirection,
paramName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
},
[
dispatch,
sortableParamName,
sortDirection,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
]
);
const getFilter = (
hasUploaded: boolean,
hasInProgress: boolean,
hasPending: boolean,
hasFinished: boolean,
hasBackup: boolean
): string | undefined => {
const filterStatus = [];
if (hasUploaded) {
filterStatus.push(STATUS.UPLOADED);
}
if (hasInProgress) {
filterStatus.push(STATUS.INPROGRESS);
}
if (hasPending) {
filterStatus.push(STATUS.PENDING);
}
if (hasFinished) {
filterStatus.push(STATUS.FINISHED);
}
if (hasBackup) {
filterStatus.push(STATUS.BACKUP);
}
if (filterStatus.length === 0) {
return undefined;
}
return filterStatus.join(",");
};
// ステータスフィルターの変更時アクション
const updateFilter = useCallback(
(
hasUploaded: boolean,
hasInProgress: boolean,
hasPending: boolean,
hasFinished: boolean,
hasBackup: boolean
) => {
const filter = getFilter(
hasUploaded,
hasInProgress,
hasPending,
hasFinished,
hasBackup
);
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: 0,
filter,
direction: sortDirection,
paramName: sortableParamName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
},
[dispatch, sortDirection, sortableParamName]
);
const onPlayBack = useCallback(
async (audioFileId: number) => {
if (
/* eslint-disable-next-line no-alert */
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
) {
return;
}
const { meta } = await dispatch(
playbackAsync({
audioFileId,
direction: sortDirection,
paramName: sortableParamName,
})
);
if (meta.requestStatus === "fulfilled") {
// ローカルストレージにソート情報を削除する
localStorage.removeItem("sortCriteria");
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());
const url = `${
import.meta.env.VITE_DESK_TOP_APP_SCHEME
}:playback?audioId=${audioFileId}`;
const a = document.createElement("a");
a.href = url;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
},
[
dispatch,
filterBackup,
filterFinished,
filterInProgress,
filterPending,
filterUploaded,
sortDirection,
sortableParamName,
t,
]
);
const onClosePopup = useCallback(
(isChanged: boolean) => {
if (isChanged) {
const filter = getFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: 0,
filter,
direction: sortDirection,
paramName: sortableParamName,
})
);
}
setIsChangeTranscriptionistPopupOpen(false);
},
[
dispatch,
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
filterBackup,
sortDirection,
sortableParamName,
]
);
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(() => {
setIsBackupPopupOpen(false);
}, []);
const onClickBackup = useCallback(() => {
setIsBackupPopupOpen(true);
}, []);
const onCloseFilePropertyPopup = useCallback(() => {
setIsFilePropertyPopupOpen(false);
}, []);
const sortIconClass = (
currentParam: SortableColumnType,
currentDirection: DirectionType,
column: SortableColumnType
) => {
if (currentParam !== column) {
return "";
}
if (currentDirection === DIRECTION.DESC) {
return styles.isActiveZa;
}
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 () => {
const displayInfoValue = localStorage.getItem("displayInfo");
let displayInfo: DisplayInfoType;
if (displayInfoValue) {
displayInfo = JSON.parse(displayInfoValue);
} else {
displayInfo = INIT_DISPLAY_INFO;
localStorage.setItem("displayInfo", JSON.stringify(displayInfo));
}
dispatch(changeDisplayInfo({ column: displayInfo }));
const filter = getFilter(true, true, true, true, false);
const { meta, payload } = await dispatch(getSortColumnAsync());
if (
meta.requestStatus === "fulfilled" &&
payload &&
!("error" in payload)
) {
// ソート情報をローカルストレージから取得する
const sortColumnValue = localStorage.getItem("sortCriteria") ?? "";
let direction: DirectionType;
let paramName: SortableColumnType;
if (sortColumnValue === "") {
direction = payload.direction;
paramName = payload.paramName;
} else {
// ソート情報をDirectionとParamNameに分割する
const sortColumn = sortColumnValue?.split(",");
const localStorageDirection = sortColumn[0].split(":")[1] ?? "";
const localStorageParamName = sortColumn[1]?.split(":")[1] ?? "";
// 正常なソート情報がローカルストレージに存在する場合はローカルストレージの情報を使用する
direction = isDirectionType(localStorageDirection)
? localStorageDirection
: payload.direction;
paramName = isSortableColumnType(localStorageParamName)
? localStorageParamName
: payload.paramName;
dispatch(changeDirection({ direction }));
dispatch(changeParamName({ paramName }));
}
dispatch(
listTasksAsync({
limit: LIMIT_TASK_NUM,
offset: 0,
filter,
direction,
paramName,
})
);
dispatch(listTypistsAsync());
dispatch(listTypistGroupsAsync());
}
})();
}, [dispatch]);
return (
<>
<BackupPopup isOpen={isBackupPopupOpen} onClose={onCloseBackupPopup} />
<FilePropertyPopup
isOpen={isFilePropertyPopupOpen}
onClose={onCloseFilePropertyPopup}
/>
<ChangeTranscriptionistPopup
isOpen={isChangeTranscriptionistPopupOpen}
onClose={onClosePopup}
/>
<div className={styles.wrap}>
<Header />
<main className={styles.main}>
<div className="">
<div className={styles.pageHeader}>
<h1 className={styles.pageTitle}>
{t(getTranslationID("dictationPage.label.title"))}
</h1>
</div>
<section className={styles.dictation}>
<div>
<DisPlayInfo />
<ul className={styles.tableFilter}>
<li>{t(getTranslationID("dictationPage.label.filter"))}:</li>
<li>
<label htmlFor="uploaded">
<input
id="uploaded"
type="checkbox"
value="flUploaded"
className={styles.formCheck}
checked={filterUploaded}
disabled={isLoading}
onChange={(e) => {
setFilterUploaded(e.target.checked);
updateFilter(
e.target.checked,
filterInProgress,
filterPending,
filterFinished,
filterBackup
);
}}
/>
{t(getTranslationID("dictationPage.label.uploaded"))}
</label>
</li>
<li>
<label htmlFor="inProgress">
<input
id="inProgress"
type="checkbox"
value="flInProgress"
className={styles.formCheck}
checked={filterInProgress}
disabled={isLoading}
onChange={(e) => {
setFilterInProgress(e.target.checked);
updateFilter(
filterUploaded,
e.target.checked,
filterPending,
filterFinished,
filterBackup
);
}}
/>
{t(getTranslationID("dictationPage.label.inProgress"))}
</label>
</li>
<li>
<label htmlFor="pending">
<input
id="pending"
type="checkbox"
value="flPending"
className={styles.formCheck}
checked={filterPending}
disabled={isLoading}
onChange={(e) => {
setFilterPending(e.target.checked);
updateFilter(
filterUploaded,
filterInProgress,
e.target.checked,
filterFinished,
filterBackup
);
}}
/>
{t(getTranslationID("dictationPage.label.pending"))}
</label>
</li>
<li>
<label htmlFor="finished">
<input
id="finished"
type="checkbox"
value="flFinished"
className={styles.formCheck}
checked={filterFinished}
disabled={isLoading}
onChange={(e) => {
setFilterFinished(e.target.checked);
updateFilter(
filterUploaded,
filterInProgress,
filterPending,
e.target.checked,
filterBackup
);
}}
/>
{t(getTranslationID("dictationPage.label.finished"))}
</label>
</li>
<li>
<label htmlFor="backup">
<input
id="backup"
type="checkbox"
value="flBackup"
className={styles.formCheck}
checked={filterBackup}
disabled={isLoading}
onChange={(e) => {
setFilterBackup(e.target.checked);
updateFilter(
filterUploaded,
filterInProgress,
filterPending,
filterFinished,
e.target.checked
);
}}
/>
{t(getTranslationID("dictationPage.label.backup"))}
</label>
</li>
</ul>
<div className={styles.tableWrap}>
<table className={`${styles.table} ${styles.dictation}`}>
<tr className={styles.tableHeader}>
<th className={styles.clm0}>{/** th is empty */}</th>
{displayColumn.JobNumber && (
<th className={styles.clm1}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.JobNumber
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.JobNumber)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.jobNumber")
)}
</a>
</th>
)}
{displayColumn.Status && (
<th className={styles.clm2}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.Status
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.Status)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(getTranslationID("dictationPage.label.status"))}
</a>
</th>
)}
{displayColumn.Priority && (
<th className={styles.clm3}>Priority</th>
)}
{displayColumn.Encryption && (
<th className={styles.clm4}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.Encryption
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.Encryption)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.encryption")
)}
</a>
</th>
)}
{displayColumn.AuthorId && (
<th className={styles.clm5}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.AuthorId
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.AuthorId)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.authorId")
)}
</a>
</th>
)}
{displayColumn.WorkType && (
<th className={styles.clm6}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.WorkType
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.WorkType)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.workType")
)}
</a>
</th>
)}
{displayColumn.FileName && (
<th className={styles.clm7}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.FileName
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileName)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.fileName")
)}
</a>
</th>
)}
{displayColumn.FileLength && (
<th className={styles.clm8}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.FileLength
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileLength)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.fileLength")
)}
</a>
</th>
)}
{displayColumn.FileSize && (
<th className={styles.clm9}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.FileSize
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.FileSize)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.fileSize")
)}
</a>
</th>
)}
{displayColumn.RecordingStartedDate && (
<th className={styles.clm10}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.RecordingStartedDate
)}`}
onClick={() =>
updateSortColumn(
SORTABLE_COLUMN.RecordingStartedDate
)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID(
"dictationPage.label.recordingStartedDate"
)
)}
</a>
</th>
)}
{displayColumn.RecordingFinishedDate && (
<th className={styles.clm11}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.RecordingFinishedDate
)}`}
onClick={() =>
updateSortColumn(
SORTABLE_COLUMN.RecordingFinishedDate
)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID(
"dictationPage.label.recordingFinishedDate"
)
)}
</a>
</th>
)}
{displayColumn.UploadDate && (
<th className={styles.clm12}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.UploadDate
)}`}
onClick={() =>
updateSortColumn(SORTABLE_COLUMN.UploadDate)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID("dictationPage.label.uploadDate")
)}
</a>
</th>
)}
{displayColumn.TranscriptionStartedDate && (
<th className={styles.clm13}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.TranscriptionStartedDate
)}`}
onClick={() =>
updateSortColumn(
SORTABLE_COLUMN.TranscriptionStartedDate
)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID(
"dictationPage.label.transcriptionStartedDate"
)
)}
</a>
</th>
)}
{displayColumn.TranscriptionFinishedDate && (
<th className={styles.clm14}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${styles.hasSort} ${sortIconClass(
sortableParamName,
sortDirection,
SORTABLE_COLUMN.TranscriptionFinishedDate
)}`}
onClick={() =>
updateSortColumn(
SORTABLE_COLUMN.TranscriptionFinishedDate
)
}
style={{
pointerEvents: isLoading ? "none" : "auto",
}}
>
{t(
getTranslationID(
"dictationPage.label.transcriptionFinishedDate"
)
)}
</a>
</th>
)}
{displayColumn.Transcriptionist && (
<th className={styles.clm15}>
{t(
getTranslationID(
"dictationPage.label.transcriptionist"
)
)}
</th>
)}
{displayColumn.Comment && (
<th className={styles.clm16}>
{t(getTranslationID("dictationPage.label.comment"))}
</th>
)}
{displayColumn.OptionItem1 && (
<th className={styles.op1}>
{t(
getTranslationID("dictationPage.label.optionItem1")
)}
</th>
)}
{displayColumn.OptionItem2 && (
<th className={styles.op2}>
{t(
getTranslationID("dictationPage.label.optionItem2")
)}
</th>
)}
{displayColumn.OptionItem3 && (
<th className={styles.op3}>
{t(
getTranslationID("dictationPage.label.optionItem3")
)}
</th>
)}
{displayColumn.OptionItem4 && (
<th className={styles.op4}>
{t(
getTranslationID("dictationPage.label.optionItem4")
)}
</th>
)}
{displayColumn.OptionItem5 && (
<th className={styles.op5}>
{t(
getTranslationID("dictationPage.label.optionItem5")
)}
</th>
)}
{displayColumn.OptionItem6 && (
<th className={styles.op6}>
{t(
getTranslationID("dictationPage.label.optionItem6")
)}
</th>
)}
{displayColumn.OptionItem7 && (
<th className={styles.op7}>
{t(
getTranslationID("dictationPage.label.optionItem7")
)}
</th>
)}
{displayColumn.OptionItem8 && (
<th className={styles.op8}>
{t(
getTranslationID("dictationPage.label.optionItem8")
)}
</th>
)}
{displayColumn.OptionItem9 && (
<th className={styles.op9}>
{t(
getTranslationID("dictationPage.label.optionItem9")
)}
</th>
)}
{displayColumn.OptionItem10 && (
<th className={styles.op10}>
{t(
getTranslationID("dictationPage.label.optionItem10")
)}
</th>
)}
</tr>
{(isChangeTranscriptionistPopupOpen || !isLoading) &&
tasks.length !== 0 &&
tasks.map((x) => (
<tr key={x.audioFileId}>
<td className={styles.clm0}>
<ul className={styles.menuInTable}>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={isNone ? styles.isDisable : ""}
onClick={() => onPlayBack(x.audioFileId)}
>
{t(
getTranslationID(
"dictationPage.label.playback"
)
)}
</a>
</li>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a onClick={() => onClickFileProperty(x)}>
{t(
getTranslationID(
"dictationPage.label.fileProperty"
)
)}
</a>
</li>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={
x.status !== STATUS.UPLOADED ||
!(isAdmin || isAuthor)
? styles.isDisable
: ""
}
onClick={() => {
onChangeTranscriptionistPopupOpen(x);
}}
>
{t(
getTranslationID(
"dictationPage.label.changeTranscriptionist"
)
)}
</a>
</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>
{/* 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"
)
)}
</a>
</li>
</ul>
</td>
{displayColumn.JobNumber && (
<td className={styles.clm1}>{x.jobNumber}</td>
)}
{displayColumn.Status && (
<td className={styles.clm2}>
{(() => {
switch (x.status) {
case STATUS.UPLOADED:
return (
<img src={uploaded} alt="Uploaded" />
);
case STATUS.PENDING:
return <img src={pending} alt="Pending" />;
case STATUS.FINISHED:
return (
<img src={finished} alt="Finished" />
);
case STATUS.INPROGRESS:
return (
<img src={inprogress} alt="InProgress" />
);
default:
return <img src={backup} alt="Backup" />;
}
})()}
{x.status}
</td>
)}
{displayColumn.Priority && (
<td
className={styles.clm3}
style={{
color: x.priority === "01" ? "red" : undefined,
}}
>
{x.priority === "01"
? PRIORITY.HIGH
: PRIORITY.NORMAL}
</td>
)}
{displayColumn.Encryption && (
<td className={styles.clm4}>
{x.isEncrypted ? (
<img src={lock} alt="encrypted" />
) : (
<>-</>
)}
</td>
)}
{displayColumn.AuthorId && (
<td className={styles.clm5}>{x.authorId}</td>
)}
{displayColumn.WorkType && (
<td className={styles.clm6}>{x.workType}</td>
)}
{displayColumn.FileName && (
<td className={styles.clm7}>
{x.fileName.replace(".zip", "")}
</td>
)}
{displayColumn.FileLength && (
<td className={styles.clm8}>{x.audioDuration}</td>
)}
{displayColumn.FileSize && (
<td className={styles.clm9}>{x.fileSize}</td>
)}
{displayColumn.RecordingStartedDate && (
<td className={styles.clm10}>
{x.audioCreatedDate}
</td>
)}
{displayColumn.RecordingFinishedDate && (
<td className={styles.clm11}>
{x.audioFinishedDate}
</td>
)}
{displayColumn.UploadDate && (
<td className={styles.clm12}>
{x.audioUploadedDate}
</td>
)}
{displayColumn.TranscriptionStartedDate && (
<td className={styles.clm13}>
{x.transcriptionStartedDate}
</td>
)}
{displayColumn.TranscriptionFinishedDate && (
<td className={styles.clm14}>
{x.transcriptionFinishedDate}
</td>
)}
{displayColumn.Transcriptionist && (
<td
className={`${styles.txWsline} ${styles.clm15}`}
>
{x.assignees.map((a, i) => (
<>
{a.typistName}
{i !== x.assignees.length - 1 && <br />}
</>
))}
</td>
)}
{displayColumn.Comment && (
<td className={styles.clm16}>{x.comment}</td>
)}
{displayColumn.OptionItem1 && (
<td className={styles.op1}>
{x.optionItemList[0].optionItemValue}
</td>
)}
{displayColumn.OptionItem2 && (
<td className={styles.op2}>
{x.optionItemList[1].optionItemValue}
</td>
)}
{displayColumn.OptionItem3 && (
<td className={styles.op3}>
{x.optionItemList[2].optionItemValue}
</td>
)}
{displayColumn.OptionItem4 && (
<td className={styles.op4}>
{x.optionItemList[3].optionItemValue}
</td>
)}
{displayColumn.OptionItem5 && (
<td className={styles.op5}>
{x.optionItemList[4].optionItemValue}
</td>
)}
{displayColumn.OptionItem6 && (
<td className={styles.op6}>
{x.optionItemList[5].optionItemValue}
</td>
)}
{displayColumn.OptionItem7 && (
<td className={styles.op7}>
{x.optionItemList[6].optionItemValue}
</td>
)}
{displayColumn.OptionItem8 && (
<td className={styles.op8}>
{x.optionItemList[7].optionItemValue}
</td>
)}
{displayColumn.OptionItem9 && (
<td className={styles.op9}>
{x.optionItemList[8].optionItemValue}
</td>
)}
{displayColumn.OptionItem10 && (
<td className={styles.op10}>
{x.optionItemList[9].optionItemValue}
</td>
)}
</tr>
))}
</table>
{(isChangeTranscriptionistPopupOpen || !isLoading) &&
tasks.length === 0 && (
<p style={{ margin: "10px", textAlign: "center" }}>
{t(getTranslationID("common.message.listEmpty"))}
</p>
)}
</div>
{isLoading && (
<img
style={{ position: "sticky" }}
src={progress_activit}
className={styles.icLoading}
alt="Loading"
/>
)}
{/** pagenation */}
<div className={styles.pagenation}>
<nav className={styles.pagenationNav}>
<span className={styles.pagenationTotal}>{`${total} ${t(
getTranslationID("dictationPage.label.title")
)}`}</span>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${
!isLoading && currentPage !== 1 ? styles.isActive : ""
}`}
onClick={getFirstPage}
>
«
</a>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${
!isLoading && currentPage !== 1 ? styles.isActive : ""
}`}
onClick={getPrevPage}
>
</a>
{`${currentPage} of ${totalPage}`}
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${
!isLoading && currentPage < totalPage
? styles.isActive
: ""
}`}
onClick={getNextPage}
>
</a>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
className={`${
!isLoading && currentPage < totalPage
? styles.isActive
: ""
}`}
onClick={getLastPage}
>
»
</a>
</nav>
</div>
<ul className={`${styles.menuAction} ${styles.alignRight}`}>
<li className={styles.alignLeft}>
<a
// TODO: 将来的に正式なURLに変更する
href="/dictations"
className={`${styles.menuLink} ${styles.isActive}`}
target="_blank"
>
{t(getTranslationID("dictationPage.label.applications"))}
<img
src={open_in_new}
alt=""
className={styles.menuIcon}
/>
</a>
</li>
<li>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
<a
onClick={onClickBackup}
className={`${styles.menuLink} ${
isAdmin ? styles.isActive : ""
}`}
>
<img src={download} alt="" className={styles.menuIcon} />
{t(getTranslationID("dictationPage.label.fileBackup"))}
</a>
</li>
</ul>
</div>
</section>
</div>
</main>
<Footer />
</div>
</>
);
};
export default DictationPage;