Files
dbgate/packages/datalib/src/CollectionGridDisplay.ts
2022-03-17 12:37:17 +01:00

114 lines
3.5 KiB
TypeScript

import _ from 'lodash';
import { GridDisplay, ChangeCacheFunc, ChangeConfigFunc, DisplayColumn } from './GridDisplay';
import { EngineDriver, ViewInfo, ColumnInfo, CollectionInfo } from 'dbgate-types';
import { GridConfig, GridCache } from './GridConfig';
function getObjectKeys(obj) {
if (_.isArray(obj)) {
return Object.keys(obj)
.slice(0, 10)
.map(x => parseInt(x));
}
if (_.isPlainObject(obj)) {
return Object.keys(obj);
}
return [];
}
function createHeaderText(path) {
let res = `${path[0]}`;
for (let i = 1; i < path.length; i++) {
const name = path[i];
if (_.isNumber(name)) res += `[${name}]`;
else res += `.${name}`;
}
return res;
}
function getColumnsForObject(basePath, obj, res: any[], display) {
for (const name of getObjectKeys(obj)) {
const uniqueName = [...basePath, name].join('.');
let column = res.find(x => x.uniqueName == uniqueName);
if (!column) {
column = getDisplayColumn(basePath, name, display);
if (basePath.length > 0) {
const lastIndex1 = _.findLastIndex(res, x => x.parentHeaderText.startsWith(column.parentHeaderText));
const lastIndex2 = _.findLastIndex(res, x => x.headerText == column.parentHeaderText);
// console.log(uniqueName, lastIndex1, lastIndex2);
if (lastIndex1 >= 0) res.splice(lastIndex1 + 1, 0, column);
else if (lastIndex2 >= 0) res.splice(lastIndex2 + 1, 0, column);
else res.push(column);
} else {
res.push(column);
}
}
if (_.isPlainObject(obj[name]) || _.isArray(obj[name])) {
column.isExpandable = true;
}
if (display.isExpandedColumn(column.uniqueName)) {
getColumnsForObject([...basePath, name], obj[name], res, display);
}
}
}
function getDisplayColumn(basePath, columnName, display) {
const uniquePath = [...basePath, columnName];
const uniqueName = uniquePath.join('.');
return {
columnName,
headerText: createHeaderText(uniquePath),
uniqueName,
uniquePath,
isStructured: true,
parentHeaderText: createHeaderText(basePath),
filterType: 'mongo',
pureName: display.collection?.pureName,
schemaName: display.collection?.schemaName,
};
}
export function analyseCollectionDisplayColumns(rows, display) {
const res = [];
const addedColumns = display?.config?.addedColumns;
for (const row of rows || []) {
getColumnsForObject([], row, res, display);
}
for (const added of addedColumns || []) {
if (res.find(x => x.uniqueName == added)) continue;
res.push(getDisplayColumn([], added, display));
}
return (
res.map(col => ({
...col,
isChecked: display.isColumnChecked(col),
})) || []
);
}
export class CollectionGridDisplay extends GridDisplay {
constructor(
public collection: CollectionInfo,
driver: EngineDriver,
config: GridConfig,
setConfig: ChangeConfigFunc,
cache: GridCache,
setCache: ChangeCacheFunc,
loadedRows,
changeSet,
readOnly = false
) {
super(config, setConfig, cache, setCache, driver);
const changedDocs = _.compact(changeSet.updates.map(chs => chs.document));
const insertedDocs = _.compact(changeSet.inserts.map(chs => chs.fields));
this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs, ...insertedDocs], this);
this.filterable = true;
this.sortable = true;
this.editable = !readOnly;
this.supportsReload = true;
this.isDynamicStructure = true;
this.changeSetKeyFields = ['_id'];
this.baseCollection = collection;
}
}