mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Allow reordering table columns using drag and drop in ERD Tool and create table. #4994
This commit is contained in:
parent
869b90121c
commit
406119d96c
Binary file not shown.
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 116 KiB |
@ -15,6 +15,7 @@ Supported Database Servers
|
|||||||
New features
|
New features
|
||||||
************
|
************
|
||||||
|
|
||||||
|
| `Issue #4994 <https://github.com/pgadmin-org/pgadmin4/issues/4994>`_ - Allow reordering table columns using drag and drop in ERD Tool.
|
||||||
| `Issue #5304 <https://github.com/pgadmin-org/pgadmin4/issues/5304>`_ - Added high availability options to AWS deployment.
|
| `Issue #5304 <https://github.com/pgadmin-org/pgadmin4/issues/5304>`_ - Added high availability options to AWS deployment.
|
||||||
|
|
||||||
Housekeeping
|
Housekeeping
|
||||||
|
@ -146,6 +146,8 @@
|
|||||||
"react-aspen": "^1.1.0",
|
"react-aspen": "^1.1.0",
|
||||||
"react-checkbox-tree": "^1.7.2",
|
"react-checkbox-tree": "^1.7.2",
|
||||||
"react-data-grid": "git+https://github.com/EnterpriseDB/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8",
|
"react-data-grid": "git+https://github.com/EnterpriseDB/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8",
|
||||||
|
"react-dnd": "^16.0.1",
|
||||||
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
"react-dropzone": "^14.2.1",
|
"react-dropzone": "^14.2.1",
|
||||||
|
@ -661,6 +661,7 @@ export default class TableSchema extends BaseUISchema {
|
|||||||
},
|
},
|
||||||
canAdd: this.canAddRowColumns,
|
canAdd: this.canAddRowColumns,
|
||||||
canEdit: true, canDelete: true,
|
canEdit: true, canDelete: true,
|
||||||
|
canReorder: (state)=>(this.inErd || this.isNew(state)),
|
||||||
// For each row edit/delete button enable/disable
|
// For each row edit/delete button enable/disable
|
||||||
canEditRow: this.canEditDeleteRowColumns,
|
canEditRow: this.canEditDeleteRowColumns,
|
||||||
canDeleteRow: this.canEditDeleteRowColumns,
|
canDeleteRow: this.canEditDeleteRowColumns,
|
||||||
|
@ -15,12 +15,15 @@ import { makeStyles } from '@material-ui/core/styles';
|
|||||||
import { PgIconButton } from '../components/Buttons';
|
import { PgIconButton } from '../components/Buttons';
|
||||||
import AddIcon from '@material-ui/icons/AddOutlined';
|
import AddIcon from '@material-ui/icons/AddOutlined';
|
||||||
import { MappedCellControl } from './MappedControl';
|
import { MappedCellControl } from './MappedControl';
|
||||||
|
import DragIndicatorRoundedIcon from '@material-ui/icons/DragIndicatorRounded';
|
||||||
import EditRoundedIcon from '@material-ui/icons/EditRounded';
|
import EditRoundedIcon from '@material-ui/icons/EditRounded';
|
||||||
import DeleteRoundedIcon from '@material-ui/icons/DeleteRounded';
|
import DeleteRoundedIcon from '@material-ui/icons/DeleteRounded';
|
||||||
import { useTable, useFlexLayout, useResizeColumns, useSortBy, useExpanded, useGlobalFilter } from 'react-table';
|
import { useTable, useFlexLayout, useResizeColumns, useSortBy, useExpanded, useGlobalFilter } from 'react-table';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { DndProvider, useDrag, useDrop } from 'react-dnd';
|
||||||
|
import {HTML5Backend} from 'react-dnd-html5-backend';
|
||||||
|
|
||||||
import gettext from 'sources/gettext';
|
import gettext from 'sources/gettext';
|
||||||
import { SCHEMA_STATE_ACTIONS, StateUtilsContext } from '.';
|
import { SCHEMA_STATE_ACTIONS, StateUtilsContext } from '.';
|
||||||
@ -74,6 +77,15 @@ const useStyles = makeStyles((theme)=>({
|
|||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
backgroundColor: theme.otherVars.tableBg,
|
backgroundColor: theme.otherVars.tableBg,
|
||||||
},
|
},
|
||||||
|
tableRowHovered: {
|
||||||
|
position: 'relative',
|
||||||
|
'& .hover-overlay': {
|
||||||
|
backgroundColor: theme.palette.primary.light,
|
||||||
|
position: 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
opacity: 0.75,
|
||||||
|
}
|
||||||
|
},
|
||||||
tableCell: {
|
tableCell: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
padding: theme.spacing(0.5),
|
padding: theme.spacing(0.5),
|
||||||
@ -96,6 +108,9 @@ const useStyles = makeStyles((theme)=>({
|
|||||||
padding: theme.spacing(0.5, 0),
|
padding: theme.spacing(0.5, 0),
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
|
btnReorder: {
|
||||||
|
cursor: 'move',
|
||||||
|
},
|
||||||
resizer: {
|
resizer: {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
width: '5px',
|
width: '5px',
|
||||||
@ -152,10 +167,12 @@ DataTableHeader.propTypes = {
|
|||||||
headerGroups: PropTypes.array.isRequired,
|
headerGroups: PropTypes.array.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function DataTableRow({row, totalRows, isResizing, schema, schemaRef, accessPath}) {
|
function DataTableRow({index, row, totalRows, isResizing, isHovered, schema, schemaRef, accessPath, moveRow, setHoverIndex}) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [key, setKey] = useState(false);
|
const [key, setKey] = useState(false);
|
||||||
const depListener = useContext(DepListenerContext);
|
const depListener = useContext(DepListenerContext);
|
||||||
|
const rowRef = useRef(null);
|
||||||
|
const dragHandleRef = useRef(null);
|
||||||
|
|
||||||
/* Memoize the row to avoid unnecessary re-render.
|
/* Memoize the row to avoid unnecessary re-render.
|
||||||
* If table data changes, then react-table re-renders the complete tables
|
* If table data changes, then react-table re-renders the complete tables
|
||||||
@ -201,28 +218,87 @@ function DataTableRow({row, totalRows, isResizing, schema, schemaRef, accessPath
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [{ handlerId }, drop] = useDrop({
|
||||||
|
accept: 'row',
|
||||||
|
collect(monitor) {
|
||||||
|
return {
|
||||||
|
handlerId: monitor.getHandlerId(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
hover(item, monitor) {
|
||||||
|
if (!rowRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.hoverIndex = null;
|
||||||
|
// Don't replace items with themselves
|
||||||
|
if (item.index === index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Determine rectangle on screen
|
||||||
|
const hoverBoundingRect = rowRef.current?.getBoundingClientRect();
|
||||||
|
// Determine mouse position
|
||||||
|
const clientOffset = monitor.getClientOffset();
|
||||||
|
// Get pixels to the top
|
||||||
|
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
||||||
|
// Only perform the move when the mouse has crossed certain part of the items height
|
||||||
|
// Dragging downwards
|
||||||
|
if (item.index < index && hoverClientY < (hoverBoundingRect.bottom - hoverBoundingRect.top)/3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Dragging upwards
|
||||||
|
if (item.index > index && hoverClientY > ((hoverBoundingRect.bottom - hoverBoundingRect.top)*2/3)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setHoverIndex(index);
|
||||||
|
item.hoverIndex = index;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [, drag] = useDrag({
|
||||||
|
type: 'row',
|
||||||
|
item: () => {
|
||||||
|
return {index};
|
||||||
|
},
|
||||||
|
end: (item)=>{
|
||||||
|
// Time to actually perform the action
|
||||||
|
setHoverIndex(null);
|
||||||
|
if(item.hoverIndex >= 0) {
|
||||||
|
moveRow(item.index, item.hoverIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* External deps values are from top schema sess data */
|
/* External deps values are from top schema sess data */
|
||||||
depsMap = depsMap.concat(externalDeps.map((source)=>_.get(schemaRef.current.top?.sessData, source)));
|
depsMap = depsMap.concat(externalDeps.map((source)=>_.get(schemaRef.current.top?.sessData, source)));
|
||||||
depsMap = depsMap.concat([totalRows, row.isExpanded, key, isResizing]);
|
depsMap = depsMap.concat([totalRows, row.isExpanded, key, isResizing, isHovered]);
|
||||||
|
|
||||||
|
drag(dragHandleRef);
|
||||||
|
drop(rowRef);
|
||||||
|
|
||||||
return useMemo(()=>
|
return useMemo(()=>
|
||||||
<div {...row.getRowProps()} className="tr">
|
<>
|
||||||
{row.cells.map((cell, ci) => {
|
<div {...row.getRowProps()} ref={rowRef} data-handler-id={handlerId}
|
||||||
let classNames = [classes.tableCell];
|
className={isHovered ? classes.tableRowHovered : null}
|
||||||
if(typeof(cell.column.id) == 'string' && cell.column.id.startsWith('btn-')) {
|
>
|
||||||
classNames.push(classes.btnCell);
|
{row.cells.map((cell, ci) => {
|
||||||
}
|
let classNames = [classes.tableCell];
|
||||||
if(cell.column.id == 'btn-edit' && row.isExpanded) {
|
if(typeof(cell.column.id) == 'string' && cell.column.id.startsWith('btn-')) {
|
||||||
classNames.push(classes.expandedIconCell);
|
classNames.push(classes.btnCell);
|
||||||
}
|
}
|
||||||
return (
|
if(cell.column.id == 'btn-edit' && row.isExpanded) {
|
||||||
<div key={ci} {...cell.getCellProps()} className={clsx(classNames)}>
|
classNames.push(classes.expandedIconCell);
|
||||||
{cell.render('Cell', {
|
}
|
||||||
reRenderRow: ()=>{setKey((currKey)=>!currKey);}
|
return (
|
||||||
})}
|
<div ref={cell.column.id == 'btn-reorder' ? dragHandleRef : null} key={ci} {...cell.getCellProps()} className={clsx(classNames)}>
|
||||||
</div>
|
{cell.render('Cell', {
|
||||||
);
|
reRenderRow: ()=>{setKey((currKey)=>!currKey);}
|
||||||
})}
|
})}
|
||||||
</div>, depsMap);
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div className='hover-overlay'></div>
|
||||||
|
</div>
|
||||||
|
</>, depsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DataGridHeader({label, canAdd, onAddClick, canSearch, onSearchTextChange}) {
|
export function DataGridHeader({label, canAdd, onAddClick, canSearch, onSearchTextChange}) {
|
||||||
@ -269,12 +345,33 @@ export default function DataGridView({
|
|||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const stateUtils = useContext(StateUtilsContext);
|
const stateUtils = useContext(StateUtilsContext);
|
||||||
const checkIsMounted = useIsMounted();
|
const checkIsMounted = useIsMounted();
|
||||||
|
const [hoverIndex, setHoverIndex] = useState();
|
||||||
|
|
||||||
/* Using ref so that schema variable is not frozen in columns closure */
|
/* Using ref so that schema variable is not frozen in columns closure */
|
||||||
const schemaRef = useRef(schema);
|
const schemaRef = useRef(schema);
|
||||||
let columns = useMemo(
|
let columns = useMemo(
|
||||||
()=>{
|
()=>{
|
||||||
let cols = [];
|
let cols = [];
|
||||||
|
if(props.canReorder) {
|
||||||
|
let colInfo = {
|
||||||
|
Header: <> </>,
|
||||||
|
id: 'btn-reorder',
|
||||||
|
accessor: ()=>{/*This is intentional (SonarQube)*/},
|
||||||
|
disableResizing: true,
|
||||||
|
sortable: false,
|
||||||
|
dataType: 'reorder',
|
||||||
|
width: 26,
|
||||||
|
minWidth: 26,
|
||||||
|
maxWidth: 26,
|
||||||
|
Cell: ()=>{
|
||||||
|
return <div className={classes.btnReorder}>
|
||||||
|
<DragIndicatorRoundedIcon fontSize="small" />
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
colInfo.Cell.displayName = 'Cell';
|
||||||
|
cols.push(colInfo);
|
||||||
|
}
|
||||||
if(props.canEdit) {
|
if(props.canEdit) {
|
||||||
let colInfo = {
|
let colInfo = {
|
||||||
Header: <> </>,
|
Header: <> </>,
|
||||||
@ -432,7 +529,7 @@ export default function DataGridView({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
return cols;
|
return cols;
|
||||||
},[props.canEdit, props.canDelete]
|
},[props.canEdit, props.canDelete, props.canReorder]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onAddClick = useCallback(()=>{
|
const onAddClick = useCallback(()=>{
|
||||||
@ -496,6 +593,15 @@ export default function DataGridView({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const moveRow = (dragIndex, hoverIndex) => {
|
||||||
|
dataDispatch({
|
||||||
|
type: SCHEMA_STATE_ACTIONS.MOVE_ROW,
|
||||||
|
path: accessPath,
|
||||||
|
oldIndex: dragIndex,
|
||||||
|
newIndex: hoverIndex,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const isResizing = _.flatMap(headerGroups, headerGroup => headerGroup.headers.map(col=>col.isResizing)).includes(true);
|
const isResizing = _.flatMap(headerGroups, headerGroup => headerGroup.headers.map(col=>col.isResizing)).includes(true);
|
||||||
|
|
||||||
if(!props.visible) {
|
if(!props.visible) {
|
||||||
@ -511,23 +617,26 @@ export default function DataGridView({
|
|||||||
setGlobalFilter(value || undefined);
|
setGlobalFilter(value || undefined);
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
<div {...getTableProps(()=>({style: {minWidth: 'unset'}}))} className={classes.table}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
<DataTableHeader headerGroups={headerGroups} />
|
<div {...getTableProps(()=>({style: {minWidth: 'unset'}}))} className={classes.table}>
|
||||||
<div {...getTableBodyProps()} className={classes.tableContentWidth}>
|
<DataTableHeader headerGroups={headerGroups} />
|
||||||
{rows.map((row, i) => {
|
<div {...getTableBodyProps()} className={classes.tableContentWidth}>
|
||||||
prepareRow(row);
|
{rows.map((row, i) => {
|
||||||
return <React.Fragment key={i}>
|
prepareRow(row);
|
||||||
<DataTableRow row={row} totalRows={rows.length} isResizing={isResizing}
|
return <React.Fragment key={i}>
|
||||||
schema={schemaRef.current} schemaRef={schemaRef} accessPath={accessPath.concat([row.index])} />
|
<DataTableRow index={i} row={row} totalRows={rows.length} isResizing={isResizing}
|
||||||
{props.canEdit && row.isExpanded &&
|
schema={schemaRef.current} schemaRef={schemaRef} accessPath={accessPath.concat([row.index])}
|
||||||
<FormView value={row.original} viewHelperProps={viewHelperProps} dataDispatch={dataDispatch}
|
moveRow={moveRow} isHovered={i == hoverIndex} setHoverIndex={setHoverIndex} />
|
||||||
schema={schemaRef.current} accessPath={accessPath.concat([row.index])} isNested={true} className={classes.expandedForm}
|
{props.canEdit && row.isExpanded &&
|
||||||
isDataGridForm={true}/>
|
<FormView value={row.original} viewHelperProps={viewHelperProps} dataDispatch={dataDispatch}
|
||||||
}
|
schema={schemaRef.current} accessPath={accessPath.concat([row.index])} isNested={true} className={classes.expandedForm}
|
||||||
</React.Fragment>;
|
isDataGridForm={true}/>
|
||||||
})}
|
}
|
||||||
|
</React.Fragment>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</DndProvider>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@ -546,6 +655,7 @@ DataGridView.propTypes = {
|
|||||||
canEdit: PropTypes.bool,
|
canEdit: PropTypes.bool,
|
||||||
canAdd: PropTypes.bool,
|
canAdd: PropTypes.bool,
|
||||||
canDelete: PropTypes.bool,
|
canDelete: PropTypes.bool,
|
||||||
|
canReorder: PropTypes.bool,
|
||||||
visible: PropTypes.bool,
|
visible: PropTypes.bool,
|
||||||
canAddRow: PropTypes.oneOfType([
|
canAddRow: PropTypes.oneOfType([
|
||||||
PropTypes.bool, PropTypes.func,
|
PropTypes.bool, PropTypes.func,
|
||||||
|
@ -134,13 +134,14 @@ export function getFieldMetaData(field, schema, value, viewHelperProps, onlyMode
|
|||||||
retData.editable = evalFunc(schema, _.isUndefined(editable) ? true : editable, value);
|
retData.editable = evalFunc(schema, _.isUndefined(editable) ? true : editable, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let {canAdd, canEdit, canDelete, canAddRow } = field;
|
let {canAdd, canEdit, canDelete, canReorder, canAddRow } = field;
|
||||||
retData.canAdd = _.isUndefined(canAdd) ? retData.canAdd : evalFunc(schema, canAdd, value);
|
retData.canAdd = _.isUndefined(canAdd) ? retData.canAdd : evalFunc(schema, canAdd, value);
|
||||||
retData.canAdd = !retData.disabled && retData.canAdd;
|
retData.canAdd = !retData.disabled && retData.canAdd;
|
||||||
retData.canEdit = _.isUndefined(canEdit) ? retData.canEdit : evalFunc(schema, canEdit, value);
|
retData.canEdit = _.isUndefined(canEdit) ? retData.canEdit : evalFunc(schema, canEdit, value);
|
||||||
retData.canEdit = !retData.disabled && retData.canEdit;
|
retData.canEdit = !retData.disabled && retData.canEdit;
|
||||||
retData.canDelete = _.isUndefined(canDelete) ? retData.canDelete : evalFunc(schema, canDelete, value);
|
retData.canDelete = _.isUndefined(canDelete) ? retData.canDelete : evalFunc(schema, canDelete, value);
|
||||||
retData.canDelete = !retData.disabled && retData.canDelete;
|
retData.canDelete = !retData.disabled && retData.canDelete;
|
||||||
|
retData.canReorder =_.isUndefined(canReorder) ? retData.canReorder : evalFunc(schema, canReorder, value);
|
||||||
retData.canAddRow = _.isUndefined(canAddRow) ? retData.canAddRow : evalFunc(schema, canAddRow, value);
|
retData.canAddRow = _.isUndefined(canAddRow) ? retData.canAddRow : evalFunc(schema, canAddRow, value);
|
||||||
return retData;
|
return retData;
|
||||||
}
|
}
|
||||||
@ -214,7 +215,7 @@ export default function FormView({
|
|||||||
|
|
||||||
/* Prepare the array of components based on the types */
|
/* Prepare the array of components based on the types */
|
||||||
for(const field of schemaRef.current.fields) {
|
for(const field of schemaRef.current.fields) {
|
||||||
let {visible, disabled, readonly, canAdd, canEdit, canDelete, canAddRow, modeSupported} =
|
let {visible, disabled, readonly, canAdd, canEdit, canDelete, canReorder, canAddRow, modeSupported} =
|
||||||
getFieldMetaData(field, schema, value, viewHelperProps);
|
getFieldMetaData(field, schema, value, viewHelperProps);
|
||||||
|
|
||||||
if(modeSupported) {
|
if(modeSupported) {
|
||||||
@ -273,7 +274,8 @@ export default function FormView({
|
|||||||
const props = {
|
const props = {
|
||||||
key: field.id, value: value[field.id] || [], viewHelperProps: viewHelperProps,
|
key: field.id, value: value[field.id] || [], viewHelperProps: viewHelperProps,
|
||||||
schema: field.schema, accessPath: accessPath.concat(field.id), dataDispatch: dataDispatch,
|
schema: field.schema, accessPath: accessPath.concat(field.id), dataDispatch: dataDispatch,
|
||||||
containerClassName: classes.controlRow, ...field, canAdd: canAdd, canEdit: canEdit, canDelete: canDelete,
|
containerClassName: classes.controlRow, ...field, canAdd: canAdd, canReorder: canReorder,
|
||||||
|
canEdit: canEdit, canDelete: canDelete,
|
||||||
visible: visible, canAddRow: canAddRow, onDelete: field.onDelete, canSearch: field.canSearch
|
visible: visible, canAddRow: canAddRow, onDelete: field.onDelete, canSearch: field.canSearch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,18 +196,29 @@ function getChangedData(topSchema, viewHelperProps, sessData, stringify=false, i
|
|||||||
}
|
}
|
||||||
} else if(!isEdit) {
|
} else if(!isEdit) {
|
||||||
if(field.type === 'collection') {
|
if(field.type === 'collection') {
|
||||||
const changeDiff = diffArray(
|
const origColl = _.get(origVal, field.id) || [];
|
||||||
_.get(origVal, field.id) || [],
|
const sessColl = _.get(sessVal, field.id) || [];
|
||||||
_.get(sessVal, field.id) || [],
|
let changeDiff = diffArray(origColl,sessColl,'cid');
|
||||||
'cid',
|
|
||||||
);
|
|
||||||
/* For fixed rows, check only the updated changes */
|
/* For fixed rows, check only the updated changes */
|
||||||
|
/* If canReorder, check the updated changes */
|
||||||
if((!_.isUndefined(field.fixedRows) && changeDiff.updated.length > 0)
|
if((!_.isUndefined(field.fixedRows) && changeDiff.updated.length > 0)
|
||||||
|| (_.isUndefined(field.fixedRows) && (
|
|| (_.isUndefined(field.fixedRows) && (
|
||||||
changeDiff.added.length > 0 || changeDiff.removed.length > 0 || changeDiff.updated.length > 0
|
changeDiff.added.length > 0 || changeDiff.removed.length > 0 || changeDiff.updated.length > 0
|
||||||
))) {
|
))
|
||||||
|
|| (field.canReorder && _.differenceBy(origColl, sessColl, 'cid'))
|
||||||
|
) {
|
||||||
let change = cleanCid(_.get(sessVal, field.id), viewHelperProps.keepCid);
|
let change = cleanCid(_.get(sessVal, field.id), viewHelperProps.keepCid);
|
||||||
attrChanged(field.id, change, true);
|
attrChanged(field.id, change, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(field.canReorder) {
|
||||||
|
changeDiff = diffArray(origColl,sessColl);
|
||||||
|
if(changeDiff.updated.length > 0) {
|
||||||
|
let change = cleanCid(_.get(sessVal, field.id), viewHelperProps.keepCid);
|
||||||
|
attrChanged(field.id, change, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attrChanged(field.id);
|
attrChanged(field.id);
|
||||||
@ -298,10 +309,11 @@ export const SCHEMA_STATE_ACTIONS = {
|
|||||||
SET_VALUE: 'set_value',
|
SET_VALUE: 'set_value',
|
||||||
ADD_ROW: 'add_row',
|
ADD_ROW: 'add_row',
|
||||||
DELETE_ROW: 'delete_row',
|
DELETE_ROW: 'delete_row',
|
||||||
|
MOVE_ROW: 'move_row',
|
||||||
RERENDER: 'rerender',
|
RERENDER: 'rerender',
|
||||||
CLEAR_DEFERRED_QUEUE: 'clear_deferred_queue',
|
CLEAR_DEFERRED_QUEUE: 'clear_deferred_queue',
|
||||||
DEFERRED_DEPCHANGE: 'deferred_depchange',
|
DEFERRED_DEPCHANGE: 'deferred_depchange',
|
||||||
BULK_UPDATE: 'bulk_update'
|
BULK_UPDATE: 'bulk_update',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDepChange = (currPath, newState, oldState, action)=>{
|
const getDepChange = (currPath, newState, oldState, action)=>{
|
||||||
@ -384,6 +396,13 @@ const sessDataReducer = (state, action)=>{
|
|||||||
/* If there is any dep listeners get the changes */
|
/* If there is any dep listeners get the changes */
|
||||||
data = getDepChange(action.path, data, state, action);
|
data = getDepChange(action.path, data, state, action);
|
||||||
break;
|
break;
|
||||||
|
case SCHEMA_STATE_ACTIONS.MOVE_ROW:
|
||||||
|
rows = _.get(data, action.path)||[];
|
||||||
|
var row = rows[action.oldIndex];
|
||||||
|
rows.splice(action.oldIndex, 1);
|
||||||
|
rows.splice(action.newIndex, 0, row);
|
||||||
|
_.set(data, action.path, rows);
|
||||||
|
break;
|
||||||
case SCHEMA_STATE_ACTIONS.CLEAR_DEFERRED_QUEUE:
|
case SCHEMA_STATE_ACTIONS.CLEAR_DEFERRED_QUEUE:
|
||||||
data.__deferred__ = [];
|
data.__deferred__ = [];
|
||||||
break;
|
break;
|
||||||
|
@ -430,7 +430,12 @@ module.exports = [{
|
|||||||
plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
|
plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
},{
|
||||||
|
test: /\.m?js$/,
|
||||||
|
resolve: {
|
||||||
|
fullySpecified: false
|
||||||
|
},
|
||||||
|
},{
|
||||||
test: /\.tsx?$|\.ts?$/,
|
test: /\.tsx?$|\.ts?$/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
|
@ -107,6 +107,11 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
exclude: /node_modules|plugins|bundle|generated|regression|[Tt]est.js|[Ss]pecs.js|[Ss]pec.js|\.spec\.js/,
|
exclude: /node_modules|plugins|bundle|generated|regression|[Tt]est.js|[Ss]pecs.js|[Ss]pec.js|\.spec\.js/,
|
||||||
|
},{
|
||||||
|
test: /\.m?js$/,
|
||||||
|
resolve: {
|
||||||
|
fullySpecified: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1791,6 +1791,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.9.2":
|
||||||
|
version "7.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
|
||||||
|
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.12.13":
|
"@babel/template@^7.12.13":
|
||||||
version "7.14.5"
|
version "7.14.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
|
||||||
@ -2351,6 +2358,21 @@
|
|||||||
"@projectstorm/react-diagrams-defaults" "^6.6.1"
|
"@projectstorm/react-diagrams-defaults" "^6.6.1"
|
||||||
"@projectstorm/react-diagrams-routing" "^6.6.1"
|
"@projectstorm/react-diagrams-routing" "^6.6.1"
|
||||||
|
|
||||||
|
"@react-dnd/asap@^5.0.1":
|
||||||
|
version "5.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-5.0.2.tgz#1f81f124c1cd6f39511c11a881cfb0f715343488"
|
||||||
|
integrity sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==
|
||||||
|
|
||||||
|
"@react-dnd/invariant@^4.0.1":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-4.0.2.tgz#b92edffca10a26466643349fac7cdfb8799769df"
|
||||||
|
integrity sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==
|
||||||
|
|
||||||
|
"@react-dnd/shallowequal@^4.0.1":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz#d1b4befa423f692fa4abf1c79209702e7d8ae4b4"
|
||||||
|
integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==
|
||||||
|
|
||||||
"@react-leaflet/core@^1.1.1":
|
"@react-leaflet/core@^1.1.1":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@react-leaflet/core/-/core-1.1.1.tgz#827fd05bb542cf874116176d8ef48d5b12163f81"
|
resolved "https://registry.yarnpkg.com/@react-leaflet/core/-/core-1.1.1.tgz#827fd05bb542cf874116176d8ef48d5b12163f81"
|
||||||
@ -4902,6 +4924,15 @@ discontinuous-range@1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
||||||
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
|
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
|
||||||
|
|
||||||
|
dnd-core@^16.0.1:
|
||||||
|
version "16.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-16.0.1.tgz#a1c213ed08961f6bd1959a28bb76f1a868360d19"
|
||||||
|
integrity sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==
|
||||||
|
dependencies:
|
||||||
|
"@react-dnd/asap" "^5.0.1"
|
||||||
|
"@react-dnd/invariant" "^4.0.1"
|
||||||
|
redux "^4.2.0"
|
||||||
|
|
||||||
doctrine@^2.1.0:
|
doctrine@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
||||||
@ -9170,7 +9201,7 @@ process-nextick-args@~2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||||
|
|
||||||
process@^0.11.10, process@~0.11.0:
|
process@~0.11.0:
|
||||||
version "0.11.10"
|
version "0.11.10"
|
||||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||||
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
||||||
@ -9521,6 +9552,24 @@ react-checkbox-tree@^1.7.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
clsx "^1.1.1"
|
clsx "^1.1.1"
|
||||||
|
|
||||||
|
react-dnd-html5-backend@^16.0.1:
|
||||||
|
version "16.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz#87faef15845d512a23b3c08d29ecfd34871688b6"
|
||||||
|
integrity sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==
|
||||||
|
dependencies:
|
||||||
|
dnd-core "^16.0.1"
|
||||||
|
|
||||||
|
react-dnd@^16.0.1:
|
||||||
|
version "16.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-16.0.1.tgz#2442a3ec67892c60d40a1559eef45498ba26fa37"
|
||||||
|
integrity sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==
|
||||||
|
dependencies:
|
||||||
|
"@react-dnd/invariant" "^4.0.1"
|
||||||
|
"@react-dnd/shallowequal" "^4.0.1"
|
||||||
|
dnd-core "^16.0.1"
|
||||||
|
fast-deep-equal "^3.1.3"
|
||||||
|
hoist-non-react-statics "^3.3.2"
|
||||||
|
|
||||||
react-dom@^16.6.3:
|
react-dom@^16.6.3:
|
||||||
version "16.14.0"
|
version "16.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89"
|
||||||
@ -9784,6 +9833,13 @@ redent@^4.0.0:
|
|||||||
indent-string "^5.0.0"
|
indent-string "^5.0.0"
|
||||||
strip-indent "^4.0.0"
|
strip-indent "^4.0.0"
|
||||||
|
|
||||||
|
redux@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
|
||||||
|
integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
reflect.ownkeys@^0.2.0:
|
reflect.ownkeys@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
|
resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
|
||||||
|
Loading…
Reference in New Issue
Block a user