ListFormEdit ekranında sütunların sıralaması
This commit is contained in:
parent
7be0b4ed88
commit
d331fb62d4
4 changed files with 369 additions and 118 deletions
|
|
@ -74903,6 +74903,20 @@
|
||||||
"ResourceName": "Platform",
|
"ResourceName": "Platform",
|
||||||
"Key": "App.Listform.ListformField.ExpectedKm",
|
"Key": "App.Listform.ListformField.ExpectedKm",
|
||||||
"Value": "Olması Gereken Km"
|
"Value": "Olması Gereken Km"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "a4130afd-d823-57b0-91e8-c0c11369801d",
|
||||||
|
"CultureName": "en",
|
||||||
|
"ResourceName": "Platform",
|
||||||
|
"Key": "App.ListFormField.DragToReorder",
|
||||||
|
"Value": "Drag to reorder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "59388a6c-8dcf-583e-b706-896644410dfe",
|
||||||
|
"CultureName": "tr",
|
||||||
|
"ResourceName": "Platform",
|
||||||
|
"Key": "App.ListFormField.DragToReorder",
|
||||||
|
"Value": "Sürükleyerek sırala"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { AdaptableCard, Container } from '@/components/shared'
|
import { AdaptableCard, Container } from '@/components/shared'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -8,12 +7,12 @@ import {
|
||||||
FormItem,
|
FormItem,
|
||||||
Input,
|
Input,
|
||||||
Notification,
|
Notification,
|
||||||
|
Segment,
|
||||||
Table,
|
Table,
|
||||||
toast,
|
toast,
|
||||||
} from '@/components/ui'
|
} from '@/components/ui'
|
||||||
import TBody from '@/components/ui/Table/TBody'
|
import TBody from '@/components/ui/Table/TBody'
|
||||||
import THead from '@/components/ui/Table/THead'
|
import THead from '@/components/ui/Table/THead'
|
||||||
import Td from '@/components/ui/Table/Td'
|
|
||||||
import Th from '@/components/ui/Table/Th'
|
import Th from '@/components/ui/Table/Th'
|
||||||
import Tr from '@/components/ui/Table/Tr'
|
import Tr from '@/components/ui/Table/Tr'
|
||||||
import {
|
import {
|
||||||
|
|
@ -26,6 +25,7 @@ import {
|
||||||
import {
|
import {
|
||||||
ColumnFormatEditDto,
|
ColumnFormatEditDto,
|
||||||
CopyListFormFieldColumnDto,
|
CopyListFormFieldColumnDto,
|
||||||
|
ListFormFieldEditTabs,
|
||||||
} from '@/proxy/admin/list-form-field/models'
|
} from '@/proxy/admin/list-form-field/models'
|
||||||
import { SelectBoxOption } from '@/types/shared'
|
import { SelectBoxOption } from '@/types/shared'
|
||||||
import { useStoreState } from '@/store'
|
import { useStoreState } from '@/store'
|
||||||
|
|
@ -33,8 +33,24 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import setNull from '@/utils/setNull'
|
import setNull from '@/utils/setNull'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { Field, Form, Formik, FormikHelpers } from 'formik'
|
import { Field, Form, Formik, FormikHelpers } from 'formik'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { FaFileMedical, FaCopy, FaEyeSlash, FaMinus, FaTimes, FaTable } from 'react-icons/fa'
|
import { FaFileMedical, FaCopy, FaTable } from 'react-icons/fa'
|
||||||
|
import {
|
||||||
|
DndContext,
|
||||||
|
DragEndEvent,
|
||||||
|
KeyboardSensor,
|
||||||
|
PointerSensor,
|
||||||
|
closestCenter,
|
||||||
|
useSensor,
|
||||||
|
useSensors,
|
||||||
|
} from '@dnd-kit/core'
|
||||||
|
import {
|
||||||
|
SortableContext,
|
||||||
|
sortableKeyboardCoordinates,
|
||||||
|
verticalListSortingStrategy,
|
||||||
|
} from '@dnd-kit/sortable'
|
||||||
|
import SortableFieldRow from './SortableFieldRow'
|
||||||
|
import { FieldOrderMode, reorderFields, sortFields } from './fieldOrder'
|
||||||
import { number, object, string } from 'yup'
|
import { number, object, string } from 'yup'
|
||||||
import FormFieldEdit from './FormFieldEdit'
|
import FormFieldEdit from './FormFieldEdit'
|
||||||
import { dbSourceTypeOptions, sqlDataTypeToDbType } from '../options'
|
import { dbSourceTypeOptions, sqlDataTypeToDbType } from '../options'
|
||||||
|
|
@ -85,7 +101,7 @@ function FormFields({
|
||||||
columns: DatabaseColumnDto[]
|
columns: DatabaseColumnDto[]
|
||||||
}) {
|
}) {
|
||||||
const { translate } = useLocalization()
|
const { translate } = useLocalization()
|
||||||
const { canCreate, canDelete } = useFieldPermission()
|
const { canCreate, canUpdate, canDelete } = useFieldPermission()
|
||||||
const [fields, setFields] = useState<ColumnFormatEditDto[]>()
|
const [fields, setFields] = useState<ColumnFormatEditDto[]>()
|
||||||
const [deleteRowId, setDeleteRowId] = useState<string | null>(null)
|
const [deleteRowId, setDeleteRowId] = useState<string | null>(null)
|
||||||
const [row, setRow] = useState<ColumnFormatEditDto | null>(null)
|
const [row, setRow] = useState<ColumnFormatEditDto | null>(null)
|
||||||
|
|
@ -93,6 +109,14 @@ function FormFields({
|
||||||
const [isCopyField, setIsCopyField] = useState(false)
|
const [isCopyField, setIsCopyField] = useState(false)
|
||||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||||
const cultureName = useStoreState((state) => state.locale.currentLang)
|
const cultureName = useStoreState((state) => state.locale.currentLang)
|
||||||
|
const [orderMode, setOrderMode] = useState<FieldOrderMode>('list')
|
||||||
|
const [isSavingOrder, setIsSavingOrder] = useState(false)
|
||||||
|
// Siralama kaydedildikten sonra liste kullanicinin son uyguladigi filtreyle yeniden okunur.
|
||||||
|
const filterRef = useRef<{ cultureName?: string; roleId?: string; userId?: string }>({})
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
||||||
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
||||||
|
)
|
||||||
|
|
||||||
// ── All DB Columns (for "Tüm Sütunları Ekle") ───────────────────────────────
|
// ── All DB Columns (for "Tüm Sütunları Ekle") ───────────────────────────────
|
||||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||||
|
|
@ -308,10 +332,50 @@ function FormFields({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDragEnd = async ({ active, over }: DragEndEvent) => {
|
||||||
|
if (!fields || !over) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const changed = reorderFields(fields, orderMode, String(active.id), String(over.id))
|
||||||
|
if (changed.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setFields(fields.map((f) => changed.find((c) => c.id === f.id) ?? f))
|
||||||
|
setIsSavingOrder(true)
|
||||||
|
try {
|
||||||
|
// Her kayit wizard seed dosyasini yeniden yazar; paralel istek ayni dosyada yarisirdi.
|
||||||
|
for (const field of changed) {
|
||||||
|
await putListFormField({ ...field, editType: ListFormFieldEditTabs.OptionsForm })
|
||||||
|
}
|
||||||
|
toast.push(
|
||||||
|
<Notification type="success" duration={2000}>
|
||||||
|
{translate('::App.Platform.FormBilgileriKaydedildi')}
|
||||||
|
</Notification>,
|
||||||
|
{ placement: 'bottom-end' },
|
||||||
|
)
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.push(
|
||||||
|
<Notification type="danger">
|
||||||
|
{translate('::App.Platform.Error')}
|
||||||
|
<code>{error}</code>
|
||||||
|
</Notification>,
|
||||||
|
{ placement: 'bottom-end' },
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
const { cultureName, roleId, userId } = filterRef.current
|
||||||
|
await getFields(cultureName, roleId, userId)
|
||||||
|
setIsSavingOrder(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!fields) {
|
if (!fields) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const orderedFields = sortFields(fields, orderMode)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Formik
|
<Formik
|
||||||
|
|
@ -333,6 +397,7 @@ function FormFields({
|
||||||
}}
|
}}
|
||||||
onSubmit={async ({ cultureName, roleId, userId }, { setSubmitting }) => {
|
onSubmit={async ({ cultureName, roleId, userId }, { setSubmitting }) => {
|
||||||
setSubmitting(true)
|
setSubmitting(true)
|
||||||
|
filterRef.current = { cultureName, roleId, userId }
|
||||||
getFields(cultureName, roleId, userId).then(() => {
|
getFields(cultureName, roleId, userId).then(() => {
|
||||||
toast.push(
|
toast.push(
|
||||||
<Notification type="success" duration={100}>
|
<Notification type="success" duration={100}>
|
||||||
|
|
@ -384,120 +449,119 @@ function FormFields({
|
||||||
<AdaptableCard className="h-full" bodyClass="h-full">
|
<AdaptableCard className="h-full" bodyClass="h-full">
|
||||||
<div className="grid 2xl:grid-cols-5 xl:grid-cols-3 lg:grid-cols-5 gap-4 h-full border-t-2">
|
<div className="grid 2xl:grid-cols-5 xl:grid-cols-3 lg:grid-cols-5 gap-4 h-full border-t-2">
|
||||||
<div className="2xl:col-span-2 xl:col-span-1 lg:col-span-2 border-r-2">
|
<div className="2xl:col-span-2 xl:col-span-1 lg:col-span-2 border-r-2">
|
||||||
<Table compact>
|
<div className="flex justify-end px-2 py-2">
|
||||||
<THead>
|
<Segment
|
||||||
<Tr>
|
size="xs"
|
||||||
<Th className="w-3/12">
|
value={[orderMode]}
|
||||||
<div>
|
onChange={(value) => {
|
||||||
{canCreate && (
|
// Tekli Segment secili ogeye tekrar tiklaninca bos deger gonderir.
|
||||||
<Button
|
const next = Array.isArray(value) ? value[0] : value
|
||||||
shape="circle"
|
if (next === 'list' || next === 'edit') {
|
||||||
variant="plain"
|
setOrderMode(next)
|
||||||
type="button"
|
}
|
||||||
size="sm"
|
}}
|
||||||
title="Add"
|
>
|
||||||
icon={<FaFileMedical />}
|
<Segment.Item value="list">
|
||||||
onClick={() => {
|
{translate('::App.ListFormFieldEdit.OptionsListOrderNo')}
|
||||||
setIsNewField(true)
|
</Segment.Item>
|
||||||
setRow({} as ColumnFormatEditDto)
|
<Segment.Item value="edit">
|
||||||
}}
|
{translate('::App.ListFormFieldEdit.EditFormOrderNo')}
|
||||||
/>
|
</Segment.Item>
|
||||||
)}
|
</Segment>
|
||||||
{canCreate && (
|
</div>
|
||||||
<Button
|
<DndContext
|
||||||
shape="circle"
|
sensors={sensors}
|
||||||
variant="plain"
|
collisionDetection={closestCenter}
|
||||||
type="button"
|
onDragEnd={onDragEnd}
|
||||||
size="sm"
|
>
|
||||||
title="Copy"
|
<SortableContext
|
||||||
icon={<FaCopy />}
|
items={orderedFields.map((f) => f.id!)}
|
||||||
onClick={async (e) => {
|
strategy={verticalListSortingStrategy}
|
||||||
e.preventDefault()
|
>
|
||||||
setIsCopyField(true)
|
<Table compact>
|
||||||
}}
|
<THead>
|
||||||
/>
|
<Tr>
|
||||||
)}
|
<Th className="w-3/12">
|
||||||
{canCreate && allDbColumns.length > 0 && (
|
<div>
|
||||||
<Button
|
{canCreate && (
|
||||||
shape="circle"
|
<Button
|
||||||
variant="plain"
|
shape="circle"
|
||||||
type="button"
|
variant="plain"
|
||||||
size="sm"
|
type="button"
|
||||||
title={translate('::App.ListFormField.AddAllColumns')}
|
size="sm"
|
||||||
icon={<FaTable />}
|
title="Add"
|
||||||
loading={isAddingAllColumns}
|
icon={<FaFileMedical />}
|
||||||
onClick={addAllColumns}
|
onClick={() => {
|
||||||
/>
|
setIsNewField(true)
|
||||||
)}
|
setRow({} as ColumnFormatEditDto)
|
||||||
</div>
|
}}
|
||||||
</Th>
|
/>
|
||||||
<Th className="w-3/12">Field</Th>
|
)}
|
||||||
<Th className="w-2/12">Culture</Th>
|
{canCreate && (
|
||||||
<Th className="hidden sm:table-cell w-2/12">Role</Th>
|
<Button
|
||||||
<Th className="hidden sm:table-cell w-2/12">User</Th>
|
shape="circle"
|
||||||
</Tr>
|
variant="plain"
|
||||||
</THead>
|
type="button"
|
||||||
<TBody>
|
size="sm"
|
||||||
{fields.map((field) => (
|
title="Copy"
|
||||||
<Tr
|
icon={<FaCopy />}
|
||||||
key={field.id}
|
onClick={async (e) => {
|
||||||
className={classNames(
|
e.preventDefault()
|
||||||
'cursor-pointer',
|
setIsCopyField(true)
|
||||||
field.id === row?.id ? 'bg-sozsoft-active dark:bg-gray-600' : '',
|
}}
|
||||||
)}
|
/>
|
||||||
onClick={() => {
|
)}
|
||||||
setRow(field)
|
{canCreate && allDbColumns.length > 0 && (
|
||||||
}}
|
<Button
|
||||||
>
|
shape="circle"
|
||||||
<Td className="flex items-center !py-1 !px-1">
|
variant="plain"
|
||||||
{canDelete && (
|
type="button"
|
||||||
<Button
|
size="sm"
|
||||||
shape="circle"
|
title={translate('::App.ListFormField.AddAllColumns')}
|
||||||
variant="plain"
|
icon={<FaTable />}
|
||||||
type="button"
|
loading={isAddingAllColumns}
|
||||||
size="sm"
|
onClick={addAllColumns}
|
||||||
title="Delete"
|
/>
|
||||||
icon={<FaMinus />}
|
)}
|
||||||
onClick={async (e) => {
|
</div>
|
||||||
e.preventDefault()
|
</Th>
|
||||||
if (field.id) {
|
<Th className="w-3/12">Field</Th>
|
||||||
setDeleteRowId(field.id)
|
<Th className="w-2/12">Culture</Th>
|
||||||
}
|
<Th className="hidden sm:table-cell w-2/12">Role</Th>
|
||||||
}}
|
<Th className="hidden sm:table-cell w-2/12">User</Th>
|
||||||
/>
|
</Tr>
|
||||||
)}
|
</THead>
|
||||||
<span style={{ visibility: !field?.visible ? 'visible' : 'hidden' }}>
|
<TBody>
|
||||||
<FaEyeSlash />
|
{orderedFields.map((field) => (
|
||||||
</span>
|
<SortableFieldRow
|
||||||
<span style={{ visibility: !field?.isActive ? 'visible' : 'hidden' }}>
|
key={field.id}
|
||||||
<FaTimes />
|
field={field}
|
||||||
</span>
|
isSelected={field.id === row?.id}
|
||||||
<span className="ml-5">
|
canDelete={canDelete}
|
||||||
{field.listOrderNo}
|
dragDisabled={
|
||||||
{field.editOrderNo ? ` (${field.editOrderNo})` : ''}
|
!canUpdate ||
|
||||||
</span>
|
isSavingOrder ||
|
||||||
</Td>
|
(orderMode === 'edit' && field.editOrderNo == null)
|
||||||
<Td className="!py-1 !px-1">{field.fieldName}</Td>
|
}
|
||||||
<Td className="align-middle text-center !py-1 !px-1">
|
dragTitle={translate('::App.ListFormField.DragToReorder')}
|
||||||
<Avatar
|
roleLabel={
|
||||||
size={18}
|
field.roleId
|
||||||
shape="circle"
|
? (roleList.find((a) => a.value === field.roleId)?.label ?? 'X')
|
||||||
src={`/img/countries/${field.cultureName ?? 'default'}.png`}
|
: undefined
|
||||||
title={field.cultureName}
|
}
|
||||||
|
userLabel={
|
||||||
|
field.userId
|
||||||
|
? (userList.find((a) => a.value === field.userId)?.label ?? 'X')
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onSelect={() => setRow(field)}
|
||||||
|
onDelete={() => field.id && setDeleteRowId(field.id)}
|
||||||
/>
|
/>
|
||||||
</Td>
|
))}
|
||||||
<Td className="hidden sm:table-cell !py-1 !px-1">
|
</TBody>
|
||||||
{field.roleId &&
|
</Table>
|
||||||
(roleList.find((a) => a.value === field.roleId)?.label ?? 'X')}
|
</SortableContext>
|
||||||
</Td>
|
</DndContext>
|
||||||
<Td className="hidden sm:table-cell !py-1 !px-1">
|
|
||||||
{field.userId &&
|
|
||||||
(userList.find((a) => a.value === field.userId)?.label ?? 'X')}
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
))}
|
|
||||||
</TBody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="2xl:col-span-3 lg:col-span-3 xl:col-span-2">
|
<div className="2xl:col-span-3 lg:col-span-3 xl:col-span-2">
|
||||||
<FormFieldEdit
|
<FormFieldEdit
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { Avatar, Button } from '@/components/ui'
|
||||||
|
import Td from '@/components/ui/Table/Td'
|
||||||
|
import Tr from '@/components/ui/Table/Tr'
|
||||||
|
import { ColumnFormatEditDto } from '@/proxy/admin/list-form-field/models'
|
||||||
|
import { useSortable } from '@dnd-kit/sortable'
|
||||||
|
import { CSS } from '@dnd-kit/utilities'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import { FaEyeSlash, FaGripVertical, FaMinus, FaTimes } from 'react-icons/fa'
|
||||||
|
|
||||||
|
function SortableFieldRow({
|
||||||
|
field,
|
||||||
|
isSelected,
|
||||||
|
canDelete,
|
||||||
|
dragDisabled,
|
||||||
|
dragTitle,
|
||||||
|
roleLabel,
|
||||||
|
userLabel,
|
||||||
|
onSelect,
|
||||||
|
onDelete,
|
||||||
|
}: {
|
||||||
|
field: ColumnFormatEditDto
|
||||||
|
isSelected: boolean
|
||||||
|
canDelete: boolean
|
||||||
|
dragDisabled: boolean
|
||||||
|
dragTitle: string
|
||||||
|
roleLabel?: string
|
||||||
|
userLabel?: string
|
||||||
|
onSelect: () => void
|
||||||
|
onDelete: () => void
|
||||||
|
}) {
|
||||||
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||||
|
id: field.id!,
|
||||||
|
disabled: dragDisabled,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tr
|
||||||
|
ref={setNodeRef}
|
||||||
|
style={{ transform: CSS.Translate.toString(transform), transition }}
|
||||||
|
className={classNames(
|
||||||
|
'cursor-pointer',
|
||||||
|
isSelected ? 'bg-sozsoft-active dark:bg-gray-600' : '',
|
||||||
|
isDragging ? 'relative z-10 opacity-60' : '',
|
||||||
|
)}
|
||||||
|
onClick={onSelect}
|
||||||
|
>
|
||||||
|
<Td className="flex items-center !py-1 !px-1">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="plain"
|
||||||
|
shape="circle"
|
||||||
|
size="xs"
|
||||||
|
title={dragTitle}
|
||||||
|
disabled={dragDisabled}
|
||||||
|
icon={<FaGripVertical />}
|
||||||
|
className={dragDisabled ? 'invisible' : 'cursor-grab'}
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}
|
||||||
|
/>
|
||||||
|
{canDelete && (
|
||||||
|
<Button
|
||||||
|
shape="circle"
|
||||||
|
variant="plain"
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
title="Delete"
|
||||||
|
icon={<FaMinus />}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
onDelete()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span style={{ visibility: !field?.visible ? 'visible' : 'hidden' }}>
|
||||||
|
<FaEyeSlash />
|
||||||
|
</span>
|
||||||
|
<span style={{ visibility: !field?.isActive ? 'visible' : 'hidden' }}>
|
||||||
|
<FaTimes />
|
||||||
|
</span>
|
||||||
|
<span className="ml-5">
|
||||||
|
{field.listOrderNo}
|
||||||
|
{field.editOrderNo ? ` (${field.editOrderNo})` : ''}
|
||||||
|
</span>
|
||||||
|
</Td>
|
||||||
|
<Td className="!py-1 !px-1">{field.fieldName}</Td>
|
||||||
|
<Td className="align-middle text-center !py-1 !px-1">
|
||||||
|
<Avatar
|
||||||
|
size={18}
|
||||||
|
shape="circle"
|
||||||
|
src={`/img/countries/${field.cultureName ?? 'default'}.png`}
|
||||||
|
title={field.cultureName}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
<Td className="hidden sm:table-cell !py-1 !px-1">{roleLabel}</Td>
|
||||||
|
<Td className="hidden sm:table-cell !py-1 !px-1">{userLabel}</Td>
|
||||||
|
</Tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SortableFieldRow
|
||||||
73
ui/src/views/admin/listForm/edit/form-fields/fieldOrder.ts
Normal file
73
ui/src/views/admin/listForm/edit/form-fields/fieldOrder.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { ColumnFormatEditDto } from '@/proxy/admin/list-form-field/models'
|
||||||
|
|
||||||
|
export type FieldOrderMode = 'list' | 'edit'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sürükleme sonucunu sıra numaralarına çevirir. Liste sırası bütün alanlar üzerindedir; form sırası
|
||||||
|
* yalnızca aynı form grubundaki, forma giren (editOrderNo dolu) alanlar arasındadır — gruplar arası
|
||||||
|
* taşıma grup değişikliğidir ve Options sekmesinden yapılır. Numaralar kapsam içinde 1'den yeniden
|
||||||
|
* dağıtılır, yalnızca değeri değişen alanlar döner.
|
||||||
|
*/
|
||||||
|
export function reorderFields(
|
||||||
|
fields: ColumnFormatEditDto[],
|
||||||
|
mode: FieldOrderMode,
|
||||||
|
activeId: string,
|
||||||
|
overId: string,
|
||||||
|
): ColumnFormatEditDto[] {
|
||||||
|
const active = fields.find((f) => f.id === activeId)
|
||||||
|
const over = fields.find((f) => f.id === overId)
|
||||||
|
if (!active || !over || active === over) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtresiz listede ayni alanin baska kultur/rol/kullanici kayitlari da durur; her biri kendi
|
||||||
|
// sirasini tasir.
|
||||||
|
const sameOwner = (f: ColumnFormatEditDto) =>
|
||||||
|
f.cultureName === active.cultureName &&
|
||||||
|
(f.roleId ?? null) === (active.roleId ?? null) &&
|
||||||
|
(f.userId ?? null) === (active.userId ?? null)
|
||||||
|
|
||||||
|
const scope = !sameOwner(over)
|
||||||
|
? []
|
||||||
|
: mode === 'list'
|
||||||
|
? sortFields(fields.filter(sameOwner), 'list')
|
||||||
|
: active.editOrderNo != null &&
|
||||||
|
over.editOrderNo != null &&
|
||||||
|
active.editGroupOrderNo === over.editGroupOrderNo
|
||||||
|
? sortFields(
|
||||||
|
fields.filter(
|
||||||
|
(f) =>
|
||||||
|
sameOwner(f) &&
|
||||||
|
f.editOrderNo != null &&
|
||||||
|
f.editGroupOrderNo === active.editGroupOrderNo,
|
||||||
|
),
|
||||||
|
'edit',
|
||||||
|
)
|
||||||
|
: []
|
||||||
|
|
||||||
|
const from = scope.indexOf(active)
|
||||||
|
const to = scope.indexOf(over)
|
||||||
|
if (from < 0 || to < 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const moved = [...scope]
|
||||||
|
moved.splice(to, 0, ...moved.splice(from, 1))
|
||||||
|
|
||||||
|
const key = mode === 'list' ? 'listOrderNo' : 'editOrderNo'
|
||||||
|
return moved
|
||||||
|
.map((f, index) => ({ field: f, order: index + 1 }))
|
||||||
|
.filter(({ field, order }) => field[key] !== order)
|
||||||
|
.map(({ field, order }) => ({ ...field, [key]: order }))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortFields(fields: ColumnFormatEditDto[], mode: FieldOrderMode) {
|
||||||
|
const last = Number.MAX_SAFE_INTEGER
|
||||||
|
return [...fields].sort((a, b) =>
|
||||||
|
mode === 'list'
|
||||||
|
? (a.listOrderNo ?? last) - (b.listOrderNo ?? last)
|
||||||
|
: (a.editGroupOrderNo ?? last) - (b.editGroupOrderNo ?? last) ||
|
||||||
|
(a.editOrderNo ?? last) - (b.editOrderNo ?? last) ||
|
||||||
|
(a.listOrderNo ?? last) - (b.listOrderNo ?? last),
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue