ascarbek 2 лет назад
Родитель
Сommit
c3a7f94cb3

+ 4 - 0
frontend/appflowy_tauri/src/appflowy_app/components/TestColors/TestColors.tsx

@@ -37,6 +37,7 @@ import { SortSvg } from '$app/components/_shared/svg/SortSvg';
 import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg';
 import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg';
 import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
 import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
 import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg';
 import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg';
+import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
 
 
 export const TestColors = () => {
 export const TestColors = () => {
   return (
   return (
@@ -110,6 +111,9 @@ export const TestColors = () => {
           <i className={'h-5 w-5'}>
           <i className={'h-5 w-5'}>
             <GridSvg></GridSvg>
             <GridSvg></GridSvg>
           </i>
           </i>
+          <i className={'h-5 w-5'}>
+            <GroupByFieldSvg></GroupByFieldSvg>
+          </i>
           <i className={'h-5 w-5'}>
           <i className={'h-5 w-5'}>
             <HideMenuSvg></HideMenuSvg>
             <HideMenuSvg></HideMenuSvg>
           </i>
           </i>

+ 9 - 7
frontend/appflowy_tauri/src/appflowy_app/components/_shared/Popup.tsx

@@ -2,7 +2,7 @@ import { MouseEvent, ReactNode, useRef } from 'react';
 import useOutsideClick from './useOutsideClick';
 import useOutsideClick from './useOutsideClick';
 
 
 export interface IPopupItem {
 export interface IPopupItem {
-  icon: ReactNode;
+  icon: ReactNode | (() => JSX.Element);
   title: string;
   title: string;
   onClick: () => void;
   onClick: () => void;
 }
 }
@@ -31,18 +31,20 @@ export const Popup = ({
   return (
   return (
     <div ref={ref} className={`${className} rounded-lg bg-white px-2 py-2 shadow-md`} style={style}>
     <div ref={ref} className={`${className} rounded-lg bg-white px-2 py-2 shadow-md`} style={style}>
       <div
       <div
-        className={`grid ${columns === 1 && 'grid-cols-1'} ${columns === 2 && 'grid-cols-2'} ${
-          columns === 3 && 'grid-cols-3'
-        } gap-x-4`}
+        className={
+          (columns === 2 ? 'grid grid-cols-2' : '') + (columns === 3 ? 'grid grid-cols-3' : '') + ' w-full gap-x-4'
+        }
       >
       >
         {items.map((item, index) => (
         {items.map((item, index) => (
           <button
           <button
             key={index}
             key={index}
-            className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 hover:bg-main-secondary'}
+            className={'flex w-full cursor-pointer items-center gap-2 rounded-lg px-2 py-2 hover:bg-main-secondary'}
             onClick={(e) => handleClick(e, item)}
             onClick={(e) => handleClick(e, item)}
           >
           >
-            {item.icon}
-            <span className={'flex-shrink-0'}>{item.title}</span>
+            <>
+              {typeof item.icon === 'function' ? item.icon() : item.icon}
+              <span className={'flex-shrink-0'}>{item.title}</span>
+            </>
           </button>
           </button>
         ))}
         ))}
       </div>
       </div>

+ 26 - 0
frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/GroupByFieldSvg.tsx

@@ -0,0 +1,26 @@
+export const GroupByFieldSvg = () => {
+  return (
+    <svg width='100%' height='100%' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
+      <path
+        d='M10 2H13C13.5523 2 14 2.44772 14 3V6'
+        stroke='currentColor'
+        strokeLinecap='round'
+        strokeLinejoin='round'
+      />
+      <path d='M6 2H3C2.44772 2 2 2.44772 2 3V6' stroke='currentColor' strokeLinecap='round' strokeLinejoin='round' />
+      <path
+        d='M6 14H3C2.44772 14 2 13.5523 2 13V10'
+        stroke='currentColor'
+        strokeLinecap='round'
+        strokeLinejoin='round'
+      />
+      <path
+        d='M10 14H13C13.5523 14 14 13.5523 14 13V10'
+        stroke='currentColor'
+        strokeLinecap='round'
+        strokeLinejoin='round'
+      />
+      <rect x='6' y='6' width='4' height='4' rx='1' stroke='currentColor' />
+    </svg>
+  );
+};

+ 2 - 6
frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx

@@ -8,6 +8,7 @@ import { DragDropContext } from 'react-beautiful-dnd';
 import { useState } from 'react';
 import { useState } from 'react';
 import { RowInfo } from '$app/stores/effects/database/row/row_cache';
 import { RowInfo } from '$app/stores/effects/database/row/row_cache';
 import { EditRow } from '$app/components/_shared/EditRow/EditRow';
 import { EditRow } from '$app/components/_shared/EditRow/EditRow';
+import { BoardToolbar } from '$app/components/board/BoardToolbar';
 
 
 export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
 export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
   const { controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutPB.Board);
   const { controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutPB.Board);
@@ -22,12 +23,7 @@ export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
   return (
   return (
     <>
     <>
       <div className='flex w-full items-center justify-between'>
       <div className='flex w-full items-center justify-between'>
-        <div className={'flex items-center text-xl font-semibold'}>
-          <div>{title}</div>
-          <button className={'ml-2 h-5 w-5'}>
-            <SettingsSvg></SettingsSvg>
-          </button>
-        </div>
+        <BoardToolbar title={title} />
 
 
         <div className='flex shrink-0 items-center gap-4'>
         <div className='flex shrink-0 items-center gap-4'>
           <SearchInput />
           <SearchInput />

+ 36 - 0
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx

@@ -0,0 +1,36 @@
+import { useAppSelector } from '$app/stores/store';
+import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
+import { Popup } from '$app/components/_shared/Popup';
+import { useRef } from 'react';
+import useOutsideClick from '$app/components/_shared/useOutsideClick';
+import { EyeOpenSvg } from '$app/components/_shared/svg/EyeOpenSvg';
+
+export const BoardFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
+  const columns = useAppSelector((state) => state.database.columns);
+  const fields = useAppSelector((state) => state.database.fields);
+  const ref = useRef<HTMLDivElement>(null);
+  useOutsideClick(ref, () => hidePopup());
+
+  return (
+    <div ref={ref} className={'absolute top-full left-full z-10 rounded-lg bg-white px-2 py-2 shadow-md'}>
+      {columns.map((column, index) => (
+        <div
+          className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-main-secondary'}
+          key={index}
+        >
+          <div className={'flex items-center gap-2 '}>
+            <i className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
+              <FieldTypeIcon fieldType={fields[column.fieldId].fieldType}></FieldTypeIcon>
+            </i>
+            <span className={'flex-shrink-0'}>{fields[column.fieldId].title}</span>
+          </div>
+          <div className={'ml-12'}>
+            <i className={'block h-5 w-5'}>
+              <EyeOpenSvg></EyeOpenSvg>
+            </i>
+          </div>
+        </div>
+      ))}
+    </div>
+  );
+};

+ 3 - 0
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx

@@ -0,0 +1,3 @@
+export const BoardGroupFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
+  return <></>;
+};

+ 48 - 0
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx

@@ -0,0 +1,48 @@
+import { useEffect, useState } from 'react';
+import { PropertiesSvg } from '$app/components/_shared/svg/PropertiesSvg';
+import { IPopupItem, Popup } from '$app/components/_shared/Popup';
+import { useTranslation } from 'react-i18next';
+import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
+
+export const BoardSettingsPopup = ({
+  hidePopup,
+  onFieldsClick,
+  onGroupClick,
+}: {
+  hidePopup: () => void;
+  onFieldsClick: () => void;
+  onGroupClick: () => void;
+}) => {
+  const [settingsItems, setSettingsItems] = useState<IPopupItem[]>([]);
+  const { t } = useTranslation('');
+  useEffect(() => {
+    setSettingsItems([
+      {
+        icon: (
+          <i className={'h-5 w-5'}>
+            <PropertiesSvg></PropertiesSvg>
+          </i>
+        ),
+        title: t('grid.settings.Properties'),
+        onClick: onFieldsClick,
+      },
+      {
+        icon: (
+          <i className={'h-5 w-5'}>
+            <GroupByFieldSvg></GroupByFieldSvg>
+          </i>
+        ),
+        title: t('grid.settings.group'),
+        onClick: onGroupClick,
+      },
+    ]);
+  }, [t]);
+
+  return (
+    <Popup
+      onOutsideClick={() => hidePopup()}
+      items={settingsItems}
+      className={'absolute top-full left-full z-10'}
+    ></Popup>
+  );
+};

+ 37 - 0
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts

@@ -0,0 +1,37 @@
+import { useState } from 'react';
+
+export const useBoardToolbar = () => {
+  const [showSettings, setShowSettings] = useState(false);
+  const [showAllFields, setShowAllFields] = useState(false);
+  const [showGroupFields, setShowGroupFields] = useState(false);
+
+  const onSettingsClick = () => {
+    setShowSettings(!showSettings);
+  };
+
+  const onFieldsClick = () => {
+    setShowSettings(false);
+    setShowAllFields(true);
+  };
+
+  const onGroupClick = () => {
+    setShowSettings(false);
+    setShowGroupFields(true);
+  };
+
+  const hidePopup = () => {
+    setShowSettings(false);
+    setShowAllFields(false);
+    setShowGroupFields(false);
+  };
+
+  return {
+    showSettings,
+    onSettingsClick,
+    onFieldsClick,
+    onGroupClick,
+    hidePopup,
+    showAllFields,
+    showGroupFields,
+  };
+};

+ 28 - 0
frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx

@@ -0,0 +1,28 @@
+import { SettingsSvg } from '$app/components/_shared/svg/SettingsSvg';
+import { useBoardToolbar } from '$app/components/board/BoardToolbar.hooks';
+import { BoardSettingsPopup } from '$app/components/board/BoardSettingsPopup';
+import { BoardFieldsPopup } from '$app/components/board/BoardFieldsPopup';
+import { BoardGroupFieldsPopup } from '$app/components/board/BoardGroupFieldsPopup';
+
+export const BoardToolbar = ({ title }: { title: string }) => {
+  const { showSettings, showAllFields, showGroupFields, onSettingsClick, onFieldsClick, onGroupClick, hidePopup } =
+    useBoardToolbar();
+
+  return (
+    <div className={'relative flex items-center gap-2'}>
+      <div className={'text-xl font-semibold'}>{title}</div>
+      <button onClick={() => onSettingsClick()} className={'h-5 w-5'}>
+        <SettingsSvg></SettingsSvg>
+      </button>
+      {showSettings && (
+        <BoardSettingsPopup
+          hidePopup={hidePopup}
+          onFieldsClick={onFieldsClick}
+          onGroupClick={onGroupClick}
+        ></BoardSettingsPopup>
+      )}
+      {showAllFields && <BoardFieldsPopup hidePopup={hidePopup}></BoardFieldsPopup>}
+      {showGroupFields && <BoardGroupFieldsPopup hidePopup={hidePopup}></BoardGroupFieldsPopup>}
+    </div>
+  );
+};