feat: подсправочник показывается целиком при выборе привязанной строки
This commit is contained in:
@@ -200,7 +200,7 @@ export default function SubdirectoryFieldConfig({
|
||||
</Select>
|
||||
{selectedSubdirectory && (
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Фильтр: «{selectedTable?.columns?.[selectedSubdirectory.parentColumnIndex ?? 0]?.name || '?'}» = «{selectedSubdirectory.childTable?.columns?.[selectedSubdirectory.childColumnIndex ?? 0]?.name || '?'}»
|
||||
Подсправочник показывается при выборе привязанных строк родителя.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { apiRequest } from '@/lib/queryClient';
|
||||
import TableFieldSelect from '@/components/TableFieldSelect';
|
||||
import TableFieldMultiSelect from '@/components/TableFieldMultiSelect';
|
||||
import type { DataTableRow, DataTableSubdirectory } from '@shared/schema';
|
||||
import type { DataTableSubdirectory } from '@shared/schema';
|
||||
|
||||
interface TableFieldValue {
|
||||
parentId?: string | null;
|
||||
@@ -67,23 +67,6 @@ export default function TableFieldWithSubdirectory({
|
||||
const showSubdirectory = !!opts.showSubdirectory;
|
||||
const subdirectoryId = opts.subdirectoryId as number | undefined;
|
||||
|
||||
const { data: tableData } = useQuery<{
|
||||
table: {
|
||||
rows: DataTableRow[];
|
||||
columns: Array<{ name: string }>;
|
||||
treeColumnIndex: number | null;
|
||||
treeDisplayColumnIndex: number | null;
|
||||
treeColumns: number[] | null;
|
||||
treeDisplayColumns: number[] | null;
|
||||
};
|
||||
}>({
|
||||
queryKey: ['/api/directories', tableId],
|
||||
enabled: !!tableId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
gcTime: 10 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { data: subdirectoriesData } = useQuery<{ subdirectories: DataTableSubdirectory[] }>({
|
||||
queryKey: ['/api/directories', tableId, 'subdirectories'],
|
||||
queryFn: async () => {
|
||||
@@ -100,24 +83,11 @@ export default function TableFieldWithSubdirectory({
|
||||
|
||||
const { parentId, childId } = parseTableValue(value);
|
||||
|
||||
const parentRow = useMemo(() => {
|
||||
if (!parentId || !tableData?.table?.rows) return null;
|
||||
return tableData.table.rows.find((r) => r.id.toString() === parentId) || null;
|
||||
}, [parentId, tableData]);
|
||||
|
||||
const isParentLinked = useMemo(() => {
|
||||
if (!subdirectory || !parentId) return false;
|
||||
return subdirectory.parentRowIds?.includes(Number(parentId)) ?? false;
|
||||
}, [subdirectory, parentId]);
|
||||
|
||||
const childFilter = useMemo(() => {
|
||||
if (!subdirectory || !parentRow) return undefined;
|
||||
const col = String(subdirectory.childColumnIndex ?? 0);
|
||||
const parentValue = parentRow.values?.[subdirectory.parentColumnIndex ?? 0] ?? '';
|
||||
if (!parentValue) return undefined;
|
||||
return { [col]: parentValue };
|
||||
}, [subdirectory, parentRow]);
|
||||
|
||||
const handleParentChange = (newParentId: string) => {
|
||||
onChange(serializeTableValue(newParentId || null, null));
|
||||
};
|
||||
@@ -144,8 +114,6 @@ export default function TableFieldWithSubdirectory({
|
||||
const childOptions = {
|
||||
...opts,
|
||||
tableId: subdirectory.childTableId,
|
||||
displayColumn: subdirectory.childTable?.columns?.[subdirectory.childColumnIndex ?? 0]?.name || undefined,
|
||||
filters: childFilter,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -158,7 +126,7 @@ export default function TableFieldWithSubdirectory({
|
||||
value={parentId || ''}
|
||||
onChange={handleParentChange}
|
||||
/>
|
||||
{isParentLinked && childFilter && (
|
||||
{isParentLinked && (
|
||||
<TableFieldSelect
|
||||
fieldId={fieldId}
|
||||
fieldCode={`${fieldCode}_sub`}
|
||||
|
||||
@@ -116,8 +116,6 @@ export default function TableEditor() {
|
||||
const [subdirectoriesOpen, setSubdirectoriesOpen] = useState(false);
|
||||
const [editingSubdirectory, setEditingSubdirectory] = useState<DataTableSubdirectory | null>(null);
|
||||
const [subdirectoryChildTableId, setSubdirectoryChildTableId] = useState<string>('none');
|
||||
const [subdirectoryParentColumnIndex, setSubdirectoryParentColumnIndex] = useState<number>(0);
|
||||
const [subdirectoryChildColumnIndex, setSubdirectoryChildColumnIndex] = useState<number>(0);
|
||||
const [subdirectoryParentRowIds, setSubdirectoryParentRowIds] = useState<Set<number>>(new Set());
|
||||
|
||||
const { filters, sort, setFilter, clearFilter, clearAll, setSort, clearSort, hasActiveFilters } = useColumnFilters();
|
||||
@@ -213,7 +211,7 @@ export default function TableEditor() {
|
||||
}, [rowEditorOpen, rowEditorInitialValues]);
|
||||
|
||||
const createSubdirectoryMutation = useMutation({
|
||||
mutationFn: async (payload: { childTableId: number; parentColumnIndex: number; childColumnIndex: number; parentRowIds: number[] }) => {
|
||||
mutationFn: async (payload: { childTableId: number; parentRowIds: number[] }) => {
|
||||
return apiRequest('POST', `/api/directories/${tableId}/subdirectories`, payload);
|
||||
},
|
||||
onSuccess: () => {
|
||||
@@ -230,7 +228,7 @@ export default function TableEditor() {
|
||||
});
|
||||
|
||||
const updateSubdirectoryMutation = useMutation({
|
||||
mutationFn: async ({ linkId, payload }: { linkId: number; payload: { childTableId?: number; parentColumnIndex?: number; childColumnIndex?: number; parentRowIds?: number[] } }) => {
|
||||
mutationFn: async ({ linkId, payload }: { linkId: number; payload: { childTableId?: number; parentRowIds?: number[] } }) => {
|
||||
return apiRequest('PATCH', `/api/directories/${tableId}/subdirectories/${linkId}`, payload);
|
||||
},
|
||||
onSuccess: () => {
|
||||
@@ -263,8 +261,6 @@ export default function TableEditor() {
|
||||
|
||||
const resetSubdirectoryForm = () => {
|
||||
setSubdirectoryChildTableId('none');
|
||||
setSubdirectoryParentColumnIndex(0);
|
||||
setSubdirectoryChildColumnIndex(0);
|
||||
setSubdirectoryParentRowIds(new Set());
|
||||
setEditingSubdirectory(null);
|
||||
};
|
||||
@@ -273,8 +269,6 @@ export default function TableEditor() {
|
||||
if (link) {
|
||||
setEditingSubdirectory(link);
|
||||
setSubdirectoryChildTableId(link.childTableId?.toString() || 'none');
|
||||
setSubdirectoryParentColumnIndex(link.parentColumnIndex ?? 0);
|
||||
setSubdirectoryChildColumnIndex(link.childColumnIndex ?? 0);
|
||||
setSubdirectoryParentRowIds(new Set(link.parentRowIds || []));
|
||||
} else {
|
||||
resetSubdirectoryForm();
|
||||
@@ -298,8 +292,6 @@ export default function TableEditor() {
|
||||
}
|
||||
const payload = {
|
||||
childTableId: childId,
|
||||
parentColumnIndex: subdirectoryParentColumnIndex,
|
||||
childColumnIndex: subdirectoryChildColumnIndex,
|
||||
parentRowIds: Array.from(subdirectoryParentRowIds),
|
||||
};
|
||||
if (editingSubdirectory?.id) {
|
||||
@@ -1793,10 +1785,9 @@ export default function TableEditor() {
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-medium text-sm truncate">{link.childTable?.name || `ID ${link.childTableId}`}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
по столбцу «{columns[link.parentColumnIndex ?? 0]?.name || '?'}» => «{link.childTable?.columns?.[link.childColumnIndex ?? 0]?.name || '?'}»
|
||||
{link.parentRowIds && link.parentRowIds.length > 0 && (
|
||||
<span className="ml-1">({link.parentRowIds.length} строк)</span>
|
||||
)}
|
||||
{link.parentRowIds && link.parentRowIds.length > 0
|
||||
? `Привязан к ${link.parentRowIds.length} строкам`
|
||||
: 'Не привязан к строкам'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -1833,41 +1824,6 @@ export default function TableEditor() {
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>Столбец родителя</Label>
|
||||
<Select value={String(subdirectoryParentColumnIndex)} onValueChange={(v) => setSubdirectoryParentColumnIndex(parseInt(v))}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Столбец" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{columns.map((col, idx) => (
|
||||
<SelectItem key={idx} value={String(idx)}>{col.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Столбец подсправочника</Label>
|
||||
<Select
|
||||
value={String(subdirectoryChildColumnIndex)}
|
||||
onValueChange={(v) => setSubdirectoryChildColumnIndex(parseInt(v))}
|
||||
disabled={subdirectoryChildTableId === 'none'}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Столбец" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{allTables
|
||||
.find((t) => t.id.toString() === subdirectoryChildTableId)
|
||||
?.columns?.map((col: any, idx: number) => (
|
||||
<SelectItem key={idx} value={String(idx)}>{col.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label className="mb-2 block">Строки родительского справочника</Label>
|
||||
<div className="border rounded p-2 max-h-48 overflow-y-auto space-y-1">
|
||||
|
||||
Reference in New Issue
Block a user