mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-14 07:24:58 +00:00
Feat metadata column order (#6622)
* feat: metdata column order * feat: hidden column support adjust column order * feat: optimzie code --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
parent
645099a405
commit
b32b3fe904
@ -6,7 +6,7 @@ import { CommonlyUsedHotkey } from '../../_basic';
|
|||||||
import { gettext } from '../../utils';
|
import { gettext } from '../../utils';
|
||||||
import { HideColumnPopover } from '../popover';
|
import { HideColumnPopover } from '../popover';
|
||||||
|
|
||||||
const HideColumnSetter = ({ readOnly, columns, wrapperClass, target, hiddenColumns, modifyHiddenColumns }) => {
|
const HideColumnSetter = ({ readOnly, columns, wrapperClass, target, hiddenColumns, modifyHiddenColumns, modifyColumnOrder }) => {
|
||||||
const [isShowSetter, setShowSetter] = useState(false);
|
const [isShowSetter, setShowSetter] = useState(false);
|
||||||
|
|
||||||
const validHiddenColumns = useMemo(() => {
|
const validHiddenColumns = useMemo(() => {
|
||||||
@ -57,6 +57,7 @@ const HideColumnSetter = ({ readOnly, columns, wrapperClass, target, hiddenColum
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
hidePopover={onSetterToggle}
|
hidePopover={onSetterToggle}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
modifyColumnOrder={modifyColumnOrder}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -70,6 +71,7 @@ HideColumnSetter.propTypes = {
|
|||||||
hiddenColumns: PropTypes.array,
|
hiddenColumns: PropTypes.array,
|
||||||
columns: PropTypes.array,
|
columns: PropTypes.array,
|
||||||
modifyHiddenColumns: PropTypes.func,
|
modifyHiddenColumns: PropTypes.func,
|
||||||
|
modifyColumnOrder: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HideColumnSetter;
|
export default HideColumnSetter;
|
||||||
|
@ -1,10 +1,66 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { DragSource, DropTarget } from 'react-dnd';
|
||||||
import { Icon, Switch } from '@seafile/sf-metadata-ui-component';
|
import { Icon, Switch } from '@seafile/sf-metadata-ui-component';
|
||||||
import { COLUMNS_ICON_CONFIG } from '../../../../_basic';
|
import { COLUMNS_ICON_CONFIG } from '../../../../_basic';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const HideColumnItem = ({ readOnly, column, isHidden, onChange }) => {
|
const dragSource = {
|
||||||
|
beginDrag: props => {
|
||||||
|
return { key: props.column.key, column: props.column };
|
||||||
|
},
|
||||||
|
endDrag(props, monitor) {
|
||||||
|
const source = monitor.getItem();
|
||||||
|
const didDrop = monitor.didDrop();
|
||||||
|
let target = {};
|
||||||
|
if (!didDrop) {
|
||||||
|
return { source, target };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDragging(props) {
|
||||||
|
const { columnIndex, currentIndex } = props;
|
||||||
|
return currentIndex > columnIndex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const dropTarget = {
|
||||||
|
drop(props, monitor) {
|
||||||
|
const source = monitor.getItem();
|
||||||
|
const { column: targetColumn } = props;
|
||||||
|
if (targetColumn.key !== source.key && source.column.frozen === targetColumn.frozen) {
|
||||||
|
const target = { key: targetColumn.key };
|
||||||
|
props.onMove(source.key, target.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dragCollect = (connect, monitor) => ({
|
||||||
|
connectDragSource: connect.dragSource(),
|
||||||
|
connectDragPreview: connect.dragPreview(),
|
||||||
|
isDragging: monitor.isDragging(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const dropCollect = (connect, monitor) => ({
|
||||||
|
connectDropTarget: connect.dropTarget(),
|
||||||
|
isOver: monitor.isOver(),
|
||||||
|
canDrop: monitor.canDrop(),
|
||||||
|
dragged: monitor.getItem(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const HideColumnItem = ({
|
||||||
|
isOver,
|
||||||
|
isDragging,
|
||||||
|
canDrop,
|
||||||
|
connectDragSource,
|
||||||
|
connectDragPreview,
|
||||||
|
connectDropTarget,
|
||||||
|
readOnly,
|
||||||
|
column,
|
||||||
|
columnIndex,
|
||||||
|
isHidden,
|
||||||
|
onChange,
|
||||||
|
onMouseEnter,
|
||||||
|
onMouseLeave,
|
||||||
|
}) => {
|
||||||
|
|
||||||
const update = useCallback(() => {
|
const update = useCallback(() => {
|
||||||
if (readOnly) return;
|
if (readOnly) return;
|
||||||
@ -12,28 +68,58 @@ const HideColumnItem = ({ readOnly, column, isHidden, onChange }) => {
|
|||||||
}, [readOnly, column, onChange]);
|
}, [readOnly, column, onChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('hide-column-item', { 'disabled': readOnly })}>
|
<>
|
||||||
<Switch
|
{connectDropTarget(
|
||||||
disabled={readOnly}
|
connectDragPreview(
|
||||||
checked={isHidden}
|
<div
|
||||||
placeholder={(
|
className={classNames('hide-column-item', {
|
||||||
<>
|
'disabled': readOnly,
|
||||||
<Icon iconName={COLUMNS_ICON_CONFIG[column.type]} />
|
'hide-column-can-drop-top': isOver && canDrop && isDragging,
|
||||||
<span className="text-truncate">{column.name}</span>
|
'hide-column-can-drop': isOver && canDrop && !isDragging
|
||||||
</>
|
})}
|
||||||
)}
|
onMouseEnter={() => onMouseEnter(columnIndex)}
|
||||||
onChange={update}
|
onMouseLeave={onMouseLeave}
|
||||||
switchClassName="hide-column-item-switch"
|
>
|
||||||
/>
|
{!readOnly && (
|
||||||
</div>
|
<>
|
||||||
|
{connectDragSource(
|
||||||
|
<div className="drag-hide-column-handle">
|
||||||
|
<Icon iconName="drag" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Switch
|
||||||
|
disabled={readOnly}
|
||||||
|
checked={isHidden}
|
||||||
|
placeholder={(
|
||||||
|
<>
|
||||||
|
<Icon iconName={COLUMNS_ICON_CONFIG[column.type]} />
|
||||||
|
<span className="text-truncate">{column.name}</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
onChange={update}
|
||||||
|
switchClassName="hide-column-item-switch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
HideColumnItem.propTypes = {
|
HideColumnItem.propTypes = {
|
||||||
readOnly: PropTypes.bool,
|
readOnly: PropTypes.bool,
|
||||||
isHidden: PropTypes.bool,
|
isHidden: PropTypes.bool,
|
||||||
|
columnIndex: PropTypes.number,
|
||||||
|
currentIndex: PropTypes.number,
|
||||||
column: PropTypes.object.isRequired,
|
column: PropTypes.object.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onMove: PropTypes.func,
|
||||||
|
onMouseEnter: PropTypes.func,
|
||||||
|
onMouseLeave: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HideColumnItem;
|
export default DropTarget('sfMetadataHiddenColumns', dropTarget, dropCollect)(
|
||||||
|
DragSource('sfMetadataHiddenColumns', dragSource, dragCollect)(HideColumnItem)
|
||||||
|
);
|
||||||
|
@ -1,26 +1,44 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { DropTarget } from 'react-dnd';
|
||||||
import { gettext } from '../../../../utils';
|
import { gettext } from '../../../../utils';
|
||||||
import HideColumn from './hide-column';
|
import HideColumn from './hide-column';
|
||||||
|
import html5DragDropContext from '../../../../../../pages/wiki2/wiki-nav/html5DragDropContext';
|
||||||
|
|
||||||
|
const HiddenColumns = ({ readOnly, columns, hiddenColumns, onChange, modifyColumnOrder }) => {
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(-1);
|
||||||
|
|
||||||
const HiddenColumns = ({ readOnly, columns, hiddenColumns, onChange }) => {
|
|
||||||
const isEmpty = useMemo(() => {
|
const isEmpty = useMemo(() => {
|
||||||
if (!Array.isArray(columns) || columns.length === 0) return true;
|
if (!Array.isArray(columns) || columns.length === 0) return true;
|
||||||
return false;
|
return false;
|
||||||
}, [columns]);
|
}, [columns]);
|
||||||
|
|
||||||
|
const onMouseEnter = useCallback((columnIndex) => {
|
||||||
|
if (currentIndex === columnIndex) return;
|
||||||
|
setCurrentIndex(columnIndex);
|
||||||
|
}, [currentIndex]);
|
||||||
|
|
||||||
|
const onMouseLeave = useCallback(() => {
|
||||||
|
setCurrentIndex(-1);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('hide-columns-list', { 'empty-hide-columns-container': isEmpty })}>
|
<div className={classnames('hide-columns-list', { 'empty-hide-columns-container': isEmpty })}>
|
||||||
{isEmpty && <div className="empty-hide-columns-list">{gettext('No properties available to be hidden')}</div>}
|
{isEmpty && <div className="empty-hide-columns-list">{gettext('No properties available to be hidden')}</div>}
|
||||||
{!isEmpty && columns.map((column) => {
|
{!isEmpty && columns.map((column, columnIndex) => {
|
||||||
return (
|
return (
|
||||||
<HideColumn
|
<HideColumn
|
||||||
key={column.key}
|
key={column.key}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
|
columnIndex={columnIndex}
|
||||||
|
currentIndex={currentIndex}
|
||||||
isHidden={!hiddenColumns.includes(column.key)}
|
isHidden={!hiddenColumns.includes(column.key)}
|
||||||
column={column}
|
column={column}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
onMove={modifyColumnOrder}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -33,6 +51,11 @@ HiddenColumns.propTypes = {
|
|||||||
hiddenColumns: PropTypes.array,
|
hiddenColumns: PropTypes.array,
|
||||||
columns: PropTypes.array,
|
columns: PropTypes.array,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
|
modifyColumnOrder: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HiddenColumns;
|
const DndHiddenColumns = DropTarget('sfMetadataHiddenColumns', {}, connect => ({
|
||||||
|
connectDropTarget: connect.dropTarget()
|
||||||
|
}))(HiddenColumns);
|
||||||
|
|
||||||
|
export default html5DragDropContext(DndHiddenColumns);
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sf-metadata-hide-columns-popover .hide-column-item .hide-column-item-switch,
|
.sf-metadata-hide-columns-popover .hide-column-item .hide-column-item-switch {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.sf-metadata-hide-columns-popover .hide-column-item .hide-column-item-switch .custom-switch {
|
.sf-metadata-hide-columns-popover .hide-column-item .hide-column-item-switch .custom-switch {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -79,7 +83,7 @@
|
|||||||
.sf-metadata-hide-columns-popover .hide-column-item .custom-switch .custom-switch-description {
|
.sf-metadata-hide-columns-popover .hide-column-item .custom-switch .custom-switch-description {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
width: 212px;
|
flex: 1;
|
||||||
color: #212529;
|
color: #212529;
|
||||||
transition: .3s color;
|
transition: .3s color;
|
||||||
}
|
}
|
||||||
@ -127,3 +131,34 @@
|
|||||||
color: #212529;
|
color: #212529;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item .drag-hide-column-handle {
|
||||||
|
width: 14px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item .drag-hide-column-handle .sf-metadata-icon {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-columns-list .hide-column-item.disabled .drag-hide-column-handle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item.hide-column-can-drop::after,
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item.hide-column-can-drop-top::before {
|
||||||
|
content: '';
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
background: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item.hide-column-can-drop::after {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-hide-columns-popover .hide-column-item.hide-column-can-drop-top::before {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { getEventClassName, gettext } from '../../../utils';
|
|||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
const HideColumnPopover = ({ hidePopover, onChange, readOnly, target, placement, columns, hiddenColumns: oldHiddenColumns }) => {
|
const HideColumnPopover = ({ hidePopover, onChange, readOnly, target, placement, columns, hiddenColumns: oldHiddenColumns, modifyColumnOrder }) => {
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [hiddenColumns, setHiddenColumns] = useState(oldHiddenColumns);
|
const [hiddenColumns, setHiddenColumns] = useState(oldHiddenColumns);
|
||||||
const displayColumns = useMemo(() => {
|
const displayColumns = useMemo(() => {
|
||||||
@ -104,7 +104,7 @@ const HideColumnPopover = ({ hidePopover, onChange, readOnly, target, placement,
|
|||||||
<div className="sf-metadata-hide-columns-search-container">
|
<div className="sf-metadata-hide-columns-search-container">
|
||||||
<SearchInput placeholder={gettext('Search property')} onKeyDown={onKeyDown} onChange={onChangeSearch} autoFocus={true}/>
|
<SearchInput placeholder={gettext('Search property')} onKeyDown={onKeyDown} onChange={onChangeSearch} autoFocus={true}/>
|
||||||
</div>
|
</div>
|
||||||
<HiddenColumns readOnly={readOnly} columns={displayColumns} hiddenColumns={hiddenColumns} onChange={hideColumn} />
|
<HiddenColumns readOnly={readOnly} columns={displayColumns} hiddenColumns={hiddenColumns} onChange={hideColumn} modifyColumnOrder={modifyColumnOrder} />
|
||||||
{!readOnly && !searchValue && (
|
{!readOnly && !searchValue && (
|
||||||
<div className="sf-metadata-hide-columns-operations">
|
<div className="sf-metadata-hide-columns-operations">
|
||||||
<div className="sf-metadata-hide-columns-operation px-2" onClick={hideAll} aria-label={gettext('Hide all')}>{gettext('Hide all')}</div>
|
<div className="sf-metadata-hide-columns-operation px-2" onClick={hideAll} aria-label={gettext('Hide all')}>{gettext('Hide all')}</div>
|
||||||
@ -125,6 +125,7 @@ HideColumnPopover.propTypes = {
|
|||||||
columns: PropTypes.array.isRequired,
|
columns: PropTypes.array.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
hidePopover: PropTypes.func.isRequired,
|
hidePopover: PropTypes.func.isRequired,
|
||||||
|
modifyColumnOrder: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HideColumnPopover;
|
export default HideColumnPopover;
|
||||||
|
@ -132,6 +132,10 @@ const Container = () => {
|
|||||||
store.modifyColumnWidth(columnKey, newWidth);
|
store.modifyColumnWidth(columnKey, newWidth);
|
||||||
}, [store]);
|
}, [store]);
|
||||||
|
|
||||||
|
const modifyColumnOrder = useCallback((sourceColumnKey, targetColumnKey) => {
|
||||||
|
store.modifyColumnOrder(sourceColumnKey, targetColumnKey);
|
||||||
|
}, [store]);
|
||||||
|
|
||||||
const recordGetterById = useCallback((recordId) => {
|
const recordGetterById = useCallback((recordId) => {
|
||||||
return metadata.id_row_map[recordId];
|
return metadata.id_row_map[recordId];
|
||||||
}, [metadata]);
|
}, [metadata]);
|
||||||
@ -159,16 +163,19 @@ const Container = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', onKeyDown);
|
document.addEventListener('keydown', onKeyDown);
|
||||||
const unsubscribeModifyFilters = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_FILTERS, modifyFilters);
|
const eventBus = window.sfMetadataContext.eventBus;
|
||||||
const unsubscribeModifySorts = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SORTS, modifySorts);
|
const unsubscribeModifyFilters = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_FILTERS, modifyFilters);
|
||||||
const unsubscribeModifyGroupbys = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_GROUPBYS, modifyGroupbys);
|
const unsubscribeModifySorts = eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_SORTS, modifySorts);
|
||||||
const unsubscribeModifyHiddenColumns = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, modifyHiddenColumns);
|
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 () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', onKeyDown);
|
document.removeEventListener('keydown', onKeyDown);
|
||||||
unsubscribeModifyFilters();
|
unsubscribeModifyFilters();
|
||||||
unsubscribeModifySorts();
|
unsubscribeModifySorts();
|
||||||
unsubscribeModifyGroupbys();
|
unsubscribeModifyGroupbys();
|
||||||
unsubscribeModifyHiddenColumns();
|
unsubscribeModifyHiddenColumns();
|
||||||
|
unsubscribeModifyColumnOrder();
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
@ -197,6 +204,7 @@ const Container = () => {
|
|||||||
deleteColumn={deleteColumn}
|
deleteColumn={deleteColumn}
|
||||||
modifyColumnData={modifyColumnData}
|
modifyColumnData={modifyColumnData}
|
||||||
modifyColumnWidth={modifyColumnWidth}
|
modifyColumnWidth={modifyColumnWidth}
|
||||||
|
modifyColumnOrder={modifyColumnOrder}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{metadata.view.type === 'image' && (<Gallery />)}
|
{metadata.view.type === 'image' && (<Gallery />)}
|
||||||
|
@ -655,7 +655,7 @@ class Records extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { recordIds, recordsCount, table, isGroupView, groupOffsetLeft, renameColumn, modifyColumnData,
|
const { recordIds, recordsCount, table, isGroupView, groupOffsetLeft, renameColumn, modifyColumnData,
|
||||||
deleteColumn } = this.props;
|
deleteColumn, modifyColumnOrder } = this.props;
|
||||||
const { recordMetrics, columnMetrics, selectedRange, colOverScanStartIdx, colOverScanEndIdx } = this.state;
|
const { recordMetrics, columnMetrics, selectedRange, colOverScanStartIdx, colOverScanEndIdx } = this.state;
|
||||||
const { columns, totalWidth, lastFrozenColumnKey } = columnMetrics;
|
const { columns, totalWidth, lastFrozenColumnKey } = columnMetrics;
|
||||||
const containerWidth = totalWidth + SEQUENCE_COLUMN_WIDTH + CANVAS_RIGHT_INTERVAL + groupOffsetLeft;
|
const containerWidth = totalWidth + SEQUENCE_COLUMN_WIDTH + CANVAS_RIGHT_INTERVAL + groupOffsetLeft;
|
||||||
@ -689,6 +689,7 @@ class Records extends Component {
|
|||||||
renameColumn={renameColumn}
|
renameColumn={renameColumn}
|
||||||
deleteColumn={deleteColumn}
|
deleteColumn={deleteColumn}
|
||||||
modifyColumnData={modifyColumnData}
|
modifyColumnData={modifyColumnData}
|
||||||
|
modifyColumnOrder={modifyColumnOrder}
|
||||||
/>
|
/>
|
||||||
{this.renderRecordsBody({ containerWidth })}
|
{this.renderRecordsBody({ containerWidth })}
|
||||||
</div>
|
</div>
|
||||||
@ -746,6 +747,7 @@ Records.propTypes = {
|
|||||||
deleteColumn: PropTypes.func,
|
deleteColumn: PropTypes.func,
|
||||||
modifyColumnData: PropTypes.func,
|
modifyColumnData: PropTypes.func,
|
||||||
modifyColumnWidth: PropTypes.func,
|
modifyColumnWidth: PropTypes.func,
|
||||||
|
modifyColumnOrder: PropTypes.func,
|
||||||
getCopiedRecordsAndColumnsFromRange: PropTypes.func,
|
getCopiedRecordsAndColumnsFromRange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,3 +7,11 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
transform: scale(.8);
|
transform: scale(.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sf-metadata-record-header-cell .rdg-can-drop > .sf-metadata-result-table-cell.column {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sf-metadata-record-header-cell .rdg-dropping > .sf-metadata-result-table-cell.column {
|
||||||
|
background: #ececec;
|
||||||
|
}
|
||||||
|
@ -2,8 +2,9 @@ import React, { useRef, useCallback, useMemo } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { UncontrolledTooltip } from 'reactstrap';
|
import { UncontrolledTooltip } from 'reactstrap';
|
||||||
|
import { DragSource, DropTarget } from 'react-dnd';
|
||||||
import { Icon } from '@seafile/sf-metadata-ui-component';
|
import { Icon } from '@seafile/sf-metadata-ui-component';
|
||||||
import { COLUMNS_ICON_CONFIG, COLUMNS_ICON_NAME } from '../../../../../../_basic';
|
import { COLUMNS_ICON_CONFIG, COLUMNS_ICON_NAME, PRIVATE_COLUMN_KEY } from '../../../../../../_basic';
|
||||||
import ResizeColumnHandle from './resize-column-handle';
|
import ResizeColumnHandle from './resize-column-handle';
|
||||||
import { EVENT_BUS_TYPE } from '../../../../../../constants';
|
import { EVENT_BUS_TYPE } from '../../../../../../constants';
|
||||||
import DropdownMenu from './dropdown-menu';
|
import DropdownMenu from './dropdown-menu';
|
||||||
@ -11,7 +12,73 @@ import { gettext } from '../../../../../../utils';
|
|||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
|
|
||||||
|
const dragSource = {
|
||||||
|
beginDrag: props => {
|
||||||
|
return { key: props.column.key, column: props.column };
|
||||||
|
},
|
||||||
|
endDrag(props, monitor) {
|
||||||
|
const source = monitor.getItem();
|
||||||
|
const didDrop = monitor.didDrop();
|
||||||
|
let target = {};
|
||||||
|
if (!didDrop) {
|
||||||
|
return { source, target };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDragging(props) {
|
||||||
|
const { column, dragged } = props;
|
||||||
|
const { key } = dragged;
|
||||||
|
return key === column.key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dropTarget = {
|
||||||
|
hover(props, monitor, component) {
|
||||||
|
// This is fired very often and lets you perform side effects.
|
||||||
|
if (!window.sfMetadataBody) return;
|
||||||
|
const defaultColumnWidth = 200;
|
||||||
|
const offsetX = monitor.getClientOffset().x;
|
||||||
|
const width = document.querySelector('.sf-metadata-wrapper')?.clientWidth;
|
||||||
|
const left = window.innerWidth - width;
|
||||||
|
if (offsetX > width - defaultColumnWidth) {
|
||||||
|
window.sfMetadataBody.scrollToRight();
|
||||||
|
} else if (offsetX < props.frozenColumnsWidth + defaultColumnWidth + left) {
|
||||||
|
window.sfMetadataBody.scrollToLeft();
|
||||||
|
} else {
|
||||||
|
window.sfMetadataBody.clearHorizontalScroll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
drop(props, monitor) {
|
||||||
|
const source = monitor.getItem();
|
||||||
|
const { column: targetColumn } = props;
|
||||||
|
if (targetColumn.key !== source.key && source.column.frozen === targetColumn.frozen) {
|
||||||
|
let target = { key: targetColumn.key };
|
||||||
|
props.onMove(source, target);
|
||||||
|
window.sfMetadataBody.clearHorizontalScroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dragCollect = (connect, monitor) => ({
|
||||||
|
connectDragSource: connect.dragSource(),
|
||||||
|
connectDragPreview: connect.dragPreview(),
|
||||||
|
isDragging: monitor.isDragging(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const dropCollect = (connect, monitor) => ({
|
||||||
|
connectDropTarget: connect.dropTarget(),
|
||||||
|
isOver: monitor.isOver(),
|
||||||
|
canDrop: monitor.canDrop(),
|
||||||
|
dragged: monitor.getItem(),
|
||||||
|
});
|
||||||
|
|
||||||
const Cell = ({
|
const Cell = ({
|
||||||
|
isOver,
|
||||||
|
isDragging,
|
||||||
|
canDrop,
|
||||||
|
connectDragSource,
|
||||||
|
connectDragPreview,
|
||||||
|
connectDropTarget,
|
||||||
frozen,
|
frozen,
|
||||||
groupOffsetLeft,
|
groupOffsetLeft,
|
||||||
isLastFrozenCell,
|
isLastFrozenCell,
|
||||||
@ -68,41 +135,67 @@ const Cell = ({
|
|||||||
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.SELECT_COLUMN, column);
|
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.SELECT_COLUMN, column);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onContextMenu = useCallback((event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const { key, name, type } = column;
|
const { key, name, type } = column;
|
||||||
const headerIconTooltip = COLUMNS_ICON_NAME[type];
|
const headerIconTooltip = COLUMNS_ICON_NAME[type];
|
||||||
return (
|
const canModifyColumnOrder = window.sfMetadataContext.canModifyColumnOrder();
|
||||||
<div key={key} className="sf-metadata-record-header-cell">
|
const cell = (
|
||||||
<div
|
<div
|
||||||
className={classnames('sf-metadata-result-table-cell column', { 'table-last--frozen': isLastFrozenCell })}
|
className={classnames('sf-metadata-result-table-cell column', { 'table-last--frozen': isLastFrozenCell })}
|
||||||
ref={headerCellRef}
|
ref={headerCellRef}
|
||||||
style={style}
|
style={style}
|
||||||
id={`sf-metadata-column-${key}`}
|
id={`sf-metadata-column-${key}`}
|
||||||
onClick={() => handleHeaderCellClick(column, frozen)}
|
onClick={() => handleHeaderCellClick(column, frozen)}
|
||||||
>
|
onContextMenu={onContextMenu}
|
||||||
<div className="sf-metadata-result-column-content sf-metadata-record-header-cell-left d-flex align-items-center text-truncate">
|
>
|
||||||
<span className="mr-2" id={`header-icon-${key}`}>
|
<div className="sf-metadata-result-column-content sf-metadata-record-header-cell-left d-flex align-items-center text-truncate">
|
||||||
<Icon iconName={COLUMNS_ICON_CONFIG[type]} className="sf-metadata-column-icon" />
|
<span className="mr-2" id={`header-icon-${key}`}>
|
||||||
</span>
|
<Icon iconName={COLUMNS_ICON_CONFIG[type]} className="sf-metadata-column-icon" />
|
||||||
<UncontrolledTooltip placement="bottom" target={`header-icon-${key}`} fade={false} trigger="hover">
|
</span>
|
||||||
{gettext(headerIconTooltip)}
|
<UncontrolledTooltip placement="bottom" target={`header-icon-${key}`} fade={false} trigger="hover">
|
||||||
</UncontrolledTooltip>
|
{gettext(headerIconTooltip)}
|
||||||
<div className="header-name d-flex">
|
</UncontrolledTooltip>
|
||||||
<span title={name} className={classnames('header-name-text', { 'double': height === 56 })}>{name}</span>
|
<div className="header-name d-flex">
|
||||||
</div>
|
<span title={name} className={classnames('header-name-text', { 'double': height === 56 })}>{name}</span>
|
||||||
</div>
|
</div>
|
||||||
{canEditColumnInfo && (
|
|
||||||
<DropdownMenu
|
|
||||||
column={column}
|
|
||||||
renameColumn={renameColumn}
|
|
||||||
deleteColumn={deleteColumn}
|
|
||||||
modifyColumnData={modifyColumnData}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<ResizeColumnHandle onDrag={onDrag} onDragEnd={onDragEnd} />
|
|
||||||
</div>
|
</div>
|
||||||
|
{canEditColumnInfo && (
|
||||||
|
<DropdownMenu
|
||||||
|
column={column}
|
||||||
|
renameColumn={renameColumn}
|
||||||
|
deleteColumn={deleteColumn}
|
||||||
|
modifyColumnData={modifyColumnData}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<ResizeColumnHandle onDrag={onDrag} onDragEnd={onDragEnd} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!canModifyColumnOrder || column.key === PRIVATE_COLUMN_KEY.FILE_NAME) {
|
||||||
|
return (
|
||||||
|
<div key={key} className="sf-metadata-record-header-cell">
|
||||||
|
{cell}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={key} className="sf-metadata-record-header-cell">
|
||||||
|
{connectDropTarget(
|
||||||
|
connectDragPreview(
|
||||||
|
connectDragSource(
|
||||||
|
<div style={{ opacity: isDragging ? 0.2 : 1 }} className={classnames('rdg-can-drop', { 'rdg-dropping': isOver && canDrop })}>
|
||||||
|
{cell}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Cell.defaultProps = {
|
Cell.defaultProps = {
|
||||||
@ -123,4 +216,6 @@ Cell.propTypes = {
|
|||||||
modifyLocalColumnWidth: PropTypes.func,
|
modifyLocalColumnWidth: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Cell;
|
export default DropTarget('sfMetadataRecordHeaderCell', dropTarget, dropCollect)(
|
||||||
|
DragSource('sfMetadataRecordHeaderCell', dragSource, dragCollect)(Cell)
|
||||||
|
);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { DropTarget } from 'react-dnd';
|
||||||
import {
|
import {
|
||||||
HEADER_HEIGHT_TYPE,
|
HEADER_HEIGHT_TYPE,
|
||||||
isEmptyObject,
|
isEmptyObject,
|
||||||
@ -12,6 +13,7 @@ import { getFrozenColumns } from '../../../../../utils/table-utils';
|
|||||||
import { isFrozen, recalculateColumnMetricsByResizeColumn } from '../../../../../utils/column-utils';
|
import { isFrozen, recalculateColumnMetricsByResizeColumn } from '../../../../../utils/column-utils';
|
||||||
import { GRID_HEADER_DEFAULT_HEIGHT, GRID_HEADER_DOUBLE_HEIGHT } from '../../../../../constants';
|
import { GRID_HEADER_DEFAULT_HEIGHT, GRID_HEADER_DOUBLE_HEIGHT } from '../../../../../constants';
|
||||||
import InsertColumn from './insert-column';
|
import InsertColumn from './insert-column';
|
||||||
|
import html5DragDropContext from '../../../../../../../pages/wiki2/wiki-nav/html5DragDropContext';
|
||||||
|
|
||||||
const RecordsHeader = ({
|
const RecordsHeader = ({
|
||||||
isGroupView,
|
isGroupView,
|
||||||
@ -28,6 +30,7 @@ const RecordsHeader = ({
|
|||||||
selectNoneRecords,
|
selectNoneRecords,
|
||||||
selectAllRecords,
|
selectAllRecords,
|
||||||
modifyColumnWidth: modifyColumnWidthAPI,
|
modifyColumnWidth: modifyColumnWidthAPI,
|
||||||
|
modifyColumnOrder: modifyColumnOrderAPI,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const [resizingColumnMetrics, setResizingColumnMetrics] = useState(null);
|
const [resizingColumnMetrics, setResizingColumnMetrics] = useState(null);
|
||||||
@ -74,8 +77,13 @@ const RecordsHeader = ({
|
|||||||
modifyColumnWidthAPI && modifyColumnWidthAPI(column, newWidth);
|
modifyColumnWidthAPI && modifyColumnWidthAPI(column, newWidth);
|
||||||
}, [modifyColumnWidthAPI]);
|
}, [modifyColumnWidthAPI]);
|
||||||
|
|
||||||
|
const modifyColumnOrder = useCallback((source, target) => {
|
||||||
|
modifyColumnOrderAPI && modifyColumnOrderAPI(source.key, target.key);
|
||||||
|
}, [modifyColumnOrderAPI]);
|
||||||
|
|
||||||
const frozenColumns = getFrozenColumns(columnMetrics.columns);
|
const frozenColumns = getFrozenColumns(columnMetrics.columns);
|
||||||
const displayColumns = columnMetrics.columns.slice(colOverScanStartIdx, colOverScanEndIdx);
|
const displayColumns = columnMetrics.columns.slice(colOverScanStartIdx, colOverScanEndIdx);
|
||||||
|
const frozenColumnsWidth = frozenColumns.reduce((total, c) => total + c.width, 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="static-sf-metadata-result-content grid-header" style={{ height: height + 1 }}>
|
<div className="static-sf-metadata-result-content grid-header" style={{ height: height + 1 }}>
|
||||||
@ -104,9 +112,11 @@ const RecordsHeader = ({
|
|||||||
column={column}
|
column={column}
|
||||||
style={style}
|
style={style}
|
||||||
isLastFrozenCell={isLastFrozenCell}
|
isLastFrozenCell={isLastFrozenCell}
|
||||||
|
frozenColumnsWidth={frozenColumnsWidth}
|
||||||
isHideTriangle={isHideTriangle}
|
isHideTriangle={isHideTriangle}
|
||||||
modifyLocalColumnWidth={modifyLocalColumnWidth}
|
modifyLocalColumnWidth={modifyLocalColumnWidth}
|
||||||
modifyColumnWidth={modifyColumnWidth}
|
modifyColumnWidth={modifyColumnWidth}
|
||||||
|
onMove={modifyColumnOrder}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -121,8 +131,10 @@ const RecordsHeader = ({
|
|||||||
groupOffsetLeft={groupOffsetLeft}
|
groupOffsetLeft={groupOffsetLeft}
|
||||||
height={height}
|
height={height}
|
||||||
column={column}
|
column={column}
|
||||||
|
frozenColumnsWidth={frozenColumnsWidth}
|
||||||
modifyLocalColumnWidth={modifyLocalColumnWidth}
|
modifyLocalColumnWidth={modifyLocalColumnWidth}
|
||||||
modifyColumnWidth={modifyColumnWidth}
|
modifyColumnWidth={modifyColumnWidth}
|
||||||
|
onMove={modifyColumnOrder}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -131,7 +143,6 @@ const RecordsHeader = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RecordsHeader.propTypes = {
|
RecordsHeader.propTypes = {
|
||||||
@ -150,4 +161,9 @@ RecordsHeader.propTypes = {
|
|||||||
selectAllRecords: PropTypes.func,
|
selectAllRecords: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RecordsHeader;
|
const DndRecordHeaderContainer = DropTarget('sfMetadataRecordHeaderCell', {}, connect => ({
|
||||||
|
connectDropTarget: connect.dropTarget()
|
||||||
|
}))(RecordsHeader);
|
||||||
|
|
||||||
|
export default html5DragDropContext(DndRecordHeaderContainer);
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ const ViewToolBar = ({ viewId }) => {
|
|||||||
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, hiddenColumns);
|
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.MODIFY_HIDDEN_COLUMNS, hiddenColumns);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const modifyColumnOrder = useCallback((sourceColumnKey, targetColumnKey) => {
|
||||||
|
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.MODIFY_COLUMN_ORDER, sourceColumnKey, targetColumnKey);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const viewChange = useCallback((view) => {
|
const viewChange = useCallback((view) => {
|
||||||
setView(view);
|
setView(view);
|
||||||
}, []);
|
}, []);
|
||||||
@ -109,6 +113,7 @@ const ViewToolBar = ({ viewId }) => {
|
|||||||
columns={viewColumns.slice(1)}
|
columns={viewColumns.slice(1)}
|
||||||
hiddenColumns={view.hidden_columns || []}
|
hiddenColumns={view.hidden_columns || []}
|
||||||
modifyHiddenColumns={modifyHiddenColumns}
|
modifyHiddenColumns={modifyHiddenColumns}
|
||||||
|
modifyColumnOrder={modifyColumnOrder}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="sf-metadata-tool-right-operations"></div>
|
<div className="sf-metadata-tool-right-operations"></div>
|
||||||
|
@ -42,6 +42,9 @@ export const EVENT_BUS_TYPE = {
|
|||||||
// change
|
// change
|
||||||
VIEW_CHANGED: 'view_changed',
|
VIEW_CHANGED: 'view_changed',
|
||||||
|
|
||||||
|
// column
|
||||||
|
MODIFY_COLUMN_ORDER: 'modify_column_order',
|
||||||
|
|
||||||
// data status
|
// data status
|
||||||
SAVING: 'saving',
|
SAVING: 'saving',
|
||||||
SAVED: 'saved',
|
SAVED: 'saved',
|
||||||
|
@ -125,6 +125,11 @@ class Context {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
canModifyColumnOrder = () => {
|
||||||
|
if (this.permission === 'r') return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
canModifyView = (view) => {
|
canModifyView = (view) => {
|
||||||
if (this.permission === 'r') return false;
|
if (this.permission === 'r') return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { VIEW_NOT_DISPLAY_COLUMN_KEYS } from '../../_basic';
|
import { getColumnByKey, VIEW_NOT_DISPLAY_COLUMN_KEYS } from '../../_basic';
|
||||||
|
|
||||||
class View {
|
class View {
|
||||||
constructor(object, columns) {
|
constructor(object, columns) {
|
||||||
@ -25,7 +25,23 @@ class View {
|
|||||||
|
|
||||||
// columns
|
// columns
|
||||||
this.available_columns = columns || [];
|
this.available_columns = columns || [];
|
||||||
this.columns = this.available_columns.filter(column => !VIEW_NOT_DISPLAY_COLUMN_KEYS.includes(column.key));
|
this.display_available_columns = this.available_columns.filter(column => !VIEW_NOT_DISPLAY_COLUMN_KEYS.includes(column.key));
|
||||||
|
this.columns = this.display_available_columns;
|
||||||
|
|
||||||
|
// order
|
||||||
|
let columnsKeys = object.columns_keys || [];
|
||||||
|
if (columnsKeys.length === 0) {
|
||||||
|
this.columns_keys = this.display_available_columns.map(c => c.key);
|
||||||
|
} else {
|
||||||
|
let columns = columnsKeys.map(key => getColumnByKey(this.display_available_columns, key)).filter(c => c);
|
||||||
|
this.display_available_columns.forEach(column => {
|
||||||
|
if (!getColumnByKey(columns, column.key)) {
|
||||||
|
columns.push(column);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.columns_keys = columns.map(c => c.key);
|
||||||
|
this.columns = columns;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -431,6 +431,19 @@ class Store {
|
|||||||
this.applyOperation(operation);
|
this.applyOperation(operation);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
modifyColumnOrder = (sourceColumnKey, targetColumnKey) => {
|
||||||
|
const type = OPERATION_TYPE.MODIFY_COLUMN_ORDER;
|
||||||
|
const { columns_keys } = this.data.view;
|
||||||
|
const targetColumnIndex = columns_keys.indexOf(targetColumnKey);
|
||||||
|
let newColumnsKeys = columns_keys.slice(0);
|
||||||
|
newColumnsKeys = newColumnsKeys.filter(key => key !== sourceColumnKey);
|
||||||
|
newColumnsKeys.splice(targetColumnIndex, 0, sourceColumnKey);
|
||||||
|
const operation = this.createOperation({
|
||||||
|
type, repo_id: this.repoId, view_id: this.viewId, new_columns_keys: newColumnsKeys, old_columns_keys: columns_keys
|
||||||
|
});
|
||||||
|
this.applyOperation(operation);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Store;
|
export default Store;
|
||||||
|
@ -171,6 +171,11 @@ export default function apply(data, operation) {
|
|||||||
data.view = new View(data.view, data.columns);
|
data.view = new View(data.view, data.columns);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
case OPERATION_TYPE.MODIFY_COLUMN_ORDER: {
|
||||||
|
const { new_columns_keys } = operation;
|
||||||
|
data.view = new View({ ...data.view, columns_keys: new_columns_keys }, data.columns);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ export const OPERATION_TYPE = {
|
|||||||
RENAME_COLUMN: 'rename_column',
|
RENAME_COLUMN: 'rename_column',
|
||||||
MODIFY_COLUMN_DATA: 'modify_column_data',
|
MODIFY_COLUMN_DATA: 'modify_column_data',
|
||||||
MODIFY_COLUMN_WIDTH: 'modify_column_width',
|
MODIFY_COLUMN_WIDTH: 'modify_column_width',
|
||||||
|
MODIFY_COLUMN_ORDER: 'modify_column_order',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OPERATION_ATTRIBUTES = {
|
export const OPERATION_ATTRIBUTES = {
|
||||||
@ -33,7 +34,8 @@ export const OPERATION_ATTRIBUTES = {
|
|||||||
[OPERATION_TYPE.RENAME_COLUMN]: ['repo_id', 'column_key', 'new_name', 'old_name'],
|
[OPERATION_TYPE.RENAME_COLUMN]: ['repo_id', 'column_key', 'new_name', 'old_name'],
|
||||||
[OPERATION_TYPE.MODIFY_COLUMN_DATA]: ['repo_id', 'column_key', 'new_data', 'old_data'],
|
[OPERATION_TYPE.MODIFY_COLUMN_DATA]: ['repo_id', 'column_key', 'new_data', 'old_data'],
|
||||||
[OPERATION_TYPE.DELETE_COLUMN]: ['repo_id', 'column_key', 'column'],
|
[OPERATION_TYPE.DELETE_COLUMN]: ['repo_id', 'column_key', 'column'],
|
||||||
[OPERATION_TYPE.MODIFY_COLUMN_WIDTH]: ['repo_id', 'column_key', 'new_width', 'old_width'],
|
[OPERATION_TYPE.MODIFY_COLUMN_WIDTH]: ['column_key', 'new_width', 'old_width'],
|
||||||
|
[OPERATION_TYPE.MODIFY_COLUMN_ORDER]: ['repo_id', 'view_id', 'new_columns_keys', 'old_columns_keys'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UNDO_OPERATION_TYPE = [
|
export const UNDO_OPERATION_TYPE = [
|
||||||
@ -61,6 +63,7 @@ export const NEED_APPLY_AFTER_SERVER_OPERATION = [
|
|||||||
OPERATION_TYPE.RENAME_COLUMN,
|
OPERATION_TYPE.RENAME_COLUMN,
|
||||||
OPERATION_TYPE.MODIFY_COLUMN_DATA,
|
OPERATION_TYPE.MODIFY_COLUMN_DATA,
|
||||||
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
||||||
|
OPERATION_TYPE.MODIFY_COLUMN_ORDER,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const VIEW_OPERATION = [
|
export const VIEW_OPERATION = [
|
||||||
@ -76,4 +79,5 @@ export const COLUMN_OPERATION = [
|
|||||||
OPERATION_TYPE.RENAME_COLUMN,
|
OPERATION_TYPE.RENAME_COLUMN,
|
||||||
OPERATION_TYPE.MODIFY_COLUMN_DATA,
|
OPERATION_TYPE.MODIFY_COLUMN_DATA,
|
||||||
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
OPERATION_TYPE.MODIFY_COLUMN_WIDTH,
|
||||||
|
OPERATION_TYPE.MODIFY_COLUMN_ORDER,
|
||||||
];
|
];
|
||||||
|
@ -97,6 +97,15 @@ class ServerOperator {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OPERATION_TYPE.MODIFY_COLUMN_ORDER: {
|
||||||
|
const { repo_id, view_id, new_columns_keys } = operation;
|
||||||
|
window.sfMetadataContext.modifyView(repo_id, view_id, { columns_keys: new_columns_keys }).then(res => {
|
||||||
|
callback({ operation });
|
||||||
|
}).catch(error => {
|
||||||
|
callback({ error: gettext('Failed to modify property order') });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OPERATION_TYPE.MODIFY_FILTERS: {
|
case OPERATION_TYPE.MODIFY_FILTERS: {
|
||||||
const { repo_id, view_id, filter_conjunction, filters } = operation;
|
const { repo_id, view_id, filter_conjunction, filters } = operation;
|
||||||
window.sfMetadataContext.modifyView(repo_id, view_id, { filters, filter_conjunction }).then(res => {
|
window.sfMetadataContext.modifyView(repo_id, view_id, { filters, filter_conjunction }).then(res => {
|
||||||
|
Loading…
Reference in New Issue
Block a user