From 6935653e159fc3ee88fa572291b34bab9566da7a Mon Sep 17 00:00:00 2001 From: Askarbek Zadauly Date: Sat, 27 May 2023 19:12:14 +0600 Subject: [PATCH] chore: Edit Row changes (#2564) * chore: checklist value and popup * chore: properties side panel * chore: reorganize checklist field * chore: delete property promt * chore: delete property reorganize * fix: dnd bug of checklist field * fix: whitespace on empty fields * chore: new checklist item * fix: duplicate view * fix: named checklist bars * chore: checklist padding * fix: onclick * chore: change to nullish coalescing operator * chore: remove empty string from use translation * fix: add missing translations * chore: refactor select option and checklist field editors --- .../components/_shared/Button.tsx | 7 +- .../components/_shared/CheckListProgress.tsx | 27 ++ .../_shared/EditRow/CellOptionsPopup.tsx | 156 -------- .../_shared/EditRow/CheckList/CheckList.tsx | 40 +++ .../EditRow/CheckList/CheckListOption.tsx | 60 ++++ .../EditRow/CheckList/CheckListPopup.tsx | 97 +++++ .../EditRow/CheckList/EditCheckListPopup.tsx | 94 +++++ .../EditRow/CheckList/NewCheckListButton.tsx | 28 ++ .../EditRow/CheckList/NewCheckListOption.tsx | 53 +++ .../EditRow/{ => Date}/DateFormatPopup.tsx | 6 +- .../EditRow/{ => Date}/DatePickerPopup.tsx | 2 +- .../{ => Date}/DateTimeFormat.hooks.ts | 0 .../EditRow/{ => Date}/DateTypeOptions.tsx | 13 +- .../EditRow/{ => Date}/EditCellDate.tsx | 8 +- .../EditRow/{ => Date}/NumberFormat.hooks.ts | 5 +- .../EditRow/{ => Date}/NumberFormatPopup.tsx | 4 +- .../EditRow/{ => Date}/TimeFormatPopup.tsx | 6 +- .../_shared/EditRow/EditCellWrapper.tsx | 46 ++- .../_shared/EditRow/EditFieldPopup.tsx | 26 +- .../components/_shared/EditRow/EditRow.tsx | 336 +++++++++++------- .../_shared/EditRow/FieldTypeName.tsx | 2 +- .../{ => InlineEditFields}/EditCellNumber.tsx | 4 +- .../{ => InlineEditFields}/EditCellText.tsx | 8 +- .../{ => InlineEditFields}/EditCellUrl.tsx | 4 +- .../EditCheckboxCell.tsx | 2 +- .../_shared/EditRow/Options/CellOption.tsx | 69 ++++ .../EditRow/{ => Options}/CellOptions.tsx | 14 +- .../EditRow/Options/CellOptionsPopup.tsx | 104 ++++++ .../{ => Options}/EditCellOptionPopup.tsx | 2 +- .../EditRow/Options/SelectedOption.tsx | 30 ++ .../_shared/EditRow/PropertiesPanel.tsx | 169 +++++++++ .../components/_shared/PopupWindow.tsx | 6 +- .../components/_shared/PromptWindow.tsx | 24 ++ .../components/_shared/Switch.tsx | 8 + .../components/_shared/svg/DragElementSvg.tsx | 12 + .../components/_shared/svg/ImageSvg.tsx | 9 + .../components/auth/Login/Login.tsx | 9 +- .../components/auth/SignUp/SignUp.tsx | 8 +- .../appflowy_app/components/board/Board.tsx | 2 - .../components/board/BoardCard.tsx | 5 +- .../components/board/BoardCell.tsx | 11 +- .../components/board/BoardCheckListCell.tsx | 37 ++ .../components/board/BoardDateCell.tsx | 2 +- .../components/board/BoardGroup.tsx | 5 +- .../components/board/BoardOptionsCell.tsx | 4 +- .../components/board/BoardSettingsPopup.tsx | 2 +- .../components/board/BoardTextCell.tsx | 3 +- .../components/board/BoardUrlCell.tsx | 4 +- .../components/board/NewBoardBlock.tsx | 14 - .../components/grid/GridCell/GridCheckBox.tsx | 2 +- .../components/grid/GridCell/GridDate.tsx | 4 +- .../grid/GridCell/GridNumberCell.tsx | 2 +- .../grid/GridCell/GridSingleSelectOptions.tsx | 6 +- .../components/grid/GridCell/GridTextCell.tsx | 2 +- .../components/grid/GridCell/GridUrl.tsx | 2 +- .../grid/GridTableHeader/GridTableHeader.tsx | 2 +- .../grid/GridTableRows/GridAddRow.tsx | 2 +- .../layout/HeaderPanel/Breadcrumbs.tsx | 4 +- .../NavigationPanel/FolderItem.hooks.ts | 14 +- .../layout/NavigationPanel/FolderItem.tsx | 4 +- .../NavigationPanel/NewFolderButton.hooks.ts | 2 +- .../layout/NavigationPanel/PageItem.hooks.ts | 11 +- .../components/layout/Workspace.hooks.ts | 2 +- .../components/tests/AllIcons.tsx | 8 + frontend/appflowy_tauri/src/main.tsx | 1 + frontend/appflowy_tauri/src/styles/switch.css | 58 +++ 66 files changed, 1281 insertions(+), 432 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx delete mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/DateFormatPopup.tsx (95%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/DatePickerPopup.tsx (98%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/DateTimeFormat.hooks.ts (100%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/DateTypeOptions.tsx (95%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/EditCellDate.tsx (67%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/NumberFormat.hooks.ts (88%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/NumberFormatPopup.tsx (97%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Date}/TimeFormatPopup.tsx (94%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => InlineEditFields}/EditCellNumber.tsx (90%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => InlineEditFields}/EditCellText.tsx (82%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => InlineEditFields}/EditCellUrl.tsx (89%) rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => InlineEditFields}/EditCheckboxCell.tsx (99%) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOption.tsx rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Options}/CellOptions.tsx (71%) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptionsPopup.tsx rename frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/{ => Options}/EditCellOptionPopup.tsx (99%) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/SelectedOption.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/PropertiesPanel.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/PromptWindow.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/Switch.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/DragElementSvg.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/ImageSvg.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckListCell.tsx delete mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/NewBoardBlock.tsx create mode 100644 frontend/appflowy_tauri/src/styles/switch.css diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx index 1055f83495..cb637e7f1c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx @@ -5,7 +5,7 @@ export const Button = ({ children, onClick, }: { - size?: 'primary' | 'medium' | 'small' | 'box-small-transparent'; + size?: 'primary' | 'medium' | 'small' | 'box-small-transparent' | 'medium-transparent'; children: ReactNode; onClick?: MouseEventHandler; }) => { @@ -21,6 +21,11 @@ export const Button = ({ case 'small': setCls('w-[68px] h-[32px] flex items-center justify-center rounded-lg bg-main-accent text-white text-xs'); break; + case 'medium-transparent': + setCls( + 'w-[170px] h-[48px] flex items-center justify-center rounded-lg border border-main-accent text-main-accent transition-colors duration-300 hover:bg-main-hovered hover:text-white' + ); + break; case 'box-small-transparent': setCls('text-black hover:text-main-accent w-[24px] h-[24px]'); break; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx new file mode 100644 index 0000000000..bea90b64eb --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx @@ -0,0 +1,27 @@ +export const CheckListProgress = ({ completed, max }: { completed: number; max: number }) => { + return ( +
+ {max > 0 && ( + <> +
+ {completed > 0 && filledCheckListBars({ amount: completed })} + {max - completed > 0 && emptyCheckListBars({ amount: max - completed })} +
+
{((100 * completed) / max).toFixed(0)}%
+ + )} +
+ ); +}; + +const filledCheckListBars = ({ amount }: { amount: number }) => { + return Array(amount) + .fill(0) + .map((item, index) =>
); +}; + +const emptyCheckListBars = ({ amount }: { amount: number }) => { + return Array(amount) + .fill(0) + .map((item, index) =>
); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx deleted file mode 100644 index 48ff2de44f..0000000000 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { KeyboardEventHandler, useEffect, useRef, useState } from 'react'; -import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; -import { useCell } from '$app/components/_shared/database-hooks/useCell'; -import { CellCache } from '$app/stores/effects/database/cell/cell_cache'; -import { FieldController } from '$app/stores/effects/database/field/field_controller'; -import { SelectOptionCellDataPB, SelectOptionColorPB, SelectOptionPB } from '@/services/backend'; -import { getBgColor } from '$app/components/_shared/getColor'; -import { useTranslation } from 'react-i18next'; -import { Details2Svg } from '$app/components/_shared/svg/Details2Svg'; -import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg'; -import { CloseSvg } from '$app/components/_shared/svg/CloseSvg'; -import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc'; -import { useAppSelector } from '$app/stores/store'; -import { ISelectOption, ISelectOptionType } from '$app/stores/reducers/database/slice'; -import { PopupWindow } from '$app/components/_shared/PopupWindow'; - -export const CellOptionsPopup = ({ - top, - left, - cellIdentifier, - cellCache, - fieldController, - onOutsideClick, - openOptionDetail, -}: { - top: number; - left: number; - cellIdentifier: CellIdentifier; - cellCache: CellCache; - fieldController: FieldController; - onOutsideClick: () => void; - openOptionDetail: (_left: number, _top: number, _select_option: SelectOptionPB) => void; -}) => { - const inputRef = useRef(null); - const { t } = useTranslation(''); - const [value, setValue] = useState(''); - const { data } = useCell(cellIdentifier, cellCache, fieldController); - const databaseStore = useAppSelector((state) => state.database); - - useEffect(() => { - if (inputRef?.current) { - inputRef.current.focus(); - } - }, [inputRef]); - - const onKeyDown: KeyboardEventHandler = async (e) => { - if (e.key === 'Enter' && value.length > 0) { - await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value }); - setValue(''); - } - }; - - const onUnselectOptionClick = async (option: SelectOptionPB) => { - await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.id]); - setValue(''); - }; - - const onToggleOptionClick = async (option: SelectOptionPB) => { - if ((data as SelectOptionCellDataPB)?.select_options?.find((selectedOption) => selectedOption.id === option.id)) { - await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.id]); - } else { - await new SelectOptionCellBackendService(cellIdentifier).selectOption([option.id]); - } - setValue(''); - }; - - const onKeyDownWrapper: KeyboardEventHandler = (e) => { - if (e.key === 'Escape') { - onOutsideClick(); - } - }; - - const onOptionDetailClick = (e: any, option: ISelectOption) => { - e.stopPropagation(); - let target = e.target as HTMLElement; - - while (!(target instanceof HTMLButtonElement)) { - if (target.parentElement === null) return; - target = target.parentElement; - } - - const selectOption = new SelectOptionPB({ - id: option.selectOptionId, - name: option.title, - color: option.color || SelectOptionColorPB.Purple, - }); - - const { right: _left, top: _top } = target.getBoundingClientRect(); - openOptionDetail(_left, _top, selectOption); - }; - - return ( - -
-
-
- {(data as SelectOptionCellDataPB)?.select_options?.map((option, index) => ( -
- {option?.name || ''} - -
- )) || ''} -
- setValue(e.target.value)} - placeholder={t('grid.selectOption.searchOption') || ''} - onKeyDown={onKeyDown} - /> -
{value.length}/30
-
-
-
{t('grid.selectOption.panelTitle') || ''}
-
- {(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map( - (option, index) => ( -
- onToggleOptionClick( - new SelectOptionPB({ - id: option.selectOptionId, - name: option.title, - color: option.color || SelectOptionColorPB.Purple, - }) - ) - } - className={ - 'flex cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-main-secondary' - } - > -
{option.title}
-
- {(data as SelectOptionCellDataPB)?.select_options?.find( - (selectedOption) => selectedOption.id === option.selectOptionId - ) && ( - - )} - -
-
- ) - )} -
-
-
- ); -}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx new file mode 100644 index 0000000000..b008191555 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx @@ -0,0 +1,40 @@ +import { SelectOptionCellDataPB } from '@/services/backend'; +import { useEffect, useRef, useState } from 'react'; +import { ISelectOptionType } from '$app_reducers/database/slice'; +import { useAppSelector } from '$app/stores/store'; +import { CheckListProgress } from '$app/components/_shared/CheckListProgress'; + +export const CheckList = ({ + data, + fieldId, + onEditClick, +}: { + data: SelectOptionCellDataPB | undefined; + fieldId: string; + onEditClick: (left: number, top: number) => void; +}) => { + const ref = useRef(null); + const [allOptionsCount, setAllOptionsCount] = useState(0); + const [selectedOptionsCount, setSelectedOptionsCount] = useState(0); + const databaseStore = useAppSelector((state) => state.database); + + useEffect(() => { + setAllOptionsCount((databaseStore.fields[fieldId]?.fieldOptions as ISelectOptionType)?.selectOptions?.length ?? 0); + }, [databaseStore, fieldId]); + + useEffect(() => { + setSelectedOptionsCount((data as SelectOptionCellDataPB)?.select_options?.length ?? 0); + }, [data]); + + const onClick = () => { + if (!ref.current) return; + const { left, top } = ref.current.getBoundingClientRect(); + onEditClick(left, top); + }; + + return ( +
+ +
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx new file mode 100644 index 0000000000..380898a35d --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx @@ -0,0 +1,60 @@ +import { SelectOptionPB } from '@/services/backend'; +import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg'; +import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg'; +import { Details2Svg } from '$app/components/_shared/svg/Details2Svg'; +import { ISelectOption } from '$app_reducers/database/slice'; +import { MouseEventHandler } from 'react'; + +export const CheckListOption = ({ + option, + checked, + onToggleOptionClick, + openCheckListDetail, +}: { + option: ISelectOption; + checked: boolean; + onToggleOptionClick: (v: SelectOptionPB) => void; + openCheckListDetail: (left: number, top: number, option: SelectOptionPB) => void; +}) => { + const onCheckListDetailClick: MouseEventHandler = (e) => { + e.stopPropagation(); + let target = e.target as HTMLElement; + + while (!(target instanceof HTMLButtonElement)) { + if (target.parentElement === null) return; + target = target.parentElement; + } + + const selectOption = new SelectOptionPB({ + id: option.selectOptionId, + name: option.title, + }); + + const { right: _left, top: _top } = target.getBoundingClientRect(); + openCheckListDetail(_left, _top, selectOption); + }; + + return ( +
+ onToggleOptionClick( + new SelectOptionPB({ + id: option.selectOptionId, + name: option.title, + }) + ) + } + > +
+ {checked ? : } +
+
{option.title}
+
+ +
+
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx new file mode 100644 index 0000000000..9b3424858d --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx @@ -0,0 +1,97 @@ +import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; +import { SelectOptionCellDataPB, SelectOptionPB } from '@/services/backend'; +import { PopupWindow } from '$app/components/_shared/PopupWindow'; +import { ISelectOptionType } from '$app_reducers/database/slice'; +import { useAppSelector } from '$app/stores/store'; +import { useCell } from '$app/components/_shared/database-hooks/useCell'; +import { CellCache } from '$app/stores/effects/database/cell/cell_cache'; +import { FieldController } from '$app/stores/effects/database/field/field_controller'; +import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc'; +import { useEffect, useState } from 'react'; +import { CheckListProgress } from '$app/components/_shared/CheckListProgress'; +import { NewCheckListOption } from '$app/components/_shared/EditRow/CheckList/NewCheckListOption'; +import { CheckListOption } from '$app/components/_shared/EditRow/CheckList/CheckListOption'; +import { NewCheckListButton } from '$app/components/_shared/EditRow/CheckList/NewCheckListButton'; + +export const CheckListPopup = ({ + left, + top, + cellIdentifier, + cellCache, + fieldController, + openCheckListDetail, + onOutsideClick, +}: { + left: number; + top: number; + cellIdentifier: CellIdentifier; + cellCache: CellCache; + fieldController: FieldController; + openCheckListDetail: (left: number, top: number, option: SelectOptionPB) => void; + onOutsideClick: () => void; +}) => { + const databaseStore = useAppSelector((state) => state.database); + const { data } = useCell(cellIdentifier, cellCache, fieldController); + + const [allOptionsCount, setAllOptionsCount] = useState(0); + const [selectedOptionsCount, setSelectedOptionsCount] = useState(0); + const [newOptions, setNewOptions] = useState([]); + + useEffect(() => { + setAllOptionsCount( + (databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType)?.selectOptions?.length ?? 0 + ); + }, [databaseStore, cellIdentifier]); + + useEffect(() => { + setSelectedOptionsCount((data as SelectOptionCellDataPB)?.select_options?.length ?? 0); + }, [data]); + + const onToggleOptionClick = async (option: SelectOptionPB) => { + if ((data as SelectOptionCellDataPB)?.select_options?.find((selectedOption) => selectedOption.id === option.id)) { + await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.id]); + } else { + await new SelectOptionCellBackendService(cellIdentifier).selectOption([option.id]); + } + }; + + return ( + +
+
+ +
+ +
+ {(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map( + (option, index) => ( + so.id === option.selectOptionId) + } + onToggleOptionClick={onToggleOptionClick} + openCheckListDetail={openCheckListDetail} + > + ) + )} + {newOptions.map((option, index) => ( + + ))} +
+
+
+ +
+
+
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx new file mode 100644 index 0000000000..45f4d4efb6 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx @@ -0,0 +1,94 @@ +import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; +import { KeyboardEventHandler, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { SelectOptionPB } from '@/services/backend'; +import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc'; +import { TrashSvg } from '$app/components/_shared/svg/TrashSvg'; +import { PopupWindow } from '$app/components/_shared/PopupWindow'; + +export const EditCheckListPopup = ({ + left, + top, + cellIdentifier, + editingSelectOption, + onOutsideClick, +}: { + left: number; + top: number; + cellIdentifier: CellIdentifier; + editingSelectOption: SelectOptionPB; + onOutsideClick: () => void; +}) => { + const inputRef = useRef(null); + const { t } = useTranslation(); + const [value, setValue] = useState(''); + + useEffect(() => { + setValue(editingSelectOption.name); + }, [editingSelectOption]); + + const onKeyDown: KeyboardEventHandler = async (e) => { + if (e.key === 'Enter' && value.length > 0) { + await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value }); + setValue(''); + } + }; + + const onKeyDownWrapper: KeyboardEventHandler = (e) => { + if (e.key === 'Escape') { + onOutsideClick(); + } + }; + + const onBlur = async () => { + const svc = new SelectOptionCellBackendService(cellIdentifier); + await svc.updateOption( + new SelectOptionPB({ + id: editingSelectOption.id, + name: value, + }) + ); + }; + + const onDeleteOptionClick = async () => { + const svc = new SelectOptionCellBackendService(cellIdentifier); + await svc.deleteOption([editingSelectOption]); + }; + + return ( + { + await onBlur(); + onOutsideClick(); + }} + left={left} + top={top} + > +
+
+ setValue(e.target.value)} + onKeyDown={onKeyDown} + onBlur={() => onBlur()} + /> +
{value.length}/30
+
+ +
+
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx new file mode 100644 index 0000000000..b9aff6a93c --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx @@ -0,0 +1,28 @@ +import AddSvg from '$app/components/_shared/svg/AddSvg'; +import { useTranslation } from 'react-i18next'; + +export const NewCheckListButton = ({ + newOptions, + setNewOptions, +}: { + newOptions: string[]; + setNewOptions: (v: string[]) => void; +}) => { + const { t } = useTranslation(); + + const newOptionClick = () => { + setNewOptions([...newOptions, '']); + }; + + return ( + + ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx new file mode 100644 index 0000000000..7c860b6720 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx @@ -0,0 +1,53 @@ +import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc'; +import { useTranslation } from 'react-i18next'; +import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; + +export const NewCheckListOption = ({ + index, + option, + newOptions, + setNewOptions, + cellIdentifier, +}: { + index: number; + option: string; + newOptions: string[]; + setNewOptions: (v: string[]) => void; + cellIdentifier: CellIdentifier; +}) => { + const { t } = useTranslation(); + + const updateNewOption = (value: string) => { + const newOptionsCopy = [...newOptions]; + newOptionsCopy[index] = value; + setNewOptions(newOptionsCopy); + }; + + const onNewOptionKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter') { + void onSaveNewOptionClick(); + } + }; + + const onSaveNewOptionClick = async () => { + await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: newOptions[index] }); + setNewOptions(newOptions.filter((_, i) => i !== index)); + }; + + return ( +
+ onNewOptionKeyDown(e as unknown as KeyboardEvent)} + className={'min-w-0 flex-1 pl-7'} + value={option} + onChange={(e) => updateNewOption(e.target.value)} + /> + +
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx similarity index 95% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateFormatPopup.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx index 287667143b..de8d2f2722 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateFormatPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx @@ -4,10 +4,10 @@ import { PopupWindow } from '$app/components/_shared/PopupWindow'; import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg'; import { useTranslation } from 'react-i18next'; import { DateFormatPB } from '@/services/backend'; -import { useDateTimeFormat } from '$app/components/_shared/EditRow/DateTimeFormat.hooks'; +import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks'; import { useAppSelector } from '$app/stores/store'; import { useEffect, useState } from 'react'; -import { IDateType } from '$app/stores/reducers/database/slice'; +import { IDateType } from '$app_reducers/database/slice'; export const DateFormatPopup = ({ left, @@ -22,7 +22,7 @@ export const DateFormatPopup = ({ fieldController: FieldController; onOutsideClick: () => void; }) => { - const { t } = useTranslation(''); + const { t } = useTranslation(); const { changeDateFormat } = useDateTimeFormat(cellIdentifier, fieldController); const databaseStore = useAppSelector((state) => state.database); const [dateType, setDateType] = useState(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DatePickerPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx similarity index 98% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DatePickerPopup.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx index bfc0830cfb..e9eb02af8e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DatePickerPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx @@ -8,7 +8,7 @@ import { useCell } from '$app/components/_shared/database-hooks/useCell'; import { CalendarData } from '$app/stores/effects/database/cell/controller_builder'; import { DateCellDataPB } from '@/services/backend'; import { PopupWindow } from '$app/components/_shared/PopupWindow'; -import { DateTypeOptions } from '$app/components/_shared/EditRow/DateTypeOptions'; +import { DateTypeOptions } from '$app/components/_shared/EditRow/Date/DateTypeOptions'; export const DatePickerPopup = ({ left, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateTimeFormat.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTimeFormat.hooks.ts similarity index 100% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateTimeFormat.hooks.ts rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTimeFormat.hooks.ts diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateTypeOptions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx similarity index 95% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateTypeOptions.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx index 9d357ced90..254382df2e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DateTypeOptions.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx @@ -1,13 +1,13 @@ -import { DateFormatPopup } from '$app/components/_shared/EditRow/DateFormatPopup'; -import { TimeFormatPopup } from '$app/components/_shared/EditRow/TimeFormatPopup'; +import { DateFormatPopup } from '$app/components/_shared/EditRow/Date/DateFormatPopup'; +import { TimeFormatPopup } from '$app/components/_shared/EditRow/Date/TimeFormatPopup'; import { MoreSvg } from '$app/components/_shared/svg/MoreSvg'; import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg'; import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg'; import { MouseEventHandler, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { IDateType } from '$app/stores/reducers/database/slice'; +import { IDateType } from '$app_reducers/database/slice'; import { useAppSelector } from '$app/stores/store'; -import { useDateTimeFormat } from '$app/components/_shared/EditRow/DateTimeFormat.hooks'; +import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks'; import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; import { FieldController } from '$app/stores/effects/database/field/field_controller'; @@ -18,7 +18,7 @@ export const DateTypeOptions = ({ cellIdentifier: CellIdentifier; fieldController: FieldController; }) => { - const { t } = useTranslation(''); + const { t } = useTranslation(); const [showDateFormatPopup, setShowDateFormatPopup] = useState(false); const [dateFormatTop, setDateFormatTop] = useState(0); @@ -105,9 +105,6 @@ export const DateTypeOptions = ({ } >
- {/* - - */} {t('grid.field.includeTime')}
{/**/} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellDate.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx similarity index 67% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellDate.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx index e4661ceeaf..08f0871d7c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellDate.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { MouseEventHandler, useRef } from 'react'; import { DateCellDataPB } from '@/services/backend'; export const EditCellDate = ({ @@ -10,15 +10,15 @@ export const EditCellDate = ({ }) => { const ref = useRef(null); - const onClick = () => { + const onClick: MouseEventHandler = () => { if (!ref.current) return; const { left, top } = ref.current.getBoundingClientRect(); onEditClick(left, top); }; return ( -
onClick()} className={'w-full px-4 py-2'}> - {data?.date || <> } +
+ {data?.date} 
); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormat.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts similarity index 88% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormat.hooks.ts rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts index 8953ab8940..945074e460 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormat.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts @@ -3,10 +3,7 @@ import { FieldController } from '$app/stores/effects/database/field/field_contro import { FieldType, NumberFormatPB } from '@/services/backend'; import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller'; import { Some } from 'ts-results'; -import { - makeDateTypeOptionContext, - makeNumberTypeOptionContext, -} from '$app/stores/effects/database/field/type_option/type_option_context'; +import { makeNumberTypeOptionContext } from '$app/stores/effects/database/field/type_option/type_option_context'; export const useNumberFormat = (cellIdentifier: CellIdentifier, fieldController: FieldController) => { const changeNumberFormat = async (format: NumberFormatPB) => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx similarity index 97% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormatPopup.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx index b755af2552..2c1502e22f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/NumberFormatPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx @@ -1,12 +1,12 @@ import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; import { FieldController } from '$app/stores/effects/database/field/field_controller'; import { PopupWindow } from '$app/components/_shared/PopupWindow'; -import { useNumberFormat } from '$app/components/_shared/EditRow/NumberFormat.hooks'; +import { useNumberFormat } from '$app/components/_shared/EditRow/Date/NumberFormat.hooks'; import { NumberFormatPB } from '@/services/backend'; import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg'; import { useAppSelector } from '$app/stores/store'; import { useEffect, useState } from 'react'; -import { INumberType } from '$app/stores/reducers/database/slice'; +import { INumberType } from '$app_reducers/database/slice'; const list = [ { format: NumberFormatPB.Num, title: 'Num' }, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/TimeFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx similarity index 94% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/TimeFormatPopup.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx index 8eb0ecabd2..d12e88ad87 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/TimeFormatPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx @@ -4,10 +4,10 @@ import { useTranslation } from 'react-i18next'; import { PopupWindow } from '$app/components/_shared/PopupWindow'; import { TimeFormatPB } from '@/services/backend'; import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg'; -import { useDateTimeFormat } from '$app/components/_shared/EditRow/DateTimeFormat.hooks'; +import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks'; import { useAppSelector } from '$app/stores/store'; import { useEffect, useState } from 'react'; -import { IDateType } from '$app/stores/reducers/database/slice'; +import { IDateType } from '$app_reducers/database/slice'; export const TimeFormatPopup = ({ left, @@ -22,7 +22,7 @@ export const TimeFormatPopup = ({ fieldController: FieldController; onOutsideClick: () => void; }) => { - const { t } = useTranslation(''); + const { t } = useTranslation(); const databaseStore = useAppSelector((state) => state.database); const [dateType, setDateType] = useState(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx index f63ad57459..9728043975 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx @@ -4,15 +4,17 @@ import { CellCache } from '$app/stores/effects/database/cell/cell_cache'; import { FieldController } from '$app/stores/effects/database/field/field_controller'; import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '@/services/backend'; import { useAppSelector } from '$app/stores/store'; -import { EditCellText } from '$app/components/_shared/EditRow/EditCellText'; +import { EditCellText } from '$app/components/_shared/EditRow/InlineEditFields/EditCellText'; import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon'; -import { EditCellDate } from '$app/components/_shared/EditRow/EditCellDate'; +import { EditCellDate } from '$app/components/_shared/EditRow/Date/EditCellDate'; import { useRef } from 'react'; -import { CellOptions } from '$app/components/_shared/EditRow/CellOptions'; -import { EditCellNumber } from '$app/components/_shared/EditRow/EditCellNumber'; -import { EditCheckboxCell } from '$app/components/_shared/EditRow/EditCheckboxCell'; -import { EditCellUrl } from '$app/components/_shared/EditRow/EditCellUrl'; +import { CellOptions } from '$app/components/_shared/EditRow/Options/CellOptions'; +import { EditCellNumber } from '$app/components/_shared/EditRow/InlineEditFields/EditCellNumber'; +import { EditCheckboxCell } from '$app/components/_shared/EditRow/InlineEditFields/EditCheckboxCell'; +import { EditCellUrl } from '$app/components/_shared/EditRow/InlineEditFields/EditCellUrl'; import { Draggable } from 'react-beautiful-dnd'; +import { DragElementSvg } from '$app/components/_shared/svg/DragElementSvg'; +import { CheckList } from '$app/components/_shared/EditRow/CheckList/CheckList'; export const EditCellWrapper = ({ index, @@ -22,6 +24,7 @@ export const EditCellWrapper = ({ onEditFieldClick, onEditOptionsClick, onEditDateClick, + onEditCheckListClick, }: { index: number; cellIdentifier: CellIdentifier; @@ -30,6 +33,7 @@ export const EditCellWrapper = ({ onEditFieldClick: (cell: CellIdentifier, left: number, top: number) => void; onEditOptionsClick: (cell: CellIdentifier, left: number, top: number) => void; onEditDateClick: (cell: CellIdentifier, left: number, top: number) => void; + onEditCheckListClick: (cell: CellIdentifier, left: number, top: number) => void; }) => { const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController); const databaseStore = useAppSelector((state) => state.database); @@ -48,26 +52,28 @@ export const EditCellWrapper = ({ ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} - className={'flex w-full items-center text-xs'} + className={'flex w-full flex-col items-start gap-2 text-xs'} >
onClick()} className={ - 'relative flex w-[180px] cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 hover:bg-shade-6' + 'relative flex cursor-pointer items-center gap-2 rounded-lg text-white transition-colors duration-200 hover:text-shade-3' } > -
+
onClick()} className={'flex h-5 w-5'}> + +
+ +
- - {databaseStore.fields[cellIdentifier.fieldId]?.title || ''} + + {databaseStore.fields[cellIdentifier.fieldId]?.title ?? ''}
-
+ +
{(cellIdentifier.fieldType === FieldType.SingleSelect || - cellIdentifier.fieldType === FieldType.MultiSelect || - cellIdentifier.fieldType === FieldType.Checklist) && + cellIdentifier.fieldType === FieldType.MultiSelect) && cellController && ( )} + {cellIdentifier.fieldType === FieldType.Checklist && cellController && ( + onEditCheckListClick(cellIdentifier, left, top)} + > + )} + {cellIdentifier.fieldType === FieldType.Checkbox && cellController && ( void; }) => { const databaseStore = useAppSelector((state) => state.database); - const { t } = useTranslation(''); + const { t } = useTranslation(); const changeTypeButtonRef = useRef(null); const [name, setName] = useState(''); @@ -56,15 +55,6 @@ export const EditFieldPopup = ({ changeFieldTypeClick(buttonTop, buttonRight); }; - // this is causing an error right now - const onDeleteFieldClick = async () => { - if (!fieldInfo) return; - const controller = new TypeOptionController(viewId, Some(fieldInfo)); - await controller.initialize(); - await controller.deleteField(); - onOutsideClick(); - }; - const onNumberFormatClick: MouseEventHandler = (e) => { e.stopPropagation(); let target = e.target as HTMLElement; @@ -96,18 +86,6 @@ export const EditFieldPopup = ({ className={'border-shades-3 flex-1 rounded border bg-main-selector px-2 py-2'} /> - -
onChangeFieldTypeClick()} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx index 8936e288d3..f592a21dd4 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx @@ -12,11 +12,16 @@ import { ChangeFieldTypePopup } from '$app/components/_shared/EditRow/ChangeFiel import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller'; import { Some } from 'ts-results'; import { FieldType, SelectOptionPB } from '@/services/backend'; -import { CellOptionsPopup } from '$app/components/_shared/EditRow/CellOptionsPopup'; -import { DatePickerPopup } from '$app/components/_shared/EditRow/DatePickerPopup'; +import { CellOptionsPopup } from '$app/components/_shared/EditRow/Options/CellOptionsPopup'; +import { DatePickerPopup } from '$app/components/_shared/EditRow/Date/DatePickerPopup'; import { DragDropContext, Droppable, OnDragEndResponder } from 'react-beautiful-dnd'; -import { EditCellOptionPopup } from '$app/components/_shared/EditRow/EditCellOptionPopup'; -import { NumberFormatPopup } from '$app/components/_shared/EditRow/NumberFormatPopup'; +import { EditCellOptionPopup } from '$app/components/_shared/EditRow/Options/EditCellOptionPopup'; +import { NumberFormatPopup } from '$app/components/_shared/EditRow/Date/NumberFormatPopup'; +import { CheckListPopup } from '$app/components/_shared/EditRow/CheckList/CheckListPopup'; +import { EditCheckListPopup } from '$app/components/_shared/EditRow/CheckList/EditCheckListPopup'; +import { PropertiesPanel } from '$app/components/_shared/EditRow/PropertiesPanel'; +import { ImageSvg } from '$app/components/_shared/svg/ImageSvg'; +import { PromptWindow } from '$app/components/_shared/PromptWindow'; export const EditRow = ({ onClose, @@ -30,7 +35,7 @@ export const EditRow = ({ rowInfo: RowInfo; }) => { const { cells, onNewColumnClick } = useRow(viewId, controller, rowInfo); - const { t } = useTranslation(''); + const { t } = useTranslation(); const [unveil, setUnveil] = useState(false); const [editingCell, setEditingCell] = useState(null); @@ -56,10 +61,21 @@ export const EditRow = ({ const [editingSelectOption, setEditingSelectOption] = useState(); + const [showEditCheckList, setShowEditCheckList] = useState(false); + const [editCheckListTop, setEditCheckListTop] = useState(0); + const [editCheckListLeft, setEditCheckListLeft] = useState(0); + const [showNumberFormatPopup, setShowNumberFormatPopup] = useState(false); const [numberFormatTop, setNumberFormatTop] = useState(0); const [numberFormatLeft, setNumberFormatLeft] = useState(0); + const [showCheckListPopup, setShowCheckListPopup] = useState(false); + const [checkListPopupTop, setCheckListPopupTop] = useState(0); + const [checkListPopupLeft, setCheckListPopupLeft] = useState(0); + + const [deletingPropertyId, setDeletingPropertyId] = useState(null); + const [showDeletePropertyPrompt, setShowDeletePropertyPrompt] = useState(false); + useEffect(() => { setUnveil(true); }, []); @@ -125,12 +141,26 @@ export const EditRow = ({ setEditCellOptionTop(_top); }; + const onOpenCheckListDetailClick = (_left: number, _top: number, _select_option: SelectOptionPB) => { + setEditingSelectOption(_select_option); + setShowEditCheckList(true); + setEditCheckListLeft(_left + 10); + setEditCheckListTop(_top); + }; + const onNumberFormat = (_left: number, _top: number) => { setShowNumberFormatPopup(true); setNumberFormatLeft(_left + 10); setNumberFormatTop(_top); }; + const onEditCheckListClick = (cellIdentifier: CellIdentifier, left: number, top: number) => { + setEditingCell(cellIdentifier); + setShowCheckListPopup(true); + setCheckListPopupLeft(left); + setCheckListPopupTop(top + 40); + }; + const onDragEnd: OnDragEndResponder = (result) => { if (!result.destination?.index) return; void controller.moveField({ @@ -140,129 +170,193 @@ export const EditRow = ({ }); }; + const onDeletePropertyClick = (fieldId: string) => { + setDeletingPropertyId(fieldId); + setShowDeletePropertyPrompt(true); + }; + + const onDelete = async () => { + if (!deletingPropertyId) return; + const fieldInfo = controller.fieldController.getField(deletingPropertyId); + if (!fieldInfo) return; + const typeController = new TypeOptionController(viewId, Some(fieldInfo)); + await typeController.initialize(); + await typeController.deleteField(); + setShowDeletePropertyPrompt(false); + }; + return ( -
onCloseClick()} - > + <>
{ - e.stopPropagation(); - }} - className={`relative flex h-[90%] w-[70%] flex-col gap-8 rounded-xl bg-white px-8 pb-4 pt-12`} + className={`fixed inset-0 z-10 flex items-center justify-center bg-black/30 backdrop-blur-sm transition-opacity duration-300 ${ + unveil ? 'opacity-100' : 'opacity-0' + }`} + onClick={() => onCloseClick()} > -
onCloseClick()} className={'absolute top-4 right-4'}> - -
+
{ + e.stopPropagation(); + }} + className={`relative flex h-[90%] w-[70%] flex-col gap-8 rounded-xl bg-white `} + > +
onCloseClick()} className={'absolute top-1 right-1'}> + +
- - - {(provided) => ( -
- {cells.map((cell, cellIndex) => ( - - ))} +
+
+
+
- )} - - -
- + + + {(provided) => ( +
+ {cells.map((cell, cellIndex) => ( + + ))} +
+ )} +
+
+ +
+ +
+
+ +
+ + {showFieldEditor && editingCell && ( + + )} + {showChangeFieldTypePopup && ( + changeFieldType(newType)} + onOutsideClick={() => setShowChangeFieldTypePopup(false)} + > + )} + {showChangeOptionsPopup && editingCell && ( + setShowChangeOptionsPopup(false)} + openOptionDetail={onOpenOptionDetailClick} + > + )} + {showDatePicker && editingCell && ( + setShowDatePicker(false)} + > + )} + {showEditCellOption && editingCell && editingSelectOption && ( + { + setShowEditCellOption(false); + }} + > + )} + {showNumberFormatPopup && editingCell && ( + { + setShowNumberFormatPopup(false); + }} + > + )} + {showCheckListPopup && editingCell && ( + setShowCheckListPopup(false)} + openCheckListDetail={onOpenCheckListDetailClick} + > + )} + {showEditCheckList && editingCell && editingSelectOption && ( + setShowEditCheckList(false)} + > + )}
- - {showFieldEditor && editingCell && ( - - )} - {showChangeFieldTypePopup && ( - changeFieldType(newType)} - onOutsideClick={() => setShowChangeFieldTypePopup(false)} - > - )} - {showChangeOptionsPopup && editingCell && ( - setShowChangeOptionsPopup(false)} - openOptionDetail={onOpenOptionDetailClick} - > - )} - {showDatePicker && editingCell && ( - setShowDatePicker(false)} - > - )} - {showEditCellOption && editingCell && editingSelectOption && ( - { - setShowEditCellOption(false); - }} - > - )} - {showNumberFormatPopup && editingCell && ( - { - setShowNumberFormatPopup(false); - }} - > - )}
-
+ {showDeletePropertyPrompt && ( + onDelete()} + onCancel={() => setShowDeletePropertyPrompt(false)} + > + )} + ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx index 4e52da0a7c..daeff4cdf0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx @@ -2,7 +2,7 @@ import { FieldType } from '@/services/backend'; import { useTranslation } from 'react-i18next'; export const FieldTypeName = ({ fieldType }: { fieldType: FieldType }) => { - const { t } = useTranslation(''); + const { t } = useTranslation(); return ( <> {fieldType === FieldType.RichText && t('grid.field.textFieldName')} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellNumber.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx similarity index 90% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellNumber.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx index 205ddd9257..efe1afd5f0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellNumber.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx @@ -11,7 +11,7 @@ export const EditCellNumber = ({ const [value, setValue] = useState(''); useEffect(() => { - setValue(data || ''); + setValue(data ?? ''); }, [data]); const save = async () => { @@ -23,7 +23,7 @@ export const EditCellNumber = ({ value={value} onChange={(e) => setValue(e.target.value)} onBlur={() => save()} - className={'w-full px-4 py-2'} + className={'w-full px-4 py-1'} > ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellText.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx similarity index 82% rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellText.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx index 1d119af3e4..80247a6f71 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellText.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx @@ -12,12 +12,12 @@ export const EditCellText = ({ const [contentRows, setContentRows] = useState(1); useEffect(() => { - setValue(data || ''); + setValue(data ?? ''); }, [data]); useEffect(() => { if (!value?.length) return; - setContentRows(Math.max(1, (value || '').split('\n').length)); + setContentRows(Math.max(1, (value ?? '').split('\n').length)); }, [value]); const onTextFieldChange = async (v: string) => { @@ -29,9 +29,9 @@ export const EditCellText = ({ }; return ( -
+