chore: get board groups and rows

This commit is contained in:
ascarbek 2023-03-12 22:29:03 +06:00
parent a9c8bad599
commit c80e77ab16
6 changed files with 56 additions and 214 deletions

View File

@ -20,9 +20,9 @@ export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fi
// ignore the return value, because we are using the subscription
void cellController.getCellData();
// dispose the cell controller when the component is unmounted
return () => {
void cellController.dispose();
// dispose is causing an error
// void cellController.dispose();
};
}, []);

View File

@ -1,30 +1,26 @@
import { useEffect, useState } from 'react';
import { DatabaseController } from '../../../stores/effects/database/database_controller';
import {
databaseActions,
DatabaseFieldMap,
IDatabaseColumn,
IDatabaseRow,
} from '../../../stores/reducers/database/slice';
import { useAppDispatch, useAppSelector } from '../../../stores/store';
import { databaseActions, DatabaseFieldMap, IDatabaseColumn } from '../../../stores/reducers/database/slice';
import { useAppDispatch } from '../../../stores/store';
import loadField from './loadField';
import { FieldInfo } from '../../../stores/effects/database/field/field_controller';
import { RowInfo } from '../../../stores/effects/database/row/row_cache';
import { ViewLayoutTypePB } from '@/services/backend';
import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller';
export const useDatabase = (viewId: string) => {
export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => {
const dispatch = useAppDispatch();
const databaseStore = useAppSelector((state) => state.database);
const boardStore = useAppSelector((state) => state.board);
const [controller, setController] = useState<DatabaseController>();
const [rows, setRows] = useState<readonly RowInfo[]>([]);
const [groups, setGroups] = useState<readonly DatabaseGroupController[]>([]);
useEffect(() => {
if (!viewId.length) return;
const c = new DatabaseController(viewId);
setController(c);
// on unmount dispose the controller
return () => void c.dispose();
// dispose is causing an error
// return () => void c.dispose();
}, [viewId]);
const loadFields = async (fieldInfos: readonly FieldInfo[]) => {
@ -45,7 +41,6 @@ export const useDatabase = (viewId: string) => {
dispatch(databaseActions.updateFields({ fields }));
dispatch(databaseActions.updateColumns({ columns }));
console.log(fields, columns);
};
useEffect(() => {
@ -61,8 +56,12 @@ export const useDatabase = (viewId: string) => {
},
});
await controller.open();
if (type === ViewLayoutTypePB.Board) {
setGroups(controller.groups.value);
}
})();
}, [controller]);
return { loadFields, controller, rows };
return { loadFields, controller, rows, groups };
};

View File

@ -1,55 +0,0 @@
import { useEffect, useState } from 'react';
import { useAppDispatch, useAppSelector } from '../../stores/store';
import { boardActions } from '../../stores/reducers/board/slice';
import { ISelectOption, ISelectOptionType } from '../../stores/reducers/database/slice';
export const useBoard = () => {
const dispatch = useAppDispatch();
const groupingFieldId = useAppSelector((state) => state.board);
const database = useAppSelector((state) => state.database);
const [title, setTitle] = useState('');
const [boardColumns, setBoardColumns] = useState<ISelectOption[]>([]);
const [movingRowId, setMovingRowId] = useState<string | undefined>(undefined);
const [ghostLocation, setGhostLocation] = useState<{ column: number; row: number }>({ column: 0, row: 0 });
useEffect(() => {
setTitle(database.title);
if (database.fields[groupingFieldId]) {
setBoardColumns(
(database.fields[groupingFieldId].fieldOptions as ISelectOptionType | undefined)?.selectOptions || []
);
}
}, [database, groupingFieldId]);
const changeGroupingField = (fieldId: string) => {
dispatch(
boardActions.setGroupingFieldId({
fieldId,
})
);
};
const onGhostItemMove = (columnIndex: number, rowIndex: number) => {
setGhostLocation({ column: columnIndex, row: rowIndex });
};
const startMove = (rowId: string) => {
setMovingRowId(rowId);
};
const endMove = () => {
setMovingRowId(undefined);
};
return {
title,
boardColumns,
groupingFieldId,
changeGroupingField,
startMove,
endMove,
onGhostItemMove,
movingRowId,
ghostLocation,
};
};

