handle readonly connection in UI

This commit is contained in:
Jan Prochazka
2022-03-17 12:37:17 +01:00
parent 34658e134f
commit 267e687e2b
16 changed files with 52 additions and 19 deletions

View File

@@ -95,7 +95,8 @@ export class CollectionGridDisplay extends GridDisplay {
cache: GridCache, cache: GridCache,
setCache: ChangeCacheFunc, setCache: ChangeCacheFunc,
loadedRows, loadedRows,
changeSet changeSet,
readOnly = false
) { ) {
super(config, setConfig, cache, setCache, driver); super(config, setConfig, cache, setCache, driver);
const changedDocs = _.compact(changeSet.updates.map(chs => chs.document)); const changedDocs = _.compact(changeSet.updates.map(chs => chs.document));
@@ -103,7 +104,7 @@ export class CollectionGridDisplay extends GridDisplay {
this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs, ...insertedDocs], this); this.columns = analyseCollectionDisplayColumns([...(loadedRows || []), ...changedDocs, ...insertedDocs], this);
this.filterable = true; this.filterable = true;
this.sortable = true; this.sortable = true;
this.editable = true; this.editable = !readOnly;
this.supportsReload = true; this.supportsReload = true;
this.isDynamicStructure = true; this.isDynamicStructure = true;
this.changeSetKeyFields = ['_id']; this.changeSetKeyFields = ['_id'];

View File

@@ -23,7 +23,8 @@ export class TableFormViewDisplay extends FormViewDisplay {
dbinfo: DatabaseInfo, dbinfo: DatabaseInfo,
displayOptions, displayOptions,
serverVersion, serverVersion,
getDictionaryDescription: DictionaryDescriptionFunc = null getDictionaryDescription: DictionaryDescriptionFunc = null,
isReadOnly = false
) { ) {
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion); super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
this.gridDisplay = new TableGridDisplay( this.gridDisplay = new TableGridDisplay(
@@ -36,7 +37,8 @@ export class TableFormViewDisplay extends FormViewDisplay {
dbinfo, dbinfo,
displayOptions, displayOptions,
serverVersion, serverVersion,
getDictionaryDescription getDictionaryDescription,
isReadOnly
); );
this.gridDisplay.addAllExpandedColumnsToSelected = true; this.gridDisplay.addAllExpandedColumnsToSelected = true;
@@ -263,4 +265,8 @@ export class TableFormViewDisplay extends FormViewDisplay {
isExpandedColumn(uniqueName: string) { isExpandedColumn(uniqueName: string) {
return this.gridDisplay.isExpandedColumn(uniqueName); return this.gridDisplay.isExpandedColumn(uniqueName);
} }
get editable() {
return this.gridDisplay.editable;
}
} }

View File

