فهرست منبع

chore: get board groups and rows

ascarbek 2 سال پیش
والد
کامیت
c80e77ab16

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts

@@ -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();
     };
   }, []);
 

+ 13 - 14
frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts

@@ -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 };
 };

+ 0 - 55
frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts

@@ -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,
-  };
-};

+ 9 - 22
frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx

@@ -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}
               />
             ))}
 

+ 12 - 18
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx

@@ -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'}>

+ 20 - 103
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx

@@ -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>
   );
 };