Compare commits

...

1 Commits

Author SHA1 Message Date
Jan Prochazka
f43ffd9af4 mongo form view WIP (blind branch?) 2021-04-05 08:52:24 +02:00
3 changed files with 301 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
import { FormViewDisplay } from './FormViewDisplay';
import _ from 'lodash';
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo, DatabaseInfo } from 'dbgate-types';
import { GridConfig, GridCache, createGridCache } from './GridConfig';
import {
Expression,
Select,
treeToSql,
dumpSqlSelect,
mergeConditions,
Condition,
OrderByExpression,
} from 'dbgate-sqltree';
import { filterName } from './filterName';
import { TableGridDisplay } from './TableGridDisplay';
import stableStringify from 'json-stable-stringify';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
import { CollectionGridDisplay } from './CollectionGridDisplay';
export class CollectionFormViewDisplay extends FormViewDisplay {
// use utility functions from GridDisplay and publish result in FromViewDisplay interface
private gridDisplay: CollectionGridDisplay;
constructor(
public collectionName: NamedObjectInfo,
driver: EngineDriver,
config: GridConfig,
setConfig: ChangeConfigFunc,
cache: GridCache,
setCache: ChangeCacheFunc,
loadedRow: any
) {
super(config, setConfig, cache, setCache, driver);
this.gridDisplay = new CollectionGridDisplay(collectionName, driver, config, setConfig, cache, setCache, [loadedRow]);
this.isLoadedCorrectly = this.gridDisplay.isLoadedCorrectly && !!this.driver;
this.columns = [];
this.addDisplayColumns(this.gridDisplay.columns);
}
addDisplayColumns(columns: DisplayColumn[]) {
for (const col of columns) {
this.columns.push(col);
}
}
navigate(row) {
const formViewKey = this.extractKey(row);
this.setConfig(cfg => ({
...cfg,
formViewKey,
}));
}
isLoadedCurrentRow(row) {
if (!row) return false;
const formViewKey = this.extractKey(row);
return stableStringify(formViewKey) == stableStringify(this.config.formViewKey);
}
navigateRowQuery(commmand: 'begin' | 'previous' | 'next' | 'end') {
if (!this.driver) return null;
const select = this.gridDisplay.createSelect();
if (!select) return null;
const { primaryKey } = this.gridDisplay.baseTable;
function getOrderBy(direction): OrderByExpression[] {
return primaryKey.columns.map(({ columnName }) => ({
exprType: 'column',
columnName,
direction,
}));
}
select.topRecords = 1;
switch (commmand) {
case 'begin':
select.orderBy = getOrderBy('ASC');
break;
case 'end':
select.orderBy = getOrderBy('DESC');
break;
case 'previous':
select.orderBy = getOrderBy('DESC');
select.where = mergeConditions(select.where, this.getPrimaryKeyOperatorCondition('<'));
break;
case 'next':
select.orderBy = getOrderBy('ASC');
select.where = mergeConditions(select.where, this.getPrimaryKeyOperatorCondition('>'));
break;
}
const sql = treeToSql(this.driver, select, dumpSqlSelect);
return sql;
}
getChangeSetRow(row): ChangeSetRowDefinition {
if (!this.baseTable) return null;
return {
pureName: this.baseTable.pureName,
schemaName: this.baseTable.schemaName,
condition: this.extractKey(row),
};
}
getChangeSetField(row, uniqueName): ChangeSetFieldDefinition {
const col = this.columns.find(x => x.uniqueName == uniqueName);
if (!col) return null;
if (!this.baseTable) return null;
if (this.baseTable.pureName != col.pureName || this.baseTable.schemaName != col.schemaName) return null;
return {
...this.getChangeSetRow(row),
uniqueName: uniqueName,
columnName: col.columnName,
};
}
toggleExpandedColumn(uniqueName: string) {
this.gridDisplay.toggleExpandedColumn(uniqueName);
this.gridDisplay.reload();
}
isExpandedColumn(uniqueName: string) {
return this.gridDisplay.isExpandedColumn(uniqueName);
}
}

View File

