素材管理 (#306) #381

マージ済み
みてるぞ が 23 個のコミットを feature/306 から main へマージ 2026-06-28 06:35:53 +09:00
3個のファイルの変更14行の追加12行の削除
コミット c9b22d346b の変更だけを表示してゐます - すべてのコミットを表示
-4
ファイルの表示
@@ -34,10 +34,6 @@ describe ('MaterialListPage', () => {
) )
}) })
expect (await screen.findByText ('素材はありません。')).toBeInTheDocument () expect (await screen.findByText ('素材はありません。')).toBeInTheDocument ()
expect (screen.getByRole ('link', { name: '新規素材を追加' })).toHaveAttribute (
'href',
'/materials/new',
)
}) })
it ('shows materials in the default card view', async () => { it ('shows materials in the default card view', async () => {
+2 -1
ファイルの表示
@@ -10,7 +10,7 @@ import FormField from '@/components/common/FormField'
import PageTitle from '@/components/common/PageTitle' import PageTitle from '@/components/common/PageTitle'
import Pagination from '@/components/common/Pagination' import Pagination from '@/components/common/Pagination'
import MainArea from '@/components/layout/MainArea' import MainArea from '@/components/layout/MainArea'
import { API_BASE_URL, SITE_TITLE } from '@/config' import { SITE_TITLE } from '@/config'
import { fetchMaterials, parseMaterialFilter } from '@/lib/materials' import { fetchMaterials, parseMaterialFilter } from '@/lib/materials'
import { materialsKeys } from '@/lib/queryKeys' import { materialsKeys } from '@/lib/queryKeys'
import { dateString, inputClass } from '@/lib/utils' import { dateString, inputClass } from '@/lib/utils'
@@ -409,6 +409,7 @@ const MaterialListPage: FC = () => {
<div className="flex flex-wrap items-center justify-between gap-3"> <div className="flex flex-wrap items-center justify-between gap-3">
<PageTitle className="my-auto"></PageTitle> <PageTitle className="my-auto"></PageTitle>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{/* TODO: 局所出力を可能にする */}
{/* <a {/* <a
href={`${ API_BASE_URL }/materials/download.zip?profile=legacy_drive`} href={`${ API_BASE_URL }/materials/download.zip?profile=legacy_drive`}
target="_blank" target="_blank"
+12 -7
ファイルの表示
@@ -2,7 +2,6 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react' import { useState } from 'react'
import { Helmet } from 'react-helmet-async' import { Helmet } from 'react-helmet-async'
import PrefetchLink from '@/components/PrefetchLink'
import FormField from '@/components/common/FormField' import FormField from '@/components/common/FormField'
import PageTitle from '@/components/common/PageTitle' import PageTitle from '@/components/common/PageTitle'
import MainArea from '@/components/layout/MainArea' import MainArea from '@/components/layout/MainArea'
@@ -33,9 +32,11 @@ const REASONS = [
'malware_or_dangerous_file', 'malware_or_dangerous_file',
'duplicate_or_low_quality', 'duplicate_or_low_quality',
'source_owner_request', 'source_owner_request',
'other'] 'other'] as const
const REASON_NAMES = { type MaterialSyncSuppressionReason = typeof REASONS[number]
const REASON_NAMES: Record<MaterialSyncSuppressionReason, string> = {
['copyright_high_risk']: '著作権への懸念', ['copyright_high_risk']: '著作権への懸念',
['copyright_takedown']: '著作者からの申出', ['copyright_takedown']: '著作者からの申出',
['adult_or_sensitive']: '成人向け', ['adult_or_sensitive']: '成人向け',
@@ -43,7 +44,11 @@ const REASON_NAMES = {
['malware_or_dangerous_file']: '危険なソフトウェア', ['malware_or_dangerous_file']: '危険なソフトウェア',
['duplicate_or_low_quality']: '重複', ['duplicate_or_low_quality']: '重複',
['source_owner_request']: '同期元管理者からの申出', ['source_owner_request']: '同期元管理者からの申出',
['other']: 'その他' } ['other']: 'その他' } as const
const reasonName = (reason: string): string =>
REASON_NAMES[reason as MaterialSyncSuppressionReason] ?? reason
const MaterialSyncSuppressionsPage: FC = () => { const MaterialSyncSuppressionsPage: FC = () => {
@@ -53,7 +58,7 @@ const MaterialSyncSuppressionsPage: FC = () => {
const [sourceUri, setSourceUri] = useState ('') const [sourceUri, setSourceUri] = useState ('')
const [drivePath, setDrivePath] = useState ('') const [drivePath, setDrivePath] = useState ('')
const [driveFileId, setDriveFileId] = useState ('') const [driveFileId, setDriveFileId] = useState ('')
const [reason, setReason] = useState (REASONS[0]) const [reason, setReason] = useState<MaterialSyncSuppressionReason> (REASONS[0])
const { data, isError, isLoading } = useQuery ({ const { data, isError, isLoading } = useQuery ({
queryKey: materialsKeys.suppressions (), queryKey: materialsKeys.suppressions (),
@@ -146,7 +151,7 @@ const MaterialSyncSuppressionsPage: FC = () => {
{({ invalid }) => ( {({ invalid }) => (
<select <select
value={reason} value={reason}
onChange={e => setReason (e.target.value)} onChange={e => setReason (e.target.value as MaterialSyncSuppressionReason)}
className={inputClass (invalid)}> className={inputClass (invalid)}>
{REASONS.map (value => ( {REASONS.map (value => (
<option key={value} value={value}> <option key={value} value={value}>
@@ -185,7 +190,7 @@ const MaterialSyncSuppressionsPage: FC = () => {
{suppression.normalizedSourceKey} {suppression.normalizedSourceKey}
</div> </div>
<div className="mt-2 text-sm text-stone-600 dark:text-stone-400"> <div className="mt-2 text-sm text-stone-600 dark:text-stone-400">
: {REASON_NAMES[suppression.reason]} / : {reasonName (suppression.reason)} /
: {dateString (suppression.createdAt)} : {dateString (suppression.createdAt)}
</div> </div>
</article>))} </article>))}