mirror of
https://github.com/Fabio286/antares.git
synced 2025-02-15 03:00:41 +01:00
feat(MySQL): check constraints management support
This commit is contained in:
parent
f083a8a185
commit
6365e07534
@ -55,6 +55,7 @@ export const defaults: Customizations = {
|
|||||||
tableArray: false,
|
tableArray: false,
|
||||||
tableRealCount: false,
|
tableRealCount: false,
|
||||||
tableDuplicate: false,
|
tableDuplicate: false,
|
||||||
|
tableCheck: false,
|
||||||
viewSettings: false,
|
viewSettings: false,
|
||||||
triggerSettings: false,
|
triggerSettings: false,
|
||||||
triggerFunctionSettings: false,
|
triggerFunctionSettings: false,
|
||||||
|
@ -47,6 +47,7 @@ export const customizations: Customizations = {
|
|||||||
tableTruncateDisableFKCheck: true,
|
tableTruncateDisableFKCheck: true,
|
||||||
tableDuplicate: true,
|
tableDuplicate: true,
|
||||||
tableDdl: true,
|
tableDdl: true,
|
||||||
|
tableCheck: true,
|
||||||
viewAdd: true,
|
viewAdd: true,
|
||||||
triggerAdd: true,
|
triggerAdd: true,
|
||||||
routineAdd: true,
|
routineAdd: true,
|
||||||
|
@ -159,6 +159,13 @@ export interface TableForeign {
|
|||||||
oldName?: string;
|
oldName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TableCheck {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
_antares_id?: string;
|
||||||
|
name: string;
|
||||||
|
clause: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateTableParams {
|
export interface CreateTableParams {
|
||||||
/** Connection UID */
|
/** Connection UID */
|
||||||
uid?: string;
|
uid?: string;
|
||||||
@ -166,6 +173,7 @@ export interface CreateTableParams {
|
|||||||
fields: TableField[];
|
fields: TableField[];
|
||||||
foreigns: TableForeign[];
|
foreigns: TableForeign[];
|
||||||
indexes: TableIndex[];
|
indexes: TableIndex[];
|
||||||
|
checks: TableCheck[];
|
||||||
options: TableOptions;
|
options: TableOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +201,11 @@ export interface AlterTableParams {
|
|||||||
changes: TableForeign[];
|
changes: TableForeign[];
|
||||||
deletions: TableForeign[];
|
deletions: TableForeign[];
|
||||||
};
|
};
|
||||||
|
checkChanges: {
|
||||||
|
additions: TableCheck[];
|
||||||
|
changes: TableCheck[];
|
||||||
|
deletions: TableCheck[];
|
||||||
|
};
|
||||||
options: TableOptions;
|
options: TableOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ export interface Customizations {
|
|||||||
tableArray?: boolean;
|
tableArray?: boolean;
|
||||||
tableRealCount?: boolean;
|
tableRealCount?: boolean;
|
||||||
tableTruncateDisableFKCheck?: boolean;
|
tableTruncateDisableFKCheck?: boolean;
|
||||||
|
tableCheck?: boolean;
|
||||||
tableDdl?: boolean;
|
tableDdl?: boolean;
|
||||||
viewAdd?: boolean;
|
viewAdd?: boolean;
|
||||||
viewSettings?: boolean;
|
viewSettings?: boolean;
|
||||||
|
@ -87,6 +87,19 @@ export default (connections: Record<string, antares.Client>) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('get-table-checks', async (event, params) => {
|
||||||
|
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await connections[params.uid].getTableChecks(params);
|
||||||
|
|
||||||
|
return { status: 'success', response: result };
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return { status: 'error', response: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-table-ddl', async (event, params) => {
|
ipcMain.handle('get-table-ddl', async (event, params) => {
|
||||||
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
|
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
|
||||||
|
|
||||||
|
@ -189,6 +189,10 @@ export abstract class BaseClient {
|
|||||||
throw new Error('Method "dropSchema" not implemented');
|
throw new Error('Method "dropSchema" not implemented');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTableChecks (...args: any) {
|
||||||
|
throw new Error('Method "getTableDll" not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
getTableDll (...args: any) {
|
getTableDll (...args: any) {
|
||||||
throw new Error('Method "getTableDll" not implemented');
|
throw new Error('Method "getTableDll" not implemented');
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,8 @@ export class MySQLClient extends BaseClient {
|
|||||||
|
|
||||||
this._ssh = new SSH2Promise({
|
this._ssh = new SSH2Promise({
|
||||||
...this._params.ssh,
|
...this._params.ssh,
|
||||||
|
reconnect: true,
|
||||||
|
reconnectTries: 3,
|
||||||
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
|
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -689,6 +691,34 @@ export class MySQLClient extends BaseClient {
|
|||||||
return rows.length ? rows[0].count : 0;
|
return rows.length ? rows[0].count : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTableChecks ({ schema, table }: { schema: string; table: string }): Promise<antares.TableCheck[]> {
|
||||||
|
const { rows } = await this.raw(`
|
||||||
|
SELECT
|
||||||
|
CONSTRAINT_NAME as name,
|
||||||
|
CHECK_CLAUSE as clausole
|
||||||
|
FROM information_schema.CHECK_CONSTRAINTS
|
||||||
|
WHERE CONSTRAINT_SCHEMA = "${schema}"
|
||||||
|
AND CONSTRAINT_NAME IN (
|
||||||
|
SELECT
|
||||||
|
CONSTRAINT_NAME
|
||||||
|
FROM
|
||||||
|
information_schema.TABLE_CONSTRAINTS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = "${schema}"
|
||||||
|
AND TABLE_NAME = "${table}"
|
||||||
|
AND CONSTRAINT_TYPE = 'CHECK'
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (rows.length) {
|
||||||
|
return rows.map(row => ({
|
||||||
|
name: row.name,
|
||||||
|
clause: row.clausole
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
async getTableOptions ({ schema, table }: { schema: string; table: string }) {
|
async getTableOptions ({ schema, table }: { schema: string; table: string }) {
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
interface TableOptionsResult {
|
interface TableOptionsResult {
|
||||||
@ -865,11 +895,13 @@ export class MySQLClient extends BaseClient {
|
|||||||
fields,
|
fields,
|
||||||
foreigns,
|
foreigns,
|
||||||
indexes,
|
indexes,
|
||||||
|
checks,
|
||||||
options
|
options
|
||||||
} = params;
|
} = params;
|
||||||
const newColumns: string[] = [];
|
const newColumns: string[] = [];
|
||||||
const newIndexes: string[] = [];
|
const newIndexes: string[] = [];
|
||||||
const newForeigns: string[] = [];
|
const newForeigns: string[] = [];
|
||||||
|
const newChecks: string[] = [];
|
||||||
|
|
||||||
let sql = `CREATE TABLE \`${schema}\`.\`${options.name}\``;
|
let sql = `CREATE TABLE \`${schema}\`.\`${options.name}\``;
|
||||||
|
|
||||||
@ -910,7 +942,13 @@ export class MySQLClient extends BaseClient {
|
|||||||
newForeigns.push(`CONSTRAINT \`${foreign.constraintName}\` FOREIGN KEY (\`${foreign.field}\`) REFERENCES \`${foreign.refTable}\` (\`${foreign.refField}\`) ON UPDATE ${foreign.onUpdate} ON DELETE ${foreign.onDelete}`);
|
newForeigns.push(`CONSTRAINT \`${foreign.constraintName}\` FOREIGN KEY (\`${foreign.field}\`) REFERENCES \`${foreign.refTable}\` (\`${foreign.refField}\`) ON UPDATE ${foreign.onUpdate} ON DELETE ${foreign.onDelete}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns].join(', ')}) COMMENT='${options.comment}', COLLATE='${options.collation}', ENGINE=${options.engine}`;
|
// ADD TABLE CHECKS
|
||||||
|
checks.forEach(check => {
|
||||||
|
if (!check.clause.trim().length) return;
|
||||||
|
newChecks.push(`${check.name ? `CONSTRAINT \`${check.name}\` ` : ''}CHECK (${check.clause})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns, ...newChecks].join(', ')}) COMMENT='${options.comment}', COLLATE='${options.collation}', ENGINE=${options.engine}`;
|
||||||
|
|
||||||
return await this.raw(sql);
|
return await this.raw(sql);
|
||||||
}
|
}
|
||||||
@ -924,6 +962,7 @@ export class MySQLClient extends BaseClient {
|
|||||||
changes,
|
changes,
|
||||||
indexChanges,
|
indexChanges,
|
||||||
foreignChanges,
|
foreignChanges,
|
||||||
|
checkChanges,
|
||||||
options
|
options
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
@ -931,6 +970,7 @@ export class MySQLClient extends BaseClient {
|
|||||||
const alterColumnsAdd: string[] = [];
|
const alterColumnsAdd: string[] = [];
|
||||||
const alterColumnsChange: string[] = [];
|
const alterColumnsChange: string[] = [];
|
||||||
const alterColumnsDrop: string[] = [];
|
const alterColumnsDrop: string[] = [];
|
||||||
|
const alterQueryes: string[] = [];
|
||||||
|
|
||||||
// OPTIONS
|
// OPTIONS
|
||||||
if ('comment' in options) alterColumnsChange.push(`COMMENT='${options.comment}'`);
|
if ('comment' in options) alterColumnsChange.push(`COMMENT='${options.comment}'`);
|
||||||
@ -976,6 +1016,12 @@ export class MySQLClient extends BaseClient {
|
|||||||
alterColumnsAdd.push(`ADD CONSTRAINT \`${addition.constraintName}\` FOREIGN KEY (\`${addition.field}\`) REFERENCES \`${addition.refTable}\` (\`${addition.refField}\`) ON UPDATE ${addition.onUpdate} ON DELETE ${addition.onDelete}`);
|
alterColumnsAdd.push(`ADD CONSTRAINT \`${addition.constraintName}\` FOREIGN KEY (\`${addition.field}\`) REFERENCES \`${addition.refTable}\` (\`${addition.refField}\`) ON UPDATE ${addition.onUpdate} ON DELETE ${addition.onDelete}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ADD TABLE CHECKS
|
||||||
|
checkChanges.additions.forEach(addition => {
|
||||||
|
if (!addition.clause.trim().length) return;
|
||||||
|
alterColumnsAdd.push(`ADD ${addition.name ? `CONSTRAINT \`${addition.name}\` ` : ''}CHECK (${addition.clause})`);
|
||||||
|
});
|
||||||
|
|
||||||
// CHANGE FIELDS
|
// CHANGE FIELDS
|
||||||
changes.forEach(change => {
|
changes.forEach(change => {
|
||||||
const typeInfo = this.getTypeInfo(change.type);
|
const typeInfo = this.getTypeInfo(change.type);
|
||||||
@ -987,9 +1033,9 @@ export class MySQLClient extends BaseClient {
|
|||||||
${change.zerofill ? 'ZEROFILL' : ''}
|
${change.zerofill ? 'ZEROFILL' : ''}
|
||||||
${change.nullable ? 'NULL' : 'NOT NULL'}
|
${change.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
${change.autoIncrement ? 'AUTO_INCREMENT' : ''}
|
${change.autoIncrement ? 'AUTO_INCREMENT' : ''}
|
||||||
|
${change.collation ? `COLLATE ${change.collation}` : ''}
|
||||||
${change.default !== null ? `DEFAULT ${change.default || '\'\''}` : ''}
|
${change.default !== null ? `DEFAULT ${change.default || '\'\''}` : ''}
|
||||||
${change.comment ? `COMMENT '${change.comment}'` : ''}
|
${change.comment ? `COMMENT '${change.comment}'` : ''}
|
||||||
${change.collation ? `COLLATE ${change.collation}` : ''}
|
|
||||||
${change.onUpdate ? `ON UPDATE ${change.onUpdate}` : ''}
|
${change.onUpdate ? `ON UPDATE ${change.onUpdate}` : ''}
|
||||||
${change.after ? `AFTER \`${change.after}\`` : 'FIRST'}`);
|
${change.after ? `AFTER \`${change.after}\`` : 'FIRST'}`);
|
||||||
});
|
});
|
||||||
@ -1020,6 +1066,13 @@ export class MySQLClient extends BaseClient {
|
|||||||
alterColumnsChange.push(`ADD CONSTRAINT \`${change.constraintName}\` FOREIGN KEY (\`${change.field}\`) REFERENCES \`${change.refTable}\` (\`${change.refField}\`) ON UPDATE ${change.onUpdate} ON DELETE ${change.onDelete}`);
|
alterColumnsChange.push(`ADD CONSTRAINT \`${change.constraintName}\` FOREIGN KEY (\`${change.field}\`) REFERENCES \`${change.refTable}\` (\`${change.refField}\`) ON UPDATE ${change.onUpdate} ON DELETE ${change.onDelete}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// CHANGE CHECK TABLE
|
||||||
|
checkChanges.changes.forEach(change => {
|
||||||
|
if (!change.clause.trim().length) return;
|
||||||
|
alterQueryes.push(`${sql} DROP CONSTRAINT \`${change.name}\``);
|
||||||
|
alterQueryes.push(`${sql} ADD ${change.name ? `CONSTRAINT \`${change.name}\` ` : ''}CHECK (${change.clause})`);
|
||||||
|
});
|
||||||
|
|
||||||
// DROP FIELDS
|
// DROP FIELDS
|
||||||
deletions.forEach(deletion => {
|
deletions.forEach(deletion => {
|
||||||
alterColumnsDrop.push(`DROP COLUMN \`${deletion.name}\``);
|
alterColumnsDrop.push(`DROP COLUMN \`${deletion.name}\``);
|
||||||
@ -1038,7 +1091,11 @@ export class MySQLClient extends BaseClient {
|
|||||||
alterColumnsDrop.push(`DROP FOREIGN KEY \`${deletion.constraintName}\``);
|
alterColumnsDrop.push(`DROP FOREIGN KEY \`${deletion.constraintName}\``);
|
||||||
});
|
});
|
||||||
|
|
||||||
const alterQueryes = [];
|
// DROP CHECK TABLE
|
||||||
|
checkChanges.deletions.forEach(deletion => {
|
||||||
|
alterQueryes.push(`${sql} DROP CONSTRAINT \`${deletion.name}\``);
|
||||||
|
});
|
||||||
|
|
||||||
if (alterColumnsAdd.length) alterQueryes.push(sql+alterColumnsAdd.join(', '));
|
if (alterColumnsAdd.length) alterQueryes.push(sql+alterColumnsAdd.join(', '));
|
||||||
if (alterColumnsChange.length) alterQueryes.push(sql+alterColumnsChange.join(', '));
|
if (alterColumnsChange.length) alterQueryes.push(sql+alterColumnsChange.join(', '));
|
||||||
if (alterColumnsDrop.length) alterQueryes.push(sql+alterColumnsDrop.join(', '));
|
if (alterColumnsDrop.length) alterQueryes.push(sql+alterColumnsDrop.join(', '));
|
||||||
|
@ -168,6 +168,8 @@ export class PostgreSQLClient extends BaseClient {
|
|||||||
try {
|
try {
|
||||||
this._ssh = new SSH2Promise({
|
this._ssh = new SSH2Promise({
|
||||||
...this._params.ssh,
|
...this._params.ssh,
|
||||||
|
reconnect: true,
|
||||||
|
reconnectTries: 3,
|
||||||
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
|
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -72,6 +72,19 @@
|
|||||||
/>
|
/>
|
||||||
<span>{{ t('database.foreignKeys') }}</span>
|
<span>{{ t('database.foreignKeys') }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-dark btn-sm ml-2 mr-0"
|
||||||
|
:disabled="isSaving || !localFields.length"
|
||||||
|
:title="t('database.manageTableChecks')"
|
||||||
|
@click="showTableChecksModal"
|
||||||
|
>
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiTableCheck"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<span>{{ t('database.tableChecks') }}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="workspace-query-info">
|
<div class="workspace-query-info">
|
||||||
<div class="d-flex" :title="t('database.schema')">
|
<div class="d-flex" :title="t('database.schema')">
|
||||||
@ -183,11 +196,19 @@
|
|||||||
@hide="hideForeignModal"
|
@hide="hideForeignModal"
|
||||||
@foreigns-update="foreignsUpdate"
|
@foreigns-update="foreignsUpdate"
|
||||||
/>
|
/>
|
||||||
|
<WorkspaceTabPropsTableChecksModal
|
||||||
|
v-if="isTableChecksModal"
|
||||||
|
:local-checks="localTableChecks"
|
||||||
|
table="new"
|
||||||
|
:workspace="workspace"
|
||||||
|
@hide="hideTableChecksModal"
|
||||||
|
@checks-update="checksUpdate"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ConnectionParams, TableField, TableForeign, TableIndex, TableOptions } from 'common/interfaces/antares';
|
import { ConnectionParams, TableCheck, TableField, TableForeign, TableIndex, TableOptions } from 'common/interfaces/antares';
|
||||||
import { uidGen } from 'common/libs/uidGen';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
@ -198,6 +219,7 @@ import BaseIcon from '@/components/BaseIcon.vue';
|
|||||||
import BaseLoader from '@/components/BaseLoader.vue';
|
import BaseLoader from '@/components/BaseLoader.vue';
|
||||||
import BaseSelect from '@/components/BaseSelect.vue';
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
import WorkspaceTabNewTableEmptyState from '@/components/WorkspaceTabNewTableEmptyState.vue';
|
import WorkspaceTabNewTableEmptyState from '@/components/WorkspaceTabNewTableEmptyState.vue';
|
||||||
|
import WorkspaceTabPropsTableChecksModal from '@/components/WorkspaceTabPropsTableChecksModal.vue';
|
||||||
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
||||||
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
||||||
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal.vue';
|
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal.vue';
|
||||||
@ -236,12 +258,16 @@ const isLoading = ref(false);
|
|||||||
const isSaving = ref(false);
|
const isSaving = ref(false);
|
||||||
const isIndexesModal = ref(false);
|
const isIndexesModal = ref(false);
|
||||||
const isForeignModal = ref(false);
|
const isForeignModal = ref(false);
|
||||||
|
const isTableChecksModal = ref(false);
|
||||||
|
|
||||||
const originalFields: Ref<TableField[]> = ref([]);
|
const originalFields: Ref<TableField[]> = ref([]);
|
||||||
const localFields: Ref<TableField[]> = ref([]);
|
const localFields: Ref<TableField[]> = ref([]);
|
||||||
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
||||||
const localKeyUsage: Ref<TableForeign[]> = ref([]);
|
const localKeyUsage: Ref<TableForeign[]> = ref([]);
|
||||||
const originalIndexes: Ref<TableIndex[]> = ref([]);
|
const originalIndexes: Ref<TableIndex[]> = ref([]);
|
||||||
const localIndexes: Ref<TableIndex[]> = ref([]);
|
const localIndexes: Ref<TableIndex[]> = ref([]);
|
||||||
|
const originalTableChecks: Ref<TableCheck[]> = ref([]);
|
||||||
|
const localTableChecks: Ref<TableCheck[]> = ref([]);
|
||||||
const tableOptions: Ref<TableOptions> = ref(null);
|
const tableOptions: Ref<TableOptions> = ref(null);
|
||||||
const localOptions: Ref<TableOptions> = ref(null);
|
const localOptions: Ref<TableOptions> = ref(null);
|
||||||
const newFieldsCounter = ref(0);
|
const newFieldsCounter = ref(0);
|
||||||
@ -274,6 +300,7 @@ const isChanged = computed(() => {
|
|||||||
return JSON.stringify(originalFields.value) !== JSON.stringify(localFields.value) ||
|
return JSON.stringify(originalFields.value) !== JSON.stringify(localFields.value) ||
|
||||||
JSON.stringify(originalKeyUsage.value) !== JSON.stringify(localKeyUsage.value) ||
|
JSON.stringify(originalKeyUsage.value) !== JSON.stringify(localKeyUsage.value) ||
|
||||||
JSON.stringify(originalIndexes.value) !== JSON.stringify(localIndexes.value) ||
|
JSON.stringify(originalIndexes.value) !== JSON.stringify(localIndexes.value) ||
|
||||||
|
JSON.stringify(originalTableChecks.value) !== JSON.stringify(localTableChecks.value) ||
|
||||||
JSON.stringify(tableOptions.value) !== JSON.stringify(localOptions.value);
|
JSON.stringify(tableOptions.value) !== JSON.stringify(localOptions.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -291,6 +318,7 @@ const saveChanges = async () => {
|
|||||||
fields: localFields.value,
|
fields: localFields.value,
|
||||||
foreigns: localKeyUsage.value,
|
foreigns: localKeyUsage.value,
|
||||||
indexes: localIndexes.value,
|
indexes: localIndexes.value,
|
||||||
|
checks: localTableChecks.value,
|
||||||
options: localOptions.value
|
options: localOptions.value
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -326,6 +354,7 @@ const clearChanges = () => {
|
|||||||
localFields.value = JSON.parse(JSON.stringify(originalFields.value));
|
localFields.value = JSON.parse(JSON.stringify(originalFields.value));
|
||||||
localIndexes.value = JSON.parse(JSON.stringify(originalIndexes.value));
|
localIndexes.value = JSON.parse(JSON.stringify(originalIndexes.value));
|
||||||
localKeyUsage.value = JSON.parse(JSON.stringify(originalKeyUsage.value));
|
localKeyUsage.value = JSON.parse(JSON.stringify(originalKeyUsage.value));
|
||||||
|
localTableChecks.value = JSON.parse(JSON.stringify(originalTableChecks.value));
|
||||||
|
|
||||||
tableOptions.value = {
|
tableOptions.value = {
|
||||||
name: '',
|
name: '',
|
||||||
@ -446,10 +475,22 @@ const hideForeignModal = () => {
|
|||||||
isForeignModal.value = false;
|
isForeignModal.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showTableChecksModal = () => {
|
||||||
|
isTableChecksModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideTableChecksModal = () => {
|
||||||
|
isTableChecksModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
const foreignsUpdate = (foreigns: TableForeign[]) => {
|
const foreignsUpdate = (foreigns: TableForeign[]) => {
|
||||||
localKeyUsage.value = foreigns;
|
localKeyUsage.value = foreigns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checksUpdate = (checks: TableCheck[]) => {
|
||||||
|
localTableChecks.value = checks;
|
||||||
|
};
|
||||||
|
|
||||||
const saveContentListener = () => {
|
const saveContentListener = () => {
|
||||||
const hasModalOpen = !!document.querySelectorAll('.modal.active').length;
|
const hasModalOpen = !!document.querySelectorAll('.modal.active').length;
|
||||||
if (props.isSelected && !hasModalOpen && isChanged.value)
|
if (props.isSelected && !hasModalOpen && isChanged.value)
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-dark btn-sm mr-0"
|
class="btn btn-dark btn-sm mr-0"
|
||||||
:disabled="isSaving"
|
:disabled="isSaving"
|
||||||
:title="t('database.manageIndexes')"
|
:title="t('database.manageForeignKeys')"
|
||||||
@click="showForeignModal"
|
@click="showForeignModal"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
@ -72,6 +72,19 @@
|
|||||||
/>
|
/>
|
||||||
<span>{{ t('database.foreignKeys') }}</span>
|
<span>{{ t('database.foreignKeys') }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-dark btn-sm ml-2 mr-0"
|
||||||
|
:disabled="isSaving"
|
||||||
|
:title="t('database.manageTableChecks')"
|
||||||
|
@click="showTableChecksModal"
|
||||||
|
>
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiTableCheck"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<span>{{ t('database.tableChecks') }}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div class="divider-vert py-3" />
|
<div class="divider-vert py-3" />
|
||||||
|
|
||||||
@ -218,11 +231,19 @@
|
|||||||
:workspace="workspace"
|
:workspace="workspace"
|
||||||
@hide="hideDdlModal"
|
@hide="hideDdlModal"
|
||||||
/>
|
/>
|
||||||
|
<WorkspaceTabPropsTableChecksModal
|
||||||
|
v-if="isTableChecksModal"
|
||||||
|
:local-checks="localTableChecks"
|
||||||
|
:table="table"
|
||||||
|
:workspace="workspace"
|
||||||
|
@hide="hideTableChecksModal"
|
||||||
|
@checks-update="checksUpdate"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { AlterTableParams, TableField, TableForeign, TableIndex, TableInfos, TableOptions } from 'common/interfaces/antares';
|
import { AlterTableParams, TableCheck, TableField, TableForeign, TableIndex, TableInfos, TableOptions } from 'common/interfaces/antares';
|
||||||
import { uidGen } from 'common/libs/uidGen';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
@ -232,6 +253,7 @@ import { useI18n } from 'vue-i18n';
|
|||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
import BaseLoader from '@/components/BaseLoader.vue';
|
import BaseLoader from '@/components/BaseLoader.vue';
|
||||||
import BaseSelect from '@/components/BaseSelect.vue';
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
|
import WorkspaceTabPropsTableChecksModal from '@/components/WorkspaceTabPropsTableChecksModal.vue';
|
||||||
import WorkspaceTabPropsTableDdlModal from '@/components/WorkspaceTabPropsTableDdlModal.vue';
|
import WorkspaceTabPropsTableDdlModal from '@/components/WorkspaceTabPropsTableDdlModal.vue';
|
||||||
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
||||||
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
||||||
@ -273,13 +295,17 @@ const isLoading = ref(false);
|
|||||||
const isSaving = ref(false);
|
const isSaving = ref(false);
|
||||||
const isIndexesModal = ref(false);
|
const isIndexesModal = ref(false);
|
||||||
const isForeignModal = ref(false);
|
const isForeignModal = ref(false);
|
||||||
|
const isTableChecksModal = ref(false);
|
||||||
const isDdlModal = ref(false);
|
const isDdlModal = ref(false);
|
||||||
|
|
||||||
const originalFields: Ref<TableField[]> = ref([]);
|
const originalFields: Ref<TableField[]> = ref([]);
|
||||||
const localFields: Ref<TableField[]> = ref([]);
|
const localFields: Ref<TableField[]> = ref([]);
|
||||||
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
||||||
const localKeyUsage: Ref<TableForeign[]> = ref([]);
|
const localKeyUsage: Ref<TableForeign[]> = ref([]);
|
||||||
const originalIndexes: Ref<TableIndex[]> = ref([]);
|
const originalIndexes: Ref<TableIndex[]> = ref([]);
|
||||||
const localIndexes: Ref<TableIndex[]> = ref([]);
|
const localIndexes: Ref<TableIndex[]> = ref([]);
|
||||||
|
const originalTableChecks: Ref<TableCheck[]> = ref([]);
|
||||||
|
const localTableChecks: Ref<TableCheck[]> = ref([]);
|
||||||
const tableOptions: Ref<TableOptions> = ref(null);
|
const tableOptions: Ref<TableOptions> = ref(null);
|
||||||
const localOptions: Ref<TableOptions> = ref({} as TableOptions);
|
const localOptions: Ref<TableOptions> = ref({} as TableOptions);
|
||||||
const lastTable = ref(null);
|
const lastTable = ref(null);
|
||||||
@ -307,6 +333,7 @@ const isChanged = computed(() => {
|
|||||||
return JSON.stringify(originalFields.value) !== JSON.stringify(localFields.value) ||
|
return JSON.stringify(originalFields.value) !== JSON.stringify(localFields.value) ||
|
||||||
JSON.stringify(originalKeyUsage.value) !== JSON.stringify(localKeyUsage.value) ||
|
JSON.stringify(originalKeyUsage.value) !== JSON.stringify(localKeyUsage.value) ||
|
||||||
JSON.stringify(originalIndexes.value) !== JSON.stringify(localIndexes.value) ||
|
JSON.stringify(originalIndexes.value) !== JSON.stringify(localIndexes.value) ||
|
||||||
|
JSON.stringify(originalTableChecks.value) !== JSON.stringify(localTableChecks.value) ||
|
||||||
JSON.stringify(tableOptions.value) !== JSON.stringify(localOptions.value);
|
JSON.stringify(tableOptions.value) !== JSON.stringify(localOptions.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -430,6 +457,27 @@ const getFieldsData = async () => {
|
|||||||
addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (workspace.value.customizations.tableCheck) {
|
||||||
|
try { // Table checks
|
||||||
|
const { status, response } = await Tables.getTableChecks(params);
|
||||||
|
|
||||||
|
if (status === 'success') {
|
||||||
|
originalTableChecks.value = response.map((check: TableCheck) => {
|
||||||
|
return {
|
||||||
|
_antares_id: uidGen(),
|
||||||
|
...check
|
||||||
|
};
|
||||||
|
});
|
||||||
|
localTableChecks.value = JSON.parse(JSON.stringify(originalTableChecks.value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -527,6 +575,33 @@ const saveChanges = async () => {
|
|||||||
// Foreigns Deletions
|
// Foreigns Deletions
|
||||||
foreignChanges.deletions = originalKeyUsage.value.filter(foreign => !localForeignIDs.includes(foreign._antares_id));
|
foreignChanges.deletions = originalKeyUsage.value.filter(foreign => !localForeignIDs.includes(foreign._antares_id));
|
||||||
|
|
||||||
|
// CHECKS
|
||||||
|
const checkChanges = {
|
||||||
|
additions: [] as TableCheck[],
|
||||||
|
changes: [] as TableCheck[],
|
||||||
|
deletions: [] as TableCheck[]
|
||||||
|
};
|
||||||
|
const originalCheckIDs = originalTableChecks.value.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
|
const localCheckIDs = localTableChecks.value.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
|
|
||||||
|
// Check Additions
|
||||||
|
checkChanges.additions = localTableChecks.value.filter(check => !originalCheckIDs.includes(check._antares_id));
|
||||||
|
|
||||||
|
// Check Changes
|
||||||
|
originalTableChecks.value.forEach(originalCheck => {
|
||||||
|
const lI = localTableChecks.value.findIndex(localCheck => localCheck._antares_id === originalCheck._antares_id);
|
||||||
|
if (JSON.stringify(originalCheck) !== JSON.stringify(localTableChecks.value[lI])) {
|
||||||
|
if (localTableChecks.value[lI]) {
|
||||||
|
checkChanges.changes.push({
|
||||||
|
...localTableChecks.value[lI]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check Deletions
|
||||||
|
checkChanges.deletions = originalTableChecks.value.filter(check => !localCheckIDs.includes(check._antares_id));
|
||||||
|
|
||||||
// ALTER
|
// ALTER
|
||||||
const params = {
|
const params = {
|
||||||
uid: props.connection.uid,
|
uid: props.connection.uid,
|
||||||
@ -543,6 +618,7 @@ const saveChanges = async () => {
|
|||||||
deletions,
|
deletions,
|
||||||
indexChanges,
|
indexChanges,
|
||||||
foreignChanges,
|
foreignChanges,
|
||||||
|
checkChanges,
|
||||||
options
|
options
|
||||||
} as unknown as AlterTableParams;
|
} as unknown as AlterTableParams;
|
||||||
|
|
||||||
@ -583,6 +659,7 @@ const clearChanges = () => {
|
|||||||
localFields.value = JSON.parse(JSON.stringify(originalFields.value));
|
localFields.value = JSON.parse(JSON.stringify(originalFields.value));
|
||||||
localIndexes.value = JSON.parse(JSON.stringify(originalIndexes.value));
|
localIndexes.value = JSON.parse(JSON.stringify(originalIndexes.value));
|
||||||
localKeyUsage.value = JSON.parse(JSON.stringify(originalKeyUsage.value));
|
localKeyUsage.value = JSON.parse(JSON.stringify(originalKeyUsage.value));
|
||||||
|
localTableChecks.value = JSON.parse(JSON.stringify(originalTableChecks.value));
|
||||||
localOptions.value = JSON.parse(JSON.stringify(tableOptions.value));
|
localOptions.value = JSON.parse(JSON.stringify(tableOptions.value));
|
||||||
newFieldsCounter.value = 0;
|
newFieldsCounter.value = 0;
|
||||||
};
|
};
|
||||||
@ -702,6 +779,14 @@ const hideForeignModal = () => {
|
|||||||
isForeignModal.value = false;
|
isForeignModal.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showTableChecksModal = () => {
|
||||||
|
isTableChecksModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideTableChecksModal = () => {
|
||||||
|
isTableChecksModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
const showDdlModal = () => {
|
const showDdlModal = () => {
|
||||||
isDdlModal.value = true;
|
isDdlModal.value = true;
|
||||||
};
|
};
|
||||||
@ -714,6 +799,10 @@ const foreignsUpdate = (foreigns: TableForeign[]) => {
|
|||||||
localKeyUsage.value = foreigns;
|
localKeyUsage.value = foreigns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checksUpdate = (checks: TableCheck[]) => {
|
||||||
|
localTableChecks.value = checks;
|
||||||
|
};
|
||||||
|
|
||||||
const saveContentListener = () => {
|
const saveContentListener = () => {
|
||||||
const hasModalOpen = !!document.querySelectorAll('.modal.active').length;
|
const hasModalOpen = !!document.querySelectorAll('.modal.active').length;
|
||||||
if (props.isSelected && !hasModalOpen && isChanged.value)
|
if (props.isSelected && !hasModalOpen && isChanged.value)
|
||||||
|
268
src/renderer/components/WorkspaceTabPropsTableChecksModal.vue
Normal file
268
src/renderer/components/WorkspaceTabPropsTableChecksModal.vue
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
<template>
|
||||||
|
<ConfirmModal
|
||||||
|
:confirm-text="t('general.confirm')"
|
||||||
|
size="medium"
|
||||||
|
class="options-modal"
|
||||||
|
@confirm="confirmChecksChange"
|
||||||
|
@hide="$emit('hide')"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="d-flex">
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiTableCheck"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<span class="cut-text">{{ t('database.tableChecks') }} "{{ table }}"</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<div class="columns col-gapless">
|
||||||
|
<div class="column col-5">
|
||||||
|
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
||||||
|
<div class="panel-header pt-0 pl-0">
|
||||||
|
<div class="d-flex">
|
||||||
|
<button class="btn btn-dark btn-sm d-flex" @click="addCheck">
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiCheckboxMarkedCirclePlusOutline"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<span>{{ t('general.add') }}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-dark btn-sm d-flex ml-2 mr-0"
|
||||||
|
:title="t('database.clearChanges')"
|
||||||
|
:disabled="!isChanged"
|
||||||
|
@click.prevent="clearChanges"
|
||||||
|
>
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiDeleteSweep"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<span>{{ t('general.clear') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ref="checksPanel" class="panel-body p-0 pr-1">
|
||||||
|
<div
|
||||||
|
v-for="check in checksProxy"
|
||||||
|
:key="check._antares_id"
|
||||||
|
class="tile tile-centered c-hand mb-1 p-1"
|
||||||
|
:class="{'selected-element': selectedCheckID === check._antares_id}"
|
||||||
|
@click="selectCheck($event, check._antares_id)"
|
||||||
|
>
|
||||||
|
<div class="tile-icon">
|
||||||
|
<div>
|
||||||
|
<BaseIcon
|
||||||
|
class="mt-2 column-key"
|
||||||
|
icon-name="mdiCheckboxMarkedCircleOutline"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title">
|
||||||
|
{{ check.name }}
|
||||||
|
</div>
|
||||||
|
<small class="tile-subtitle text-gray d-inline-block cut-text" style="width: 100%;">{{ check.clause }}</small>
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
<button
|
||||||
|
class="btn btn-link remove-field p-0 mr-2"
|
||||||
|
:title="t('general.delete')"
|
||||||
|
@click.prevent="removeCheck(check._antares_id)"
|
||||||
|
>
|
||||||
|
<BaseIcon
|
||||||
|
icon-name="mdiClose"
|
||||||
|
:size="18"
|
||||||
|
class="mt-2"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column col-7 pl-2 editor-col">
|
||||||
|
<form
|
||||||
|
v-if="selectedCheckObj"
|
||||||
|
:style="{ height: modalInnerHeight + 'px'}"
|
||||||
|
class="form-horizontal"
|
||||||
|
>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label col-3">
|
||||||
|
{{ t('general.name') }}
|
||||||
|
</label>
|
||||||
|
<div class="column">
|
||||||
|
<input
|
||||||
|
v-model="selectedCheckObj.name"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label col-3">
|
||||||
|
{{ t('database.checkClause') }}
|
||||||
|
</label>
|
||||||
|
<div class="column">
|
||||||
|
<textarea
|
||||||
|
v-model="selectedCheckObj.clause"
|
||||||
|
class="form-input"
|
||||||
|
style="resize: vertical;"
|
||||||
|
rows="5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div v-if="!checksProxy.length" class="empty">
|
||||||
|
<div class="empty-icon">
|
||||||
|
<BaseIcon
|
||||||
|
class="mr-1"
|
||||||
|
icon-name="mdiCheckboxMarkedCircleOutline"
|
||||||
|
:size="48"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="empty-title h5">
|
||||||
|
{{ t('database.thereAreNoTableChecks') }}
|
||||||
|
</p>
|
||||||
|
<div class="empty-action">
|
||||||
|
<button class="btn btn-primary" @click="addCheck">
|
||||||
|
{{ t('database.createNewCheck') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ConfirmModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TableCheck } from 'common/interfaces/antares';
|
||||||
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
|
import { computed, onMounted, onUnmounted, Ref, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
localChecks: Array,
|
||||||
|
table: String,
|
||||||
|
workspace: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['hide', 'checks-update']);
|
||||||
|
|
||||||
|
const checksPanel: Ref<HTMLDivElement> = ref(null);
|
||||||
|
const checksProxy: Ref<TableCheck[]> = ref([]);
|
||||||
|
const selectedCheckID = ref('');
|
||||||
|
const modalInnerHeight = ref(400);
|
||||||
|
|
||||||
|
const selectedCheckObj = computed(() => checksProxy.value.find(index => index._antares_id === selectedCheckID.value));
|
||||||
|
const isChanged = computed(() => JSON.stringify(props.localChecks) !== JSON.stringify(checksProxy.value));
|
||||||
|
|
||||||
|
const confirmChecksChange = () => {
|
||||||
|
const filteredChecks = checksProxy.value.filter(check => check.clause.trim().length);
|
||||||
|
emit('checks-update', filteredChecks);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectCheck = (event: MouseEvent, id: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
if (selectedCheckID.value !== id && !(event.target as any).classList.contains('remove-field'))
|
||||||
|
selectedCheckID.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getModalInnerHeight = () => {
|
||||||
|
const modalBody = document.querySelector('.modal-body');
|
||||||
|
if (modalBody)
|
||||||
|
modalInnerHeight.value = modalBody.clientHeight - (parseFloat(getComputedStyle(modalBody).paddingTop) + parseFloat(getComputedStyle(modalBody).paddingBottom));
|
||||||
|
};
|
||||||
|
|
||||||
|
const addCheck = () => {
|
||||||
|
const uid = uidGen();
|
||||||
|
checksProxy.value = [...checksProxy.value, {
|
||||||
|
_antares_id: uid,
|
||||||
|
name: `CHK_${uid.substring(0, 4)}`,
|
||||||
|
clause: ''
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (checksProxy.value.length === 1)
|
||||||
|
resetSelectedID();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
checksPanel.value.scrollTop = checksPanel.value.scrollHeight + 60;
|
||||||
|
selectedCheckID.value = uid;
|
||||||
|
}, 20);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeCheck = (id: string) => {
|
||||||
|
checksProxy.value = checksProxy.value.filter(index => index._antares_id !== id);
|
||||||
|
|
||||||
|
if (selectedCheckID.value === id && checksProxy.value.length)
|
||||||
|
resetSelectedID();
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearChanges = () => {
|
||||||
|
checksProxy.value = JSON.parse(JSON.stringify(props.localChecks));
|
||||||
|
if (!checksProxy.value.some(index => index._antares_id === selectedCheckID.value))
|
||||||
|
resetSelectedID();
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetSelectedID = () => {
|
||||||
|
selectedCheckID.value = checksProxy.value.length ? checksProxy.value[0]._antares_id : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checksProxy.value = JSON.parse(JSON.stringify(props.localChecks));
|
||||||
|
|
||||||
|
if (checksProxy.value.length)
|
||||||
|
resetSelectedID();
|
||||||
|
|
||||||
|
getModalInnerHeight();
|
||||||
|
window.addEventListener('resize', getModalInnerHeight);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', getModalInnerHeight);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tile {
|
||||||
|
border-radius: $border-radius;
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: background 0.2s;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
|
.tile-action {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.tile-action {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected-element {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fields-list {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-field svg {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -126,6 +126,7 @@ export const enUS = {
|
|||||||
insert: 'Insert',
|
insert: 'Insert',
|
||||||
indexes: 'Indexes',
|
indexes: 'Indexes',
|
||||||
foreignKeys: 'Foreign keys',
|
foreignKeys: 'Foreign keys',
|
||||||
|
tableChecks: 'Table checks',
|
||||||
length: 'Length',
|
length: 'Length',
|
||||||
unsigned: 'Unsigned',
|
unsigned: 'Unsigned',
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
@ -190,12 +191,15 @@ export const enUS = {
|
|||||||
addNewField: 'Add new field',
|
addNewField: 'Add new field',
|
||||||
manageIndexes: 'Manage indexes',
|
manageIndexes: 'Manage indexes',
|
||||||
manageForeignKeys: 'Manage foreign keys',
|
manageForeignKeys: 'Manage foreign keys',
|
||||||
|
manageTableChecks: 'Manage table checks',
|
||||||
allowNull: 'Allow NULL',
|
allowNull: 'Allow NULL',
|
||||||
zeroFill: 'Zero fill',
|
zeroFill: 'Zero fill',
|
||||||
customValue: 'Custom value',
|
customValue: 'Custom value',
|
||||||
onUpdate: 'On update',
|
onUpdate: 'On update',
|
||||||
deleteField: 'Delete field',
|
deleteField: 'Delete field',
|
||||||
createNewIndex: 'Create new index',
|
createNewIndex: 'Create new index',
|
||||||
|
createNewCheck: 'Create new check',
|
||||||
|
checkClause: 'Check clause',
|
||||||
addToIndex: 'Add to index',
|
addToIndex: 'Add to index',
|
||||||
createNewTable: 'Create new table',
|
createNewTable: 'Create new table',
|
||||||
emptyTable: 'Empty table',
|
emptyTable: 'Empty table',
|
||||||
@ -205,6 +209,7 @@ export const enUS = {
|
|||||||
emptyConfirm: 'Do you confirm to empty',
|
emptyConfirm: 'Do you confirm to empty',
|
||||||
thereAreNoIndexes: 'There are no indexes',
|
thereAreNoIndexes: 'There are no indexes',
|
||||||
thereAreNoForeign: 'There are no foreign keys',
|
thereAreNoForeign: 'There are no foreign keys',
|
||||||
|
thereAreNoTableChecks: 'There are no table checks',
|
||||||
createNewForeign: 'Create new foreign key',
|
createNewForeign: 'Create new foreign key',
|
||||||
referenceTable: 'Ref. table',
|
referenceTable: 'Ref. table',
|
||||||
referenceField: 'Ref. field',
|
referenceField: 'Ref. field',
|
||||||
|
@ -71,7 +71,7 @@ export const ruRU = {
|
|||||||
title: 'Название',
|
title: 'Название',
|
||||||
archive: 'Архив',
|
archive: 'Архив',
|
||||||
undo: 'Отменить',
|
undo: 'Отменить',
|
||||||
moveTo: 'Переместить в',
|
moveTo: 'Переместить в'
|
||||||
},
|
},
|
||||||
connection: {
|
connection: {
|
||||||
connectionName: 'Название соединения',
|
connectionName: 'Название соединения',
|
||||||
@ -109,7 +109,7 @@ export const ruRU = {
|
|||||||
searchForConnections: 'Поиск соединений',
|
searchForConnections: 'Поиск соединений',
|
||||||
keepAliveInterval: 'Интервал поддержания соединения',
|
keepAliveInterval: 'Интервал поддержания соединения',
|
||||||
singleConnection: 'Одно соединение',
|
singleConnection: 'Одно соединение',
|
||||||
connection: 'Соединение',
|
connection: 'Соединение'
|
||||||
},
|
},
|
||||||
database: {
|
database: {
|
||||||
schema: 'Схема',
|
schema: 'Схема',
|
||||||
@ -277,7 +277,7 @@ export const ruRU = {
|
|||||||
switchDatabase: 'Переключить базу данных',
|
switchDatabase: 'Переключить базу данных',
|
||||||
searchForElements: 'Поиск элементов',
|
searchForElements: 'Поиск элементов',
|
||||||
searchForSchemas: 'Поиск схем',
|
searchForSchemas: 'Поиск схем',
|
||||||
savedQueries: 'Сохранённые запросы',
|
savedQueries: 'Сохранённые запросы'
|
||||||
},
|
},
|
||||||
application: {
|
application: {
|
||||||
settings: 'Настройки',
|
settings: 'Настройки',
|
||||||
@ -408,7 +408,7 @@ export const ruRU = {
|
|||||||
openNotes: 'Открыть заметки',
|
openNotes: 'Открыть заметки',
|
||||||
debugConsole: 'Отладочная консоль',
|
debugConsole: 'Отладочная консоль',
|
||||||
executedQueries: 'Выполненные запросы',
|
executedQueries: 'Выполненные запросы',
|
||||||
sizeLimitError: 'Превышен максимальный размер {size}',
|
sizeLimitError: 'Превышен максимальный размер {size}'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Адрес',
|
address: 'Адрес',
|
||||||
@ -573,6 +573,6 @@ export const ruRU = {
|
|||||||
manufacturer: 'Производитель',
|
manufacturer: 'Производитель',
|
||||||
model: 'Модель',
|
model: 'Модель',
|
||||||
fuel: 'Топливо',
|
fuel: 'Топливо',
|
||||||
vin: 'Vin',
|
vin: 'Vin'
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
@ -36,6 +36,10 @@ export default class {
|
|||||||
return ipcRenderer.invoke('get-table-indexes', unproxify(params));
|
return ipcRenderer.invoke('get-table-indexes', unproxify(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getTableChecks (params: { uid: string; schema: string; table: string }): Promise<IpcResponse> {
|
||||||
|
return ipcRenderer.invoke('get-table-checks', unproxify(params));
|
||||||
|
}
|
||||||
|
|
||||||
static getTableDll (params: { uid: string; schema: string; table: string }): Promise<IpcResponse<string>> {
|
static getTableDll (params: { uid: string; schema: string; table: string }): Promise<IpcResponse<string>> {
|
||||||
return ipcRenderer.invoke('get-table-ddl', unproxify(params));
|
return ipcRenderer.invoke('get-table-ddl', unproxify(params));
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ export interface QueryLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DebugLog {
|
export interface DebugLog {
|
||||||
level: 'log' | 'info' | 'warn' | 'error';
|
level: 'log' | 'info' | 'warn' | 'error' | string;
|
||||||
process: 'renderer' | 'main' | 'worker';
|
process: 'renderer' | 'main' | 'worker';
|
||||||
message: string;
|
message: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user