View File

@ -2,29 +2,17 @@ import { SettingsSvg } from '../_shared/svg/SettingsSvg';
import { SearchInput } from '../_shared/SearchInput';
import { BoardBlock } from './BoardBlock';
import { NewBoardBlock } from './NewBoardBlock';
import { useBoard } from './Board.hooks';
import { useDatabase } from '../_shared/database-hooks/useDatabase';
import { ViewLayoutTypePB } from '@/services/backend';
export const Board = ({ viewId }: { viewId: string }) => {
const { controller, rows } = useDatabase(viewId);
const {
title,
boardColumns,
groupingFieldId,
changeGroupingField,
startMove,
endMove,
onGhostItemMove,
movingRowId,
ghostLocation,
} = useBoard();
const { controller, rows, groups } = useDatabase(viewId, ViewLayoutTypePB.Board);
return (
<>
<div className='flex w-full items-center justify-between'>
<div className={'flex items-center text-xl font-semibold'}>
<div>{title}</div>
<div>{'Kanban'}</div>
<button className={'ml-2 h-5 w-5'}>
<SettingsSvg></SettingsSvg>
</button>
@ -37,16 +25,15 @@ export const Board = ({ viewId }: { viewId: string }) => {
<div className={'relative w-full flex-1 overflow-auto'}>
<div className={'absolute flex h-full flex-shrink-0 items-start justify-start gap-4'}>
{controller &&
boardColumns?.map((column, index) => (
groups &&
groups.map((group, index) => (
<BoardBlock
key={index}
viewId={viewId}
controller={controller}
key={index}
title={column.title}
rows={rows}
groupingFieldId={groupingFieldId}
startMove={startMove}
endMove={endMove}
rows={group.rows}
title={group.name}
allRows={rows}
/>
))}

View File

@ -3,23 +3,20 @@ import AddSvg from '../_shared/svg/AddSvg';
import { BoardCard } from './BoardCard';
import { RowInfo } from '../../stores/effects/database/row/row_cache';
import { DatabaseController } from '../../stores/effects/database/database_controller';
import { RowPB } from '@/services/backend';
export const BoardBlock = ({
viewId,
controller,
title,
groupingFieldId,
rows,
startMove,
endMove,
allRows,
}: {
viewId: string;
controller: DatabaseController;
title: string;
groupingFieldId: string;
rows: readonly RowInfo[];
startMove: (id: string) => void;
endMove: () => void;
rows: RowPB[];
allRows: readonly RowInfo[];
}) => {
return (
<div className={'flex h-full w-[250px] flex-col rounded-lg bg-surface-1'}>
@ -38,17 +35,14 @@ export const BoardBlock = ({
</div>
</div>
<div className={'flex flex-1 flex-col gap-1 overflow-auto px-2'}>
{rows.map((row, index) => (
<BoardCard
viewId={viewId}
controller={controller}
key={index}
groupingFieldId={groupingFieldId}
row={row}
startMove={() => startMove(row.row.id)}
endMove={() => endMove()}
></BoardCard>
))}
{rows.map((row_pb, index) => {
const row = allRows.find((r) => r.row.id === row_pb.id);
return row ? (
<BoardCard viewId={viewId} controller={controller} key={index} rowInfo={row}></BoardCard>
) : (
<span key={index}></span>
);
})}
</div>
<div className={'p-2'}>
<button className={'flex w-full items-center gap-2 rounded-lg px-2 py-2 hover:bg-surface-2'}>

View File

@ -1,121 +1,38 @@
import { DatabaseFieldMap, IDatabaseColumn, IDatabaseRow } from '../../stores/reducers/database/slice';
import { Details2Svg } from '../_shared/svg/Details2Svg';
import { FieldType } from '../../../services/backend';
import { getBgColor } from '../_shared/getColor';
import { MouseEventHandler, useEffect, useRef, useState } from 'react';
import { RowInfo } from '../../stores/effects/database/row/row_cache';
import { useRow } from '../_shared/database-hooks/useRow';
import { DatabaseController } from '../../stores/effects/database/database_controller';
import { useAppSelector } from '../../stores/store';
import { BoardCell } from './BoardCell';
export const BoardCard = ({
viewId,
controller,
groupingFieldId,
// fields,
// columns,
row,
startMove,
endMove,
rowInfo,
}: {
viewId: string;
controller: DatabaseController;
groupingFieldId: string;
// fields: DatabaseFieldMap;
// columns: IDatabaseColumn[];
row: RowInfo;
startMove: () => void;
endMove: () => void;
rowInfo: RowInfo;
}) => {
const { cells } = useRow(viewId, controller, row);
const databaseStore = useAppSelector((state) => state.database);
const [isMoving, setIsMoving] = useState(false);
const [isDown, setIsDown] = useState(false);
const [ghostWidth, setGhostWidth] = useState(0);
const [ghostHeight, setGhostHeight] = useState(0);
const [ghostLeft, setGhostLeft] = useState(0);
const [ghostTop, setGhostTop] = useState(0);
const el = useRef<HTMLDivElement>(null);
useEffect(() => {
if (el.current?.getBoundingClientRect && isMoving) {
const { left, top, width, height } = el.current.getBoundingClientRect();
setGhostWidth(width);
setGhostHeight(height);
setGhostLeft(left);
setGhostTop(top);
startMove();
const gEl = document.getElementById('ghost-block');
if (gEl?.innerHTML) {
gEl.innerHTML = el.current.innerHTML;
}
}
}, [el, isMoving]);
const onMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {
setGhostLeft(ghostLeft + e.movementX);
setGhostTop(ghostTop + e.movementY);
};
const onMouseUp: MouseEventHandler<HTMLDivElement> = (e) => {
setIsMoving(false);
endMove();
};
const dragStart = () => {
if (isDown) {
setIsMoving(true);
setIsDown(false);
}
};
const { cells } = useRow(viewId, controller, rowInfo);
return (
<>
<div
ref={el}
onMouseDown={() => setIsDown(true)}
onMouseMove={dragStart}
onMouseUp={() => setIsDown(false)}
onClick={() => console.log('on click')}
className={`relative cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2 transition-transform duration-100 hover:bg-main-selector `}
>
<button className={'absolute right-4 top-2.5 h-5 w-5 rounded hover:bg-surface-2'}>
<Details2Svg></Details2Svg>
</button>
<div className={'flex flex-col gap-3'}>
{cells.map((cell, index) => (
<BoardCell
key={index}
cellIdentifier={cell.cellIdentifier}
cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
fieldController={controller.fieldController}
></BoardCell>
))}
</div>
<div
onClick={() => console.log('on click')}
className={`relative cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2 transition-transform duration-100 hover:bg-main-selector `}
>
<button className={'absolute right-4 top-2.5 h-5 w-5 rounded hover:bg-surface-2'}>
<Details2Svg></Details2Svg>
</button>
<div className={'flex flex-col gap-3'}>
{cells.map((cell, index) => (
<BoardCell
key={index}
cellIdentifier={cell.cellIdentifier}
cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
fieldController={controller.fieldController}
></BoardCell>
))}
</div>
{isMoving && (
<div
onMouseMove={onMouseMove}
onMouseUp={onMouseUp}
onMouseLeave={onMouseUp}
id={'ghost-block'}
className={
'fixed z-10 rotate-6 scale-105 cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2'
}
style={{
width: `${ghostWidth}px`,
height: `${ghostHeight}px`,
left: `${ghostLeft}px`,
top: `${ghostTop}px`,
}}
>
&nbsp;
</div>
)}
</>
</div>
);
};