Files
dbgate/packages/web/src/tableeditor/TableEditor.svelte
Jan Prochazka e0b8eb3e79 tabstrips
2022-02-13 08:22:23 +01:00

371 lines
11 KiB
Svelte

<script lang="ts" context="module">
const getCurrentEditor = () => getActiveComponent('TableEditor');
registerCommand({
id: 'tableEditor.addColumn',
category: 'Table editor',
name: 'Add column',
icon: 'icon add-column',
toolbar: true,
isRelatedToTab: true,
testEnabled: () => getCurrentEditor()?.writable(),
onClick: () => getCurrentEditor().addColumn(),
});
registerCommand({
id: 'tableEditor.addPrimaryKey',
category: 'Table editor',
name: 'Add primary key',
icon: 'icon add-key',
toolbar: true,
isRelatedToTab: true,
testEnabled: () => getCurrentEditor()?.allowAddPrimaryKey(),
onClick: () => getCurrentEditor().addPrimaryKey(),
});
registerCommand({
id: 'tableEditor.addForeignKey',
category: 'Table editor',
name: 'Add foreign key',
icon: 'icon add-key',
toolbar: true,
isRelatedToTab: true,
testEnabled: () => getCurrentEditor()?.writable(),
onClick: () => getCurrentEditor().addForeignKey(),
});
registerCommand({
id: 'tableEditor.addIndex',
category: 'Table editor',
name: 'Add index',
icon: 'icon add-key',
toolbar: true,
isRelatedToTab: true,
testEnabled: () => getCurrentEditor()?.writable(),
onClick: () => getCurrentEditor().addIndex(),
});
registerCommand({
id: 'tableEditor.addUnique',
category: 'Table editor',
name: 'Add unique',
icon: 'icon add-key',
toolbar: true,
isRelatedToTab: true,
testEnabled: () => getCurrentEditor()?.writable(),
onClick: () => getCurrentEditor().addUnique(),
});
</script>
<script lang="ts">
import { editorDeleteColumn, editorDeleteConstraint } from 'dbgate-tools';
import _ from 'lodash';
import { onMount, tick } from 'svelte';
import invalidateCommands from '../commands/invalidateCommands';
import registerCommand from '../commands/registerCommand';
import ColumnLabel from '../elements/ColumnLabel.svelte';
import ConstraintLabel from '../elements/ConstraintLabel.svelte';
import ForeignKeyObjectListControl from '../elements/ForeignKeyObjectListControl.svelte';
import Link from '../elements/Link.svelte';
import ObjectListControl from '../elements/ObjectListControl.svelte';
import { showModal } from '../modals/modalTools';
import useEditorData from '../query/useEditorData';
import createActivator, { getActiveComponent } from '../utility/createActivator';
import { useDbCore } from '../utility/metadataLoaders';
import ColumnEditorModal from './ColumnEditorModal.svelte';
import ForeignKeyEditorModal from './ForeignKeyEditorModal.svelte';
import IndexEditorModal from './IndexEditorModal.svelte';
import PrimaryKeyEditorModal from './PrimaryKeyEditorModal.svelte';
import UniqueEditorModal from './UniqueEditorModal.svelte';
export const activator = createActivator('TableEditor', true);
export let tableInfo;
export let setTableInfo;
export let dbInfo;
export let driver;
export function writable() {
return !!setTableInfo;
}
export function addColumn() {
showModal(ColumnEditorModal, {
setTableInfo,
tableInfo,
driver,
onAddNext: async () => {
await tick();
addColumn();
},
});
}
export function allowAddPrimaryKey() {
return writable() && !tableInfo?.primaryKey;
}
export function addPrimaryKey() {
showModal(PrimaryKeyEditorModal, {
setTableInfo,
tableInfo,
});
}
export function addForeignKey() {
showModal(ForeignKeyEditorModal, {
setTableInfo,
tableInfo,
dbInfo,
});
}
export function addIndex() {
showModal(IndexEditorModal, {
setTableInfo,
tableInfo,
dbInfo,
});
}
export function addUnique() {
showModal(UniqueEditorModal, {
setTableInfo,
tableInfo,
dbInfo,
});
}
$: columns = tableInfo?.columns;
$: primaryKey = tableInfo?.primaryKey;
$: foreignKeys = tableInfo?.foreignKeys;
$: dependencies = tableInfo?.dependencies;
$: indexes = tableInfo?.indexes;
$: uniques = tableInfo?.uniques;
$: {
tableInfo;
invalidateCommands();
}
</script>
<div class="wrapper">
<ObjectListControl
collection={columns?.map((x, index) => ({ ...x, ordinal: index + 1 }))}
title={`Columns (${columns?.length || 0})`}
emptyMessage="No columns defined"
clickable={writable()}
on:clickrow={e => showModal(ColumnEditorModal, { columnInfo: e.detail, tableInfo, setTableInfo, driver })}
onAddNew={writable() ? addColumn : null}
columns={[
{
fieldName: 'notNull',
header: 'Nullability',
sortable: true,
slot: 0,
},
{
fieldName: 'dataType',
header: 'Data Type',
sortable: true,
},
{
fieldName: 'defaultValue',
header: 'Default value',
sortable: true,
},
driver?.dialect?.columnProperties?.isSparse && {
fieldName: 'isSparse',
header: 'Is Sparse',
sortable: true,
slot: 1,
},
{
fieldName: 'computedExpression',
header: 'Computed Expression',
sortable: true,
},
driver?.dialect?.columnProperties?.isPersisted && {
fieldName: 'isPersisted',
header: 'Is Persisted',
sortable: true,
slot: 2,
},
driver?.dialect?.columnProperties?.isUnsigned && {
fieldName: 'isUnsigned',
header: 'Unsigned',
sortable: true,
slot: 4,
},
driver?.dialect?.columnProperties?.isZerofill && {
fieldName: 'isZerofill',
header: 'Zero fill',
sortable: true,
slot: 5,
},
driver?.dialect?.columnProperties?.columnComment && {
fieldName: 'columnComment',
header: 'Comment',
sortable: true,
},
writable()
? {
fieldName: 'actions',
sortable: true,
slot: 3,
}
: null,
]}
>
<svelte:fragment slot="0" let:row>{row?.notNull ? 'NOT NULL' : 'NULL'}</svelte:fragment>
<svelte:fragment slot="1" let:row>{row?.isSparse ? 'YES' : 'NO'}</svelte:fragment>
<svelte:fragment slot="2" let:row>{row?.isPersisted ? 'YES' : 'NO'}</svelte:fragment>
<svelte:fragment slot="3" let:row
><Link
onClick={e => {
e.stopPropagation();
setTableInfo(tbl => editorDeleteColumn(tbl, row));
}}>Remove</Link
></svelte:fragment
>
<svelte:fragment slot="4" let:row>{row?.isUnsigned ? 'YES' : 'NO'}</svelte:fragment>
<svelte:fragment slot="5" let:row>{row?.isZerofill ? 'YES' : 'NO'}</svelte:fragment>
<svelte:fragment slot="name" let:row><ColumnLabel {...row} forceIcon /></svelte:fragment>
</ObjectListControl>
<ObjectListControl
collection={_.compact([primaryKey])}
title="Primary key"
emptyMessage={writable() ? 'No primary key defined' : null}
onAddNew={writable() && !primaryKey && columns?.length > 0 ? addPrimaryKey : null}
clickable={writable()}
on:clickrow={e => showModal(PrimaryKeyEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
columns={[
{
fieldName: 'columns',
header: 'Columns',
slot: 0,
},
writable()
? {
fieldName: 'actions',
sortable: true,
slot: 1,
}
: null,
]}
>
<svelte:fragment slot="name" let:row><ConstraintLabel {...row} /></svelte:fragment>
<svelte:fragment slot="0" let:row>{row?.columns.map(x => x.columnName).join(', ')}</svelte:fragment>
<svelte:fragment slot="1" let:row
><Link
onClick={e => {
e.stopPropagation();
setTableInfo(tbl => editorDeleteConstraint(tbl, row));
}}>Remove</Link
></svelte:fragment
>
</ObjectListControl>
<ObjectListControl
collection={indexes}
onAddNew={writable() && columns?.length > 0 ? addIndex : null}
title={`Indexes (${indexes?.length || 0})`}
emptyMessage={writable() ? 'No index defined' : null}
clickable={writable()}
on:clickrow={e => showModal(IndexEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
columns={[
{
fieldName: 'columns',
header: 'Columns',
slot: 0,
},
{
fieldName: 'unique',
header: 'Unique',
slot: 1,
},
writable()
? {
fieldName: 'actions',
sortable: true,
slot: 2,
}
: null,
]}
>
<svelte:fragment slot="name" let:row><ConstraintLabel {...row} /></svelte:fragment>
<svelte:fragment slot="0" let:row>{row?.columns.map(x => x.columnName).join(', ')}</svelte:fragment>
<svelte:fragment slot="1" let:row>{row?.isUnique ? 'YES' : 'NO'}</svelte:fragment>
<svelte:fragment slot="2" let:row
><Link
onClick={e => {
e.stopPropagation();
setTableInfo(tbl => editorDeleteConstraint(tbl, row));
}}>Remove</Link
></svelte:fragment
>
</ObjectListControl>
<ObjectListControl
collection={uniques}
onAddNew={writable() && columns?.length > 0 ? addUnique : null}
title={`Unique constraints (${uniques?.length || 0})`}
emptyMessage={writable() ? 'No unique defined' : null}
clickable={writable()}
on:clickrow={e => showModal(UniqueEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
columns={[
{
fieldName: 'columns',
header: 'Columns',
slot: 0,
},
writable()
? {
fieldName: 'actions',
sortable: true,
slot: 1,
}
: null,
]}
>
<svelte:fragment slot="name" let:row><ConstraintLabel {...row} /></svelte:fragment>
<svelte:fragment slot="0" let:row>{row?.columns.map(x => x.columnName).join(', ')}</svelte:fragment>
<svelte:fragment slot="1" let:row
><Link
onClick={e => {
e.stopPropagation();
setTableInfo(tbl => editorDeleteConstraint(tbl, row));
}}>Remove</Link
></svelte:fragment
>
</ObjectListControl>
<ForeignKeyObjectListControl
collection={foreignKeys}
onAddNew={writable() && columns?.length > 0 ? addForeignKey : null}
title={`Foreign keys (${foreignKeys?.length || 0})`}
emptyMessage={writable() ? 'No foreign key defined' : null}
clickable={writable()}
onRemove={row => setTableInfo(tbl => editorDeleteConstraint(tbl, row))}
on:clickrow={e => showModal(ForeignKeyEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo, dbInfo })}
/>
<ForeignKeyObjectListControl collection={dependencies} title="Dependencies" />
</div>
<style>
.wrapper {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: var(--theme-bg-0);
overflow: auto;
}
</style>