From 0aa7c7da00a3895df2dc2cfe1ef43f96d91efb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=9B=BD=E7=92=87?= <37972689+YangGuoXuan-0503@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:09:47 +0800 Subject: [PATCH] fix: metadata loading error, view op done (#6660) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: metadata loading error, view op done * feat: update code --------- Co-authored-by: 杨国璇 --- .../components/table/container.js | 219 ------------------ .../metadata-view/components/table/index.js | 189 ++++++++++++++- .../metadata/metadata-view/hooks/metadata.js | 30 +++ 3 files changed, 215 insertions(+), 223 deletions(-) delete mode 100644 frontend/src/metadata/metadata-view/components/table/container.js diff --git a/frontend/src/metadata/metadata-view/components/table/container.js b/frontend/src/metadata/metadata-view/components/table/container.js deleted file mode 100644 index e45dd285bb..0000000000 --- a/frontend/src/metadata/metadata-view/components/table/container.js +++ /dev/null @@ -1,219 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import toaster from '../../../../components/toast'; -import { EVENT_BUS_TYPE, PER_LOAD_NUMBER, MAX_LOAD_NUMBER } from '../../constants'; -import { CommonlyUsedHotkey, getValidGroupbys } from '../../_basic'; -import { gettext } from '../../utils'; -import { useMetadata } from '../../hooks'; -import TableMain from './table-main'; -import Gallery from './gallery'; -import { Utils } from '../../../../utils/utils'; - -import './index.css'; - -const Container = () => { - const [isLoadingMore, setLoadingMore] = useState(false); - const { metadata, errorMsg, store } = useMetadata(); - const containerRef = useRef(null); - - const onKeyDown = useCallback((event) => { - if (event.target.className.includes('editor-main')) return; - if (CommonlyUsedHotkey.isModF(event)) { - event.preventDefault(); - window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.SEARCH_CELLS); - return; - } - }, []); - - const isGroupView = useMemo(() => { - const validGroupbys = getValidGroupbys(metadata.view.groupbys, metadata.columns); - return validGroupbys.length > 0; - }, [metadata]); - - const loadMore = useCallback(async () => { - if (!metadata.hasMore) return; - setLoadingMore(true); - - try { - await store.loadMore(PER_LOAD_NUMBER); - setLoadingMore(false); - } catch (error) { - const errorMsg = Utils.getErrorMsg(error); - toaster.danger(errorMsg); - setLoadingMore(false); - return; - } - - }, [metadata, store]); - - const loadAll = useCallback(async (maxLoadNumber, callback) => { - if (!metadata.hasMore) return; - setLoadingMore(true); - const rowsCount = metadata.row_ids.length; - const loadNumber = rowsCount % MAX_LOAD_NUMBER !== 0 ? MAX_LOAD_NUMBER - rowsCount % MAX_LOAD_NUMBER : MAX_LOAD_NUMBER; - try { - await store.loadMore(loadNumber); - setLoadingMore(false); - } catch (error) { - const errorMsg = Utils.getErrorMsg(error); - toaster.danger(errorMsg); - setLoadingMore(false); - return; - } - if (store.data.hasMore && store.data.row_ids.length < maxLoadNumber) { - loadAll(maxLoadNumber, callback); - } else { - typeof callback === 'function' && callback(store.data.hasMore); - setLoadingMore(false); - } - }, [metadata, store]); - - const modifyRecords = useCallback((rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData, isCopyPaste = false) => { - store.modifyRecords(rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData, isCopyPaste); - }, [store]); - - const modifyRecord = useCallback((rowId, updates, oldRowData, originalUpdates, originalOldRowData) => { - const rowIds = [rowId]; - const idRowUpdates = { [rowId]: updates }; - const idOriginalRowUpdates = { [rowId]: originalUpdates }; - const idOldRowData = { [rowId]: oldRowData }; - const idOriginalOldRowData = { [rowId]: originalOldRowData }; - modifyRecords(rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData); - }, [modifyRecords]); - - const getAdjacentRowsIds = useCallback((rowIds) => { - const rowIdsLen = metadata.row_ids.length; - let rowIdsInOrder = []; - let upperRowIds = []; - let belowRowIds = []; - let rowIdMap = {}; - rowIds.forEach(rowId => rowIdMap[rowId] = rowId); - metadata.row_ids.forEach((rowId, index) => { - if (!rowIdMap[rowId]) { - return; - } - const upperRowId = index === 0 ? null : metadata.row_ids[index - 1]; - const belowRowId = index === rowIdsLen - 1 ? null : metadata.row_ids[index + 1]; - rowIdsInOrder.push(rowId); - upperRowIds.push(upperRowId); - belowRowIds.push(belowRowId); - }); - return { rowIdsInOrder, upperRowIds, belowRowIds }; - }, [metadata]); - - const modifyFilters = useCallback((filters, filterConjunction, basicFilters) => { - store.modifyFilters(filterConjunction, filters, basicFilters); - }, [store]); - - const modifySorts = useCallback((sorts) => { - store.modifySorts(sorts); - }, [store]); - - const modifyGroupbys = useCallback((groupbys) => { - store.modifyGroupbys(groupbys); - }, [store]); - - const modifyHiddenColumns = useCallback((hiddenColumns) => { - store.modifyHiddenColumns(hiddenColumns); - }, [store]); - - const renameColumn = useCallback((columnKey, newName, oldName) => { - store.renameColumn(columnKey, newName, oldName); - }, [store]); - - const deleteColumn = useCallback((columnKey, oldColumn) => { - store.deleteColumn(columnKey, oldColumn); - }, [store]); - - const modifyColumnData = useCallback((columnKey, newData, oldData) => { - store.modifyColumnData(columnKey, newData, oldData); - }, [store]); - - const modifyColumnWidth = useCallback((columnKey, newWidth) => { - store.modifyColumnWidth(columnKey, newWidth); - }, [store]); - - const modifyColumnOrder = useCallback((sourceColumnKey, targetColumnKey) => { - store.modifyColumnOrder(sourceColumnKey, targetColumnKey); - }, [store]); - - const recordGetterById = useCallback((recordId) => { - return metadata.id_row_map[recordId]; - }, [metadata]); - - const recordGetter = useCallback((recordIndex) => { - const recordId = metadata.view.rows[recordIndex]; - return recordId && recordGetterById(recordId); - }, [metadata, recordGetterById]); - - const groupRecordGetter = useCallback((groupRecordIndex) => { - if (!window.sfMetadataBody || !window.sfMetadataBody.getGroupRecordByIndex) return null; - const groupRecord = window.sfMetadataBody.getGroupRecordByIndex(groupRecordIndex); - const recordId = groupRecord.rowId; - return recordId && recordGetterById(recordId); - }, [recordGetterById]); - - const recordGetterByIndex = useCallback(({ isGroupView, groupRecordIndex, recordIndex }) => { - if (isGroupView) return groupRecordGetter(groupRecordIndex); - return recordGetter(recordIndex); - }, [groupRecordGetter, recordGetter]); - - const getTableContentRect = useCallback(() => { - return containerRef?.current?.getBoundingClientRect() || { x: 0, right: window.innerWidth }; - }, [containerRef]); - - useEffect(() => { - document.addEventListener('keydown', onKeyDown); - const eventBus = window.sfMetadataContext.eventBus; - const unsubscribeModifyFilters = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_FILTERS, modifyFilters); - const unsubscribeModifySorts = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SORTS, modifySorts); - const unsubscribeModifyGroupbys = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_GROUPBYS, modifyGroupbys); - const unsubscribeModifyHiddenColumns = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, modifyHiddenColumns); - const unsubscribeModifyColumnOrder = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_COLUMN_ORDER, modifyColumnOrder); - return () => { - document.removeEventListener('keydown', onKeyDown); - unsubscribeModifyFilters(); - unsubscribeModifySorts(); - unsubscribeModifyGroupbys(); - unsubscribeModifyHiddenColumns(); - unsubscribeModifyColumnOrder(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - <> -
-
- {errorMsg && (
{gettext(errorMsg)}
)} - {!errorMsg && ( -
- {metadata.view.type === 'table' && ( - - )} - {metadata.view.type === 'image' && ()} -
- )} -
-
- - ); -}; - -export default Container; diff --git a/frontend/src/metadata/metadata-view/components/table/index.js b/frontend/src/metadata/metadata-view/components/table/index.js index 1ae29e0768..f888f29332 100644 --- a/frontend/src/metadata/metadata-view/components/table/index.js +++ b/frontend/src/metadata/metadata-view/components/table/index.js @@ -1,15 +1,196 @@ -import React from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { CenteredLoading } from '@seafile/sf-metadata-ui-component'; +import toaster from '../../../../components/toast'; +import { EVENT_BUS_TYPE, PER_LOAD_NUMBER, MAX_LOAD_NUMBER } from '../../constants'; +import { CommonlyUsedHotkey, getValidGroupbys } from '../../_basic'; +import { gettext } from '../../utils'; import { useMetadata } from '../../hooks'; -import Container from './container'; +import TableMain from './table-main'; +import Gallery from './gallery'; +import { Utils } from '../../../../utils/utils'; import './index.css'; const Table = () => { - const { isLoading } = useMetadata(); + const [isLoadingMore, setLoadingMore] = useState(false); + const { isLoading, metadata, errorMsg, store } = useMetadata(); + const containerRef = useRef(null); + + const onKeyDown = useCallback((event) => { + if (event.target.className.includes('editor-main')) return; + if (CommonlyUsedHotkey.isModF(event)) { + event.preventDefault(); + window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.SEARCH_CELLS); + return; + } + }, []); + + const isGroupView = useMemo(() => { + if (isLoading || !metadata) return false; + const validGroupbys = getValidGroupbys(metadata.view.groupbys, metadata.columns); + return validGroupbys.length > 0; + }, [isLoading, metadata]); + + const loadMore = useCallback(async () => { + if (!metadata.hasMore) return; + setLoadingMore(true); + + try { + await store.loadMore(PER_LOAD_NUMBER); + setLoadingMore(false); + } catch (error) { + const errorMsg = Utils.getErrorMsg(error); + toaster.danger(errorMsg); + setLoadingMore(false); + return; + } + + }, [metadata, store]); + + const loadAll = useCallback(async (maxLoadNumber, callback) => { + if (!metadata.hasMore) return; + setLoadingMore(true); + const rowsCount = metadata.row_ids.length; + const loadNumber = rowsCount % MAX_LOAD_NUMBER !== 0 ? MAX_LOAD_NUMBER - rowsCount % MAX_LOAD_NUMBER : MAX_LOAD_NUMBER; + try { + await store.loadMore(loadNumber); + setLoadingMore(false); + } catch (error) { + const errorMsg = Utils.getErrorMsg(error); + toaster.danger(errorMsg); + setLoadingMore(false); + return; + } + if (store.data.hasMore && store.data.row_ids.length < maxLoadNumber) { + loadAll(maxLoadNumber, callback); + } else { + typeof callback === 'function' && callback(store.data.hasMore); + setLoadingMore(false); + } + }, [metadata, store]); + + const modifyRecords = useCallback((rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData, isCopyPaste = false) => { + store.modifyRecords(rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData, isCopyPaste); + }, [store]); + + const modifyRecord = useCallback((rowId, updates, oldRowData, originalUpdates, originalOldRowData) => { + const rowIds = [rowId]; + const idRowUpdates = { [rowId]: updates }; + const idOriginalRowUpdates = { [rowId]: originalUpdates }; + const idOldRowData = { [rowId]: oldRowData }; + const idOriginalOldRowData = { [rowId]: originalOldRowData }; + modifyRecords(rowIds, idRowUpdates, idOriginalRowUpdates, idOldRowData, idOriginalOldRowData); + }, [modifyRecords]); + + const getAdjacentRowsIds = useCallback((rowIds) => { + const rowIdsLen = metadata.row_ids.length; + let rowIdsInOrder = []; + let upperRowIds = []; + let belowRowIds = []; + let rowIdMap = {}; + rowIds.forEach(rowId => rowIdMap[rowId] = rowId); + metadata.row_ids.forEach((rowId, index) => { + if (!rowIdMap[rowId]) { + return; + } + const upperRowId = index === 0 ? null : metadata.row_ids[index - 1]; + const belowRowId = index === rowIdsLen - 1 ? null : metadata.row_ids[index + 1]; + rowIdsInOrder.push(rowId); + upperRowIds.push(upperRowId); + belowRowIds.push(belowRowId); + }); + return { rowIdsInOrder, upperRowIds, belowRowIds }; + }, [metadata]); + + const renameColumn = useCallback((columnKey, newName, oldName) => { + store.renameColumn(columnKey, newName, oldName); + }, [store]); + + const deleteColumn = useCallback((columnKey, oldColumn) => { + store.deleteColumn(columnKey, oldColumn); + }, [store]); + + const modifyColumnData = useCallback((columnKey, newData, oldData) => { + store.modifyColumnData(columnKey, newData, oldData); + }, [store]); + + const modifyColumnWidth = useCallback((columnKey, newWidth) => { + store.modifyColumnWidth(columnKey, newWidth); + }, [store]); + + const modifyColumnOrder = useCallback((sourceColumnKey, targetColumnKey) => { + store.modifyColumnOrder(sourceColumnKey, targetColumnKey); + }, [store]); + + const recordGetterById = useCallback((recordId) => { + return metadata.id_row_map[recordId]; + }, [metadata]); + + const recordGetter = useCallback((recordIndex) => { + const recordId = metadata.view.rows[recordIndex]; + return recordId && recordGetterById(recordId); + }, [metadata, recordGetterById]); + + const groupRecordGetter = useCallback((groupRecordIndex) => { + if (!window.sfMetadataBody || !window.sfMetadataBody.getGroupRecordByIndex) return null; + const groupRecord = window.sfMetadataBody.getGroupRecordByIndex(groupRecordIndex); + const recordId = groupRecord.rowId; + return recordId && recordGetterById(recordId); + }, [recordGetterById]); + + const recordGetterByIndex = useCallback(({ isGroupView, groupRecordIndex, recordIndex }) => { + if (isGroupView) return groupRecordGetter(groupRecordIndex); + return recordGetter(recordIndex); + }, [groupRecordGetter, recordGetter]); + + const getTableContentRect = useCallback(() => { + return containerRef?.current?.getBoundingClientRect() || { x: 0, right: window.innerWidth }; + }, [containerRef]); + + useEffect(() => { + document.addEventListener('keydown', onKeyDown); + return () => { + document.removeEventListener('keydown', onKeyDown); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); if (isLoading) return (); - return (); + + return ( + <> +
+
+ {errorMsg && (
{gettext(errorMsg)}
)} + {!errorMsg && ( +
+ {metadata.view.type === 'table' && ( + + )} + {metadata.view.type === 'image' && ()} +
+ )} +
+
+ + ); }; export default Table; diff --git a/frontend/src/metadata/metadata-view/hooks/metadata.js b/frontend/src/metadata/metadata-view/hooks/metadata.js index 08906497ae..528e88bff6 100644 --- a/frontend/src/metadata/metadata-view/hooks/metadata.js +++ b/frontend/src/metadata/metadata-view/hooks/metadata.js @@ -45,6 +45,26 @@ export const MetadataProvider = ({ }); }, []); + const modifyFilters = useCallback((filters, filterConjunction, basicFilters) => { + window.sfMetadataStore.modifyFilters(filterConjunction, filters, basicFilters); + }, []); + + const modifySorts = useCallback((sorts) => { + window.sfMetadataStore.modifySorts(sorts); + }, []); + + const modifyGroupbys = useCallback((groupbys) => { + window.sfMetadataStore.modifyGroupbys(groupbys); + }, []); + + const modifyHiddenColumns = useCallback((hiddenColumns) => { + window.sfMetadataStore.modifyHiddenColumns(hiddenColumns); + }, []); + + const modifyColumnOrder = useCallback((sourceColumnKey, targetColumnKey) => { + window.sfMetadataStore.modifyColumnOrder(sourceColumnKey, targetColumnKey); + }, []); + // init useEffect(() => { setLoading(true); @@ -72,6 +92,11 @@ export const MetadataProvider = ({ const unsubscribeHandleTableError = eventBus.subscribe(EVENT_BUS_TYPE.TABLE_ERROR, handleTableError); const unsubscribeUpdateRows = eventBus.subscribe(EVENT_BUS_TYPE.UPDATE_TABLE_ROWS, updateMetadata); const unsubscribeReloadData = eventBus.subscribe(EVENT_BUS_TYPE.RELOAD_DATA, reloadMetadata); + const unsubscribeModifyFilters = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_FILTERS, modifyFilters); + const unsubscribeModifySorts = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SORTS, modifySorts); + const unsubscribeModifyGroupbys = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_GROUPBYS, modifyGroupbys); + const unsubscribeModifyHiddenColumns = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, modifyHiddenColumns); + const unsubscribeModifyColumnOrder = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_COLUMN_ORDER, modifyColumnOrder); return () => { window.sfMetadataContext.destroy(); @@ -81,6 +106,11 @@ export const MetadataProvider = ({ unsubscribeHandleTableError(); unsubscribeUpdateRows(); unsubscribeReloadData(); + unsubscribeModifyFilters(); + unsubscribeModifySorts(); + unsubscribeModifyGroupbys(); + unsubscribeModifyHiddenColumns(); + unsubscribeModifyColumnOrder(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [repoID, viewID]);