@@ -36,7 +36,8 @@ export class TableGridDisplay extends GridDisplay {
dbinfo: DatabaseInfo, dbinfo: DatabaseInfo,
public displayOptions: any, public displayOptions: any,
serverVersion, serverVersion,
public getDictionaryDescription: DictionaryDescriptionFunc = null public getDictionaryDescription: DictionaryDescriptionFunc = null,
isReadOnly = false
) { ) {
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion); super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
@@ -53,7 +54,7 @@ export class TableGridDisplay extends GridDisplay {
this.filterable = true; this.filterable = true;
this.sortable = true; this.sortable = true;
this.groupable = true; this.groupable = true;
this.editable = true; this.editable = !isReadOnly;
this.supportsReload = true; this.supportsReload = true;
this.baseTable = this.table; this.baseTable = this.table;
if (this.table && this.table.columns) { if (this.table && this.table.columns) {

View File

@@ -14,6 +14,7 @@
export let isBold = false; export let isBold = false;
export let isBusy = false; export let isBusy = false;
export let statusIcon = undefined; export let statusIcon = undefined;
export let statusIconBefore = undefined;
export let statusTitle = undefined; export let statusTitle = undefined;
export let extInfo = undefined; export let extInfo = undefined;
export let menu = undefined; export let menu = undefined;
@@ -101,6 +102,11 @@
<FontIcon style={`color:${colorMark}`} icon="icon square" /> <FontIcon style={`color:${colorMark}`} icon="icon square" />
{/if} {/if}
{title} {title}
{#if statusIconBefore}
<span class="status">
<FontIcon icon={statusIconBefore} />
</span>
{/if}
{#if statusIcon} {#if statusIcon}
<span class="status"> <span class="status">
<FontIcon icon={statusIcon} title={statusTitle} /> <FontIcon icon={statusIcon} title={statusTitle} />

View File

@@ -200,6 +200,7 @@
: _.get($currentDatabase, 'connection._id') == data._id} : _.get($currentDatabase, 'connection._id') == data._id}
statusIcon={statusIcon || engineStatusIcon} statusIcon={statusIcon || engineStatusIcon}
statusTitle={statusTitle || engineStatusTitle} statusTitle={statusTitle || engineStatusTitle}
statusIconBefore={data.isReadOnly ? 'icon lock' : null}
{extInfo} {extInfo}
colorMark={passProps?.connectionColorFactory && passProps?.connectionColorFactory({ conid: data._id })} colorMark={passProps?.connectionColorFactory && passProps?.connectionColorFactory({ conid: data._id })}
menu={getContextMenu} menu={getContextMenu}

View File

@@ -177,7 +177,7 @@
driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: 'New table' }, driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: 'New table' },
driver?.databaseEngineTypes?.includes('document') && { onClick: handleNewCollection, text: 'New collection' }, driver?.databaseEngineTypes?.includes('document') && { onClick: handleNewCollection, text: 'New collection' },
{ divider: true }, { divider: true },
{ onClick: handleImport, text: 'Import' }, !connection.isReadOnly && { onClick: handleImport, text: 'Import' },
{ onClick: handleExport, text: 'Export' }, { onClick: handleExport, text: 'Export' },
{ onClick: handleShowDiagram, text: 'Show diagram' }, { onClick: handleShowDiagram, text: 'Show diagram' },
{ onClick: handleSqlGenerator, text: 'SQL Generator' }, { onClick: handleSqlGenerator, text: 'SQL Generator' },

View File

@@ -69,8 +69,7 @@
import _ from 'lodash'; import _ from 'lodash';
import registerCommand from '../commands/registerCommand'; import registerCommand from '../commands/registerCommand';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import { getBoolSettingsValue } from '../settings/settingsTools'; import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
import { getLocalStorage, getLocalStorage, getLocalStorage, setLocalStorage } from '../utility/storageCache';
export let config; export let config;
export let setConfig; export let setConfig;

View File

@@ -70,7 +70,8 @@
extendedDbInfo, extendedDbInfo,
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) }, { showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
$serverVersion, $serverVersion,
table => getDictionaryDescription(table, conid, database, $apps, $connections) table => getDictionaryDescription(table, conid, database, $apps, $connections),
$connection?.isReadOnly
) )
: null; : null;
@@ -86,7 +87,8 @@
extendedDbInfo, extendedDbInfo,
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) }, { showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
$serverVersion, $serverVersion,
table => getDictionaryDescription(table, conid, database, $apps, $connections) table => getDictionaryDescription(table, conid, database, $apps, $connections),
$connection?.isReadOnly
) )
: null; : null;

View File

