mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 02:48:51 +00:00
feat: init sdoc summary when add summary column (#6449)
* feat: init sdoc summary when add summary column * feat/meta: add summary single sdoc * optimize some naming * add summarize files api * optimize code * feat: update code * feat: optimzie code * feat: rebase code * fix/mv: fix invalid path param when create summary * feat/mv: add batch update summary text func * feat/mv: add some details in parameter judgment * feat: optimize code * feat: delete useless import * execute return api * feat/summary: execute file not found situation * fix: summary --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { PRIVATE_COLUMN_KEY } from '../../_basic';
|
||||
import { getColumnByKey, PRIVATE_COLUMN_KEY } from '../../_basic';
|
||||
import { gettext } from '../../utils';
|
||||
import { siteRoot } from '../../../../utils/constants';
|
||||
import { Utils } from '../../../../utils/utils';
|
||||
import { useMetadata } from '../../hooks';
|
||||
import toaster from '../../../../components/toast';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@@ -12,6 +14,7 @@ const OPERATION = {
|
||||
COPY_SELECTED: 'copy-selected',
|
||||
OPEN_PARENT_FOLDER: 'open-parent-folder',
|
||||
OPEN_IN_NEW_TAB: 'open-new-tab',
|
||||
GENERATE_SUMMARY: 'generate-summary',
|
||||
};
|
||||
|
||||
const ContextMenu = ({
|
||||
@@ -22,23 +25,55 @@ const ContextMenu = ({
|
||||
recordGetterByIndex,
|
||||
onClearSelected,
|
||||
onCopySelected,
|
||||
updateRecords,
|
||||
}) => {
|
||||
const menuRef = useRef(null);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [position, setPosition] = useState({ top: 0, left: 0 });
|
||||
const { metadata } = useMetadata();
|
||||
|
||||
const options = useMemo(() => {
|
||||
if (!visible) return [];
|
||||
const permission = window.sfMetadataContext.getPermission();
|
||||
const isReadonly = permission === 'r';
|
||||
const { columns } = metadata;
|
||||
const summaryColumn = getColumnByKey(columns, PRIVATE_COLUMN_KEY.FILE_SUMMARY);
|
||||
const canModifyRow = window.sfMetadataContext.canModifyRow;
|
||||
let list = [];
|
||||
|
||||
if (selectedRange) {
|
||||
!isReadonly && list.push({ value: OPERATION.CLEAR_SELECTED, label: gettext('Clear selected') });
|
||||
list.push({ value: OPERATION.COPY_SELECTED, label: gettext('Copy selected') });
|
||||
|
||||
if (summaryColumn) {
|
||||
const { topLeft, bottomRight } = selectedRange;
|
||||
for (let i = topLeft.rowIdx; i <= bottomRight.rowIdx; i++) {
|
||||
const record = recordGetterByIndex({ isGroupView, groupRecordIndex: topLeft.groupRecordIndex, recordIndex: i });
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
if (Utils.isSdocFile(fileName) && canModifyRow(record)) {
|
||||
list.push({ value: OPERATION.GENERATE_SUMMARY, label: gettext('Generate summary') });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
if (Object.keys(recordMetrics.idSelectedRecordMap).length > 1) {
|
||||
const selectedRecords = Object.keys(recordMetrics.idSelectedRecordMap);
|
||||
if (selectedRecords.length > 1) {
|
||||
if (summaryColumn) {
|
||||
const isIncludeSdocRecord = selectedRecords.filter(id => {
|
||||
const record = metadata.id_row_map[id];
|
||||
if (record) {
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
return Utils.isSdocFile(fileName) && canModifyRow(record);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (isIncludeSdocRecord.length > 0) {
|
||||
list.push({ value: OPERATION.GENERATE_SUMMARY, label: gettext('Generate summary') });
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -49,9 +84,15 @@ const ContextMenu = ({
|
||||
const isFolder = record[PRIVATE_COLUMN_KEY.IS_DIR];
|
||||
list.push({ value: OPERATION.OPEN_IN_NEW_TAB, label: isFolder ? gettext('Open folder in new tab') : gettext('Open file in new tab') });
|
||||
list.push({ value: OPERATION.OPEN_PARENT_FOLDER, label: gettext('Open parent folder') });
|
||||
if (summaryColumn) {
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
if (Utils.isSdocFile(fileName) && canModifyRow(record)) {
|
||||
list.push({ value: OPERATION.GENERATE_SUMMARY, label: gettext('Generate summary') });
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}, [isGroupView, selectedPosition, recordMetrics, selectedRange, recordGetterByIndex]);
|
||||
}, [visible, isGroupView, selectedPosition, recordMetrics, selectedRange, metadata, recordGetterByIndex]);
|
||||
|
||||
const handleHide = useCallback((event) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||
@@ -89,6 +130,66 @@ const ContextMenu = ({
|
||||
window.open(url, '_blank');
|
||||
}, [isGroupView, recordGetterByIndex, selectedPosition]);
|
||||
|
||||
const generateSummary = useCallback(() => {
|
||||
const canModifyRow = window.sfMetadataContext.canModifyRow;
|
||||
const selectedRecords = Object.keys(recordMetrics.idSelectedRecordMap);
|
||||
const summaryColumnKey = PRIVATE_COLUMN_KEY.FILE_SUMMARY;
|
||||
let paths = [];
|
||||
let idOldRecordData = {};
|
||||
let idOriginalOldRecordData = {};
|
||||
if (selectedRange) {
|
||||
const { topLeft, bottomRight } = selectedRange;
|
||||
for (let i = topLeft.rowIdx; i <= bottomRight.rowIdx; i++) {
|
||||
const record = recordGetterByIndex({ isGroupView, groupRecordIndex: topLeft.groupRecordIndex, recordIndex: i });
|
||||
if (!canModifyRow(record)) continue;
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
if (!Utils.isSdocFile(fileName)) continue;
|
||||
const parentDir = record[PRIVATE_COLUMN_KEY.PARENT_DIR];
|
||||
paths.push(Utils.joinPath(parentDir, fileName));
|
||||
idOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
idOriginalOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
}
|
||||
} else if (selectedRecords.length > 0) {
|
||||
selectedRecords.forEach(recordId => {
|
||||
const record = metadata.id_row_map[recordId];
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
if (Utils.isSdocFile(fileName) && canModifyRow(record)) {
|
||||
const parentDir = record[PRIVATE_COLUMN_KEY.PARENT_DIR];
|
||||
paths.push(Utils.joinPath(parentDir, fileName));
|
||||
idOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
idOriginalOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
}
|
||||
});
|
||||
} else if (selectedPosition) {
|
||||
const { groupRecordIndex, rowIdx } = selectedPosition;
|
||||
const record = recordGetterByIndex({ isGroupView, groupRecordIndex, recordIndex: rowIdx });
|
||||
const fileName = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
if (Utils.isSdocFile(fileName) && canModifyRow(record)) {
|
||||
const parentDir = record[PRIVATE_COLUMN_KEY.PARENT_DIR];
|
||||
paths.push(Utils.joinPath(parentDir, fileName));
|
||||
idOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
idOriginalOldRecordData[record[PRIVATE_COLUMN_KEY.ID]] = { [summaryColumnKey]: record[summaryColumnKey] };
|
||||
}
|
||||
}
|
||||
if (paths.length === 0) return;
|
||||
window.sfMetadataContext.generateSummary(paths).then(res => {
|
||||
const updatedRecords = res.data.rows;
|
||||
let recordIds = [];
|
||||
let idRecordUpdates = {};
|
||||
let idOriginalRecordUpdates = {};
|
||||
updatedRecords.forEach(updatedRecord => {
|
||||
const { _id: updateRecordId, _summary } = updatedRecord;
|
||||
recordIds.push(updateRecordId);
|
||||
idRecordUpdates[updateRecordId] = { [summaryColumnKey]: _summary };
|
||||
idOriginalRecordUpdates[updateRecordId] = { [summaryColumnKey]: _summary };
|
||||
});
|
||||
updateRecords({ recordIds, idRecordUpdates, idOriginalRecordUpdates, idOldRecordData, idOriginalOldRecordData });
|
||||
}).catch(error => {
|
||||
const errorMessage = gettext('Failed to generate summary');
|
||||
toaster.danger(errorMessage);
|
||||
});
|
||||
}, [isGroupView, selectedRange, selectedPosition, recordMetrics, metadata, recordGetterByIndex, updateRecords]);
|
||||
|
||||
const handleOptionClick = useCallback((event, option) => {
|
||||
event.stopPropagation();
|
||||
switch (option.value) {
|
||||
@@ -108,12 +209,16 @@ const ContextMenu = ({
|
||||
onClearSelected && onClearSelected();
|
||||
break;
|
||||
}
|
||||
case OPERATION.GENERATE_SUMMARY: {
|
||||
generateSummary && generateSummary();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setVisible(false);
|
||||
}, [onOpenFileInNewTab, onOpenParentFolder, onCopySelected, onClearSelected]);
|
||||
}, [onOpenFileInNewTab, onOpenParentFolder, onCopySelected, onClearSelected, generateSummary]);
|
||||
|
||||
const getMenuPosition = (x = 0, y = 0) => {
|
||||
let menuStyles = {
|
||||
|
Reference in New Issue
Block a user