summaryrefslogtreecommitdiff
path: root/lib/pq/pq-review-table-new
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pq/pq-review-table-new')
-rw-r--r--lib/pq/pq-review-table-new/pq-filter-sheet.tsx247
-rw-r--r--lib/pq/pq-review-table-new/user-combobox.tsx2
-rw-r--r--lib/pq/pq-review-table-new/vendors-table-columns.tsx114
-rw-r--r--lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx26
-rw-r--r--lib/pq/pq-review-table-new/vendors-table.tsx17
5 files changed, 321 insertions, 85 deletions
diff --git a/lib/pq/pq-review-table-new/pq-filter-sheet.tsx b/lib/pq/pq-review-table-new/pq-filter-sheet.tsx
index ff1b890b..fe525a46 100644
--- a/lib/pq/pq-review-table-new/pq-filter-sheet.tsx
+++ b/lib/pq/pq-review-table-new/pq-filter-sheet.tsx
@@ -7,7 +7,7 @@ import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { CalendarIcon, ChevronRight, Search, X } from "lucide-react"
import { customAlphabet } from "nanoid"
-import { parseAsStringEnum, useQueryState } from "nuqs"
+import { parseAsStringEnum, useQueryState, parseAsString } from "nuqs"
import { Button } from "@/components/ui/button"
import {
@@ -40,8 +40,11 @@ const pqFilterSchema = z.object({
requesterName: z.string().optional(),
pqNumber: z.string().optional(),
vendorName: z.string().optional(),
+ vendorCode: z.string().optional(),
+ type: z.string().optional(),
+ projectName: z.string().optional(),
status: z.string().optional(),
- evaluationResult: z.string().optional(),
+ pqItems: z.string().optional(),
createdAtRange: z.object({
from: z.date().optional(),
to: z.date().optional(),
@@ -57,13 +60,13 @@ const pqStatusOptions = [
{ value: "REJECTED", label: "거부됨" },
]
-// 평가 결과 옵션 정의
-const evaluationResultOptions = [
- { value: "APPROVED", label: "승인" },
- { value: "SUPPLEMENT", label: "보완" },
- { value: "REJECTED", label: "불가" },
+// PQ 유형 옵션 정의
+const pqTypeOptions = [
+ { value: "GENERAL", label: "일반 PQ" },
+ { value: "PROJECT", label: "프로젝트 PQ" },
]
+
type PQFilterFormValues = z.infer<typeof pqFilterSchema>
interface PQFilterSheetProps {
@@ -106,6 +109,10 @@ export function PQFilterSheet({
// 현재 URL의 페이지 파라미터도 가져옴
const [page, setPage] = useQueryState("page", { defaultValue: "1" })
+ // DateRangePicker의 from/to 파라미터 직접 읽기
+ const [fromParam, setFromParam] = useQueryState("from", parseAsString.withDefault(""))
+ const [toParam, setToParam] = useQueryState("to", parseAsString.withDefault(""))
+
// 폼 상태 초기화
const form = useForm<PQFilterFormValues>({
resolver: zodResolver(pqFilterSchema),
@@ -113,8 +120,11 @@ export function PQFilterSheet({
requesterName: "",
pqNumber: "",
vendorName: "",
+ vendorCode: "",
+ type: "",
+ projectName: "",
status: "",
- evaluationResult: "",
+ pqItems: "",
createdAtRange: {
from: undefined,
to: undefined,
@@ -128,12 +138,22 @@ export function PQFilterSheet({
const currentFiltersString = JSON.stringify(filters);
// 패널이 열렸고, 필터가 있고, 마지막에 적용된 필터와 다를 때만 업데이트
- if (isOpen && filters && filters.length > 0 && currentFiltersString !== lastAppliedFilters.current) {
+ if (isOpen && (filters && filters.length > 0 || fromParam || toParam) && currentFiltersString !== lastAppliedFilters.current) {
setIsInitializing(true);
const formValues = { ...form.getValues() };
let formUpdated = false;
+ // DateRangePicker의 from/to 파라미터 처리
+ if (fromParam || toParam) {
+ formValues.createdAtRange = {
+ from: fromParam ? new Date(fromParam) : undefined,
+ to: toParam ? new Date(toParam) : undefined,
+ };
+ formUpdated = true;
+ }
+
+ // 기존 필터 처리
filters.forEach(filter => {
if (filter.id === "createdAt" && Array.isArray(filter.value) && filter.value.length > 0) {
formValues.createdAtRange = {
@@ -156,7 +176,7 @@ export function PQFilterSheet({
setIsInitializing(false);
}
- }, [filters, isOpen])
+ }, [filters, fromParam, toParam, isOpen])
// 현재 적용된 필터 카운트
const getActiveFilterCount = () => {
@@ -171,7 +191,13 @@ async function onSubmit(data: PQFilterFormValues) {
startTransition(async () => {
try {
// 필터 배열 생성
- const newFilters = []
+ const newFilters: Array<{
+ id: string;
+ value: string | string[];
+ type: string;
+ operator: string;
+ rowId: string;
+ }> = []
if (data.requesterName?.trim()) {
newFilters.push({
@@ -203,6 +229,36 @@ async function onSubmit(data: PQFilterFormValues) {
})
}
+ if (data.vendorCode?.trim()) {
+ newFilters.push({
+ id: "vendorCode",
+ value: data.vendorCode.trim(),
+ type: "text",
+ operator: "iLike",
+ rowId: generateId()
+ })
+ }
+
+ if (data.type?.trim()) {
+ newFilters.push({
+ id: "type",
+ value: data.type.trim(),
+ type: "select",
+ operator: "eq",
+ rowId: generateId()
+ })
+ }
+
+ if (data.projectName?.trim()) {
+ newFilters.push({
+ id: "projectName",
+ value: data.projectName.trim(),
+ type: "text",
+ operator: "iLike",
+ rowId: generateId()
+ })
+ }
+
if (data.status?.trim()) {
newFilters.push({
id: "status",
@@ -213,24 +269,24 @@ async function onSubmit(data: PQFilterFormValues) {
})
}
- if (data.evaluationResult?.trim()) {
+ if (data.pqItems?.trim()) {
newFilters.push({
- id: "evaluationResult",
- value: data.evaluationResult.trim(),
- type: "select",
- operator: "eq",
+ id: "pqItems",
+ value: data.pqItems.trim(),
+ type: "text",
+ operator: "iLike",
rowId: generateId()
})
}
- // 생성일 범위 추가
+ // PQ 전송일 범위 추가 (createdAt)
if (data.createdAtRange?.from) {
newFilters.push({
id: "createdAt",
value: [
data.createdAtRange.from.toISOString().split('T')[0],
- data.createdAtRange.to ? data.createdAtRange.to.toISOString().split('T')[0] : undefined
- ].filter(Boolean),
+ data.createdAtRange.to?.toISOString().split('T')[0]
+ ].filter((v): v is string => v !== undefined),
type: "date",
operator: "isBetween",
rowId: generateId()
@@ -289,8 +345,11 @@ async function onSubmit(data: PQFilterFormValues) {
requesterName: "",
pqNumber: "",
vendorName: "",
+ vendorCode: "",
+ type: "",
+ projectName: "",
status: "",
- evaluationResult: "",
+ pqItems: "",
createdAtRange: { from: undefined, to: undefined },
});
@@ -373,11 +432,11 @@ async function onSubmit(data: PQFilterFormValues) {
name="requesterName"
render={({ field }) => (
<FormItem>
- <FormLabel>요청자명</FormLabel>
+ <FormLabel>PQ/실사 요청자</FormLabel>
<FormControl>
<div className="relative">
<Input
- placeholder="요청자명 입력"
+ placeholder="PQ/실사 요청자 입력"
{...field}
className={cn(field.value && "pr-8", "bg-white")}
disabled={isInitializing}
@@ -411,11 +470,11 @@ async function onSubmit(data: PQFilterFormValues) {
name="pqNumber"
render={({ field }) => (
<FormItem>
- <FormLabel>PQ 번호</FormLabel>
+ <FormLabel>PQ No.</FormLabel>
<FormControl>
<div className="relative">
<Input
- placeholder="PQ 번호 입력"
+ placeholder="PQ No. 입력"
{...field}
className={cn(field.value && "pr-8", "bg-white")}
disabled={isInitializing}
@@ -449,7 +508,7 @@ async function onSubmit(data: PQFilterFormValues) {
name="vendorName"
render={({ field }) => (
<FormItem>
- <FormLabel>협력업체명</FormLabel>
+ <FormLabel>협력업체</FormLabel>
<FormControl>
<div className="relative">
<Input
@@ -482,7 +541,7 @@ async function onSubmit(data: PQFilterFormValues) {
/>
{/* PQ 상태 */}
- <FormField
+ {/* <FormField
control={form.control}
name="status"
render={({ field }) => (
@@ -527,15 +586,15 @@ async function onSubmit(data: PQFilterFormValues) {
<FormMessage />
</FormItem>
)}
- />
+ /> */}
- {/* 평가 결과 */}
+ {/* PQ 유형 */}
<FormField
control={form.control}
- name="evaluationResult"
+ name="type"
render={({ field }) => (
<FormItem>
- <FormLabel>평가 결과</FormLabel>
+ <FormLabel>PQ 유형</FormLabel>
<Select
value={field.value}
onValueChange={field.onChange}
@@ -544,7 +603,7 @@ async function onSubmit(data: PQFilterFormValues) {
<FormControl>
<SelectTrigger className={cn(field.value && "pr-8", "bg-white")}>
<div className="flex justify-between w-full">
- <SelectValue placeholder="평가 결과 선택" />
+ <SelectValue placeholder="PQ 유형 선택" />
{field.value && (
<Button
type="button"
@@ -553,7 +612,7 @@ async function onSubmit(data: PQFilterFormValues) {
className="h-4 w-4 -mr-2"
onClick={(e) => {
e.stopPropagation();
- form.setValue("evaluationResult", "");
+ form.setValue("type", "");
}}
disabled={isInitializing}
>
@@ -565,7 +624,7 @@ async function onSubmit(data: PQFilterFormValues) {
</SelectTrigger>
</FormControl>
<SelectContent>
- {evaluationResultOptions.map(option => (
+ {pqTypeOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
@@ -577,13 +636,127 @@ async function onSubmit(data: PQFilterFormValues) {
)}
/>
- {/* PQ 생성일 */}
+ {/* 프로젝트명 */}
+ {/* <FormField
+ control={form.control}
+ name="projectName"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>프로젝트명</FormLabel>
+ <FormControl>
+ <div className="relative">
+ <Input
+ placeholder="프로젝트명 입력"
+ {...field}
+ className={cn(field.value && "pr-8", "bg-white")}
+ disabled={isInitializing}
+ />
+ {field.value && (
+ <Button
+ type="button"
+ variant="ghost"
+ size="icon"
+ className="absolute right-0 top-0 h-full px-2"
+ onClick={(e) => {
+ e.stopPropagation();
+ form.setValue("projectName", "");
+ }}
+ disabled={isInitializing}
+ >
+ <X className="size-3.5" />
+ <span className="sr-only">Clear</span>
+ </Button>
+ )}
+ </div>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ /> */}
+
+ {/* 협력업체 코드 */}
+ <FormField
+ control={form.control}
+ name="vendorCode"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>협력업체 코드</FormLabel>
+ <FormControl>
+ <div className="relative">
+ <Input
+ placeholder="협력업체 코드 입력"
+ {...field}
+ className={cn(field.value && "pr-8", "bg-white")}
+ disabled={isInitializing}
+ />
+ {field.value && (
+ <Button
+ type="button"
+ variant="ghost"
+ size="icon"
+ className="absolute right-0 top-0 h-full px-2"
+ onClick={(e) => {
+ e.stopPropagation();
+ form.setValue("vendorCode", "");
+ }}
+ disabled={isInitializing}
+ >
+ <X className="size-3.5" />
+ <span className="sr-only">Clear</span>
+ </Button>
+ )}
+ </div>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 실사품목 */}
+ <FormField
+ control={form.control}
+ name="pqItems"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>실사품목</FormLabel>
+ <FormControl>
+ <div className="relative">
+ <Input
+ placeholder="실사품목 입력"
+ {...field}
+ className={cn(field.value && "pr-8", "bg-white")}
+ disabled={isInitializing}
+ />
+ {field.value && (
+ <Button
+ type="button"
+ variant="ghost"
+ size="icon"
+ className="absolute right-0 top-0 h-full px-2"
+ onClick={(e) => {
+ e.stopPropagation();
+ form.setValue("pqItems", "");
+ }}
+ disabled={isInitializing}
+ >
+ <X className="size-3.5" />
+ <span className="sr-only">Clear</span>
+ </Button>
+ )}
+ </div>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* PQ 전송일 */}
<FormField
control={form.control}
name="createdAtRange"
render={({ field }) => (
<FormItem>
- <FormLabel>PQ 생성일</FormLabel>
+ <FormLabel>PQ 전송일 범위</FormLabel>
<FormControl>
<div className="relative">
<DateRangePicker
@@ -591,8 +764,8 @@ async function onSubmit(data: PQFilterFormValues) {
triggerClassName="w-full bg-white"
align="start"
showClearButton={true}
- placeholder="PQ 생성일 범위를 선택하세요"
- value={field.value || undefined}
+ placeholder="PQ 전송일 범위를 선택하세요"
+ defaultDateRange={field.value?.from ? field.value : undefined}
onChange={field.onChange}
disabled={isInitializing}
/>
diff --git a/lib/pq/pq-review-table-new/user-combobox.tsx b/lib/pq/pq-review-table-new/user-combobox.tsx
index 560f675a..3e0264ed 100644
--- a/lib/pq/pq-review-table-new/user-combobox.tsx
+++ b/lib/pq/pq-review-table-new/user-combobox.tsx
@@ -87,7 +87,7 @@ export function UserCombobox({
{users.map((user) => (
<CommandItem
key={user.id}
- value={user.email} // 이메일을 value로 사용
+ value={`${user.name} ${user.email}`} // 이메일 및 이름을 value로 사용
onSelect={() => {
onChange(user.id)
setOpen(false)
diff --git a/lib/pq/pq-review-table-new/vendors-table-columns.tsx b/lib/pq/pq-review-table-new/vendors-table-columns.tsx
index e3687f52..ffa15e56 100644
--- a/lib/pq/pq-review-table-new/vendors-table-columns.tsx
+++ b/lib/pq/pq-review-table-new/vendors-table-columns.tsx
@@ -122,25 +122,54 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef
// ----------------------------------------------------------------
const selectColumn: ColumnDef<PQSubmission> = {
id: "select",
- header: ({ table }) => (
- <Checkbox
- checked={
- table.getIsAllPageRowsSelected() ||
- (table.getIsSomePageRowsSelected() && "indeterminate")
- }
- onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
- aria-label="Select all"
- className="translate-y-0.5"
- />
- ),
- cell: ({ row }) => (
- <Checkbox
- checked={row.getIsSelected()}
- onCheckedChange={(value) => row.toggleSelected(!!value)}
- aria-label="Select row"
- className="translate-y-0.5"
- />
- ),
+ header: ({ table }) => {
+ const selectedRows = table.getSelectedRowModel().rows;
+ const isAllSelected = table.getIsAllPageRowsSelected();
+ const isSomeSelected = table.getIsSomePageRowsSelected();
+
+ return (
+ <Checkbox
+ checked={isAllSelected}
+ indeterminate={isSomeSelected && !isAllSelected}
+ onCheckedChange={(value) => {
+ if (value) {
+ // 전체 선택: 첫 번째 행만 선택
+ table.toggleAllRowsSelected(false);
+ if (table.getRowModel().rows.length > 0) {
+ table.getRowModel().rows[0].toggleSelected(true);
+ }
+ } else {
+ // 전체 해제
+ table.toggleAllRowsSelected(false);
+ }
+ }}
+ aria-label="Select all"
+ className="translate-y-0.5"
+ />
+ );
+ },
+ cell: ({ row, table }) => {
+ const selectedRows = table.getSelectedRowModel().rows;
+ const isCurrentlySelected = row.getIsSelected();
+
+ return (
+ <Checkbox
+ checked={isCurrentlySelected}
+ onCheckedChange={(value) => {
+ if (value) {
+ // 체크하려는 경우: 이미 선택된 행이 있으면 모두 해제하고 현재 행만 선택
+ table.toggleAllRowsSelected(false);
+ row.toggleSelected(true);
+ } else {
+ // 체크 해제하는 경우
+ row.toggleSelected(false);
+ }
+ }}
+ aria-label="Select row"
+ className="translate-y-0.5"
+ />
+ );
+ },
size: 40,
enableSorting: false,
enableHiding: false,
@@ -172,7 +201,7 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef
cell: ({ row }) => (
<div className="flex flex-col">
<span className="font-medium">{row.getValue("vendorName")}</span>
- <span className="text-xs text-muted-foreground">{row.original.vendorCode ? row.original.vendorCode : "-"}/{row.original.taxId}</span>
+ {/* <span className="text-xs text-muted-foreground">{row.original.vendorCode ? row.original.vendorCode : "-"}/{row.original.taxId}</span> */}
</div>
),
enableSorting: true,
@@ -408,6 +437,26 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef
)
},
}
+ const investigationRequestedAtColumn: ColumnDef<PQSubmission> = {
+ accessorKey: "investigationRequestedAt",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="실사 의뢰일" />
+ ),
+ cell: ({ row }) => {
+ const investigation = row.original.investigation;
+
+ if (!investigation || !investigation.requestedAt) {
+ return <span className="text-muted-foreground">-</span>;
+ }
+ const dateVal = investigation.requestedAt
+
+ return (
+ <div className="flex items-center gap-2">
+ <span>{dateVal ? formatDate(dateVal, 'KR') : "-"}</span>
+ </div>
+ )
+ },
+ }
const investigationNotesColumn: ColumnDef<PQSubmission> = {
accessorKey: "investigationNotes",
@@ -484,26 +533,7 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef
}
- const investigationRequestedAtColumn: ColumnDef<PQSubmission> = {
- accessorKey: "investigationRequestedAt",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="실사 의뢰일" />
- ),
- cell: ({ row }) => {
- const investigation = row.original.investigation;
-
- if (!investigation || !investigation.requestedAt) {
- return <span className="text-muted-foreground">-</span>;
- }
- const dateVal = investigation.requestedAt
- return (
- <div className="flex items-center gap-2">
- <span>{dateVal ? formatDate(dateVal, 'KR') : "-"}</span>
- </div>
- )
- },
- }
const investigationForecastedAtColumn: ColumnDef<PQSubmission> = {
@@ -651,9 +681,9 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef
)}
</DropdownMenuItem>
- {/* 방문실사 버튼 - 제품검사평가 또는 방문실사평가인 경우에만 표시 */}
- {pq.investigation &&
- (pq.investigation.investigationMethod === "PRODUCT_INSPECTION" ||
+ {/* 방문실사 버튼 - PQ가 승인됨 상태이고 제품검사평가 또는 방문실사평가인 경우에만 표시 */}
+ {pq.status === "APPROVED" && pq.investigation &&
+ (pq.investigation.investigationMethod === "PRODUCT_INSPECTION" ||
pq.investigation.investigationMethod === "SITE_VISIT_EVAL") && (
<>
<DropdownMenuItem
diff --git a/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx b/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx
index a5185cab..ea6b6189 100644
--- a/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx
+++ b/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx
@@ -624,7 +624,11 @@ const handleOpenRequestDialog = async () => {
variant="outline"
size="sm"
onClick={() => setIsCancelDialogOpen(true)}
- disabled={isLoading || selectedRows.length === 0}
+ disabled={
+ isLoading ||
+ selectedRows.length === 0 ||
+ !selectedRows.every(row => row.original.investigation?.investigationStatus === "PLANNED")
+ }
className="gap-2"
>
<X className="size-4" aria-hidden="true" />
@@ -636,7 +640,11 @@ const handleOpenRequestDialog = async () => {
variant="outline"
size="sm"
onClick={() => setIsReRequestDialogOpen(true)}
- disabled={isLoading || selectedRows.length === 0}
+ disabled={
+ isLoading ||
+ selectedRows.length === 0 ||
+ !selectedRows.every(row => row.original.investigation?.investigationStatus === "CANCELED")
+ }
className="gap-2"
>
<RefreshCw className="size-4" aria-hidden="true" />
@@ -648,7 +656,19 @@ const handleOpenRequestDialog = async () => {
variant="outline"
size="sm"
onClick={() => setIsSendResultsDialogOpen(true)}
- disabled={isLoading || selectedRows.length === 0}
+ disabled={
+ isLoading ||
+ selectedRows.length === 0 ||
+ !selectedRows.every(row => {
+ const investigation = row.original.investigation;
+ if (!investigation) return false;
+
+ // 실사 완료 상태이거나 평가 결과가 있는 경우에만 활성화
+ return investigation.investigationStatus === "COMPLETED" ||
+ investigation.evaluationResult === "REJECTED" ||
+ investigation.evaluationResult === "SUPPLEMENT";
+ })
+ }
className="gap-2"
>
<Send className="size-4" aria-hidden="true" />
diff --git a/lib/pq/pq-review-table-new/vendors-table.tsx b/lib/pq/pq-review-table-new/vendors-table.tsx
index 191c8bfa..f8f9928e 100644
--- a/lib/pq/pq-review-table-new/vendors-table.tsx
+++ b/lib/pq/pq-review-table-new/vendors-table.tsx
@@ -265,8 +265,9 @@ export function PQSubmissionsTable({ promises, className }: PQSubmissionsTablePr
{ label: "승인됨", value: "APPROVED" },
{ label: "거부됨", value: "REJECTED" },
]},
+ { id: "pqItems", label: "실사품목", type: "text" },
- { id: "createdAt", label: "생성일", type: "date" },
+ { id: "createdAt", label: "PQ 전송일", type: "date" },
{ id: "submittedAt", label: "제출일", type: "date" },
{ id: "approvedAt", label: "승인일", type: "date" },
{ id: "rejectedAt", label: "거부일", type: "date" },
@@ -286,8 +287,18 @@ export function PQSubmissionsTable({ promises, className }: PQSubmissionsTablePr
}),
columnVisibility: currentSettings.columnVisibility,
columnPinning: currentSettings.pinnedColumns,
+ // DateRangePicker의 from/to 파라미터를 위한 상태
+ columnFilters: initialSettings.from || initialSettings.to ? [
+ {
+ id: "createdAt",
+ value: {
+ from: initialSettings.from ? new Date(initialSettings.from) : undefined,
+ to: initialSettings.to ? new Date(initialSettings.to) : undefined,
+ }
+ }
+ ] : [],
}
- }, [currentSettings, initialSettings.sort, columns])
+ }, [currentSettings, initialSettings.sort, initialSettings.from, initialSettings.to, columns])
const { table } = useDataTable({
data: tableData.data,
@@ -297,6 +308,8 @@ export function PQSubmissionsTable({ promises, className }: PQSubmissionsTablePr
filterFields, // RFQ와 달리 빈 배열이 아닌 실제 필터 필드 사용
enablePinning: true,
enableAdvancedFilter: true,
+ enableRowSelection: true,
+ maxSelections: 1,
initialState,
getRowId: (originalRow) => String(originalRow.id),
shallow: false,