mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-01 19:03:58 +00:00
perspective display - mongo nested objects
This commit is contained in:
@@ -3,6 +3,8 @@ import _max from 'lodash/max';
|
|||||||
import _range from 'lodash/max';
|
import _range from 'lodash/max';
|
||||||
import _fill from 'lodash/fill';
|
import _fill from 'lodash/fill';
|
||||||
import _findIndex from 'lodash/findIndex';
|
import _findIndex from 'lodash/findIndex';
|
||||||
|
import _isPlainObject from 'lodash/isPlainObject';
|
||||||
|
import _isArray from 'lodash/isArray';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
|
||||||
const dbg = debug('dbgate:PerspectiveDisplay');
|
const dbg = debug('dbgate:PerspectiveDisplay');
|
||||||
@@ -167,13 +169,30 @@ export class PerspectiveDisplay {
|
|||||||
// return _findIndex(this.columns, x => x.dataNode.designerId == node.designerId);
|
// return _findIndex(this.columns, x => x.dataNode.designerId == node.designerId);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
extractArray(value) {
|
||||||
|
if (_isArray(value)) return value;
|
||||||
|
if (_isPlainObject(value)) return [value];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
collectRows(sourceRows: any[], nodes: PerspectiveTreeNode[]): CollectedPerspectiveDisplayRow[] {
|
collectRows(sourceRows: any[], nodes: PerspectiveTreeNode[]): CollectedPerspectiveDisplayRow[] {
|
||||||
// console.log('********** COLLECT ROWS', sourceRows);
|
// console.log('********** COLLECT ROWS', sourceRows);
|
||||||
const columnNodes = nodes.filter(x => x.isCheckedColumn);
|
const columnNodes = nodes.filter(x => x.generatesDataGridColumn);
|
||||||
const treeNodes = nodes.filter(x => x.isCheckedNode);
|
const treeNodes = nodes.filter(x => x.generatesHiearchicGridColumn);
|
||||||
|
|
||||||
// console.log('columnNodes', columnNodes);
|
// console.log(
|
||||||
// console.log('treeNodes', treeNodes);
|
// 'columnNodes',
|
||||||
|
// columnNodes.map(x => x.title)
|
||||||
|
// );
|
||||||
|
// console.log(
|
||||||
|
// 'treeNodes',
|
||||||
|
// treeNodes.map(x => x.title)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// console.log(
|
||||||
|
// 'nodes',
|
||||||
|
// nodes.map(x => x.title)
|
||||||
|
// );
|
||||||
|
|
||||||
const columnIndexes = columnNodes.map(node => this.findColumnIndexFromNode(node));
|
const columnIndexes = columnNodes.map(node => this.findColumnIndexFromNode(node));
|
||||||
|
|
||||||
@@ -181,14 +200,14 @@ export class PerspectiveDisplay {
|
|||||||
for (const sourceRow of sourceRows) {
|
for (const sourceRow of sourceRows) {
|
||||||
// console.log('PROCESS SOURCE', sourceRow);
|
// console.log('PROCESS SOURCE', sourceRow);
|
||||||
// row.startIndex = startIndex;
|
// row.startIndex = startIndex;
|
||||||
const rowData = columnNodes.map(node => sourceRow[node.codeName]);
|
const rowData = columnNodes.map(node => sourceRow[node.fieldName]);
|
||||||
const subRowCollections = [];
|
const subRowCollections = [];
|
||||||
|
|
||||||
for (const node of treeNodes) {
|
for (const node of treeNodes) {
|
||||||
// console.log('sourceRow[node.fieldName]', node.fieldName, sourceRow[node.fieldName]);
|
// console.log('sourceRow[node.fieldName]', node.fieldName, sourceRow[node.fieldName]);
|
||||||
if (sourceRow[node.fieldName]) {
|
if (sourceRow[node.fieldName]) {
|
||||||
const subrows = {
|
const subrows = {
|
||||||
rows: this.collectRows(sourceRow[node.fieldName], node.childNodes),
|
rows: this.collectRows(this.extractArray(sourceRow[node.fieldName]), node.childNodes),
|
||||||
};
|
};
|
||||||
subRowCollections.push(subrows);
|
subRowCollections.push(subrows);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -797,6 +797,7 @@ export class PerspectivePatternColumnNode extends PerspectiveTreeNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get generatesHiearchicGridColumn() {
|
get generatesHiearchicGridColumn() {
|
||||||
|
// console.log('generatesHiearchicGridColumn', this.parentTableNode?.nodeConfig?.checkedColumns, this.codeName + '::');
|
||||||
return !!this.parentTableNode?.nodeConfig?.checkedColumns?.find(x => x.startsWith(this.codeName + '::'));
|
return !!this.parentTableNode?.nodeConfig?.checkedColumns?.find(x => x.startsWith(this.codeName + '::'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { TableInfo } from 'dbgate-types';
|
|
||||||
import { PerspectiveDisplay } from '../PerspectiveDisplay';
|
import { PerspectiveDisplay } from '../PerspectiveDisplay';
|
||||||
import { PerspectiveTableNode } from '../PerspectiveTreeNode';
|
import { PerspectiveTableNode } from '../PerspectiveTreeNode';
|
||||||
import { chinookDbInfo } from './chinookDbInfo';
|
import { chinookDbInfo } from './chinookDbInfo';
|
||||||
@@ -7,9 +6,6 @@ import artistDataFlat from './artistDataFlat';
|
|||||||
import artistDataAlbum from './artistDataAlbum';
|
import artistDataAlbum from './artistDataAlbum';
|
||||||
import artistDataAlbumTrack from './artistDataAlbumTrack';
|
import artistDataAlbumTrack from './artistDataAlbumTrack';
|
||||||
import { processPerspectiveDefaultColunns } from '../processPerspectiveDefaultColunns';
|
import { processPerspectiveDefaultColunns } from '../processPerspectiveDefaultColunns';
|
||||||
import { DatabaseAnalyser, isCollectionInfo } from 'dbgate-tools';
|
|
||||||
import { analyseDataPattern } from '../PerspectiveDataPattern';
|
|
||||||
import { PerspectiveDataProvider } from '../PerspectiveDataProvider';
|
|
||||||
|
|
||||||
test('test flat view', () => {
|
test('test flat view', () => {
|
||||||
const artistTable = chinookDbInfo.tables.find(x => x.pureName == 'Artist');
|
const artistTable = chinookDbInfo.tables.find(x => x.pureName == 'Artist');
|
||||||
@@ -144,52 +140,3 @@ test('test two level nesting', () => {
|
|||||||
expect(display.rows[2].rowSpans).toEqual([1, 2, 1]);
|
expect(display.rows[2].rowSpans).toEqual([1, 2, 1]);
|
||||||
expect(display.rows[2].rowCellSkips).toEqual([true, false, false]);
|
expect(display.rows[2].rowCellSkips).toEqual([true, false, false]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('test nosql display', () => {
|
|
||||||
const collectionInfo = {
|
|
||||||
objectTypeField: 'collections',
|
|
||||||
pureName: 'Account',
|
|
||||||
};
|
|
||||||
const dbInfo = {
|
|
||||||
...DatabaseAnalyser.createEmptyStructure(),
|
|
||||||
collections: [collectionInfo],
|
|
||||||
};
|
|
||||||
const accountData = [
|
|
||||||
{ name: 'jan', email: 'jan@foo.co', follows: [{ name: 'lucie' }, { name: 'petr' }] },
|
|
||||||
{ name: 'romeo', email: 'romeo@foo.co', follows: [{ name: 'julie' }, { name: 'wiliam' }] },
|
|
||||||
];
|
|
||||||
const config = createPerspectiveConfig({ pureName: 'Account' });
|
|
||||||
const dataPatterns = {
|
|
||||||
[config.rootDesignerId]: analyseDataPattern(
|
|
||||||
{
|
|
||||||
conid: 'conid',
|
|
||||||
database: 'db',
|
|
||||||
pureName: 'Account',
|
|
||||||
},
|
|
||||||
accountData
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
const configColumns = processPerspectiveDefaultColunns(
|
|
||||||
config,
|
|
||||||
{ conid: { db: dbInfo } },
|
|
||||||
dataPatterns,
|
|
||||||
'conid',
|
|
||||||
'db'
|
|
||||||
);
|
|
||||||
const root = new PerspectiveTableNode(
|
|
||||||
collectionInfo,
|
|
||||||
{ conid: { db: dbInfo } },
|
|
||||||
configColumns,
|
|
||||||
null,
|
|
||||||
new PerspectiveDataProvider(null, null, dataPatterns),
|
|
||||||
{ conid: 'conid', database: 'db' },
|
|
||||||
null,
|
|
||||||
configColumns.rootDesignerId
|
|
||||||
);
|
|
||||||
const display = new PerspectiveDisplay(root, accountData);
|
|
||||||
|
|
||||||
expect(display.rows.length).toEqual(2);
|
|
||||||
expect(display.rows[0].rowData).toEqual(['jan']);
|
|
||||||
expect(display.rows[1].rowData).toEqual(['romeo']);
|
|
||||||
});
|
|
||||||
|
|||||||
98
packages/datalib/src/tests/PerspectiveDisplayNoSql.test.ts
Normal file
98
packages/datalib/src/tests/PerspectiveDisplayNoSql.test.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { PerspectiveDisplay } from '../PerspectiveDisplay';
|
||||||
|
import { PerspectiveTableNode } from '../PerspectiveTreeNode';
|
||||||
|
import { createPerspectiveConfig, PerspectiveNodeConfig } from '../PerspectiveConfig';
|
||||||
|
import { processPerspectiveDefaultColunns } from '../processPerspectiveDefaultColunns';
|
||||||
|
import { DatabaseAnalyser } from 'dbgate-tools';
|
||||||
|
import { analyseDataPattern } from '../PerspectiveDataPattern';
|
||||||
|
import { PerspectiveDataProvider } from '../PerspectiveDataProvider';
|
||||||
|
|
||||||
|
const accountData = [
|
||||||
|
{
|
||||||
|
name: 'jan',
|
||||||
|
email: 'jan@foo.co',
|
||||||
|
follows: [{ name: 'lucie' }, { name: 'petr' }],
|
||||||
|
nested: { email: 'jan@nest.cz' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'romeo',
|
||||||
|
email: 'romeo@foo.co',
|
||||||
|
follows: [{ name: 'julie' }, { name: 'wiliam' }],
|
||||||
|
nested: { email: 'romeo@nest.cz' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function createDisplay(cfgFunc?: (cfg: PerspectiveNodeConfig) => void) {
|
||||||
|
const collectionInfo = {
|
||||||
|
objectTypeField: 'collections',
|
||||||
|
pureName: 'Account',
|
||||||
|
};
|
||||||
|
const dbInfo = {
|
||||||
|
...DatabaseAnalyser.createEmptyStructure(),
|
||||||
|
collections: [collectionInfo],
|
||||||
|
};
|
||||||
|
const config = createPerspectiveConfig({ pureName: 'Account' });
|
||||||
|
const dataPatterns = {
|
||||||
|
[config.rootDesignerId]: analyseDataPattern(
|
||||||
|
{
|
||||||
|
conid: 'conid',
|
||||||
|
database: 'db',
|
||||||
|
pureName: 'Account',
|
||||||
|
},
|
||||||
|
accountData
|
||||||
|
),
|
||||||
|
};
|
||||||
|
const configColumns = processPerspectiveDefaultColunns(
|
||||||
|
config,
|
||||||
|
{ conid: { db: dbInfo } },
|
||||||
|
dataPatterns,
|
||||||
|
'conid',
|
||||||
|
'db'
|
||||||
|
);
|
||||||
|
if (cfgFunc) {
|
||||||
|
cfgFunc(configColumns.nodes[0]);
|
||||||
|
}
|
||||||
|
const root = new PerspectiveTableNode(
|
||||||
|
collectionInfo,
|
||||||
|
{ conid: { db: dbInfo } },
|
||||||
|
configColumns,
|
||||||
|
null,
|
||||||
|
new PerspectiveDataProvider(null, null, dataPatterns),
|
||||||
|
{ conid: 'conid', database: 'db' },
|
||||||
|
null,
|
||||||
|
configColumns.rootDesignerId
|
||||||
|
);
|
||||||
|
|
||||||
|
const display = new PerspectiveDisplay(root, accountData);
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
test('test nosql display', () => {
|
||||||
|
const display = createDisplay();
|
||||||
|
|
||||||
|
expect(display.rows.length).toEqual(2);
|
||||||
|
expect(display.rows[0].rowData).toEqual(['jan']);
|
||||||
|
expect(display.rows[1].rowData).toEqual(['romeo']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test nosql nested array display', () => {
|
||||||
|
const display = createDisplay(cfg => {
|
||||||
|
cfg.checkedColumns = ['name', 'follows::name'];
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(display.rows.length).toEqual(4);
|
||||||
|
expect(display.rows[0].rowData).toEqual(['jan', 'lucie']);
|
||||||
|
expect(display.rows[1].rowData).toEqual([undefined, 'petr']);
|
||||||
|
expect(display.rows[2].rowData).toEqual(['romeo', 'julie']);
|
||||||
|
expect(display.rows[3].rowData).toEqual([undefined, 'wiliam']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test nosql nested object', () => {
|
||||||
|
const display = createDisplay(cfg => {
|
||||||
|
cfg.checkedColumns = ['name', 'nested::email'];
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(display.rows.length).toEqual(2);
|
||||||
|
expect(display.rows[0].rowData).toEqual(['jan', 'jan@nest.cz']);
|
||||||
|
expect(display.rows[1].rowData).toEqual(['romeo', 'romeo@nest.cz']);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user