@@ -0,0 +1,172 @@
<script lang="ts" context="module">
async function loadRow(props, sql) {
const { conid, database } = props;
if (!sql) return null;
const response = await axiosInstance.request({
url: 'database-connections/query-data',
method: 'post',
params: {
conid,
database,
},
data: { sql },
});
if (response.data.errorMessage) return response.data;
return response.data.rows[0];
}
</script>
<script lang="ts">
import { changeSetToSql, createChangeSet } from 'dbgate-datalib';
import { scriptToSql } from 'dbgate-sqltree';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { showModal } from '../modals/modalTools';
import axiosInstance from '../utility/axiosInstance';
import ChangeSetFormer from './ChangeSetFormer';
import FormView from './FormView.svelte';
export let formDisplay;
export let changeSetState;
export let dispatchChangeSet;
export let masterLoadedTime;
export let conid;
export let database;
export let onReferenceSourceChanged;
let isLoadingData = false;
let isLoadedData = false;
let rowData = null;
let isLoadingCount = false;
let isLoadedCount = false;
let loadedTime = new Date().getTime();
let allRowCount = null;
let rowCountBefore = null;
let errorMessage = null;
const handleLoadCurrentRow = async () => {
if (isLoadingData) return;
let newLoadedRow = false;
if (formDisplay.config.formViewKeyRequested || formDisplay.config.formViewKey) {
isLoadingData = true;
const row = await loadRow($$props, formDisplay.getCurrentRowQuery());
isLoadingData = false;
isLoadedData = true;
rowData = row;
loadedTime = new Date().getTime();
newLoadedRow = row;
}
if (formDisplay.config.formViewKeyRequested && newLoadedRow) {
formDisplay.cancelRequestKey(newLoadedRow);
}
if (!newLoadedRow && !formDisplay.config.formViewKeyRequested) {
await handleNavigate('first');
}
};
const handleLoadRowCount = async () => {
isLoadingCount = true;
const countRow = await loadRow($$props, formDisplay.getCountQuery());
const countBeforeRow = await loadRow($$props, formDisplay.getBeforeCountQuery());
isLoadedCount = true;
isLoadingCount = false;
allRowCount = countRow ? parseInt(countRow.count) : null;
rowCountBefore = countBeforeRow ? parseInt(countBeforeRow.count) : null;
};
const handleNavigate = async command => {
isLoadingData = true;
const row = await loadRow($$props, formDisplay.navigateRowQuery(command));
if (row) {
formDisplay.navigate(row);
}
isLoadingData = false;
isLoadedData = true;
isLoadedCount = false;
allRowCount = null;
rowCountBefore = null;
rowData = row;
loadedTime = new Date().getTime();
};
export function reload() {
isLoadingData = false;
isLoadedData = false;
isLoadingCount = false;
isLoadedCount = false;
rowData = null;
loadedTime = new Date().getTime();
allRowCount = null;
rowCountBefore = null;
errorMessage = null;
}
$: {
if (masterLoadedTime && masterLoadedTime > loadedTime) {
formDisplay.reload();
}
}
$: {
if (formDisplay.cache.refreshTime > loadedTime) {
reload();
}
}
$: {
if (formDisplay.isLoadedCorrectly) {
if (!isLoadedData && !isLoadingData) handleLoadCurrentRow();
if (isLoadedData && !isLoadingCount && !isLoadedCount) handleLoadRowCount();
}
}
$: former = new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay);
$: if (onReferenceSourceChanged && rowData) onReferenceSourceChanged([rowData], loadedTime);
async function handleConfirmSql(sql) {
const resp = await axiosInstance.request({
url: 'database-connections/query-data',
method: 'post',
params: {
conid,
database,
},
data: { sql },
});
const { errorMessage } = resp.data || {};
if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else {
dispatchChangeSet({ type: 'reset', value: createChangeSet() });
formDisplay.reload();
}
}
function handleSave() {
const script = changeSetToSql(changeSetState && changeSetState.value, formDisplay.dbinfo);
const sql = scriptToSql(formDisplay.driver, script);
showModal(ConfirmSqlModal, {
sql,
onConfirm: () => handleConfirmSql(sql),
engine: formDisplay.engine,
});
}
</script>
<FormView
{...$$props}
{former}
isLoading={isLoadingData}
{allRowCount}
{rowCountBefore}
onSave={handleSave}
onNavigate={handleNavigate}
/>

View File

@@ -21,6 +21,7 @@
import CollectionDataGridCore from '../datagrid/CollectionDataGridCore.svelte';
import { useCollectionInfo, useConnectionInfo } from '../utility/metadataLoaders';
import { extensions } from '../stores';
import CollectionFormView from '../formview/CollectionFormView.svelte';
export let tabid;
export let conid;
@@ -72,5 +73,6 @@
{changeSetStore}
{dispatchChangeSet}
gridCoreComponent={CollectionDataGridCore}
formViewComponent={CollectionFormView}
isDynamicStructure
/>