mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
757 lines
23 KiB
JavaScript
757 lines
23 KiB
JavaScript
/////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
import _ from 'lodash';
|
|
import PropTypes from 'prop-types';
|
|
import clsx from 'clsx';
|
|
|
|
import { SelectColumn } from 'react-data-grid';
|
|
import React, { useContext, useEffect, useLayoutEffect, useReducer, useRef, useState } from 'react';
|
|
|
|
import { Box } from '@material-ui/core';
|
|
import { makeStyles } from '@material-ui/styles';
|
|
import KeyboardArrowRightRoundedIcon from '@material-ui/icons/KeyboardArrowRightRounded';
|
|
import KeyboardArrowDownRoundedIcon from '@material-ui/icons/KeyboardArrowDownRounded';
|
|
import InfoIcon from '@material-ui/icons/InfoRounded';
|
|
|
|
import gettext from 'sources/gettext';
|
|
import url_for from 'sources/url_for';
|
|
|
|
|
|
import { FILTER_NAME, SCHEMA_DIFF_EVENT } from '../SchemaDiffConstants';
|
|
import { SchemaDiffContext, SchemaDiffEventsContext } from './SchemaDiffComponent';
|
|
import { InputCheckbox } from '../../../../../static/js/components/FormComponents';
|
|
import PgReactDataGrid from '../../../../../static/js/components/PgReactDataGrid';
|
|
import Notifier from '../../../../../static/js/helpers/Notifier';
|
|
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
root: {
|
|
|
|
paddingTop: '0.5rem',
|
|
display: 'flex',
|
|
height: '100%',
|
|
flexDirection: 'column',
|
|
color: theme.palette.text.primary,
|
|
backgroundColor: theme.otherVars.qtDatagridBg,
|
|
border: 'none',
|
|
fontSize: '13px',
|
|
'& .rdg': {
|
|
flex: 1,
|
|
borderTop: '1px solid' + theme.otherVars.borderColor,
|
|
},
|
|
'--rdg-background-color': theme.palette.default.main,
|
|
'--rdg-selection-color': theme.palette.primary.main,
|
|
'& .rdg-cell': {
|
|
padding: 0,
|
|
boxShadow: 'none',
|
|
color: theme.otherVars.schemaDiff.diffColorFg + ' !important',
|
|
...theme.mixins.panelBorder.right,
|
|
...theme.mixins.panelBorder.bottom,
|
|
'&[aria-colindex="1"]': {
|
|
padding: 0,
|
|
},
|
|
'&[aria-selected=true]:not([role="columnheader"]):not([aria-colindex="1"])': {
|
|
outlineWidth: '0',
|
|
outlineOffset: '-1px',
|
|
color: theme.otherVars.qtDatagridSelectFg,
|
|
},
|
|
'&[aria-selected=true][aria-colindex="1"]': {
|
|
outlineWidth: 0,
|
|
}
|
|
},
|
|
'& .rdg-header-row .rdg-cell': {
|
|
padding: 0,
|
|
paddingLeft: '0.5rem',
|
|
boxShadow: 'none',
|
|
},
|
|
'& .rdg-header-row': {
|
|
backgroundColor: theme.palette.background.default,
|
|
},
|
|
'& .rdg-row': {
|
|
backgroundColor: theme.palette.background.default,
|
|
'&[aria-selected=true]': {
|
|
backgroundColor: theme.palette.primary.light,
|
|
color: theme.otherVars.qtDatagridSelectFg,
|
|
'& .rdg-cell:nth-child(1)': {
|
|
backgroundColor: 'transparent',
|
|
outlineColor: 'transparent',
|
|
color: theme.palette.primary.contrastText,
|
|
}
|
|
},
|
|
}
|
|
},
|
|
grid: {
|
|
fontSize: '13px',
|
|
'--rdg-selection-color': 'none'
|
|
},
|
|
subRow: {
|
|
paddingLeft: '1rem'
|
|
},
|
|
recordRow: {
|
|
marginLeft: '2.7rem',
|
|
height: '1.3rem',
|
|
width: '1.3rem',
|
|
display: 'inline-block',
|
|
marginRight: '0.3rem',
|
|
paddingLeft: '0.5rem',
|
|
},
|
|
rowIcon: {
|
|
display: 'inline-block !important',
|
|
height: '1.3rem',
|
|
width: '1.3rem'
|
|
},
|
|
cellExpand: {
|
|
display: 'table',
|
|
blockSize: '100%',
|
|
|
|
'& span': {
|
|
display: 'table-cell',
|
|
verticalAlign: 'middle',
|
|
cursor: 'pointer',
|
|
}
|
|
},
|
|
gridPanel: {
|
|
'--rdg-background-color': theme.palette.default.main + ' !important',
|
|
},
|
|
source: {
|
|
backgroundColor: theme.otherVars.schemaDiff.sourceRowColor,
|
|
color: theme.otherVars.schemaDiff.diffSelectFG,
|
|
paddingLeft: '0.5rem',
|
|
},
|
|
target: {
|
|
backgroundColor: theme.otherVars.schemaDiff.targetRowColor,
|
|
color: theme.otherVars.schemaDiff.diffSelectFG,
|
|
paddingLeft: '0.5rem',
|
|
},
|
|
different: {
|
|
backgroundColor: theme.otherVars.schemaDiff.diffRowColor,
|
|
color: theme.otherVars.schemaDiff.diffSelectFG,
|
|
paddingLeft: '0.5rem',
|
|
},
|
|
identical: {
|
|
paddingLeft: '0.5rem',
|
|
color: theme.otherVars.schemaDiff.diffColorFg,
|
|
},
|
|
selectCell: {
|
|
padding: '0 0.3rem'
|
|
},
|
|
headerSelectCell: {
|
|
padding: '0rem 0.3rem 0 0.3rem'
|
|
},
|
|
count: {
|
|
display: 'inline-block !important',
|
|
},
|
|
countStyle: {
|
|
fontWeight: 900,
|
|
fontSize: '0.8rem',
|
|
paddingLeft: '0.3rem',
|
|
},
|
|
countLabel: {
|
|
paddingLeft: '1rem',
|
|
},
|
|
selectedRow: {
|
|
paddingLeft: '0.5rem',
|
|
backgroundColor: theme.palette.primary.light
|
|
},
|
|
selectedRowCheckBox: {
|
|
paddingLeft: '0.5rem',
|
|
backgroundColor: theme.otherVars.schemaDiff.diffSelCheckbox,
|
|
},
|
|
selChBox: {
|
|
paddingLeft: 0,
|
|
},
|
|
noRowsIcon:{
|
|
width: '1.1rem',
|
|
height: '1.1rem',
|
|
marginRight: '0.5rem',
|
|
}
|
|
|
|
}));
|
|
|
|
function useFocusRef(isSelected) {
|
|
const ref = useRef(null);
|
|
|
|
useLayoutEffect(() => {
|
|
if (!isSelected) return;
|
|
ref.current?.focus({ preventScroll: true });
|
|
}, [isSelected]);
|
|
|
|
return {
|
|
ref,
|
|
tabIndex: isSelected ? 0 : -1
|
|
};
|
|
}
|
|
|
|
function setRecordCount(row, filterParams) {
|
|
row['identicalCount'] = 0;
|
|
row['differentCount'] = 0;
|
|
row['sourceOnlyCount'] = 0;
|
|
row['targetOnlyCount'] = 0;
|
|
|
|
row.children.map((ch) => {
|
|
if (filterParams.includes(ch.status)) {
|
|
if (ch.status == FILTER_NAME.IDENTICAL) {
|
|
row['identicalCount'] = row['identicalCount'] + 1;
|
|
} else if (ch.status == FILTER_NAME.DIFFERENT) {
|
|
row['differentCount'] = row['differentCount'] + 1;
|
|
} else if (ch.status == FILTER_NAME.SOURCE_ONLY) {
|
|
row['sourceOnlyCount'] = row['sourceOnlyCount'] + 1;
|
|
} else if (ch.status == FILTER_NAME.TARGET_ONLY) {
|
|
row['targetOnlyCount'] = row['targetOnlyCount'] + 1;
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
function CellExpanderFormatter({
|
|
row,
|
|
isCellSelected,
|
|
expanded,
|
|
filterParams,
|
|
onCellExpand,
|
|
classes
|
|
}) {
|
|
const { ref, tabIndex } = useFocusRef(isCellSelected);
|
|
'identicalCount' in row && setRecordCount(row, filterParams);
|
|
|
|
function handleKeyDown(e) {
|
|
if (e.key === ' ' || e.key === 'Enter') {
|
|
e.preventDefault();
|
|
onCellExpand();
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={classes.cellExpand}>
|
|
<span onClick={onCellExpand} onKeyDown={handleKeyDown}>
|
|
<span ref={ref} tabIndex={tabIndex} className={'identicalCount' in row ? classes.subRow : null}>
|
|
{expanded ? <KeyboardArrowDownRoundedIcon /> : <KeyboardArrowRightRoundedIcon />} <span className={clsx(row.icon, classes.rowIcon)}></span>{row.label}
|
|
{
|
|
'identicalCount' in row ?
|
|
<span className={clsx(classes.count)}>
|
|
{
|
|
filterParams.includes(FILTER_NAME.IDENTICAL) && <><span className={classes.countLabel}>{FILTER_NAME.IDENTICAL}:</span> <span className={classes.countStyle}>{row.identicalCount} </span></>
|
|
}
|
|
{
|
|
filterParams.includes(FILTER_NAME.DIFFERENT) && <><span className={classes.countLabel}>{FILTER_NAME.DIFFERENT}:</span> <span className={classes.countStyle}>{row.differentCount} </span></>
|
|
}
|
|
{
|
|
filterParams.includes(FILTER_NAME.SOURCE_ONLY) && <><span className={classes.countLabel}>{FILTER_NAME.SOURCE_ONLY}:</span> <span className={classes.countStyle}>{row.sourceOnlyCount} </span></>
|
|
}
|
|
{
|
|
filterParams.includes(FILTER_NAME.TARGET_ONLY) && <><span className={classes.countLabel}>{FILTER_NAME.TARGET_ONLY}: </span><span className={classes.countStyle}>{row.targetOnlyCount}</span></>
|
|
}
|
|
</span>
|
|
: null
|
|
|
|
}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
CellExpanderFormatter.propTypes = {
|
|
row: PropTypes.object,
|
|
isCellSelected: PropTypes.bool,
|
|
expanded: PropTypes.bool,
|
|
onCellExpand: PropTypes.func,
|
|
filterParams: PropTypes.array,
|
|
classes: PropTypes.object
|
|
};
|
|
|
|
|
|
function toggleSubRow(rows, id, filterParams) {
|
|
const newRows = [...rows];
|
|
const rowIndex = newRows.findIndex((r) => r.id === id);
|
|
|
|
const row = newRows[rowIndex];
|
|
if (!row) return newRows;
|
|
const { children } = row;
|
|
if (!children) return newRows;
|
|
|
|
if (children.length > 0) {
|
|
newRows[rowIndex] = { ...row, isExpanded: !row.isExpanded };
|
|
if (!row.isExpanded) {
|
|
let tempChild = [];
|
|
expandRows(children, filterParams, tempChild, newRows, rowIndex);
|
|
} else {
|
|
collapseRows(newRows, filterParams, rowIndex);
|
|
}
|
|
return newRows;
|
|
} else {
|
|
newRows.splice(rowIndex, 1);
|
|
return newRows;
|
|
}
|
|
}
|
|
|
|
function expandRows(children, filterParams, tempChild, newRows, rowIndex) {
|
|
children.map((child) => {
|
|
if ('children' in child) {
|
|
let tempSubChild = [];
|
|
child.children.map((subChild) => {
|
|
if (filterParams.includes(subChild.status)) {
|
|
tempSubChild.push(subChild);
|
|
}
|
|
});
|
|
|
|
if (tempSubChild.length > 0) {
|
|
tempChild.push(child);
|
|
}
|
|
|
|
}
|
|
else {
|
|
if (filterParams.includes(child.status)) {
|
|
tempChild.push(child);
|
|
}
|
|
|
|
}
|
|
});
|
|
if (tempChild.length > 0) {
|
|
newRows.splice(rowIndex + 1, 0, ...tempChild);
|
|
} else {
|
|
newRows.splice(rowIndex, 1);
|
|
}
|
|
}
|
|
|
|
function collapseRows(newRows, filterParams, rowIndex) {
|
|
let totalChild = 0;
|
|
let filteredChild = newRows[rowIndex].children.filter((el) => {
|
|
if (el?.children) {
|
|
let clist = el.children.filter((subch) => {
|
|
return filterParams.includes(subch.status);
|
|
});
|
|
if (clist.length > 0) {
|
|
return el;
|
|
}
|
|
} else {
|
|
return el?.status ? filterParams.includes(el.status) : el;
|
|
}
|
|
});
|
|
let totalChCount = filteredChild.length;
|
|
for (let i = 0; i < filteredChild.length; i++) {
|
|
let _index = i + 1;
|
|
let indx = totalChild ? rowIndex + totalChild + _index : rowIndex + _index;
|
|
if (newRows[indx]?.isExpanded) {
|
|
let filteredSubChild = newRows[indx].children.filter((el) => {
|
|
return filterParams.includes(el.status);
|
|
});
|
|
totalChild += filteredSubChild.length;
|
|
}
|
|
}
|
|
newRows.splice(rowIndex + 1, totalChild ? totalChCount + totalChild : totalChCount);
|
|
}
|
|
|
|
function getChildrenRows(data) {
|
|
if ('children' in data) {
|
|
return data.children;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
function checkRowExpanedStatus(rows, record) {
|
|
if (rows.length > 0) {
|
|
let tempRecord = rows.filter((rec) => {
|
|
return rec.parentId == record.parentId && rec.label == record.label;
|
|
});
|
|
return tempRecord.length > 0 ? tempRecord[0].isExpanded : false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function prepareRows(rows, gridData, filterParams) {
|
|
let newRows = [];
|
|
|
|
let adedIds = [];
|
|
gridData.map((record) => {
|
|
let childrens = getChildrenRows(record);
|
|
|
|
if (childrens.length > 0) {
|
|
childrens.map((child) => {
|
|
let subChildrens = getChildrenRows(child);
|
|
let tempChildList = [];
|
|
subChildrens.map((subChild) => {
|
|
if (filterParams.includes(subChild.status)) {
|
|
tempChildList.push(subChild);
|
|
adedIds.push(subChild.id);
|
|
}
|
|
});
|
|
|
|
if (!adedIds.includes(record.id) && tempChildList.length > 0) {
|
|
adedIds.push(record.id);
|
|
record.isExpanded = true;
|
|
newRows.push(record);
|
|
}
|
|
|
|
if (!adedIds.includes(child.id) && tempChildList.length > 0) {
|
|
adedIds.push(child.id);
|
|
child.isExpanded = checkRowExpanedStatus(rows, child);
|
|
newRows.push(child);
|
|
newRows = checkAndAddChild(child, newRows, tempChildList);
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
});
|
|
|
|
return newRows;
|
|
}
|
|
|
|
function checkAndAddChild(child, newRows, tempChildList) {
|
|
if (child.isExpanded) {
|
|
newRows = newRows.concat(tempChildList);
|
|
}
|
|
|
|
return newRows;
|
|
}
|
|
|
|
function reducer(rows, { type, id, filterParams, gridData }) {
|
|
switch (type) {
|
|
case 'toggleSubRow':
|
|
return toggleSubRow(rows, id, filterParams);
|
|
case 'applyFilter':
|
|
return prepareRows(rows, gridData, filterParams);
|
|
default:
|
|
return rows;
|
|
}
|
|
}
|
|
|
|
export function ResultGridComponent({ gridData, allRowIds, filterParams, selectedRowIds, transId, sourceData, targetData }) {
|
|
const classes = useStyles();
|
|
const [rows, dispatch] = useReducer(reducer, [...gridData]);
|
|
const [selectedRows, setSelectedRows] = useState([]);
|
|
const [rootSelection, setRootSelection] = useState(false);
|
|
const [activeRow, setActiveRow] = useState(null);
|
|
const schemaDiffToolContext = useContext(SchemaDiffContext);
|
|
|
|
function checkAllChildInclude(row, tempSelectedRows) {
|
|
let isChildAllInclude = true;
|
|
row.metadata.children.map((id) => {
|
|
if (!tempSelectedRows.includes(id) && id !== `${row.id}`) {
|
|
isChildAllInclude = false;
|
|
}
|
|
});
|
|
return isChildAllInclude;
|
|
}
|
|
|
|
function selectedResultRows(row, tempSelectedRows) {
|
|
if (row.metadata.isRoot) {
|
|
tempSelectedRows.push(`${row.id}`, ...row.metadata.children);
|
|
tempSelectedRows.push(...row.metadata.subChildren);
|
|
} else if (row.metadata.subChildren) {
|
|
tempSelectedRows.push(...row.metadata.dependencies);
|
|
tempSelectedRows.push(`${row.id}`, ...row.metadata.subChildren);
|
|
let isChildAllInclude = checkAllChildInclude(row, tempSelectedRows);
|
|
isChildAllInclude && tempSelectedRows.push(`${row.metadata.parentId}`);
|
|
} else {
|
|
tempSelectedRows.push(...row.dependencieRowIds);
|
|
tempSelectedRows.push(`${row.id}`);
|
|
let isChildAllInclude = checkAllChildInclude(row, tempSelectedRows);
|
|
isChildAllInclude && tempSelectedRows.push(`${row.metadata.parentId}`);
|
|
|
|
for(let rowData of rows) {
|
|
if (rowData.id == row.metadata.parentId) {
|
|
let isChildInclude = checkAllChildInclude(rowData, tempSelectedRows);
|
|
isChildInclude && tempSelectedRows.push(`${rowData.metadata.parentId}`);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
function deselectChildAndSubChild(children, tempSelectedRows) {
|
|
children.map((chid) => {
|
|
let indx = tempSelectedRows.indexOf(chid);
|
|
indx != -1 && tempSelectedRows.splice(indx, 1);
|
|
});
|
|
}
|
|
|
|
function deselectResultRows(row, tempSelectedRows) {
|
|
if (row.metadata.isRoot) {
|
|
deselectChildAndSubChild(row.metadata.subChildren, tempSelectedRows);
|
|
|
|
deselectChildAndSubChild(row.metadata.children, tempSelectedRows);
|
|
|
|
let rootIndex = tempSelectedRows.indexOf(`${row.id}`);
|
|
rootIndex != -1 && tempSelectedRows.splice(rootIndex, 1);
|
|
|
|
} else if (row.metadata.subChildren) {
|
|
deselectChildAndSubChild(row.metadata.subChildren, tempSelectedRows);
|
|
|
|
let isChildAllInclude = true;
|
|
row.metadata.children.map((id) => {
|
|
if (tempSelectedRows.includes(id)) {
|
|
isChildAllInclude = false;
|
|
}
|
|
});
|
|
|
|
let rootIndex = tempSelectedRows.indexOf(`${row.id}`);
|
|
rootIndex != -1 && tempSelectedRows.splice(rootIndex, 1);
|
|
|
|
let parentIndex = tempSelectedRows.indexOf(`${row.metadata.parentId}`);
|
|
(!isChildAllInclude && parentIndex != -1) && tempSelectedRows.splice(parentIndex, 1);
|
|
|
|
row.metadata.dependencies.map((depid) => {
|
|
let depIndex = tempSelectedRows.indexOf(`${depid}`);
|
|
depIndex != -1 && tempSelectedRows.splice(depIndex, 1);
|
|
});
|
|
|
|
} else {
|
|
let elementIndex = tempSelectedRows.indexOf(`${row.id}`);
|
|
elementIndex != -1 && tempSelectedRows.splice(elementIndex, 1);
|
|
|
|
let parentElIndex = tempSelectedRows.indexOf(`${row.metadata.parentId}`);
|
|
parentElIndex != -1 && tempSelectedRows.splice(parentElIndex, 1);
|
|
|
|
let rootIndex = tempSelectedRows.indexOf(`${row.metadata.rootId}`);
|
|
rootIndex != -1 && tempSelectedRows.splice(rootIndex, 1);
|
|
|
|
row.dependencieRowIds.map((id) => {
|
|
let deptRowIndex = tempSelectedRows.indexOf(`${id}`);
|
|
deptRowIndex != -1 && tempSelectedRows.splice(deptRowIndex, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
function getStyleClassName(row, selectedRowIds, isCellSelected, activeRowId, isCheckbox = false) {
|
|
let clsName = null;
|
|
if (selectedRowIds.includes(`${row.id}`) || isCellSelected || row.id == activeRowId) {
|
|
clsName = isCheckbox ? classes.selectedRowCheckBox : classes.selectedRow;
|
|
} else {
|
|
if (row.status == FILTER_NAME.DIFFERENT) {
|
|
clsName = classes.different;
|
|
} else if (row.status == FILTER_NAME.SOURCE_ONLY) {
|
|
clsName = classes.source;
|
|
} else if (row.status == FILTER_NAME.TARGET_ONLY) {
|
|
clsName = classes.target;
|
|
} else if (row.status == FILTER_NAME.IDENTICAL) {
|
|
clsName = classes.identical;
|
|
}
|
|
}
|
|
|
|
return clsName;
|
|
}
|
|
|
|
const columns = [
|
|
{
|
|
key: 'id',
|
|
...SelectColumn,
|
|
minWidth: 30,
|
|
width: 30,
|
|
headerRenderer() {
|
|
return (
|
|
<InputCheckbox
|
|
cid={_.uniqueId('rgc')}
|
|
className={classes.headerSelectCell}
|
|
value={selectedRows.length == allRowIds.length ? rootSelection : false}
|
|
size='small'
|
|
onChange={(e) => {
|
|
if (e.target.checked) {
|
|
setRootSelection(true);
|
|
setSelectedRows([...allRowIds]);
|
|
selectedRowIds([...allRowIds]);
|
|
} else {
|
|
setRootSelection(false);
|
|
setSelectedRows([]);
|
|
selectedRowIds([]);
|
|
}
|
|
}
|
|
}
|
|
></InputCheckbox>
|
|
);
|
|
},
|
|
formatter({ row, isCellSelected }) {
|
|
isCellSelected && setActiveRow(row.id);
|
|
return (
|
|
<Box className={!row?.children && clsx(getStyleClassName(row, selectedRows, isCellSelected, activeRow, true), classes.selChBox)}>
|
|
<InputCheckbox
|
|
className={classes.selectCell}
|
|
cid={`${row.id}`}
|
|
value={selectedRows.includes(`${row.id}`)}
|
|
size='small'
|
|
onChange={(e) => {
|
|
setSelectedRows((prev) => {
|
|
let tempSelectedRows = [...prev];
|
|
if (!prev.includes(e.target.id)) {
|
|
selectedResultRows(row, tempSelectedRows);
|
|
tempSelectedRows.length === allRowIds.length && setRootSelection(true);
|
|
} else {
|
|
deselectResultRows(row, tempSelectedRows);
|
|
}
|
|
tempSelectedRows = new Set(tempSelectedRows);
|
|
selectedRowIds([...tempSelectedRows]);
|
|
return [...tempSelectedRows];
|
|
});
|
|
}
|
|
}
|
|
></InputCheckbox>
|
|
</Box>
|
|
);
|
|
}
|
|
},
|
|
{
|
|
key: 'label',
|
|
name: 'Objects',
|
|
width: '80%',
|
|
colSpan(args) {
|
|
if (args.type === 'ROW' && 'children' in args.row) {
|
|
return 2;
|
|
}
|
|
|
|
return 1;
|
|
},
|
|
formatter({ row, isCellSelected }) {
|
|
const hasChildren = row.children !== undefined;
|
|
isCellSelected && setActiveRow(row.id);
|
|
return (
|
|
<>
|
|
{hasChildren && (
|
|
|
|
<CellExpanderFormatter
|
|
row={row}
|
|
isCellSelected={isCellSelected}
|
|
expanded={row.isExpanded === true}
|
|
filterParams={filterParams}
|
|
onCellExpand={() => dispatch({ id: row.id, type: 'toggleSubRow', filterParams: filterParams, gridData: gridData, selectedRows: selectedRows })}
|
|
classes={classes}
|
|
/>
|
|
)}
|
|
<div className="rdg-cell-value">
|
|
|
|
{!hasChildren && (
|
|
<Box className={clsx(getStyleClassName(row, selectedRows, isCellSelected, activeRow), classes.status)}>
|
|
<span className={clsx(classes.recordRow, row.icon)}></span>
|
|
{row.label}
|
|
</Box>
|
|
)}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
},
|
|
{
|
|
key: 'status',
|
|
name: 'Comparison Result',
|
|
formatter({ row, isCellSelected }) {
|
|
isCellSelected && setActiveRow(row.id);
|
|
|
|
return (
|
|
<Box className={getStyleClassName(row, selectedRows, isCellSelected, activeRow)}>
|
|
{row.status}
|
|
</Box>
|
|
);
|
|
}
|
|
},
|
|
];
|
|
|
|
useEffect(() => {
|
|
let tempRows = gridData;
|
|
tempRows.map((row) => {
|
|
dispatch({ id: row.id, type: 'applyFilter', filterParams: filterParams, gridData: gridData, selectedRows: selectedRows });
|
|
});
|
|
}, [filterParams]);
|
|
|
|
const eventBus = useContext(SchemaDiffEventsContext);
|
|
const rowSelectionTimeoutRef = useRef();
|
|
|
|
const rowSelection = (rowIdx) => {
|
|
if (rowSelectionTimeoutRef.current) {
|
|
clearTimeout(rowSelectionTimeoutRef.current);
|
|
rowSelectionTimeoutRef.current = null;
|
|
}
|
|
|
|
rowSelectionTimeoutRef.current = setTimeout(()=> {
|
|
rowSelectionTimeoutRef.current = null;
|
|
const row = rows[rowIdx];
|
|
if (row.ddlData != undefined && row.status != FILTER_NAME.IDENTICAL) {
|
|
eventBus.fireEvent(SCHEMA_DIFF_EVENT.TRIGGER_CHANGE_RESULT_SQL, row.ddlData);
|
|
} else if (row.status == FILTER_NAME.IDENTICAL) {
|
|
let url_params = {
|
|
'trans_id': transId,
|
|
'source_sid': sourceData.sid,
|
|
'source_did': sourceData.did,
|
|
'source_scid': row.source_scid,
|
|
'target_sid': targetData.sid,
|
|
'target_did': targetData.did,
|
|
'target_scid': row.target_scid,
|
|
'comp_status': row.status,
|
|
'source_oid': row.source_oid,
|
|
'target_oid': row.target_oid,
|
|
'node_type': row.itemType,
|
|
};
|
|
|
|
let baseUrl = url_for('schema_diff.ddl_compare', url_params);
|
|
schemaDiffToolContext.api.get(baseUrl).then((res) => {
|
|
row.ddlData = {
|
|
'SQLdiff': res.data.diff_ddl,
|
|
'sourceSQL': res.data.source_ddl,
|
|
'targetSQL': res.data.target_ddl
|
|
};
|
|
eventBus.fireEvent(SCHEMA_DIFF_EVENT.TRIGGER_CHANGE_RESULT_SQL, row.ddlData);
|
|
}).catch((err) => {
|
|
Notifier.alert(err.message);
|
|
});
|
|
} else {
|
|
eventBus.fireEvent(SCHEMA_DIFF_EVENT.TRIGGER_CHANGE_RESULT_SQL, {});
|
|
}
|
|
}, 250);
|
|
};
|
|
|
|
function rowKeyGetter(row) {
|
|
return row.id;
|
|
}
|
|
|
|
return (
|
|
<Box className={classes.root} flexGrow="1" minHeight="0" id="schema-diff-grid">
|
|
{
|
|
gridData ?
|
|
<PgReactDataGrid
|
|
id="schema-diff-result-grid"
|
|
columns={columns} rows={rows}
|
|
className={clsx('big-grid', classes.gridPanel, classes.grid)}
|
|
treeDepth={2}
|
|
enableRowSelect={true}
|
|
defaultColumnOptions={{
|
|
resizable: true
|
|
}}
|
|
headerRowHeight={28}
|
|
rowHeight={28}
|
|
onItemSelect={rowSelection}
|
|
enableCellSelect={false}
|
|
rowKeyGetter={rowKeyGetter}
|
|
direction={'vertical-lr'}
|
|
noRowsText={gettext('No difference found')}
|
|
noRowsIcon={<InfoIcon className={classes.noRowsIcon} />}
|
|
/>
|
|
:
|
|
<>
|
|
{gettext('Loading result grid...')}
|
|
</>
|
|
}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
ResultGridComponent.propTypes = {
|
|
gridData: PropTypes.array,
|
|
allRowIds: PropTypes.array,
|
|
filterParams: PropTypes.array,
|
|
selectedRowIds: PropTypes.func,
|
|
transId: PropTypes.number,
|
|
sourceData: PropTypes.object,
|
|
targetData: PropTypes.object,
|
|
'sourceData.sid': PropTypes.number,
|
|
'sourceData.did': PropTypes.number,
|
|
'targetData.sid': PropTypes.number,
|
|
'targetData.did': PropTypes.number,
|
|
};
|