mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-24 00:16:00 +00:00
Merge branch 'master' into develop
This commit is contained in:
@@ -56,7 +56,7 @@
|
||||
id: 'dataGrid.cloneRows',
|
||||
category: 'Data grid',
|
||||
name: 'Clone rows',
|
||||
toolbarName: 'Clone',
|
||||
toolbarName: 'Clone row(s)',
|
||||
keyText: 'CtrlOrCommand+Shift+C',
|
||||
testEnabled: () => getCurrentDataGrid()?.getGrider()?.editable,
|
||||
onClick: () => getCurrentDataGrid().cloneRows(),
|
||||
|
||||
@@ -167,8 +167,8 @@
|
||||
async function detectSize(tables, domTables) {
|
||||
await tick();
|
||||
const rects = _.values(domTables).map(x => x.getRect());
|
||||
const maxX = _.max(rects.map(x => x.right));
|
||||
const maxY = _.max(rects.map(x => x.bottom));
|
||||
const maxX = rects.length > 0 ? _.max(rects.map(x => x.right)) : 0;
|
||||
const maxY = rects.length > 0 ? _.max(rects.map(x => x.bottom)) : 0;
|
||||
|
||||
canvasWidth = Math.max(3000, maxX + 50);
|
||||
canvasHeight = Math.max(3000, maxY + 50);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
mergeConditions,
|
||||
Source,
|
||||
ResultField,
|
||||
Expression,
|
||||
} from 'dbgate-sqltree';
|
||||
import { EngineDriver } from 'dbgate-types';
|
||||
import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
|
||||
@@ -78,25 +79,27 @@ export class DesignerQueryDumper {
|
||||
return select;
|
||||
}
|
||||
|
||||
addConditions(select: Select, tables: DesignerTableInfo[]) {
|
||||
buildConditionFromFilterField(tables: DesignerTableInfo[], filterField: string, getExpression?: Function): Condition {
|
||||
const conditions = [];
|
||||
|
||||
for (const column of this.designer.columns || []) {
|
||||
if (!column.filter) continue;
|
||||
const table = (this.designer.tables || []).find(x => x.designerId == column.designerId);
|
||||
if (!table) continue;
|
||||
if (!tables.find(x => x.designerId == table.designerId)) continue;
|
||||
if (!column[filterField]) continue;
|
||||
|
||||
if (!column.isCustomExpression) {
|
||||
const table = (this.designer.tables || []).find(x => x.designerId == column.designerId);
|
||||
if (!table) continue;
|
||||
if (!tables.find(x => x.designerId == table.designerId)) continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const condition = parseFilter(column.filter, findDesignerFilterType(column, this.designer));
|
||||
const condition = parseFilter(column[filterField], findDesignerFilterType(column, this.designer));
|
||||
if (condition) {
|
||||
select.where = mergeConditions(
|
||||
select.where,
|
||||
conditions.push(
|
||||
_.cloneDeepWith(condition, expr => {
|
||||
if (expr.exprType == 'placeholder')
|
||||
return {
|
||||
exprType: 'column',
|
||||
columnName: column.columnName,
|
||||
source: findQuerySource(this.designer, column.designerId),
|
||||
};
|
||||
if (expr.exprType == 'placeholder') {
|
||||
if (getExpression) return getExpression(column);
|
||||
return this.getColumnExpression(column);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -105,33 +108,79 @@ export class DesignerQueryDumper {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (conditions.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (conditions.length == 1) {
|
||||
return conditions[0];
|
||||
}
|
||||
|
||||
return {
|
||||
conditionType: 'and',
|
||||
conditions,
|
||||
};
|
||||
}
|
||||
|
||||
addConditionsCore(select: Select, tables: DesignerTableInfo[], filterFields, selectField, getExpression?) {
|
||||
const conditions: Condition[] = _.compact(
|
||||
filterFields.map(field => this.buildConditionFromFilterField(tables, field, getExpression))
|
||||
);
|
||||
|
||||
if (conditions.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (conditions.length == 0) {
|
||||
select[selectField] = mergeConditions(select[selectField], conditions[0]);
|
||||
return;
|
||||
}
|
||||
select[selectField] = mergeConditions(select[selectField], {
|
||||
conditionType: 'or',
|
||||
conditions,
|
||||
});
|
||||
}
|
||||
|
||||
addConditions(select: Select, tables: DesignerTableInfo[]) {
|
||||
const additionalFilterCount = this.designer.settings?.additionalFilterCount || 0;
|
||||
const filterFields = ['filter', ..._.range(additionalFilterCount).map(index => `additionalFilter${index + 1}`)];
|
||||
this.addConditionsCore(select, tables, filterFields, 'where');
|
||||
}
|
||||
|
||||
addGroupConditions(select: Select, tables: DesignerTableInfo[], selectIsGrouped: boolean) {
|
||||
for (const column of this.designer.columns || []) {
|
||||
if (!column.groupFilter) continue;
|
||||
const table = (this.designer.tables || []).find(x => x.designerId == column.designerId);
|
||||
if (!table) continue;
|
||||
if (!tables.find(x => x.designerId == table.designerId)) continue;
|
||||
|
||||
const condition = parseFilter(column.groupFilter, findDesignerFilterType(column, this.designer));
|
||||
if (condition) {
|
||||
select.having = mergeConditions(
|
||||
select.having,
|
||||
_.cloneDeepWith(condition, expr => {
|
||||
if (expr.exprType == 'placeholder') {
|
||||
return this.getColumnOutputExpression(column, selectIsGrouped);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
const additionalGroupFilterCount = this.designer.settings?.additionalGroupFilterCount || 0;
|
||||
const filterFields = [
|
||||
'groupFilter',
|
||||
..._.range(additionalGroupFilterCount).map(index => `additionalGroupFilter${index + 1}`),
|
||||
];
|
||||
this.addConditionsCore(select, tables, filterFields, 'having', column =>
|
||||
this.getColumnResultField(column, selectIsGrouped)
|
||||
);
|
||||
}
|
||||
|
||||
getColumnOutputExpression(col, selectIsGrouped): ResultField {
|
||||
getColumnExpression(col): Expression {
|
||||
const source = findQuerySource(this.designer, col.designerId);
|
||||
const { columnName, isCustomExpression, customExpression } = col;
|
||||
|
||||
const res: Expression = isCustomExpression
|
||||
? {
|
||||
exprType: 'raw',
|
||||
sql: customExpression,
|
||||
}
|
||||
: {
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
source,
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
getColumnResultField(col, selectIsGrouped): ResultField {
|
||||
const { columnName } = col;
|
||||
let { alias } = col;
|
||||
|
||||
const exprCore = this.getColumnExpression(col);
|
||||
|
||||
if (selectIsGrouped && !col.isGrouped) {
|
||||
// use aggregate
|
||||
const aggregate = col.aggregate == null || col.aggregate == '---' ? 'MAX' : col.aggregate;
|
||||
@@ -142,20 +191,12 @@ export class DesignerQueryDumper {
|
||||
func: aggregate == 'COUNT DISTINCT' ? 'COUNT' : aggregate,
|
||||
argsPrefix: aggregate == 'COUNT DISTINCT' ? 'DISTINCT' : null,
|
||||
alias,
|
||||
args: [
|
||||
{
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
source,
|
||||
},
|
||||
],
|
||||
args: [exprCore],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
exprType: 'column',
|
||||
columnName,
|
||||
...exprCore,
|
||||
alias,
|
||||
source,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -179,24 +220,21 @@ export class DesignerQueryDumper {
|
||||
}
|
||||
}
|
||||
|
||||
const topLevelColumns = (this.designer.columns || []).filter(col =>
|
||||
topLevelTables.find(tbl => tbl.designerId == col.designerId)
|
||||
const topLevelColumns = (this.designer.columns || []).filter(
|
||||
col =>
|
||||
topLevelTables.find(tbl => tbl.designerId == col.designerId) || (col.isCustomExpression && col.customExpression)
|
||||
);
|
||||
const selectIsGrouped = !!topLevelColumns.find(x => x.isGrouped || (x.aggregate && x.aggregate != '---'));
|
||||
const outputColumns = topLevelColumns.filter(x => x.isOutput);
|
||||
if (outputColumns.length == 0) {
|
||||
res.selectAll = true;
|
||||
} else {
|
||||
res.columns = outputColumns.map(col => this.getColumnOutputExpression(col, selectIsGrouped));
|
||||
res.columns = outputColumns.map(col => this.getColumnResultField(col, selectIsGrouped));
|
||||
}
|
||||
|
||||
const groupedColumns = topLevelColumns.filter(x => x.isGrouped);
|
||||
if (groupedColumns.length > 0) {
|
||||
res.groupBy = groupedColumns.map(col => ({
|
||||
exprType: 'column',
|
||||
columnName: col.columnName,
|
||||
source: findQuerySource(this.designer, col.designerId),
|
||||
}));
|
||||
res.groupBy = groupedColumns.map(col => this.getColumnExpression(col));
|
||||
}
|
||||
|
||||
const orderColumns = _.sortBy(
|
||||
@@ -205,10 +243,8 @@ export class DesignerQueryDumper {
|
||||
);
|
||||
if (orderColumns.length > 0) {
|
||||
res.orderBy = orderColumns.map(col => ({
|
||||
exprType: 'column',
|
||||
...this.getColumnExpression(col),
|
||||
direction: col.sortOrder < 0 ? 'DESC' : 'ASC',
|
||||
columnName: col.columnName,
|
||||
source: findQuerySource(this.designer, col.designerId),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,14 @@ export type DesignerColumnInfo = {
|
||||
sortOrder?: number;
|
||||
filter?: string;
|
||||
groupFilter?: string;
|
||||
isCustomExpression?: boolean;
|
||||
customExpression?: string;
|
||||
};
|
||||
|
||||
export type DesignerSettings = {
|
||||
isDistinct?: boolean;
|
||||
additionalFilterCount?: number;
|
||||
additionalGroupFilterCount?: number;
|
||||
};
|
||||
|
||||
export type DesignerInfo = {
|
||||
|
||||
@@ -13,8 +13,11 @@
|
||||
import SelectField from '../forms/SelectField.svelte';
|
||||
import TextField from '../forms/TextField.svelte';
|
||||
import InlineButton from '../buttons/InlineButton.svelte';
|
||||
import uuidv1 from 'uuid/v1';
|
||||
|
||||
import TableControl from './TableControl.svelte';
|
||||
import FormStyledButton from '../buttons/FormStyledButton.svelte';
|
||||
import _ from 'lodash';
|
||||
|
||||
export let value;
|
||||
export let onChange;
|
||||
@@ -35,8 +38,56 @@
|
||||
}));
|
||||
};
|
||||
|
||||
const addExpressionColumn = () => {
|
||||
onChange(current => ({
|
||||
...current,
|
||||
columns: [...(current.columns || []), { isCustomExpression: true, isOutput: true, designerId: uuidv1() }],
|
||||
}));
|
||||
};
|
||||
|
||||
const addOrCondition = () => {
|
||||
onChange(current => ({
|
||||
...current,
|
||||
settings: {
|
||||
...current?.settings,
|
||||
additionalFilterCount: (current?.settings?.additionalFilterCount ?? 0) + 1,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const removeOrCondition = () => {
|
||||
onChange(current => ({
|
||||
...current,
|
||||
settings: {
|
||||
...current?.settings,
|
||||
additionalFilterCount: (current?.settings?.additionalFilterCount ?? 1) - 1,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const addGroupOrCondition = () => {
|
||||
onChange(current => ({
|
||||
...current,
|
||||
settings: {
|
||||
...current?.settings,
|
||||
additionalGroupFilterCount: (current?.settings?.additionalGroupFilterCount ?? 0) + 1,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const removeGroupOrCondition = () => {
|
||||
onChange(current => ({
|
||||
...current,
|
||||
settings: {
|
||||
...current?.settings,
|
||||
additionalGroupFilterCount: (current?.settings?.additionalGroupFilterCount ?? 1) - 1,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
$: columns = value?.columns;
|
||||
$: tables = value?.tables;
|
||||
$: settings = value?.settings;
|
||||
$: hasGroupedColumn = !!(columns || []).find(x => x.isGrouped);
|
||||
</script>
|
||||
|
||||
@@ -44,18 +95,49 @@
|
||||
<TableControl
|
||||
rows={columns || []}
|
||||
columns={[
|
||||
{ fieldName: 'columnName', header: 'Column/Expression' },
|
||||
{ fieldName: 'columnName', slot: 8, 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: 'filter', header: 'Filter', slot: 5, props: { filterField: 'filter' } },
|
||||
..._.range(settings?.additionalFilterCount || 0).map(index => ({
|
||||
fieldName: `additionalFilter${index + 1}`,
|
||||
header: `OR Filter ${index + 2}`,
|
||||
slot: 5,
|
||||
props: { filterField: `additionalFilter${index + 1}` },
|
||||
})),
|
||||
hasGroupedColumn && {
|
||||
fieldName: 'groupFilter',
|
||||
header: 'Group filter',
|
||||
slot: 5,
|
||||
props: { filterField: 'groupFilter' },
|
||||
},
|
||||
..._.range(hasGroupedColumn ? settings?.additionalGroupFilterCount || 0 : 0).map(index => ({
|
||||
fieldName: `additionalGroupFilter${index + 1}`,
|
||||
header: `OR group filter ${index + 2}`,
|
||||
slot: 5,
|
||||
props: { filterField: `additionalGroupFilter${index + 1}` },
|
||||
})),
|
||||
{ fieldName: 'actions', header: '', slot: 7 },
|
||||
]}
|
||||
>
|
||||
<svelte:fragment slot="8" let:row>
|
||||
{#if row.isCustomExpression}
|
||||
<TextField
|
||||
style="min-width:calc(100% - 9px)"
|
||||
value={row.customExpression}
|
||||
on:input={e => {
|
||||
changeColumn({ ...row, customExpression: e.target.value });
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
{row.columnName}
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="0" let:row>
|
||||
<CheckboxField
|
||||
checked={row.isOutput}
|
||||
@@ -67,6 +149,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="1" let:row>
|
||||
<TextField
|
||||
style="min-width:calc(100% - 9px)"
|
||||
value={row.alias}
|
||||
on:input={e => {
|
||||
changeColumn({ ...row, alias: e.target.value });
|
||||
@@ -86,6 +169,7 @@
|
||||
{#if !row.isGrouped}
|
||||
<SelectField
|
||||
isNative
|
||||
style="min-width:calc(100% - 9px)"
|
||||
value={row.aggregate}
|
||||
on:change={e => {
|
||||
changeColumn({ ...row, aggregate: e.detail });
|
||||
@@ -97,6 +181,7 @@
|
||||
<svelte:fragment slot="4" let:row>
|
||||
<SelectField
|
||||
isNative
|
||||
style="min-width:calc(100% - 9px)"
|
||||
value={row.sortOrder}
|
||||
on:change={e => {
|
||||
changeColumn({ ...row, sortOrder: parseInt(e.detail) });
|
||||
@@ -112,21 +197,12 @@
|
||||
]}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="5" let:row>
|
||||
<svelte:fragment slot="5" let:row let:filterField>
|
||||
<DataFilterControl
|
||||
filterType={findDesignerFilterType(row, value)}
|
||||
filter={row.filter}
|
||||
filter={row[filterField]}
|
||||
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 });
|
||||
changeColumn({ ...row, [filterField]: filter });
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
@@ -134,6 +210,17 @@
|
||||
<InlineButton on:click={() => removeColumn(row)}>Remove</InlineButton>
|
||||
</svelte:fragment>
|
||||
</TableControl>
|
||||
<FormStyledButton value="Add custom expression" on:click={addExpressionColumn} style="width:200px" />
|
||||
<FormStyledButton value="Add OR condition" on:click={addOrCondition} style="width:200px" />
|
||||
{#if settings?.additionalFilterCount > 0}
|
||||
<FormStyledButton value="Remove OR condition" on:click={removeOrCondition} style="width:200px" />
|
||||
{/if}
|
||||
{#if hasGroupedColumn}
|
||||
<FormStyledButton value="Add group OR condition" on:click={addGroupOrCondition} style="width:200px" />
|
||||
{/if}
|
||||
{#if hasGroupedColumn && settings?.additionalGroupFilterCount > 0}
|
||||
<FormStyledButton value="Remove group OR condition" on:click={removeGroupOrCondition} style="width:200px" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -141,4 +228,4 @@
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
header: string;
|
||||
component?: any;
|
||||
getProps?: any;
|
||||
props?: any;
|
||||
formatter?: any;
|
||||
slot?: number;
|
||||
isHighlighted?: Function;
|
||||
@@ -25,6 +26,7 @@
|
||||
export let clickable = false;
|
||||
export let disableFocusOutline = false;
|
||||
export let emptyMessage = null;
|
||||
export let noCellPadding = false;
|
||||
|
||||
export let domTable = undefined;
|
||||
|
||||
@@ -77,21 +79,24 @@
|
||||
}}
|
||||
>
|
||||
{#each columnList as col}
|
||||
<td class:isHighlighted={col.isHighlighted && col.isHighlighted(row)}>
|
||||
{@const rowProps = { ...col.props, ...(col.getProps ? col.getProps(row) : null) }}
|
||||
<td class:isHighlighted={col.isHighlighted && col.isHighlighted(row)} class:noCellPadding>
|
||||
{#if col.component}
|
||||
<svelte:component this={col.component} {...col.getProps(row)} />
|
||||
<svelte:component this={col.component} {...rowProps} />
|
||||
{:else if col.formatter}
|
||||
{col.formatter(row)}
|
||||
{:else if col.slot != null}
|
||||
{#if col.slot == -1}<slot name="-1" {row} {index} />
|
||||
{:else if col.slot == 0}<slot name="0" {row} {index} />
|
||||
{:else if col.slot == 1}<slot name="1" {row} {index} />
|
||||
{:else if col.slot == 2}<slot name="2" {row} {index} />
|
||||
{:else if col.slot == 3}<slot name="3" {row} {index} />
|
||||
{:else if col.slot == 4}<slot name="4" {row} {index} />
|
||||
{:else if col.slot == 5}<slot name="5" {row} {index} />
|
||||
{:else if col.slot == 6}<slot name="6" {row} {index} />
|
||||
{:else if col.slot == 7}<slot name="7" {row} {index} />
|
||||
{:else if col.slot == 0}<slot name="0" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 1}<slot name="1" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 2}<slot name="2" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 3}<slot name="3" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 4}<slot name="4" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 5}<slot name="5" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 6}<slot name="6" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 7}<slot name="7" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 8}<slot name="8" {row} {index} {...rowProps} />
|
||||
{:else if col.slot == 9}<slot name="9" {row} {index} {...rowProps} />
|
||||
{/if}
|
||||
{:else}
|
||||
{row[col.fieldName] || ''}
|
||||
@@ -136,6 +141,9 @@
|
||||
}
|
||||
tbody td {
|
||||
border: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
tbody td:not(.noCellPadding) {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,13 @@
|
||||
import 'ace-builds/src-noconflict/theme-tomorrow_night';
|
||||
import 'ace-builds/src-noconflict/theme-twilight';
|
||||
|
||||
import { currentDropDownMenu, currentEditorFontSize, currentEditorTheme, currentThemeDefinition } from '../stores';
|
||||
import {
|
||||
currentDropDownMenu,
|
||||
currentEditorFontSize,
|
||||
currentEditorFont,
|
||||
currentEditorTheme,
|
||||
currentThemeDefinition,
|
||||
} from '../stores';
|
||||
import _ from 'lodash';
|
||||
import { handleCommandKeyDown } from '../commands/CommandListener.svelte';
|
||||
import resizeObserver from '../utility/resizeObserver';
|
||||
@@ -223,12 +229,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: watchOptions(options);
|
||||
function watchOptions(newOption: any) {
|
||||
$: watchOptions(options, $currentEditorFont);
|
||||
function watchOptions(newOption: any, fontFamily) {
|
||||
if (editor) {
|
||||
editor.setOptions({
|
||||
...stdOptions,
|
||||
...newOption,
|
||||
fontFamily: fontFamily || 'Menlo, Monaco, Ubuntu Mono, Consolas, source-code-pro, monospace',
|
||||
// fontFamily: 'tahoma,Menlo',
|
||||
// fontSize: '10pt',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,10 @@
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if driver?.showConnectionField('windowsDomain', $values)}
|
||||
<FormTextField label="Domain (specify to use NTLM authentication)" name="windowsDomain" disabled={isConnected} />
|
||||
{/if}
|
||||
|
||||
{#if driver?.showConnectionField('isReadOnly', $values)}
|
||||
<FormCheckboxField label="Is read only" name="isReadOnly" disabled={isConnected} />
|
||||
{/if}
|
||||
|
||||
@@ -127,7 +127,7 @@ ORDER BY
|
||||
<div class="heading">Editor theme</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="col-6">
|
||||
<div class="col-4">
|
||||
<FormFieldTemplateLarge label="Theme" type="combo">
|
||||
<SelectField
|
||||
isNative
|
||||
@@ -139,7 +139,7 @@ ORDER BY
|
||||
</FormFieldTemplateLarge>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="col-4">
|
||||
<FormFieldTemplateLarge label="Font size " type="combo">
|
||||
<SelectField
|
||||
isNative
|
||||
@@ -150,6 +150,10 @@ ORDER BY
|
||||
/>
|
||||
</FormFieldTemplateLarge>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<FormTextField name="editor.fontFamily" label="Editor font family" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor">
|
||||
|
||||
@@ -68,6 +68,7 @@ export const currentEditorTheme = getElectron()
|
||||
export const currentEditorFontSize = getElectron()
|
||||
? writableSettingsValue(null, 'currentEditorFontSize')
|
||||
: writableWithStorage(null, 'currentEditorFontSize');
|
||||
export const currentEditorFont = writableSettingsValue(null, 'editor.fontFamily');
|
||||
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
||||
export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected));
|
||||
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
||||
|
||||
Reference in New Issue
Block a user