import { __ } from '@wordpress/i18n' import React, { useEffect, useMemo, useState } from 'react' import classnames from 'classnames' import { getSnippetType, isSnippetActive } from '../../../utils/snippets/snippets' import { buildUrl } from '../../../utils/urls' import { ListTable } from '../../common/ListTable' import { SnippetViewToggle } from '../../common/SnippetViewToggle' import { SnippetsCardGrid } from './SnippetsCardGrid' import { SnippetsTableNavigation, SnippetsTableToolbar } from './SnippetsTableControls' import { SearchResultsIndicator } from './SnippetsTableSearch' import { getTableColumns } from './TableColumns' import { useFilteredSnippets } from './WithFilteredSnippetsContext' import { INDEX_STATUS, useSnippetsFilters } from './WithSnippetsTableFilters' import { BULK_ACTIONS, TRASHED_BULK_ACTIONS, useApplyBulkAction } from './useApplyBulkAction' import type { ListTableAction, ListTableSortDirection } from '../../common/ListTable' import type { SnippetsTableAction } from './useApplyBulkAction' import type { Snippet } from '../../../types/Snippet' import type { SnippetView } from '../../../types/SnippetView' import type { ReactNode } from 'react' interface ManageTableSettings { hiddenColumns: Set truncateRowValues: boolean } const useManageTableSettings = (): ManageTableSettings => { const [hiddenColumns, setHiddenColumns] = useState( () => new Set(window.CODE_SNIPPETS_MANAGE?.hiddenColumns ?? []) ) const [truncateRowValues, setTruncateRowValues] = useState( () => 0 !== Number(window.CODE_SNIPPETS_MANAGE?.truncateRowValues ?? 1) ) useEffect(() => { const screenOptions = document.getElementById('adv-settings') if (!screenOptions) { return } const updateHiddenColumns = () => { setHiddenColumns( new Set(Array.from(screenOptions.querySelectorAll( '.hide-column-tog:not(:checked)' )) .map(toggle => toggle.value)) ) setTruncateRowValues( screenOptions.querySelector( '#snippets-table-truncate-row-values' )?.checked ?? true ) } updateHiddenColumns() screenOptions.addEventListener('change', updateHiddenColumns) return () => { screenOptions.removeEventListener('change', updateHiddenColumns) } }, []) return { hiddenColumns, truncateRowValues } } const NoItemsMessage = () => { const { currentType, currentTag, searchQuery } = useSnippetsFilters() const emptyMessage = currentType ? __("You don't have snippets of this type yet.", 'code-snippets') : __("You don't have any snippets yet.", 'code-snippets') return searchQuery || currentTag ? <> {__('No snippets were found matching the current search query.', 'code-snippets')} {__(' Please enter a new query or use the "Clear Filters" button above.', 'code-snippets')} : <> {emptyMessage}{' '} {__('Add a new snippet.', 'code-snippets')} } const getRowClassName = ( snippet: Snippet, activeByCondition: Map ): string => classnames( 'snippet', `snippet ${isSnippetActive(snippet, activeByCondition) ? 'active' : 'inactive'}-snippet`, `${getSnippetType(snippet)}-snippet`, `${snippet.scope}-snippet`, { 'trashed-snippet': snippet.trashed } ) interface SnippetsViewProps { snippetView: SnippetView setSnippetView: (view: SnippetView) => void snippets: Snippet[] actions: ListTableAction[] doAction: (action: SnippetsTableAction | undefined, selected: Set) => Promise extraTableNav: (which: 'top' | 'bottom') => ReactNode hiddenColumns: Set truncateRowValues: boolean } const SnippetsView: React.FC = ({ snippetView, setSnippetView, snippets, actions, doAction, extraTableNav, hiddenColumns, truncateRowValues }) => { const { activeByCondition } = useFilteredSnippets() const columns = useMemo(() => getTableColumns(hiddenColumns), [hiddenColumns]) const itemsPerPage = window.CODE_SNIPPETS_MANAGE?.snippetsPerPage const pageCount = itemsPerPage && Math.ceil(snippets.length / itemsPerPage) const endTableNav = (which: 'top' | 'bottom') => 'top' === which ? : null return 'card' === snippetView ? } beforeGrid={} /> : snippet.id} initialSort={getInitialSort()} className={classnames({ 'truncate-row-values': truncateRowValues })} columns={columns} actions={actions} doAction={doAction} totalPages={pageCount} extraTableNav={extraTableNav} selectAllControl endTableNav={endTableNav} rowClassName={snippet => getRowClassName(snippet, activeByCondition)} noItems={} beforeTable={} /> } /** * The "Snippets List Order" setting names a default ordering for the table, * which sorting is now expressed through columns. Map one to the other so the * setting still decides how the list opens; clicking a heading overrides it for * the rest of the visit, as it does for any other starting order. */ const LIST_ORDER_SORTS: Record = { 'priority-asc': { columnId: 'priority', direction: 'asc' }, 'name-asc': { columnId: 'name', direction: 'asc' }, 'name-desc': { columnId: 'name', direction: 'desc' }, 'modified-desc': { columnId: 'date', direction: 'desc' }, 'modified-asc': { columnId: 'date', direction: 'asc' } } const getInitialSort = () => LIST_ORDER_SORTS[window.CODE_SNIPPETS_MANAGE?.listOrder ?? ''] ?? undefined export interface SnippetsListTableProps { snippetView: SnippetView setSnippetView: (view: SnippetView) => void } export const SnippetsListTable: React.FC = ({ snippetView, setSnippetView }) => { const { snippetsByStatus } = useFilteredSnippets() const { currentStatus, setCurrentStatus } = useSnippetsFilters() const { hiddenColumns, truncateRowValues } = useManageTableSettings() const currentSnippets = useMemo( () => snippetsByStatus.get(currentStatus) ?? [], [snippetsByStatus, currentStatus] ) const applyBulkAction = useApplyBulkAction(currentSnippets) useEffect(() => { if (INDEX_STATUS !== currentStatus && !snippetsByStatus.has(currentStatus)) { setCurrentStatus(INDEX_STATUS) } }, [currentStatus, setCurrentStatus, snippetsByStatus]) const extraTableNav = (which: 'top' | 'bottom') => return ( <>
) }