@@ -82,6 +82,9 @@ export default class ChangeSetFormer extends Former {
redo() { redo() {
this.dispatchChangeSet({ type: 'redo' }); this.dispatchChangeSet({ type: 'redo' });
} }
get editable() {
return this.display.editable;
}
get canUndo() { get canUndo() {
return this.changeSetState.canUndo; return this.changeSetState.canUndo;
} }

View File

@@ -327,6 +327,7 @@
const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => { const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => {
switch (action.type) { switch (action.type) {
case 'show': { case 'show': {
if (!former.editable) return {};
const column = getCellColumn(action.cell); const column = getCellColumn(action.cell);
if (!column) return state; if (!column) return state;
if (column.uniquePath.length > 1) return state; if (column.uniquePath.length > 1) return state;

View File

@@ -93,6 +93,7 @@
'icon dots-vertical': 'mdi mdi-dots-vertical', 'icon dots-vertical': 'mdi mdi-dots-vertical',
'icon add': 'mdi mdi-plus-circle', 'icon add': 'mdi mdi-plus-circle',
'icon json': 'mdi mdi-code-json', 'icon json': 'mdi mdi-code-json',
'icon lock': 'mdi mdi-lock',
'icon run': 'mdi mdi-play', 'icon run': 'mdi mdi-play',
'icon chevron-down': 'mdi mdi-chevron-down', 'icon chevron-down': 'mdi mdi-chevron-down',

View File

@@ -3,13 +3,17 @@
import FormSelectField from '../forms/FormSelectField.svelte'; import FormSelectField from '../forms/FormSelectField.svelte';
import getConnectionLabel from '../utility/getConnectionLabel'; import getConnectionLabel from '../utility/getConnectionLabel';
import { useConnectionList } from '../utility/metadataLoaders'; import { useConnectionList } from '../utility/metadataLoaders';
export let allowChooseModel = false; export let allowChooseModel = false;
export let direction;
$: connections = useConnectionList(); $: connections = useConnectionList();
$: connectionOptions = [ $: connectionOptions = [
...(allowChooseModel ? [{ label: '(DB Model)', value: '__model' }] : []), ...(allowChooseModel ? [{ label: '(DB Model)', value: '__model' }] : []),
..._.sortBy( ..._.sortBy(
($connections || []).map(conn => ({ ($connections || [])
.filter(conn => (direction == 'target' ? !conn.isReadOnly : true))
.map(conn => ({
value: conn._id, value: conn._id,
label: getConnectionLabel(conn), label: getConnectionLabel(conn),
})), })),

View File

@@ -114,7 +114,7 @@
/> />
{#if storageType == 'database' || storageType == 'query'} {#if storageType == 'database' || storageType == 'query'}
<FormConnectionSelect name={connectionIdField} label="Server" /> <FormConnectionSelect name={connectionIdField} label="Server" {direction} />
<FormDatabaseSelect conidName={connectionIdField} name={databaseNameField} label="Database" /> <FormDatabaseSelect conidName={connectionIdField} name={databaseNameField} label="Database" />
{/if} {/if}
{#if storageType == 'database'} {#if storageType == 'database'}

View File

@@ -89,7 +89,8 @@
$cache, $cache,
cache.update, cache.update,
loadedRows, loadedRows,
$changeSetStore?.value $changeSetStore?.value,
$connection?.isReadOnly
) )
: null; : null;
// $: console.log('LOADED ROWS MONGO', loadedRows); // $: console.log('LOADED ROWS MONGO', loadedRows);

View File

@@ -44,7 +44,11 @@ import { statusBarTabInfo } from '../utility/statusBarStore';
<div class="container"> <div class="container">
{#if databaseName} {#if databaseName}
<div class="item"> <div class="item">
{#if connection?.isReadOnly}
<FontIcon icon="icon lock" padRight />
{:else}
<FontIcon icon="icon database" padRight /> <FontIcon icon="icon database" padRight />
{/if}
{databaseName} {databaseName}
</div> </div>
{#if dbid} {#if dbid}

View File

@@ -390,6 +390,9 @@
<div class="db-name-inner"> <div class="db-name-inner">
<FontIcon icon={getDbIcon(tabGroup.tabDbKey)} /> <FontIcon icon={getDbIcon(tabGroup.tabDbKey)} />
{tabGroup.tabDbName} {tabGroup.tabDbName}
{#if $connectionList?.find(x => x._id == tabGroup.tabs[0]?.props?.conid)?.isReadOnly}
<FontIcon icon="icon lock" />
{/if}
</div> </div>
<div <div