mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: move fields dnd
This commit is contained in:
parent
d1d667c497
commit
c7acf9a594
@ -12,8 +12,10 @@ import { CellOptions } from '$app/components/_shared/EditRow/CellOptions';
|
|||||||
import { EditCellNumber } from '$app/components/_shared/EditRow/EditCellNumber';
|
import { EditCellNumber } from '$app/components/_shared/EditRow/EditCellNumber';
|
||||||
import { EditCheckboxCell } from '$app/components/_shared/EditRow/EditCheckboxCell';
|
import { EditCheckboxCell } from '$app/components/_shared/EditRow/EditCheckboxCell';
|
||||||
import { EditCellUrl } from '$app/components/_shared/EditRow/EditCellUrl';
|
import { EditCellUrl } from '$app/components/_shared/EditRow/EditCellUrl';
|
||||||
|
import { Draggable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
export const EditCellWrapper = ({
|
export const EditCellWrapper = ({
|
||||||
|
index,
|
||||||
cellIdentifier,
|
cellIdentifier,
|
||||||
cellCache,
|
cellCache,
|
||||||
fieldController,
|
fieldController,
|
||||||
@ -21,6 +23,7 @@ export const EditCellWrapper = ({
|
|||||||
onEditOptionsClick,
|
onEditOptionsClick,
|
||||||
onEditDateClick,
|
onEditDateClick,
|
||||||
}: {
|
}: {
|
||||||
|
index: number;
|
||||||
cellIdentifier: CellIdentifier;
|
cellIdentifier: CellIdentifier;
|
||||||
cellCache: CellCache;
|
cellCache: CellCache;
|
||||||
fieldController: FieldController;
|
fieldController: FieldController;
|
||||||
@ -39,50 +42,61 @@ export const EditCellWrapper = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'flex w-full items-center text-xs'}>
|
<Draggable draggableId={cellIdentifier.fieldId} index={index}>
|
||||||
<div
|
{(provided) => (
|
||||||
ref={el}
|
<div
|
||||||
onClick={() => onClick()}
|
ref={provided.innerRef}
|
||||||
className={'relative flex w-[180px] cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 hover:bg-shade-6'}
|
{...provided.draggableProps}
|
||||||
>
|
{...provided.dragHandleProps}
|
||||||
<div className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
|
className={'flex w-full items-center text-xs'}
|
||||||
<FieldTypeIcon fieldType={cellIdentifier.fieldType}></FieldTypeIcon>
|
>
|
||||||
|
<div
|
||||||
|
ref={el}
|
||||||
|
onClick={() => onClick()}
|
||||||
|
className={
|
||||||
|
'relative flex w-[180px] cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 hover:bg-shade-6'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
|
||||||
|
<FieldTypeIcon fieldType={cellIdentifier.fieldType}></FieldTypeIcon>
|
||||||
|
</div>
|
||||||
|
<span className={'overflow-hidden text-ellipsis whitespace-nowrap'}>
|
||||||
|
{databaseStore.fields[cellIdentifier.fieldId].title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={'flex-1 cursor-pointer rounded-lg hover:bg-shade-6'}>
|
||||||
|
{(cellIdentifier.fieldType === FieldType.SingleSelect ||
|
||||||
|
cellIdentifier.fieldType === FieldType.MultiSelect ||
|
||||||
|
cellIdentifier.fieldType === FieldType.Checklist) &&
|
||||||
|
cellController && (
|
||||||
|
<CellOptions
|
||||||
|
data={data as SelectOptionCellDataPB | undefined}
|
||||||
|
onEditClick={onEditOptionsClick}
|
||||||
|
></CellOptions>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cellIdentifier.fieldType === FieldType.Checkbox && cellController && (
|
||||||
|
<EditCheckboxCell data={data as boolean | undefined} cellController={cellController}></EditCheckboxCell>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cellIdentifier.fieldType === FieldType.DateTime && (
|
||||||
|
<EditCellDate data={data as DateCellDataPB | undefined} onEditClick={onEditDateClick}></EditCellDate>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cellIdentifier.fieldType === FieldType.Number && cellController && (
|
||||||
|
<EditCellNumber data={data as string | undefined} cellController={cellController}></EditCellNumber>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cellIdentifier.fieldType === FieldType.URL && cellController && (
|
||||||
|
<EditCellUrl data={data as URLCellDataPB | undefined} cellController={cellController}></EditCellUrl>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cellIdentifier.fieldType === FieldType.RichText && cellController && (
|
||||||
|
<EditCellText data={data as string | undefined} cellController={cellController}></EditCellText>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span className={'overflow-hidden text-ellipsis whitespace-nowrap'}>
|
)}
|
||||||
{databaseStore.fields[cellIdentifier.fieldId].title}
|
</Draggable>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={'flex-1 cursor-pointer rounded-lg hover:bg-shade-6'}>
|
|
||||||
{(cellIdentifier.fieldType === FieldType.SingleSelect ||
|
|
||||||
cellIdentifier.fieldType === FieldType.MultiSelect ||
|
|
||||||
cellIdentifier.fieldType === FieldType.Checklist) &&
|
|
||||||
cellController && (
|
|
||||||
<CellOptions
|
|
||||||
data={data as SelectOptionCellDataPB | undefined}
|
|
||||||
onEditClick={onEditOptionsClick}
|
|
||||||
></CellOptions>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{cellIdentifier.fieldType === FieldType.Checkbox && cellController && (
|
|
||||||
<EditCheckboxCell data={data as boolean | undefined} cellController={cellController}></EditCheckboxCell>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{cellIdentifier.fieldType === FieldType.DateTime && (
|
|
||||||
<EditCellDate data={data as DateCellDataPB | undefined} onEditClick={onEditDateClick}></EditCellDate>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{cellIdentifier.fieldType === FieldType.Number && cellController && (
|
|
||||||
<EditCellNumber data={data as string | undefined} cellController={cellController}></EditCellNumber>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{cellIdentifier.fieldType === FieldType.URL && cellController && (
|
|
||||||
<EditCellUrl data={data as URLCellDataPB | undefined} cellController={cellController}></EditCellUrl>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{cellIdentifier.fieldType === FieldType.RichText && cellController && (
|
|
||||||
<EditCellText data={data as string | undefined} cellController={cellController}></EditCellText>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,7 @@ import { Some } from 'ts-results';
|
|||||||
import { FieldType } from '@/services/backend';
|
import { FieldType } from '@/services/backend';
|
||||||
import { CellOptionsPopup } from '$app/components/_shared/EditRow/CellOptionsPopup';
|
import { CellOptionsPopup } from '$app/components/_shared/EditRow/CellOptionsPopup';
|
||||||
import { DatePickerPopup } from '$app/components/_shared/EditRow/DatePickerPopup';
|
import { DatePickerPopup } from '$app/components/_shared/EditRow/DatePickerPopup';
|
||||||
|
import { DragDropContext, Droppable, OnDragEndResponder } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
export const EditRow = ({
|
export const EditRow = ({
|
||||||
onClose,
|
onClose,
|
||||||
@ -105,6 +106,11 @@ export const EditRow = ({
|
|||||||
setShowDatePicker(true);
|
setShowDatePicker(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDragEnd: OnDragEndResponder = (result) => {
|
||||||
|
if (!result.destination?.index) return;
|
||||||
|
void controller.moveField(result.source.droppableId, result.source.index, result.destination.index);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`fixed inset-0 z-10 flex items-center justify-center bg-black/30 backdrop-blur-sm transition-opacity duration-300 ${
|
className={`fixed inset-0 z-10 flex items-center justify-center bg-black/30 backdrop-blur-sm transition-opacity duration-300 ${
|
||||||
@ -117,19 +123,35 @@ export const EditRow = ({
|
|||||||
<CloseSvg></CloseSvg>
|
<CloseSvg></CloseSvg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={`flex flex-1 flex-col gap-2 ${showFieldEditor ? 'overflow-hidden' : 'overflow-auto'}`}>
|
|
||||||
{cells.map((cell, cellIndex) => (
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<EditCellWrapper
|
<Droppable droppableId={'field-list'}>
|
||||||
key={cellIndex}
|
{(provided) => (
|
||||||
cellIdentifier={cell.cellIdentifier}
|
<div
|
||||||
cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
|
{...provided.droppableProps}
|
||||||
fieldController={controller.fieldController}
|
ref={provided.innerRef}
|
||||||
onEditFieldClick={(top: number, right: number) => onEditFieldClick(cell.cellIdentifier, top, right)}
|
className={`flex flex-1 flex-col gap-2 ${
|
||||||
onEditOptionsClick={(left: number, top: number) => onEditOptionsClick(cell.cellIdentifier, left, top)}
|
showFieldEditor || showChangeOptionsPopup || showDatePicker ? 'overflow-hidden' : 'overflow-auto'
|
||||||
onEditDateClick={(left: number, top: number) => onEditDateClick(cell.cellIdentifier, left, top)}
|
}`}
|
||||||
></EditCellWrapper>
|
>
|
||||||
))}
|
{cells.map((cell, cellIndex) => (
|
||||||
</div>
|
<EditCellWrapper
|
||||||
|
index={cellIndex}
|
||||||
|
key={cellIndex}
|
||||||
|
cellIdentifier={cell.cellIdentifier}
|
||||||
|
cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
|
||||||
|
fieldController={controller.fieldController}
|
||||||
|
onEditFieldClick={(top: number, right: number) => onEditFieldClick(cell.cellIdentifier, top, right)}
|
||||||
|
onEditOptionsClick={(left: number, top: number) =>
|
||||||
|
onEditOptionsClick(cell.cellIdentifier, left, top)
|
||||||
|
}
|
||||||
|
onEditDateClick={(left: number, top: number) => onEditDateClick(cell.cellIdentifier, left, top)}
|
||||||
|
></EditCellWrapper>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
|
||||||
<div className={'border-t border-shade-6 pt-2'}>
|
<div className={'border-t border-shade-6 pt-2'}>
|
||||||
<button
|
<button
|
||||||
|
@ -5,10 +5,12 @@ import {
|
|||||||
DatabaseEventGetFields,
|
DatabaseEventGetFields,
|
||||||
DatabaseEventGetGroup,
|
DatabaseEventGetGroup,
|
||||||
DatabaseEventGetGroups,
|
DatabaseEventGetGroups,
|
||||||
|
DatabaseEventMoveField,
|
||||||
DatabaseEventMoveGroup,
|
DatabaseEventMoveGroup,
|
||||||
DatabaseEventMoveGroupRow,
|
DatabaseEventMoveGroupRow,
|
||||||
DatabaseEventMoveRow,
|
DatabaseEventMoveRow,
|
||||||
DatabaseGroupIdPB,
|
DatabaseGroupIdPB,
|
||||||
|
MoveFieldPayloadPB,
|
||||||
MoveGroupPayloadPB,
|
MoveGroupPayloadPB,
|
||||||
MoveGroupRowPayloadPB,
|
MoveGroupRowPayloadPB,
|
||||||
MoveRowPayloadPB,
|
MoveRowPayloadPB,
|
||||||
@ -96,6 +98,16 @@ export class DatabaseBackendService {
|
|||||||
return DatabaseEventMoveGroup(payload);
|
return DatabaseEventMoveGroup(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
moveField = (fieldId: string, fromIndex: number, toIndex: number) => {
|
||||||
|
const payload = MoveFieldPayloadPB.fromObject({
|
||||||
|
view_id: this.viewId,
|
||||||
|
field_id: fieldId,
|
||||||
|
from_index: fromIndex,
|
||||||
|
to_index: toIndex,
|
||||||
|
});
|
||||||
|
return DatabaseEventMoveField(payload);
|
||||||
|
};
|
||||||
|
|
||||||
/// Get all fields in database
|
/// Get all fields in database
|
||||||
getFields = async (fieldIds?: FieldIdPB[]) => {
|
getFields = async (fieldIds?: FieldIdPB[]) => {
|
||||||
const payload = GetFieldPayloadPB.fromObject({ view_id: this.viewId });
|
const payload = GetFieldPayloadPB.fromObject({ view_id: this.viewId });
|
||||||
|
@ -102,6 +102,10 @@ export class DatabaseController {
|
|||||||
return this.backendService.moveGroup(fromGroupId, toGroupId);
|
return this.backendService.moveGroup(fromGroupId, toGroupId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
moveField = (fieldId: string, fromIndex: number, toIndex: number) => {
|
||||||
|
return this.backendService.moveField(fieldId, fromIndex, toIndex);
|
||||||
|
};
|
||||||
|
|
||||||
private loadGroup = async () => {
|
private loadGroup = async () => {
|
||||||
const result = await this.backendService.loadGroups();
|
const result = await this.backendService.loadGroups();
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
|
Loading…
Reference in New Issue
Block a user