このコミットが含まれているのは:
@@ -11,19 +11,20 @@ import { toast } from '@/components/ui/use-toast'
|
||||
import { SITE_TITLE } from '@/config'
|
||||
import { createMaterialSyncSuppression, fetchMaterialSyncSuppressions } from '@/lib/materials'
|
||||
import { materialsKeys } from '@/lib/queryKeys'
|
||||
import { dateString, inputClass } from '@/lib/utils'
|
||||
import { localisedDateString, inputClass } from '@/lib/utils'
|
||||
import { useUITranslation } from '@/lib/useUITranslation'
|
||||
|
||||
import type { FC, FormEvent } from 'react'
|
||||
|
||||
import type { MaterialSyncSuppressionSourceKind } from '@/types'
|
||||
|
||||
const SOURCE_KIND_LABELS: Record<MaterialSyncSuppressionSourceKind, string> = {
|
||||
uri: 'URI',
|
||||
google_drive_path: 'Google Drive ファイル',
|
||||
google_drive_path_prefix: 'Google Drive フォルダ',
|
||||
google_drive_file: 'Google Drive ファイル Id.',
|
||||
legacy_drive_path: '汎用ファイル',
|
||||
legacy_drive_path_prefix: '汎用フォルダ' }
|
||||
uri: 'suppressions.sources.uri',
|
||||
google_drive_path: 'suppressions.sources.google_drive_path',
|
||||
google_drive_path_prefix: 'suppressions.sources.google_drive_path_prefix',
|
||||
google_drive_file: 'suppressions.sources.google_drive_file',
|
||||
legacy_drive_path: 'suppressions.sources.legacy_drive_path',
|
||||
legacy_drive_path_prefix: 'suppressions.sources.legacy_drive_path_prefix' }
|
||||
|
||||
const REASONS = [
|
||||
'copyright_high_risk',
|
||||
@@ -37,23 +38,9 @@ const REASONS = [
|
||||
|
||||
type MaterialSyncSuppressionReason = typeof REASONS[number]
|
||||
|
||||
const REASON_NAMES: Record<MaterialSyncSuppressionReason, string> = {
|
||||
['copyright_high_risk']: '著作権への懸念',
|
||||
['copyright_takedown']: '著作者からの申出',
|
||||
['adult_or_sensitive']: '成人向け',
|
||||
['personal_information']: '個人情報',
|
||||
['malware_or_dangerous_file']: '危険なソフトウェア',
|
||||
['duplicate_or_low_quality']: '重複',
|
||||
['source_owner_request']: '同期元管理者からの申出',
|
||||
['other']: 'その他' } as const
|
||||
|
||||
|
||||
const reasonName = (reason: string): string =>
|
||||
REASON_NAMES[reason as MaterialSyncSuppressionReason] ?? reason
|
||||
|
||||
|
||||
const MaterialSyncSuppressionsPage: FC = () => {
|
||||
const locale = useLocale ()
|
||||
const { message, label } = useUITranslation ('materials')
|
||||
const qc = useQueryClient ()
|
||||
const [sourceKind, setSourceKind] =
|
||||
useState<MaterialSyncSuppressionSourceKind> ('uri')
|
||||
@@ -80,10 +67,10 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
setSourceUri ('')
|
||||
setDrivePath ('')
|
||||
setDriveFileId ('')
|
||||
toast ({ title: '同期元抑止を登録しました' })
|
||||
toast ({ title: label ('suppressions.registered') })
|
||||
},
|
||||
onError: () => {
|
||||
toast ({ title: '同期元抑止の登録に失敗しました' })
|
||||
toast ({ title: label ('suppressions.registerFailed') })
|
||||
}})
|
||||
|
||||
const handleSubmit = (event: FormEvent) => {
|
||||
@@ -96,11 +83,11 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
return (
|
||||
<MainArea>
|
||||
<Helmet>
|
||||
<title>{`素材同期抑止 | ${ SITE_TITLE }`}</title>
|
||||
<title>{message ('suppressions.title').text} | {SITE_TITLE}</title>
|
||||
</Helmet>
|
||||
|
||||
<div className="space-y-5">
|
||||
<PageTitle>同期抑止</PageTitle>
|
||||
<PageTitle>{label ('suppressions.heading')}</PageTitle>
|
||||
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
@@ -108,21 +95,21 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
text-stone-900 dark:border-stone-700 dark:bg-stone-900
|
||||
dark:text-stone-100">
|
||||
<div className="space-y-3">
|
||||
<FormField label="同期元種別">
|
||||
<FormField label={label ('suppressions.sourceKind')}>
|
||||
{({ invalid }) => (
|
||||
<select
|
||||
value={sourceKind}
|
||||
onChange={e => setSourceKind (
|
||||
e.target.value as MaterialSyncSuppressionSourceKind)}
|
||||
className={inputClass (invalid)}>
|
||||
{Object.entries (SOURCE_KIND_LABELS).map (([value, label]) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
{Object.entries (SOURCE_KIND_LABELS).map (([value, key]) => (
|
||||
<option key={value} value={value} lang={message (key).language}>
|
||||
{message (key).text}
|
||||
</option>))}
|
||||
</select>)}
|
||||
</FormField>
|
||||
|
||||
<FormField label="同期元 URI">
|
||||
<FormField label={label ('suppressions.sourceUri')}>
|
||||
{({ invalid }) => (
|
||||
<input
|
||||
type="text"
|
||||
@@ -131,7 +118,7 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
className={inputClass (invalid)}/>)}
|
||||
</FormField>
|
||||
|
||||
<FormField label="Google Drive パス">
|
||||
<FormField label={label ('suppressions.drivePath')}>
|
||||
{({ invalid }) => (
|
||||
<input
|
||||
type="text"
|
||||
@@ -140,7 +127,7 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
className={inputClass (invalid)}/>)}
|
||||
</FormField>
|
||||
|
||||
<FormField label="Google Drive ファイル Id.">
|
||||
<FormField label={label ('suppressions.driveFileId')}>
|
||||
{({ invalid }) => (
|
||||
<input
|
||||
type="text"
|
||||
@@ -149,15 +136,16 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
className={inputClass (invalid)}/>)}
|
||||
</FormField>
|
||||
|
||||
<FormField label="事由">
|
||||
<FormField label={label ('suppressions.reason')}>
|
||||
{({ invalid }) => (
|
||||
<select
|
||||
value={reason}
|
||||
onChange={e => setReason (e.target.value as MaterialSyncSuppressionReason)}
|
||||
className={inputClass (invalid)}>
|
||||
{REASONS.map (value => (
|
||||
<option key={value} value={value}>
|
||||
{REASON_NAMES[value]}
|
||||
<option key={value} value={value}
|
||||
lang={message (`suppressions.reasons.${value}`).language}>
|
||||
{message (`suppressions.reasons.${value}`).text}
|
||||
</option>))}
|
||||
</select>)}
|
||||
</FormField>
|
||||
@@ -168,14 +156,14 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
className="mt-4 rounded bg-blue-600 px-4 py-2 text-white
|
||||
disabled:bg-gray-400"
|
||||
disabled={createMutation.isPending}>
|
||||
登録
|
||||
{label ('suppressions.register')}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
{isLoading && <p>Loading...</p>}
|
||||
{isLoading && <p>{label ('common:loading')}</p>}
|
||||
{isError && (
|
||||
<p className="text-red-600 dark:text-red-300">
|
||||
同期元抑止一覧の取得に失敗しました.
|
||||
{label ('suppressions.error')}
|
||||
</p>)}
|
||||
|
||||
<div className="space-y-3">
|
||||
@@ -186,14 +174,20 @@ const MaterialSyncSuppressionsPage: FC = () => {
|
||||
text-stone-900 shadow-sm dark:border-stone-700
|
||||
dark:bg-stone-900 dark:text-stone-100">
|
||||
<div className="font-medium">
|
||||
{SOURCE_KIND_LABELS[suppression.sourceKind]}
|
||||
{label (SOURCE_KIND_LABELS[suppression.sourceKind])}
|
||||
</div>
|
||||
<div className="break-all text-sm text-stone-700 dark:text-stone-300">
|
||||
{suppression.normalizedSourceKey}
|
||||
</div>
|
||||
<div className="mt-2 text-sm text-stone-600 dark:text-stone-400">
|
||||
事由: {reasonName (suppression.reason)} /
|
||||
登録: {dateString (suppression.createdAt)}
|
||||
{label ('suppressions.reasonPrefix')}
|
||||
{REASONS.includes (suppression.reason as MaterialSyncSuppressionReason)
|
||||
? label (`suppressions.reasons.${suppression.reason}`)
|
||||
: suppression.reason} /{' '}
|
||||
{label ('suppressions.registeredPrefix')}
|
||||
<time dateTime={suppression.createdAt} lang={locale}>
|
||||
{localisedDateString (suppression.createdAt, locale)}
|
||||
</time>
|
||||
</div>
|
||||
</article>))}
|
||||
</div>
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする