Compare commits
1 Commits
quick-expo
...
mongoform
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f43ffd9af4 |
127
packages/datalib/src/CollectionFormViewDisplay.ts
Normal file
127
packages/datalib/src/CollectionFormViewDisplay.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
172
packages/web/src/formview/CollectionFormView.svelte
Normal file
172
packages/web/src/formview/CollectionFormView.svelte
Normal 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}
|
||||
/>
|
||||
@@ -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
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user