mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 17:33:18 +00:00
optimize kanban (#7054)
* optimize kanban * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code --------- Co-authored-by: zhouwenxuan <aries@Mac.local> Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
@@ -7,10 +7,10 @@ import DetailItem from '../../../components/dirent-detail/detail-item';
|
|||||||
import { Utils } from '../../../utils/utils';
|
import { Utils } from '../../../utils/utils';
|
||||||
import metadataAPI from '../../api';
|
import metadataAPI from '../../api';
|
||||||
import Column from '../../model/metadata/column';
|
import Column from '../../model/metadata/column';
|
||||||
import { getCellValueByColumn, getOptionName, getColumnOptionNamesByIds, getColumnOptionNameById, getFileNameFromRecord } from '../../utils/cell';
|
import { getCellValueByColumn, getOptionName, getColumnOptionNamesByIds, getColumnOptionNameById, getFileNameFromRecord, geRecordIdFromRecord, getFileObjIdFromRecord } from '../../utils/cell';
|
||||||
import { normalizeFields } from './utils';
|
import { normalizeFields } from './utils';
|
||||||
import { gettext } from '../../../utils/constants';
|
import { gettext } from '../../../utils/constants';
|
||||||
import { CellType, PREDEFINED_COLUMN_KEYS, PRIVATE_COLUMN_KEY } from '../../constants';
|
import { CellType, EVENT_BUS_TYPE, PREDEFINED_COLUMN_KEYS, PRIVATE_COLUMN_KEY } from '../../constants';
|
||||||
import { getColumnOptions, getColumnOriginName } from '../../utils/column';
|
import { getColumnOptions, getColumnOriginName } from '../../utils/column';
|
||||||
import { SYSTEM_FOLDERS } from './constants';
|
import { SYSTEM_FOLDERS } from './constants';
|
||||||
import Location from './location';
|
import Location from './location';
|
||||||
@@ -22,46 +22,24 @@ const MetadataDetails = ({ repoID, filePath, repoInfo, direntType, updateRecord
|
|||||||
const [metadata, setMetadata] = useState({ record: {}, fields: [] });
|
const [metadata, setMetadata] = useState({ record: {}, fields: [] });
|
||||||
const permission = useMemo(() => repoInfo.permission !== 'admin' && repoInfo.permission !== 'rw' ? 'r' : 'rw', [repoInfo]);
|
const permission = useMemo(() => repoInfo.permission !== 'admin' && repoInfo.permission !== 'rw' ? 'r' : 'rw', [repoInfo]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setLoading(true);
|
|
||||||
if (SYSTEM_FOLDERS.find(folderPath => filePath.startsWith(folderPath))) {
|
|
||||||
setLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dirName = Utils.getDirName(filePath);
|
|
||||||
const fileName = Utils.getFileName(filePath);
|
|
||||||
let parentDir = direntType === 'file' ? dirName : dirName.slice(0, dirName.length - fileName.length - 1);
|
|
||||||
if (!parentDir.startsWith('/')) {
|
|
||||||
parentDir = '/' + parentDir;
|
|
||||||
}
|
|
||||||
metadataAPI.getMetadataRecordInfo(repoID, parentDir, fileName).then(res => {
|
|
||||||
const { results, metadata } = res.data;
|
|
||||||
const record = Array.isArray(results) && results.length > 0 ? results[0] : {};
|
|
||||||
const fields = normalizeFields(metadata).map(field => new Column(field));
|
|
||||||
updateRecord && updateRecord(record);
|
|
||||||
setMetadata({ record, fields });
|
|
||||||
setLoading(false);
|
|
||||||
}).catch(error => {
|
|
||||||
const errMessage = Utils.getErrorMsg(error);
|
|
||||||
toaster.danger(errMessage);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
}, [repoID, filePath, direntType, updateRecord]);
|
|
||||||
|
|
||||||
const onChange = useCallback((fieldKey, newValue) => {
|
const onChange = useCallback((fieldKey, newValue) => {
|
||||||
const { record, fields } = metadata;
|
const { record, fields } = metadata;
|
||||||
const field = fields.find(f => f.key === fieldKey);
|
const field = fields.find(f => f.key === fieldKey);
|
||||||
const fileName = getColumnOriginName(field);
|
const fileName = getColumnOriginName(field);
|
||||||
|
const recordId = geRecordIdFromRecord(record);
|
||||||
|
const fileObjId = getFileObjIdFromRecord(record);
|
||||||
let update = { [fileName]: newValue };
|
let update = { [fileName]: newValue };
|
||||||
if (field.type === CellType.SINGLE_SELECT) {
|
if (field.type === CellType.SINGLE_SELECT) {
|
||||||
update = { [fileName]: getColumnOptionNameById(field, newValue) };
|
update = { [fileName]: getColumnOptionNameById(field, newValue) };
|
||||||
} else if (field.type === CellType.MULTIPLE_SELECT) {
|
} else if (field.type === CellType.MULTIPLE_SELECT) {
|
||||||
update = { [fileName]: newValue ? getColumnOptionNamesByIds(field, newValue) : [] };
|
update = { [fileName]: newValue ? getColumnOptionNamesByIds(field, newValue) : [] };
|
||||||
}
|
}
|
||||||
metadataAPI.modifyRecord(repoID, record._id, update, record._obj_id).then(res => {
|
metadataAPI.modifyRecord(repoID, recordId, update, fileObjId).then(res => {
|
||||||
const newMetadata = { ...metadata, record: { ...record, ...update } };
|
const newMetadata = { ...metadata, record: { ...record, ...update } };
|
||||||
setMetadata(newMetadata);
|
setMetadata(newMetadata);
|
||||||
|
if (window?.sfMetadataContext?.eventBus) {
|
||||||
|
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.LOCAL_RECORD_CHANGED, recordId, update);
|
||||||
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
const errorMsg = Utils.getErrorMsg(error);
|
const errorMsg = Utils.getErrorMsg(error);
|
||||||
toaster.danger(errorMsg);
|
toaster.danger(errorMsg);
|
||||||
@@ -98,6 +76,48 @@ const MetadataDetails = ({ repoID, filePath, repoInfo, direntType, updateRecord
|
|||||||
});
|
});
|
||||||
}, [repoID, metadata]);
|
}, [repoID, metadata]);
|
||||||
|
|
||||||
|
const localRecordChanged = useCallback((recordId, updates) => {
|
||||||
|
if (geRecordIdFromRecord(metadata?.record) !== recordId) return;
|
||||||
|
const newMetadata = { ...metadata, record: { ...metadata.record, ...updates } };
|
||||||
|
setMetadata(newMetadata);
|
||||||
|
}, [metadata]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoading(true);
|
||||||
|
if (SYSTEM_FOLDERS.find(folderPath => filePath.startsWith(folderPath))) {
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dirName = Utils.getDirName(filePath);
|
||||||
|
const fileName = Utils.getFileName(filePath);
|
||||||
|
let parentDir = direntType === 'file' ? dirName : dirName.slice(0, dirName.length - fileName.length - 1);
|
||||||
|
if (!parentDir.startsWith('/')) {
|
||||||
|
parentDir = '/' + parentDir;
|
||||||
|
}
|
||||||
|
metadataAPI.getMetadataRecordInfo(repoID, parentDir, fileName).then(res => {
|
||||||
|
const { results, metadata } = res.data;
|
||||||
|
const record = Array.isArray(results) && results.length > 0 ? results[0] : {};
|
||||||
|
const fields = normalizeFields(metadata).map(field => new Column(field));
|
||||||
|
updateRecord && updateRecord(record);
|
||||||
|
setMetadata({ record, fields });
|
||||||
|
setLoading(false);
|
||||||
|
}).catch(error => {
|
||||||
|
const errMessage = Utils.getErrorMsg(error);
|
||||||
|
toaster.danger(errMessage);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}, [repoID, filePath, direntType, updateRecord]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const eventBus = window?.sfMetadataContext?.eventBus;
|
||||||
|
if (!eventBus) return;
|
||||||
|
const unsubscribeLocalRecordChanged = eventBus.subscribe(EVENT_BUS_TYPE.LOCAL_RECORD_DETAIL_CHANGED, localRecordChanged);
|
||||||
|
return () => {
|
||||||
|
unsubscribeLocalRecordChanged();
|
||||||
|
};
|
||||||
|
}, [localRecordChanged]);
|
||||||
|
|
||||||
if (isLoading) return null;
|
if (isLoading) return null;
|
||||||
const { fields, record } = metadata;
|
const { fields, record } = metadata;
|
||||||
if (!record._id) return null;
|
if (!record._id) return null;
|
||||||
|
@@ -3,16 +3,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const EVENT_BUS_TYPE = {
|
export const EVENT_BUS_TYPE = {
|
||||||
QUERY_COLLABORATORS: 'query-collaborators',
|
QUERY_COLLABORATORS: 'query_collaborators',
|
||||||
QUERY_COLLABORATOR: 'query-collaborator',
|
QUERY_COLLABORATOR: 'query_collaborator',
|
||||||
UPDATE_TABLE_ROWS: 'update-table-rows',
|
UPDATE_TABLE_ROWS: 'update_table_rows',
|
||||||
|
|
||||||
// table
|
// table
|
||||||
LOCAL_TABLE_CHANGED: 'local-table-changed',
|
LOCAL_TABLE_CHANGED: 'local_table_changed',
|
||||||
SERVER_TABLE_CHANGED: 'server-table-changed',
|
SERVER_TABLE_CHANGED: 'server_table_changed',
|
||||||
TABLE_ERROR: 'table-error',
|
TABLE_ERROR: 'table_error',
|
||||||
OPEN_EDITOR: 'open-editor',
|
OPEN_EDITOR: 'open_editor',
|
||||||
CLOSE_EDITOR: 'close-editor',
|
CLOSE_EDITOR: 'close_editor',
|
||||||
SELECT_CELL: 'select_cell',
|
SELECT_CELL: 'select_cell',
|
||||||
SELECT_START: 'select_start',
|
SELECT_START: 'select_start',
|
||||||
SELECT_UPDATE: 'select_update',
|
SELECT_UPDATE: 'select_update',
|
||||||
@@ -21,14 +21,16 @@ export const EVENT_BUS_TYPE = {
|
|||||||
SELECT_NONE: 'select_none',
|
SELECT_NONE: 'select_none',
|
||||||
COPY_CELLS: 'copy_cells',
|
COPY_CELLS: 'copy_cells',
|
||||||
PASTE_CELLS: 'paste_cells',
|
PASTE_CELLS: 'paste_cells',
|
||||||
SEARCH_CELLS: 'search-cells',
|
SEARCH_CELLS: 'search_cells',
|
||||||
CLOSE_SEARCH_CELLS: 'close-search-cells',
|
CLOSE_SEARCH_CELLS: 'close_search_cells',
|
||||||
OPEN_SELECT: 'open-select',
|
OPEN_SELECT: 'open_select',
|
||||||
UPDATE_LINKED_RECORDS: 'update_linked_records',
|
UPDATE_LINKED_RECORDS: 'update_linked_records',
|
||||||
SELECT_COLUMN: 'select_column',
|
SELECT_COLUMN: 'select_column',
|
||||||
DRAG_ENTER: 'drag_enter',
|
DRAG_ENTER: 'drag_enter',
|
||||||
COLLAPSE_ALL_GROUPS: 'collapse_all_groups',
|
COLLAPSE_ALL_GROUPS: 'collapse_all_groups',
|
||||||
EXPAND_ALL_GROUPS: 'expand_all_groups',
|
EXPAND_ALL_GROUPS: 'expand_all_groups',
|
||||||
|
LOCAL_RECORD_CHANGED: 'local_record_changed',
|
||||||
|
LOCAL_RECORD_DETAIL_CHANGED: 'local_record_detail_changed',
|
||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
RELOAD_DATA: 'reload_data',
|
RELOAD_DATA: 'reload_data',
|
||||||
|
@@ -70,6 +70,10 @@ export const MetadataViewProvider = ({
|
|||||||
window.sfMetadataStore.modifySettings(settings);
|
window.sfMetadataStore.modifySettings(settings);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const updateLocalRecord = useCallback((recordId, update) => {
|
||||||
|
window.sfMetadataStore.modifyLocalRecord(recordId, update);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// init
|
// init
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -103,6 +107,7 @@ export const MetadataViewProvider = ({
|
|||||||
const unsubscribeModifyHiddenColumns = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, modifyHiddenColumns);
|
const unsubscribeModifyHiddenColumns = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, modifyHiddenColumns);
|
||||||
const unsubscribeModifyColumnOrder = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_COLUMN_ORDER, modifyColumnOrder);
|
const unsubscribeModifyColumnOrder = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_COLUMN_ORDER, modifyColumnOrder);
|
||||||
const unsubscribeModifySettings = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SETTINGS, modifySettings);
|
const unsubscribeModifySettings = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SETTINGS, modifySettings);
|
||||||
|
const unsubscribeLocalRecordChanged = eventBus.subscribe(EVENT_BUS_TYPE.LOCAL_RECORD_CHANGED, updateLocalRecord);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (window.sfMetadataContext) {
|
if (window.sfMetadataContext) {
|
||||||
@@ -120,6 +125,7 @@ export const MetadataViewProvider = ({
|
|||||||
unsubscribeModifyHiddenColumns();
|
unsubscribeModifyHiddenColumns();
|
||||||
unsubscribeModifyColumnOrder();
|
unsubscribeModifyColumnOrder();
|
||||||
unsubscribeModifySettings();
|
unsubscribeModifySettings();
|
||||||
|
unsubscribeLocalRecordChanged();
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [repoID, viewID]);
|
}, [repoID, viewID]);
|
||||||
|
@@ -408,6 +408,17 @@ class Store {
|
|||||||
this.applyOperation(operation);
|
this.applyOperation(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modifyLocalRecord(row_id, updates) {
|
||||||
|
const type = OPERATION_TYPE.MODIFY_LOCAL_RECORD;
|
||||||
|
const operation = this.createOperation({
|
||||||
|
type,
|
||||||
|
row_id,
|
||||||
|
repo_id: this.repoId,
|
||||||
|
updates
|
||||||
|
});
|
||||||
|
this.applyOperation(operation);
|
||||||
|
}
|
||||||
|
|
||||||
modifyFilters(filterConjunction, filters, basicFilters = []) {
|
modifyFilters(filterConjunction, filters, basicFilters = []) {
|
||||||
const type = OPERATION_TYPE.MODIFY_FILTERS;
|
const type = OPERATION_TYPE.MODIFY_FILTERS;
|
||||||
const operation = this.createOperation({
|
const operation = this.createOperation({
|
||||||
|
@@ -96,6 +96,27 @@ export default function apply(data, operation) {
|
|||||||
data.id_row_map[row_id] = updatedRow;
|
data.id_row_map[row_id] = updatedRow;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
case OPERATION_TYPE.MODIFY_LOCAL_RECORD: {
|
||||||
|
const { row_id, updates } = operation;
|
||||||
|
const { rows } = data;
|
||||||
|
const modifyTime = dayjs().utc().format(UTC_FORMAT_DEFAULT);
|
||||||
|
const modifier = window.sfMetadataContext.getUsername();
|
||||||
|
let updatedRows = [...rows];
|
||||||
|
rows.forEach((row, index) => {
|
||||||
|
const { _id: rowId } = row;
|
||||||
|
if (rowId === row_id && updates) {
|
||||||
|
const updatedRow = Object.assign({}, row, updates, {
|
||||||
|
'_mtime': modifyTime,
|
||||||
|
'_last_modifier': modifier,
|
||||||
|
});
|
||||||
|
updatedRows[index] = updatedRow;
|
||||||
|
data.id_row_map[rowId] = updatedRow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data.rows = updatedRows;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
case OPERATION_TYPE.MODIFY_FILTERS: {
|
case OPERATION_TYPE.MODIFY_FILTERS: {
|
||||||
const { filter_conjunction, filters, basic_filters } = operation;
|
const { filter_conjunction, filters, basic_filters } = operation;
|
||||||
data.view.filter_conjunction = filter_conjunction;
|
data.view.filter_conjunction = filter_conjunction;
|
||||||
|
@@ -10,6 +10,7 @@ export const OPERATION_TYPE = {
|
|||||||
LOCK_RECORD_VIA_BUTTON: 'lock_record_via_button',
|
LOCK_RECORD_VIA_BUTTON: 'lock_record_via_button',
|
||||||
MODIFY_RECORD_VIA_BUTTON: 'modify_record_via_button',
|
MODIFY_RECORD_VIA_BUTTON: 'modify_record_via_button',
|
||||||
MODIFY_SETTINGS: 'modify_settings',
|
MODIFY_SETTINGS: 'modify_settings',
|
||||||
|
MODIFY_LOCAL_RECORD: 'modify_local_record',
|
||||||
|
|
||||||
// column
|
// column
|
||||||
INSERT_COLUMN: 'insert_column',
|
INSERT_COLUMN: 'insert_column',
|
||||||
@@ -53,6 +54,7 @@ export const OPERATION_ATTRIBUTES = {
|
|||||||
[OPERATION_TYPE.RENAME_PEOPLE_NAME]: ['repo_id', 'people_id', 'new_name', 'old_name'],
|
[OPERATION_TYPE.RENAME_PEOPLE_NAME]: ['repo_id', 'people_id', 'new_name', 'old_name'],
|
||||||
[OPERATION_TYPE.DELETE_PEOPLE_PHOTOS]: ['repo_id', 'people_id', 'deleted_photos'],
|
[OPERATION_TYPE.DELETE_PEOPLE_PHOTOS]: ['repo_id', 'people_id', 'deleted_photos'],
|
||||||
[OPERATION_TYPE.MODIFY_SETTINGS]: ['repo_id', 'view_id', 'settings'],
|
[OPERATION_TYPE.MODIFY_SETTINGS]: ['repo_id', 'view_id', 'settings'],
|
||||||
|
[OPERATION_TYPE.MODIFY_LOCAL_RECORD]: ['repo_id', 'row_id', 'updates'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UNDO_OPERATION_TYPE = [
|
export const UNDO_OPERATION_TYPE = [
|
||||||
@@ -64,6 +66,7 @@ export const UNDO_OPERATION_TYPE = [
|
|||||||
// only apply operation on the local
|
// only apply operation on the local
|
||||||
export const LOCAL_APPLY_OPERATION_TYPE = [
|
export const LOCAL_APPLY_OPERATION_TYPE = [
|
||||||
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
||||||
|
OPERATION_TYPE.MODIFY_LOCAL_RECORD,
|
||||||
];
|
];
|
||||||
|
|
||||||
// apply operation after exec operation on the server
|
// apply operation after exec operation on the server
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
.sf-metadata-kanban-card .sf-metadata-kanban-card-header .sf-metadata-file-name {
|
.sf-metadata-kanban-card .sf-metadata-kanban-card-header .sf-metadata-file-name {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
flex: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sf-metadata-kanban-card .sf-metadata-kanban-card-header .sf-metadata-file-name:hover {
|
.sf-metadata-kanban-card .sf-metadata-kanban-card-header .sf-metadata-file-name:hover {
|
||||||
|
@@ -4,6 +4,14 @@
|
|||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sf-metadata-view-kanban-board .smooth-dnd-container.vertical {
|
||||||
|
height: calc(100% - 32px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-view-kanban-board .smooth-dnd-container.vertical .smooth-dnd-draggable-wrapper:last-child .sf-metadata-kanban-card {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sf-metadata-view-kanban-board .smooth-dnd-container.vertical > .smooth-dnd-draggable-wrapper {
|
.sf-metadata-view-kanban-board .smooth-dnd-container.vertical > .smooth-dnd-draggable-wrapper {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ const Board = ({
|
|||||||
onUnFreezed,
|
onUnFreezed,
|
||||||
onOpenFile,
|
onOpenFile,
|
||||||
onSelectCard,
|
onSelectCard,
|
||||||
|
updateDragging,
|
||||||
}) => {
|
}) => {
|
||||||
const [isDraggingOver, setDraggingOver] = useState(false);
|
const [isDraggingOver, setDraggingOver] = useState(false);
|
||||||
const boardName = useMemo(() => `sf_metadata_kanban_board_${board.key}`, [board]);
|
const boardName = useMemo(() => `sf_metadata_kanban_board_${board.key}`, [board]);
|
||||||
@@ -34,8 +35,9 @@ const Board = ({
|
|||||||
const { metadata } = useMetadataView();
|
const { metadata } = useMetadataView();
|
||||||
|
|
||||||
const onDragStart = useCallback(({ payload }) => {
|
const onDragStart = useCallback(({ payload }) => {
|
||||||
|
updateDragging(true);
|
||||||
return payload;
|
return payload;
|
||||||
}, []);
|
}, [updateDragging]);
|
||||||
|
|
||||||
const onDragEnd = useCallback((targetBoardIndex, result) => {
|
const onDragEnd = useCallback((targetBoardIndex, result) => {
|
||||||
if (isDraggingOver) {
|
if (isDraggingOver) {
|
||||||
@@ -44,12 +46,11 @@ const Board = ({
|
|||||||
|
|
||||||
const { addedIndex, payload } = result;
|
const { addedIndex, payload } = result;
|
||||||
const { boardIndex: sourceBoardIndex, cardIndex: sourceCardIndex } = payload;
|
const { boardIndex: sourceBoardIndex, cardIndex: sourceCardIndex } = payload;
|
||||||
if (sourceBoardIndex === targetBoardIndex) return;
|
if (sourceBoardIndex !== targetBoardIndex && sourceCardIndex !== null && addedIndex !== null) {
|
||||||
if (sourceCardIndex !== null && addedIndex !== null) {
|
|
||||||
onMove(targetBoardIndex, sourceBoardIndex, sourceCardIndex);
|
onMove(targetBoardIndex, sourceBoardIndex, sourceCardIndex);
|
||||||
}
|
}
|
||||||
|
setTimeout(() => updateDragging(false), 0);
|
||||||
}, [isDraggingOver, onMove]);
|
}, [isDraggingOver, onMove, updateDragging]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section draggable={false} className="sf-metadata-view-kanban-board">
|
<section draggable={false} className="sf-metadata-view-kanban-board">
|
||||||
@@ -120,6 +121,7 @@ Board.propTypes = {
|
|||||||
onUnFreezed: PropTypes.func,
|
onUnFreezed: PropTypes.func,
|
||||||
onOpenFile: PropTypes.func.isRequired,
|
onOpenFile: PropTypes.func.isRequired,
|
||||||
onSelectCard: PropTypes.func.isRequired,
|
onSelectCard: PropTypes.func.isRequired,
|
||||||
|
updateDragging: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Board;
|
export default Board;
|
||||||
|
@@ -2,12 +2,10 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sf-metadata-view-kanban-boards .smooth-dnd-container.horizontal {
|
.sf-metadata-view-kanban-boards .smooth-dnd-container.horizontal {
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
@@ -23,6 +23,7 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
|||||||
const [haveFreezed, setHaveFreezed] = useState(false);
|
const [haveFreezed, setHaveFreezed] = useState(false);
|
||||||
const [isImagePreviewerVisible, setImagePreviewerVisible] = useState(false);
|
const [isImagePreviewerVisible, setImagePreviewerVisible] = useState(false);
|
||||||
const [selectedCard, setSelectedCard] = useState('');
|
const [selectedCard, setSelectedCard] = useState('');
|
||||||
|
const [isDragging, setDragging] = useState(false);
|
||||||
|
|
||||||
const currentImageRef = useRef(null);
|
const currentImageRef = useRef(null);
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
@@ -188,6 +189,7 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
|||||||
|
|
||||||
const onSelectCard = useCallback((record) => {
|
const onSelectCard = useCallback((record) => {
|
||||||
const recordId = geRecordIdFromRecord(record);
|
const recordId = geRecordIdFromRecord(record);
|
||||||
|
if (selectedCard === recordId) return;
|
||||||
const name = getFileNameFromRecord(record);
|
const name = getFileNameFromRecord(record);
|
||||||
const path = getParentDirFromRecord(record);
|
const path = getParentDirFromRecord(record);
|
||||||
const isDir = checkIsDir(record);
|
const isDir = checkIsDir(record);
|
||||||
@@ -201,13 +203,17 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
|||||||
setSelectedCard(recordId);
|
setSelectedCard(recordId);
|
||||||
onCloseSettings();
|
onCloseSettings();
|
||||||
showDirentDetail();
|
showDirentDetail();
|
||||||
}, [onCloseSettings, showDirentDetail, updateCurrentDirent]);
|
}, [selectedCard, onCloseSettings, showDirentDetail, updateCurrentDirent]);
|
||||||
|
|
||||||
const handleClickOutside = useCallback((event) => {
|
const handleClickOutside = useCallback((event) => {
|
||||||
if (!containerRef.current.contains(event.target)) return;
|
if (isDragging) return;
|
||||||
setSelectedCard(null);
|
setSelectedCard(null);
|
||||||
updateCurrentDirent();
|
updateCurrentDirent();
|
||||||
}, [updateCurrentDirent]);
|
}, [isDragging, updateCurrentDirent]);
|
||||||
|
|
||||||
|
const updateDragging = useCallback((isDragging) => {
|
||||||
|
setDragging(isDragging);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isDirentDetailShow) {
|
if (!isDirentDetailShow) {
|
||||||
@@ -250,6 +256,7 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
|||||||
onUnFreezed={onUnFreezed}
|
onUnFreezed={onUnFreezed}
|
||||||
onOpenFile={onOpenFile}
|
onOpenFile={onOpenFile}
|
||||||
onSelectCard={onSelectCard}
|
onSelectCard={onSelectCard}
|
||||||
|
updateDragging={updateDragging}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@@ -25,7 +25,8 @@ const Kanban = () => {
|
|||||||
error && toaster.danger(error);
|
error && toaster.danger(error);
|
||||||
},
|
},
|
||||||
success_callback: () => {
|
success_callback: () => {
|
||||||
// do nothing
|
const eventBus = window.sfMetadataContext.eventBus;
|
||||||
|
eventBus.dispatch(EVENT_BUS_TYPE.LOCAL_RECORD_DETAIL_CHANGED, rowId, updates);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [store]);
|
}, [store]);
|
||||||
|
Reference in New Issue
Block a user