mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-01 00:23:57 +00:00
query design columns
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
export let targetDragColumn$;
|
export let targetDragColumn$;
|
||||||
export let onCreateReference;
|
export let onCreateReference;
|
||||||
export let onAddReferenceByColumn;
|
export let onAddReferenceByColumn;
|
||||||
|
export let onSelectColumn;
|
||||||
|
|
||||||
$: designerColumn = (designer.columns || []).find(
|
$: designerColumn = (designer.columns || []).find(
|
||||||
x => x.designerId == designerId && x.columnName == column.columnName
|
x => x.designerId == designerId && x.columnName == column.columnName
|
||||||
@@ -84,13 +85,18 @@
|
|||||||
class:isDragTarget={$targetDragColumn$ &&
|
class:isDragTarget={$targetDragColumn$ &&
|
||||||
$targetDragColumn$.designerId == designerId &&
|
$targetDragColumn$.designerId == designerId &&
|
||||||
$targetDragColumn$.columnName == column.columnName}
|
$targetDragColumn$.columnName == column.columnName}
|
||||||
|
on:mousedown={e =>
|
||||||
|
onSelectColumn({
|
||||||
|
...column,
|
||||||
|
designerId,
|
||||||
|
})}
|
||||||
use:contextMenu={createMenu}
|
use:contextMenu={createMenu}
|
||||||
>
|
>
|
||||||
<CheckboxField
|
<CheckboxField
|
||||||
checked={!!(designer.columns || []).find(
|
checked={!!(designer.columns || []).find(
|
||||||
x => x.designerId == designerId && x.columnName == column.columnName && x.isOutput
|
x => x.designerId == designerId && x.columnName == column.columnName && x.isOutput
|
||||||
)}
|
)}
|
||||||
onChange={e => {
|
on:change={e => {
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
onChangeColumn(
|
onChangeColumn(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
export let targetDragColumn$;
|
export let targetDragColumn$;
|
||||||
|
|
||||||
export let domCanvas;
|
export let domCanvas;
|
||||||
export let domTablesRef;
|
// export let domTablesRef;
|
||||||
export let designer;
|
export let designer;
|
||||||
export let onMoveReferences;
|
export let onMoveReferences;
|
||||||
|
|
||||||
@@ -104,6 +104,7 @@
|
|||||||
class="wrapper"
|
class="wrapper"
|
||||||
style={`left: ${movingPosition ? movingPosition.left : left}px; top:${movingPosition ? movingPosition.top : top}px`}
|
style={`left: ${movingPosition ? movingPosition.left : left}px; top:${movingPosition ? movingPosition.top : top}px`}
|
||||||
bind:this={domWrapper}
|
bind:this={domWrapper}
|
||||||
|
on:mousedown={() => onBringToFront(table)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="header"
|
class="header"
|
||||||
@@ -125,6 +126,7 @@
|
|||||||
{designer}
|
{designer}
|
||||||
{designerId}
|
{designerId}
|
||||||
{onChangeColumn}
|
{onChangeColumn}
|
||||||
|
{onSelectColumn}
|
||||||
{sourceDragColumn$}
|
{sourceDragColumn$}
|
||||||
{targetDragColumn$}
|
{targetDragColumn$}
|
||||||
{onCreateReference}
|
{onCreateReference}
|
||||||
|
|||||||
136
packages/web/src/elements/QueryDesignColumns.svelte
Normal file
136
packages/web/src/elements/QueryDesignColumns.svelte
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
function getTableDisplayName(column, tables) {
|
||||||
|
const table = (tables || []).find(x => x.designerId == column.designerId);
|
||||||
|
if (table) return table.alias || table.pureName;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { map } from 'lodash';
|
||||||
|
import DataFilterControl from '../datagrid/DataFilterControl.svelte';
|
||||||
|
import { findDesignerFilterType } from '../designer/designerTools';
|
||||||
|
import CheckboxField from '../forms/CheckboxField.svelte';
|
||||||
|
import SelectField from '../forms/SelectField.svelte';
|
||||||
|
import TextField from '../forms/TextField.svelte';
|
||||||
|
import InlineButton from './InlineButton.svelte';
|
||||||
|
|
||||||
|
import TableControl from './TableControl.svelte';
|
||||||
|
|
||||||
|
export let value;
|
||||||
|
export let onChange;
|
||||||
|
|
||||||
|
const changeColumn = col => {
|
||||||
|
onChange(current => ({
|
||||||
|
...current,
|
||||||
|
columns: (current.columns || []).map(x =>
|
||||||
|
x.designerId == col.designerId && x.columnName == col.columnName ? col : x
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeColumn = col => {
|
||||||
|
onChange(current => ({
|
||||||
|
...current,
|
||||||
|
columns: (current.columns || []).filter(x => x.designerId != col.designerId || x.columnName != col.columnName),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
$: columns = value?.columns;
|
||||||
|
$: tables = value?.tables;
|
||||||
|
$: hasGroupedColumn = !!(columns || []).find(x => x.isGrouped);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<TableControl
|
||||||
|
rows={columns || []}
|
||||||
|
columns={[
|
||||||
|
{ fieldName: 'columnName', header: 'Column/Expression' },
|
||||||
|
{ fieldName: 'tableDisplayName', header: 'Table', formatter: row => getTableDisplayName(row, tables) },
|
||||||
|
{ fieldName: 'isOutput', header: 'Output', slot: 0 },
|
||||||
|
{ fieldName: 'alias', header: 'Alias', slot: 1 },
|
||||||
|
{ fieldName: 'isGrouped', header: 'Group by', slot: 2 },
|
||||||
|
{ fieldName: 'aggregate', header: 'Aggregate', slot: 3 },
|
||||||
|
{ fieldName: 'sortOrder', header: 'Sort order', slot: 4 },
|
||||||
|
{ fieldName: 'filter', header: 'Filter', slot: 5 },
|
||||||
|
hasGroupedColumn && { fieldName: 'groupFilter', header: 'Group filter', slot: 6 },
|
||||||
|
{ fieldName: 'actions', header: '', slot: 7 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="0" let:row>
|
||||||
|
<CheckboxField
|
||||||
|
checked={row.isOutput}
|
||||||
|
onChange={e => {
|
||||||
|
if (e.target.checked) changeColumn({ ...row, isOutput: true });
|
||||||
|
else changeColumn({ ...row, isOutput: false });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="1" let:row>
|
||||||
|
<TextField
|
||||||
|
value={row.alias}
|
||||||
|
on:input={e => {
|
||||||
|
changeColumn({ ...row, alias: e.target.value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="2" let:row>
|
||||||
|
<CheckboxField
|
||||||
|
checked={row.isGrouped}
|
||||||
|
on:change={e => {
|
||||||
|
if (e.target.checked) changeColumn({ ...row, isGrouped: true });
|
||||||
|
else changeColumn({ ...row, isGrouped: false });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="3" let:row>
|
||||||
|
{#if !row.isGrouped}
|
||||||
|
<SelectField
|
||||||
|
isNative
|
||||||
|
value={row.aggregate}
|
||||||
|
on:change={e => {
|
||||||
|
changeColumn({ ...row, aggregate: e.detail });
|
||||||
|
}}
|
||||||
|
options={['---', 'MIN', 'MAX', 'COUNT', 'COUNT DISTINCT', 'SUM', 'AVG'].map(x => ({ label: x, value: x }))}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="4" let:row>
|
||||||
|
<SelectField
|
||||||
|
isNative
|
||||||
|
value={row.sortOrder}
|
||||||
|
on:change={e => {
|
||||||
|
changeColumn({ ...row, sortOrder: parseInt(e.detail) });
|
||||||
|
}}
|
||||||
|
options={[
|
||||||
|
{ label: '---', value: '0' },
|
||||||
|
{ label: '1st, ascending', value: '1' },
|
||||||
|
{ label: '1st, descending', value: '-1' },
|
||||||
|
{ label: '2nd, ascending', value: '2' },
|
||||||
|
{ label: '2nd, descending', value: '-2' },
|
||||||
|
{ label: '3rd, ascending', value: '3' },
|
||||||
|
{ label: '3rd, descending', value: '-3' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="5" let:row>
|
||||||
|
<DataFilterControl
|
||||||
|
filterType={findDesignerFilterType(row, value)}
|
||||||
|
filter={row.filter}
|
||||||
|
setFilter={filter => {
|
||||||
|
changeColumn({ ...row, filter });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="6" let:row>
|
||||||
|
<DataFilterControl
|
||||||
|
filterType={findDesignerFilterType(row, value)}
|
||||||
|
filter={row.groupFilter}
|
||||||
|
setFilter={groupFilter => {
|
||||||
|
changeColumn({ ...row, groupFilter });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="7" let:row>
|
||||||
|
<InlineButton on:click={() => removeColumn(row)}>Remove</InlineButton>
|
||||||
|
</svelte:fragment>
|
||||||
|
</TableControl>
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
interface TabDef {
|
interface TabDef {
|
||||||
label: string;
|
label: string;
|
||||||
slot?: number;
|
slot?: number;
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
{#each tabs as tab, index}
|
{#each _.compact(tabs) as tab, index}
|
||||||
<div class="tab-item" class:selected={value == index} on:click={() => (value = index)}>
|
<div class="tab-item" class:selected={value == index} on:click={() => (value = index)}>
|
||||||
<span class="ml-2">
|
<span class="ml-2">
|
||||||
{tab.label}
|
{tab.label}
|
||||||
@@ -30,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
{#each tabs as tab, index}
|
{#each _.compact(tabs) as tab, index}
|
||||||
<div class="container" class:isInline class:tabVisible={index == value}>
|
<div class="container" class:isInline class:tabVisible={index == value}>
|
||||||
<svelte:component this={tab.component} {...tab.props} />
|
<svelte:component this={tab.component} {...tab.props} />
|
||||||
{#if tab.slot != null}
|
{#if tab.slot != null}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@
|
|||||||
import createReducer from '../utility/createReducer';
|
import createReducer from '../utility/createReducer';
|
||||||
import createUndoReducer from '../utility/createUndoReducer';
|
import createUndoReducer from '../utility/createUndoReducer';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { findEngineDriver } from 'dbgate-tools';
|
||||||
|
import { generateDesignedQuery } from '../designer/designerTools';
|
||||||
|
import QueryDesignColumns from '../elements/QueryDesignColumns.svelte';
|
||||||
|
|
||||||
export let tabid;
|
export let tabid;
|
||||||
export let conid;
|
export let conid;
|
||||||
@@ -60,6 +63,7 @@
|
|||||||
let domEditor;
|
let domEditor;
|
||||||
|
|
||||||
$: connection = useConnectionInfo({ conid });
|
$: connection = useConnectionInfo({ conid });
|
||||||
|
$: engine = findEngineDriver($connection, $extensions);
|
||||||
|
|
||||||
$: effect = useEffect(() => {
|
$: effect = useEffect(() => {
|
||||||
return onSession(sessionId);
|
return onSession(sessionId);
|
||||||
@@ -85,6 +89,10 @@
|
|||||||
invalidateCommands();
|
invalidateCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: setEditorData($modelState.value);
|
||||||
|
|
||||||
|
$: generatePreview($modelState.value, engine);
|
||||||
|
|
||||||
export function canKill() {
|
export function canKill() {
|
||||||
return !!sessionId;
|
return !!sessionId;
|
||||||
}
|
}
|
||||||
@@ -132,6 +140,12 @@
|
|||||||
return $editorState.value || '';
|
return $editorState.value || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generatePreview = (value, engine) => {
|
||||||
|
if (!engine || !value) return;
|
||||||
|
const sql = generateDesignedQuery(value, engine);
|
||||||
|
sqlPreview = sqlFormatter.format(sql);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSessionDone = () => {
|
const handleSessionDone = () => {
|
||||||
busy = false;
|
busy = false;
|
||||||
// timerLabel.stop();
|
// timerLabel.stop();
|
||||||
@@ -152,8 +166,6 @@
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
$: setEditorData($modelState.value);
|
|
||||||
|
|
||||||
const [modelState, dispatchModel] = createUndoReducer({
|
const [modelState, dispatchModel] = createUndoReducer({
|
||||||
tables: [],
|
tables: [],
|
||||||
references: [],
|
references: [],
|
||||||
@@ -169,21 +181,50 @@
|
|||||||
// )}
|
// )}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<QueryDesigner
|
|
||||||
value={$modelState.value || {}}
|
|
||||||
{conid}
|
|
||||||
{database}
|
|
||||||
engine={$connection && $connection.engine}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<!--
|
|
||||||
<VerticalSplitter initialValue="70%">
|
<VerticalSplitter initialValue="70%">
|
||||||
<ResultTabs {sessionId} {executeNumber}>
|
<svelte:fragment slot="1">
|
||||||
<TabPage label="Columns" key="columns">
|
<QueryDesigner
|
||||||
<QueryDesignColumns value={modelState.value || {}} onChange={handleChange} />
|
value={$modelState.value || {}}
|
||||||
</TabPage>
|
{conid}
|
||||||
<TabPage label="SQL" key="sql">
|
{database}
|
||||||
<SqlEditor value={sqlPreview} {engine} readOnly />
|
engine={$connection && $connection.engine}
|
||||||
</TabPage>
|
onChange={handleChange}
|
||||||
</ResultTabs>
|
/>
|
||||||
</VerticalSplitter> -->
|
</svelte:fragment>
|
||||||
|
|
||||||
|
<svelte:fragment slot="2">
|
||||||
|
<ResultTabs
|
||||||
|
tabs={[
|
||||||
|
{
|
||||||
|
label: 'Columns',
|
||||||
|
component: QueryDesignColumns,
|
||||||
|
props: {
|
||||||
|
value: $modelState.value || {},
|
||||||
|
onChange: handleChange,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'SQL',
|
||||||
|
component: SqlEditor,
|
||||||
|
props: {
|
||||||
|
engine: $connection && $connection.engine,
|
||||||
|
readOnly: true,
|
||||||
|
value: sqlPreview,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
visibleResultTabs && { label: 'Messages', slot: 0 },
|
||||||
|
]}
|
||||||
|
{sessionId}
|
||||||
|
{executeNumber}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="0">
|
||||||
|
<SocketMessageView
|
||||||
|
eventName={sessionId ? `session-info-${sessionId}` : null}
|
||||||
|
{executeNumber}
|
||||||
|
showProcedure
|
||||||
|
showLine
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
</ResultTabs>
|
||||||
|
</svelte:fragment>
|
||||||
|
</VerticalSplitter>
|
||||||
|
|||||||
Reference in New Issue
Block a user