Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ability to drag field from form to sidebar #1162

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { DragEndEvent, DragOverEvent, DragStartEvent, DropAnimation } from '@dnd-kit/core';
import type {
DragEndEvent,
DragOverEvent,
DragStartEvent,
DropAnimation,
UniqueIdentifier,
} from '@dnd-kit/core';
import {
DndContext,
DragOverlay,
Expand All @@ -18,6 +24,7 @@ import {
import type { IFieldInstance } from '@teable/sdk/model';
import { useEffect, useMemo, useState } from 'react';
import { FieldSetting } from '../../grid/components';
import { FORM_SIDEBAR_DROPPABLE_ID } from '../constant';
import { FormEditorMain } from './FormEditorMain';
import { FormFieldEditor } from './FormFieldEditor';
import { DragItem, FormSidebar } from './FormSidebar';
Expand All @@ -41,6 +48,7 @@ export const FormEditor = () => {
const [innerVisibleFields, setInnerVisibleFields] = useState([...visibleFields]);
const [activeField, setActiveField] = useState<IFieldInstance | null>(null);
const [activeSidebarField, setActiveSidebarField] = useState<IFieldInstance | null>(null);
const [sidebarAdditionalFieldId, setSidebarAdditionalFieldId] = useState<string | null>(null);
const [additionalFieldData, setAdditionalFieldData] = useState<{
field: IFieldInstance;
index: number;
Expand Down Expand Up @@ -73,6 +81,7 @@ export const FormEditor = () => {
setActiveField(null);
setActiveSidebarField(null);
setAdditionalFieldData(null);
setSidebarAdditionalFieldId(null);
};

const onDragStart = (event: DragStartEvent) => {
Expand All @@ -93,17 +102,24 @@ export const FormEditor = () => {
const { over, active } = event;
const activeData = active.data?.current || {};
const overData = over?.data?.current || {};
const overId: UniqueIdentifier | undefined = over?.id;
const { fromSidebar, field } = activeData;
const { index, isContainer } = overData;

if (fromSidebar && (index != null || isContainer)) {
if (fromSidebar && (index != null || isContainer) && !sidebarAdditionalFieldId) {
setAdditionalFieldData({ field, index: index ?? 0 });
}

if (activeField && overId === FORM_SIDEBAR_DROPPABLE_ID && !additionalFieldData) {
const sourceDragId = activeField.id;
setSidebarAdditionalFieldId(sourceDragId);
}
};

// eslint-disable-next-line sonarjs/cognitive-complexity
const onDragEnd = async (event: DragEndEvent) => {
const { over } = event;
const overId: UniqueIdentifier | undefined = over?.id;
const overData = over?.data?.current || {};

const { index: targetIndex, isContainer } = overData;
Expand Down Expand Up @@ -183,6 +199,18 @@ export const FormEditor = () => {
},
]);
}

if (activeField && overId === FORM_SIDEBAR_DROPPABLE_ID) {
const sourceDragId = activeField.id;
await view?.updateColumnMeta([
{
fieldId: sourceDragId,
columnMeta: {
visible: false,
},
},
]);
}
};

return (
Expand All @@ -195,7 +223,7 @@ export const FormEditor = () => {
sensors={sensors}
autoScroll
>
<FormSidebar />
<FormSidebar sidebarAdditionalFieldId={sidebarAdditionalFieldId} />
<FormEditorMain fields={renderFields} />
<FieldSetting />
<DragOverlay adjustScale={false} dropAnimation={dropAnimation}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
import { useDroppable } from '@dnd-kit/core';
import type { FieldType } from '@teable/core';
import { DraggableHandle, Plus } from '@teable/icons';
import { useView } from '@teable/sdk';
Expand All @@ -16,6 +17,7 @@ import {
import { useTranslation } from 'next-i18next';
import type { FC } from 'react';
import { useMemo } from 'react';
import { FORM_SIDEBAR_DROPPABLE_ID } from '@/features/app/blocks/view/form/constant';
import { FieldOperator } from '@/features/app/components/field-setting';
import { tableConfig } from '@/features/i18n/table.config';
import { useFieldSettingStore } from '../../field/useFieldSettingStore';
Expand Down Expand Up @@ -67,14 +69,20 @@ export const DragItem: FC<IDragItemProps> = (props) => {
);
};

export const FormSidebar = () => {
interface IFormSidebarProps {
sidebarAdditionalFieldId: string | null;
}

export const FormSidebar: FC<IFormSidebarProps> = (props) => {
const { sidebarAdditionalFieldId } = props;
const isHydrated = useIsHydrated();
const view = useView() as FormView | undefined;
const activeViewId = view?.id;
const allFields = useFields({ withHidden: true, withDenied: true });
const getFieldStatic = useFieldStaticGetter();
const { openSetting } = useFieldSettingStore();
const { t } = useTranslation(tableConfig.i18nNamespaces);
const { setNodeRef } = useDroppable({ id: FORM_SIDEBAR_DROPPABLE_ID });

const { hiddenFields, visibleFields, unavailableFields } = useMemo(() => {
if (!activeViewId) {
Expand All @@ -93,6 +101,9 @@ export const FormSidebar = () => {
return unavailableFields.push(field);
}
if (view.columnMeta?.[id]?.visible) {
if (sidebarAdditionalFieldId && sidebarAdditionalFieldId === id) {
hiddenFields.push(field);
}
return visibleFields.push(field);
}
hiddenFields.push(field);
Expand All @@ -102,7 +113,7 @@ export const FormSidebar = () => {
visibleFields,
unavailableFields,
};
}, [activeViewId, allFields, view?.columnMeta]);
}, [activeViewId, allFields, view?.columnMeta, sidebarAdditionalFieldId]);

const onFieldShown = (field: IFieldInstance) => {
view &&
Expand Down Expand Up @@ -151,11 +162,16 @@ export const FormSidebar = () => {

<div className="mb-4 h-auto grow overflow-y-auto px-4">
{isHydrated && (
<>
<div ref={setNodeRef}>
{hiddenFields.map((field) => {
const { id } = field;
return (
<DraggableItem key={id} id={id} field={field}>
<DraggableItem
key={'sidebar_' + id}
id={id}
field={field}
draggingClassName={'opacity-50'}
>
<DragItem
field={field}
onClick={() => onFieldShown(field)}
Expand All @@ -176,11 +192,11 @@ export const FormSidebar = () => {
/>
);
})}
</>
<div className="flex h-16 w-full items-center justify-center rounded border-2 border-dashed text-[13px] text-slate-400 dark:text-slate-600">
{t('table:form.hideFieldTip')}
</div>
</div>
)}
<div className="flex h-16 w-full items-center justify-center rounded border-2 border-dashed text-[13px] text-slate-400 dark:text-slate-600">
{t('table:form.hideFieldTip')}
</div>
</div>

<div className="w-full px-4">
Expand Down
Loading