diff --git a/configs/seeds/host/data/App.Languages.LanguageText.json b/configs/seeds/host/data/App.Languages.LanguageText.json index 7ad87c11..3d8f4a87 100644 --- a/configs/seeds/host/data/App.Languages.LanguageText.json +++ b/configs/seeds/host/data/App.Languages.LanguageText.json @@ -74903,6 +74903,20 @@ "ResourceName": "Platform", "Key": "App.Listform.ListformField.ExpectedKm", "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" } ] } diff --git a/ui/src/views/admin/listForm/edit/form-fields/FormFields.tsx b/ui/src/views/admin/listForm/edit/form-fields/FormFields.tsx index e6525d17..e726ff94 100644 --- a/ui/src/views/admin/listForm/edit/form-fields/FormFields.tsx +++ b/ui/src/views/admin/listForm/edit/form-fields/FormFields.tsx @@ -1,6 +1,5 @@ import { AdaptableCard, Container } from '@/components/shared' import { - Avatar, Button, Checkbox, Dialog, @@ -8,12 +7,12 @@ import { FormItem, Input, Notification, + Segment, Table, toast, } from '@/components/ui' import TBody from '@/components/ui/Table/TBody' import THead from '@/components/ui/Table/THead' -import Td from '@/components/ui/Table/Td' import Th from '@/components/ui/Table/Th' import Tr from '@/components/ui/Table/Tr' import { @@ -26,6 +25,7 @@ import { import { ColumnFormatEditDto, CopyListFormFieldColumnDto, + ListFormFieldEditTabs, } from '@/proxy/admin/list-form-field/models' import { SelectBoxOption } from '@/types/shared' import { useStoreState } from '@/store' @@ -33,8 +33,24 @@ import { useLocalization } from '@/utils/hooks/useLocalization' import setNull from '@/utils/setNull' import classNames from 'classnames' import { Field, Form, Formik, FormikHelpers } from 'formik' -import { useCallback, useEffect, useState } from 'react' -import { FaFileMedical, FaCopy, FaEyeSlash, FaMinus, FaTimes, FaTable } from 'react-icons/fa' +import { useCallback, useEffect, useRef, useState } from 'react' +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 FormFieldEdit from './FormFieldEdit' import { dbSourceTypeOptions, sqlDataTypeToDbType } from '../options' @@ -85,7 +101,7 @@ function FormFields({ columns: DatabaseColumnDto[] }) { const { translate } = useLocalization() - const { canCreate, canDelete } = useFieldPermission() + const { canCreate, canUpdate, canDelete } = useFieldPermission() const [fields, setFields] = useState() const [deleteRowId, setDeleteRowId] = useState(null) const [row, setRow] = useState(null) @@ -93,6 +109,14 @@ function FormFields({ const [isCopyField, setIsCopyField] = useState(false) const [fieldList, setFieldList] = useState([]) const cultureName = useStoreState((state) => state.locale.currentLang) + const [orderMode, setOrderMode] = useState('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") ─────────────────────────────── 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( + + {translate('::App.Platform.FormBilgileriKaydedildi')} + , + { placement: 'bottom-end' }, + ) + } catch (error: any) { + toast.push( + + {translate('::App.Platform.Error')} + {error} + , + { placement: 'bottom-end' }, + ) + } finally { + const { cultureName, roleId, userId } = filterRef.current + await getFields(cultureName, roleId, userId) + setIsSavingOrder(false) + } + } + if (!fields) { return <> } + const orderedFields = sortFields(fields, orderMode) + return ( <> { setSubmitting(true) + filterRef.current = { cultureName, roleId, userId } getFields(cultureName, roleId, userId).then(() => { toast.push( @@ -384,120 +449,119 @@ function FormFields({
- - - - - - - - - - - - {fields.map((field) => ( - { - setRow(field) - }} - > - - - +
-
- {canCreate && ( -
-
FieldCultureRoleUser
- {canDelete && ( - {field.fieldName} - + { + // Tekli Segment secili ogeye tekrar tiklaninca bos deger gonderir. + const next = Array.isArray(value) ? value[0] : value + if (next === 'list' || next === 'edit') { + setOrderMode(next) + } + }} + > + + {translate('::App.ListFormFieldEdit.OptionsListOrderNo')} + + + {translate('::App.ListFormFieldEdit.EditFormOrderNo')} + + + + + f.id!)} + strategy={verticalListSortingStrategy} + > + + + + + + + + + + + + {orderedFields.map((field) => ( + a.value === field.roleId)?.label ?? 'X') + : undefined + } + userLabel={ + field.userId + ? (userList.find((a) => a.value === field.userId)?.label ?? 'X') + : undefined + } + onSelect={() => setRow(field)} + onDelete={() => field.id && setDeleteRowId(field.id)} /> - - - - - ))} - -
+
+ {canCreate && ( +
+
FieldCultureRoleUser
- {field.roleId && - (roleList.find((a) => a.value === field.roleId)?.label ?? 'X')} - - {field.userId && - (userList.find((a) => a.value === field.userId)?.label ?? 'X')} -
+ ))} +
+ +
void + onDelete: () => void +}) { + const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ + id: field.id!, + disabled: dragDisabled, + }) + + return ( + + +