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 index 3bb53e472c..825f396b92 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CellOptionsPopup.tsx @@ -1,4 +1,4 @@ -import { KeyboardEventHandler, useEffect, useRef, useState } from 'react'; +import { KeyboardEventHandler, MouseEventHandler, 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'; @@ -21,6 +21,7 @@ export const CellOptionsPopup = ({ cellCache, fieldController, onOutsideClick, + openOptionDetail, }: { top: number; left: number; @@ -28,6 +29,7 @@ export const CellOptionsPopup = ({ cellCache: CellCache; fieldController: FieldController; onOutsideClick: () => void; + openOptionDetail: (_left: number, _top: number) => void; }) => { const ref = useRef(null); const inputRef = useRef(null); @@ -88,6 +90,19 @@ export const CellOptionsPopup = ({ } }; + const onOptionDetailClick: MouseEventHandler = (e) => { + e.stopPropagation(); + let target = e.target as HTMLElement; + + while (!(target instanceof HTMLButtonElement)) { + if (target.parentElement === null) return; + target = target.parentElement; + } + + const { right: _left, top: _top } = target.getBoundingClientRect(); + openOptionDetail(_left, _top); + }; + return (
{value.length}/30
-
{t('grid.selectOption.panelTitle') || ''}
+
{t('grid.selectOption.panelTitle') || ''}
{(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map( (option, index) => ( @@ -148,7 +163,7 @@ export const CellOptionsPopup = ({ )} -
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellOptionPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellOptionPopup.tsx new file mode 100644 index 0000000000..f57bc37925 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellOptionPopup.tsx @@ -0,0 +1,185 @@ +import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; +import { CellCache } from '$app/stores/effects/database/cell/cell_cache'; +import { FieldController } from '$app/stores/effects/database/field/field_controller'; +import { KeyboardEventHandler, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { SelectOptionCellDataPB, SelectOptionColorPB } from '@/services/backend'; +import { getBgColor } from '$app/components/_shared/getColor'; +import { CloseSvg } from '$app/components/_shared/svg/CloseSvg'; +import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc'; +import useOutsideClick from '$app/components/_shared/useOutsideClick'; +import { TrashSvg } from '$app/components/_shared/svg/TrashSvg'; +import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg'; + +export const EditCellOptionPopup = ({ + left, + top, + cellIdentifier, + cellCache, + fieldController, + onOutsideClick, +}: { + left: number; + top: number; + cellIdentifier: CellIdentifier; + cellCache: CellCache; + fieldController: FieldController; + onOutsideClick: () => void; +}) => { + const ref = useRef(null); + const inputRef = useRef(null); + const { t } = useTranslation(''); + const [adjustedTop, setAdjustedTop] = useState(-100); + const [value, setValue] = useState(''); + + useOutsideClick(ref, async () => { + onOutsideClick(); + }); + + useEffect(() => { + if (!ref.current) return; + const { height } = ref.current.getBoundingClientRect(); + if (top + height > window.innerHeight) { + setAdjustedTop(window.innerHeight - height); + } else { + setAdjustedTop(top); + } + }, [ref, window, top, left]); + + 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 onDeleteOptionClick = () => { + console.log('delete option'); + }; + + return ( +
+
+
+ setValue(e.target.value)} + onKeyDown={onKeyDown} + /> +
{value.length}/30
+
+ +
+
{t('grid.selectOption.colorPanelTitle')}
+
+
+
+
+ {t('grid.selectOption.purpleColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.pinkColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.lightPinkColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.orangeColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.yellowColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.limeColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.greenColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.aquaColor')} +
+ + + +
+
+
+
+ {t('grid.selectOption.blueColor')} +
+ + + +
+
+
+
+ ); +}; 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 af5956f21a..cc7afbc68b 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 @@ -15,6 +15,7 @@ import { FieldType } from '@/services/backend'; import { CellOptionsPopup } from '$app/components/_shared/EditRow/CellOptionsPopup'; import { DatePickerPopup } from '$app/components/_shared/EditRow/DatePickerPopup'; import { DragDropContext, Droppable, OnDragEndResponder } from 'react-beautiful-dnd'; +import { EditCellOptionPopup } from '$app/components/_shared/EditRow/EditCellOptionPopup'; export const EditRow = ({ onClose, @@ -48,6 +49,10 @@ export const EditRow = ({ const [datePickerTop, setDatePickerTop] = useState(0); const [datePickerLeft, setDatePickerLeft] = useState(0); + const [showEditCellOption, setShowEditCellOption] = useState(false); + const [editCellOptionTop, setEditCellOptionTop] = useState(0); + const [editCellOptionLeft, setEditCellOptionLeft] = useState(0); + useEffect(() => { setUnveil(true); }, []); @@ -106,6 +111,12 @@ export const EditRow = ({ setShowDatePicker(true); }; + const onOpenOptionDetailClick = (_left: number, _top: number) => { + setShowEditCellOption(true); + setEditCellOptionLeft(_left); + setEditCellOptionTop(_top); + }; + const onDragEnd: OnDragEndResponder = (result) => { if (!result.destination?.index) return; void controller.moveField({ @@ -202,6 +213,7 @@ export const EditRow = ({ cellCache={controller.databaseViewCache.getRowCache().getCellCache()} fieldController={controller.fieldController} onOutsideClick={() => setShowChangeOptionsPopup(false)} + openOptionDetail={onOpenOptionDetailClick} > )} {showDatePicker && editingCell && ( @@ -214,6 +226,18 @@ export const EditRow = ({ onOutsideClick={() => setShowDatePicker(false)} > )} + {showEditCellOption && editingCell && ( + { + setShowEditCellOption(false); + }} + > + )} );