mirror of https://github.com/Fabio286/antares.git
refactor: ts and composition api on more elements
This commit is contained in:
parent
5a50ba88e8
commit
84826ff4c0
|
@ -73,6 +73,19 @@ export interface TypesGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tables
|
// Tables
|
||||||
|
export interface TableInfos {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
rows: number;
|
||||||
|
created: Date;
|
||||||
|
updated: Date;
|
||||||
|
engine: string;
|
||||||
|
comment: string;
|
||||||
|
size: number;
|
||||||
|
autoIncrement: number;
|
||||||
|
collation: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TableField {
|
export interface TableField {
|
||||||
name: string;
|
name: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
@ -87,7 +100,7 @@ export interface TableField {
|
||||||
unsigned?: boolean;
|
unsigned?: boolean;
|
||||||
zerofill?: boolean;
|
zerofill?: boolean;
|
||||||
order?: number;
|
order?: number;
|
||||||
default?: number | string;
|
default?: string;
|
||||||
enumValues?: string;
|
enumValues?: string;
|
||||||
charset?: string;
|
charset?: string;
|
||||||
collation?: string;
|
collation?: string;
|
||||||
|
@ -97,6 +110,7 @@ export interface TableField {
|
||||||
comment?: string;
|
comment?: string;
|
||||||
after?: string;
|
after?: string;
|
||||||
orgName?: string;
|
orgName?: string;
|
||||||
|
length?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableIndex {
|
export interface TableIndex {
|
||||||
|
@ -170,6 +184,7 @@ export interface AlterTableParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Views
|
// Views
|
||||||
|
export type ViewInfos = TableInfos
|
||||||
export interface CreateViewParams {
|
export interface CreateViewParams {
|
||||||
schema: string;
|
schema: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -185,6 +200,18 @@ export interface AlterViewParams extends CreateViewParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triggers
|
// Triggers
|
||||||
|
export interface TriggerInfos {
|
||||||
|
name: string;
|
||||||
|
statement: string;
|
||||||
|
timing: string;
|
||||||
|
definer: string;
|
||||||
|
event: string;
|
||||||
|
table: string;
|
||||||
|
sqlMode: string;
|
||||||
|
created: Date;
|
||||||
|
charset: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateTriggerParams {
|
export interface CreateTriggerParams {
|
||||||
definer?: string;
|
definer?: string;
|
||||||
schema: string;
|
schema: string;
|
||||||
|
@ -200,6 +227,19 @@ export interface AlterTriggerParams extends CreateTriggerParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routines & Functions
|
// Routines & Functions
|
||||||
|
export interface RoutineInfos {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
definer: string;
|
||||||
|
created: string;
|
||||||
|
updated: string;
|
||||||
|
comment?: string;
|
||||||
|
charset?: string;
|
||||||
|
security?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FunctionInfos = RoutineInfos
|
||||||
|
|
||||||
export interface FunctionParam {
|
export interface FunctionParam {
|
||||||
context: string;
|
context: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -244,6 +284,29 @@ export interface AlterFunctionParams extends CreateFunctionParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
export interface EventInfos {
|
||||||
|
name: string;
|
||||||
|
definition: string;
|
||||||
|
type: string;
|
||||||
|
definer: string;
|
||||||
|
body: string;
|
||||||
|
starts: string;
|
||||||
|
ends: string;
|
||||||
|
enabled: boolean;
|
||||||
|
executeAt: string;
|
||||||
|
intervalField: string;
|
||||||
|
intervalValue: string;
|
||||||
|
onCompletion: string;
|
||||||
|
originator: string;
|
||||||
|
sqlMode: string;
|
||||||
|
created: string;
|
||||||
|
updated: string;
|
||||||
|
lastExecuted: string;
|
||||||
|
comment: string;
|
||||||
|
charset: string;
|
||||||
|
timezone: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateEventParams {
|
export interface CreateEventParams {
|
||||||
definer?: string;
|
definer?: string;
|
||||||
schema: string;
|
schema: string;
|
||||||
|
@ -263,6 +326,17 @@ export interface AlterEventParams extends CreateEventParams {
|
||||||
oldName?: string;
|
oldName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Schema
|
||||||
|
export interface SchemaInfos {
|
||||||
|
name: string;
|
||||||
|
size: number;
|
||||||
|
tables: TableInfos[];
|
||||||
|
functions: RoutineInfos[];
|
||||||
|
procedures: RoutineInfos[];
|
||||||
|
triggers: TriggerInfos[];
|
||||||
|
schedulers: EventInfos[];
|
||||||
|
}
|
||||||
|
|
||||||
// Query
|
// Query
|
||||||
export interface QueryBuilderObject {
|
export interface QueryBuilderObject {
|
||||||
schema: string;
|
schema: string;
|
||||||
|
|
|
@ -172,7 +172,10 @@ export default (connections: {[key: string]: antares.Client}) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('export', (event, { uid, type, tables, ...rest }) => {
|
ipcMain.handle('export', (event, { uid, type, tables, ...rest }) => {
|
||||||
if (exporter !== null) return;
|
if (exporter !== null) {
|
||||||
|
exporter.kill();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve/*, reject */) => {
|
return new Promise((resolve/*, reject */) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -265,7 +268,10 @@ export default (connections: {[key: string]: antares.Client}) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('import-sql', async (event, options) => {
|
ipcMain.handle('import-sql', async (event, options) => {
|
||||||
if (importer !== null) return;
|
if (importer !== null) {
|
||||||
|
importer.kill();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve/*, reject */) => {
|
return new Promise((resolve/*, reject */) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -321,7 +321,7 @@ export class MySQLClient extends AntaresCore {
|
||||||
return filteredDatabases.map(db => {
|
return filteredDatabases.map(db => {
|
||||||
if (schemas.has(db.Database)) {
|
if (schemas.has(db.Database)) {
|
||||||
// TABLES
|
// TABLES
|
||||||
const remappedTables = tablesArr.filter(table => table.Db === db.Database).map(table => {
|
const remappedTables: antares.TableInfos[] = tablesArr.filter(table => table.Db === db.Database).map(table => {
|
||||||
let tableType;
|
let tableType;
|
||||||
switch (table.Comment) {
|
switch (table.Comment) {
|
||||||
case 'VIEW':
|
case 'VIEW':
|
||||||
|
@ -350,7 +350,7 @@ export class MySQLClient extends AntaresCore {
|
||||||
});
|
});
|
||||||
|
|
||||||
// PROCEDURES
|
// PROCEDURES
|
||||||
const remappedProcedures = procedures.filter(procedure => procedure.Db === db.Database).map(procedure => {
|
const remappedProcedures: antares.RoutineInfos[] = procedures.filter(procedure => procedure.Db === db.Database).map(procedure => {
|
||||||
return {
|
return {
|
||||||
name: procedure.Name,
|
name: procedure.Name,
|
||||||
type: procedure.Type,
|
type: procedure.Type,
|
||||||
|
@ -364,7 +364,7 @@ export class MySQLClient extends AntaresCore {
|
||||||
});
|
});
|
||||||
|
|
||||||
// FUNCTIONS
|
// FUNCTIONS
|
||||||
const remappedFunctions = functions.filter(func => func.Db === db.Database).map(func => {
|
const remappedFunctions: antares.FunctionInfos[] = functions.filter(func => func.Db === db.Database).map(func => {
|
||||||
return {
|
return {
|
||||||
name: func.Name,
|
name: func.Name,
|
||||||
type: func.Type,
|
type: func.Type,
|
||||||
|
@ -378,7 +378,7 @@ export class MySQLClient extends AntaresCore {
|
||||||
});
|
});
|
||||||
|
|
||||||
// SCHEDULERS
|
// SCHEDULERS
|
||||||
const remappedSchedulers = schedulers.filter(scheduler => scheduler.Db === db.Database).map(scheduler => {
|
const remappedSchedulers: antares.EventInfos[] = schedulers.filter(scheduler => scheduler.Db === db.Database).map(scheduler => {
|
||||||
return {
|
return {
|
||||||
name: scheduler.EVENT_NAME,
|
name: scheduler.EVENT_NAME,
|
||||||
definition: scheduler.EVENT_DEFINITION,
|
definition: scheduler.EVENT_DEFINITION,
|
||||||
|
@ -404,7 +404,7 @@ export class MySQLClient extends AntaresCore {
|
||||||
});
|
});
|
||||||
|
|
||||||
// TRIGGERS
|
// TRIGGERS
|
||||||
const remappedTriggers = triggersArr.filter(trigger => trigger.Db === db.Database).map(trigger => {
|
const remappedTriggers: antares.TriggerInfos[] = triggersArr.filter(trigger => trigger.Db === db.Database).map(trigger => {
|
||||||
return {
|
return {
|
||||||
name: trigger.Trigger,
|
name: trigger.Trigger,
|
||||||
statement: trigger.Statement,
|
statement: trigger.Statement,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, watch } from 'vue';
|
||||||
import * as ace from 'ace-builds';
|
import * as ace from 'ace-builds';
|
||||||
import 'ace-builds/webpack-resolver';
|
import 'ace-builds/webpack-resolver';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
@ -28,7 +28,6 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const mode = ref(props.mode);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editorTheme,
|
editorTheme,
|
||||||
|
@ -40,7 +39,7 @@ const {
|
||||||
let editor: ace.Ace.Editor;
|
let editor: ace.Ace.Editor;
|
||||||
const id = uidGen();
|
const id = uidGen();
|
||||||
|
|
||||||
watch(mode, () => {
|
watch(() => props.mode, () => {
|
||||||
if (editor)
|
if (editor)
|
||||||
editor.session.setMode(`ace/mode/${props.mode}`);
|
editor.session.setMode(`ace/mode/${props.mode}`);
|
||||||
});
|
});
|
||||||
|
@ -82,7 +81,7 @@ watch(lineWrap, () => {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
editor = ace.edit(`editor-${id}`, {
|
editor = ace.edit(`editor-${id}`, {
|
||||||
mode: `ace/mode/${mode.value}`,
|
mode: `ace/mode/${props.mode}`,
|
||||||
theme: `ace/theme/${editorTheme.value}`,
|
theme: `ace/theme/${editorTheme.value}`,
|
||||||
value: props.modelValue || '',
|
value: props.modelValue || '',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from '@vue/reactivity';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { ref, watch } from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
message: {
|
message: {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
class="form-select pl-1 pr-4"
|
class="form-select pl-1 pr-4"
|
||||||
:class="{'small-select': size === 'small'}"
|
:class="{'small-select': size === 'small'}"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
@blur="$emit('blur')"
|
@blur="emit('blur')"
|
||||||
>
|
>
|
||||||
<option v-if="!isValidDefault" :value="modelValue">
|
<option v-if="!isValidDefault" :value="modelValue">
|
||||||
{{ modelValue === null ? 'NULL' : modelValue }}
|
{{ modelValue === null ? 'NULL' : modelValue }}
|
||||||
|
@ -20,88 +20,84 @@
|
||||||
</select>
|
</select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, Ref, ref } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import Tables from '@/ipc-api/Tables';
|
import Tables from '@/ipc-api/Tables';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import { TEXT, LONG_TEXT } from 'common/fieldTypes';
|
import { TEXT, LONG_TEXT } from 'common/fieldTypes';
|
||||||
export default {
|
|
||||||
name: 'ForeignKeySelect',
|
const props = defineProps({
|
||||||
props: {
|
|
||||||
modelValue: [String, Number],
|
modelValue: [String, Number],
|
||||||
keyUsage: Object,
|
keyUsage: Object,
|
||||||
size: {
|
size: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
emits: ['update:modelValue', 'blur'],
|
|
||||||
setup () {
|
const emit = defineEmits(['update:modelValue', 'blur']);
|
||||||
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
|
||||||
return { addNotification, selectedWorkspace };
|
const editField: Ref<HTMLSelectElement> = ref(null);
|
||||||
},
|
const foreignList = ref([]);
|
||||||
data () {
|
|
||||||
return {
|
const isValidDefault = computed(() => {
|
||||||
foreignList: []
|
if (!foreignList.value.length) return true;
|
||||||
};
|
if (props.modelValue === null) return false;
|
||||||
},
|
return foreignList.value.some(foreign => foreign.foreign_column.toString() === props.modelValue.toString());
|
||||||
computed: {
|
});
|
||||||
isValidDefault () {
|
|
||||||
if (!this.foreignList.length) return true;
|
const onChange = () => {
|
||||||
if (this.modelValue === null) return false;
|
emit('update:modelValue', editField.value.value);
|
||||||
return this.foreignList.some(foreign => foreign.foreign_column.toString() === this.modelValue.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async created () {
|
|
||||||
let foreignDesc;
|
|
||||||
const params = {
|
|
||||||
uid: this.selectedWorkspace,
|
|
||||||
schema: this.keyUsage.refSchema,
|
|
||||||
table: this.keyUsage.refTable
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cutText = (val: string) => {
|
||||||
|
if (typeof val !== 'string') return val;
|
||||||
|
return val.length > 15 ? `${val.substring(0, 15)}...` : val;
|
||||||
|
};
|
||||||
|
|
||||||
|
let foreignDesc;
|
||||||
|
const params = {
|
||||||
|
uid: selectedWorkspace.value,
|
||||||
|
schema: props.keyUsage.refSchema,
|
||||||
|
table: props.keyUsage.refTable
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
try { // Field data
|
try { // Field data
|
||||||
const { status, response } = await Tables.getTableColumns(params);
|
const { status, response } = await Tables.getTableColumns(params);
|
||||||
|
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
const textField = response.find(field => [...TEXT, ...LONG_TEXT].includes(field.type) && field.name !== this.keyUsage.refField);
|
const textField = response.find((field: {type: string; name: string}) => [...TEXT, ...LONG_TEXT].includes(field.type) && field.name !== props.keyUsage.refField);
|
||||||
foreignDesc = textField ? textField.name : false;
|
foreignDesc = textField ? textField.name : false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
try { // Foregn list
|
try { // Foregn list
|
||||||
const { status, response } = await Tables.getForeignList({
|
const { status, response } = await Tables.getForeignList({
|
||||||
...params,
|
...params,
|
||||||
column: this.keyUsage.refField,
|
column: props.keyUsage.refField,
|
||||||
description: foreignDesc
|
description: foreignDesc
|
||||||
});
|
});
|
||||||
|
|
||||||
if (status === 'success')
|
if (status === 'success')
|
||||||
this.foreignList = response.rows;
|
foreignList.value = response.rows;
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
},
|
})();
|
||||||
methods: {
|
|
||||||
onChange () {
|
|
||||||
this.$emit('update:modelValue', this.$refs.editField.value);
|
|
||||||
},
|
|
||||||
cutText (val) {
|
|
||||||
if (typeof val !== 'string') return val;
|
|
||||||
return val.length > 15 ? `${val.substring(0, 15)}...` : val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -55,30 +55,25 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
import { Ref, ref } from 'vue';
|
||||||
name: 'ModalAskCredentials',
|
|
||||||
emits: ['close-asking', 'credentials'],
|
const credentials = ref({
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
credentials: {
|
|
||||||
user: '',
|
user: '',
|
||||||
password: ''
|
password: ''
|
||||||
}
|
});
|
||||||
|
const firstInput: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const emit = defineEmits(['close-asking', 'credentials']);
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
emit('close-asking');
|
||||||
};
|
};
|
||||||
},
|
|
||||||
created () {
|
const sendCredentials = () => {
|
||||||
|
emit('credentials', credentials.value);
|
||||||
|
};
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.firstInput.focus();
|
firstInput.value.focus();
|
||||||
}, 20);
|
}, 20);
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('close-asking');
|
|
||||||
},
|
|
||||||
sendCredentials () {
|
|
||||||
this.$emit('credentials', this.credentials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -47,50 +47,39 @@
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, PropType, Ref, ref } from 'vue';
|
||||||
import { NUMBER, FLOAT } from 'common/fieldTypes';
|
import { NUMBER, FLOAT } from 'common/fieldTypes';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import { FunctionParam } from 'common/interfaces/antares';
|
||||||
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
|
||||||
export default {
|
// eslint-disable-next-line camelcase
|
||||||
name: 'ModalAskParameters',
|
type LocalRoutineParams = FunctionParam & {_antares_id: string};
|
||||||
components: {
|
|
||||||
ConfirmModal
|
const props = defineProps({
|
||||||
},
|
localRoutine: Object as PropType<{name: string; parameters: LocalRoutineParams[]}>,
|
||||||
props: {
|
|
||||||
localRoutine: Object,
|
|
||||||
client: String
|
client: String
|
||||||
},
|
});
|
||||||
emits: ['confirm', 'close'],
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
values: {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
inParameters () {
|
|
||||||
return this.localRoutine.parameters.filter(param => param.context === 'IN');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
const emit = defineEmits(['confirm', 'close']);
|
||||||
this.$refs.firstInput[0].focus();
|
|
||||||
}, 20);
|
const firstInput: Ref<HTMLInputElement[]> = ref(null);
|
||||||
},
|
const values: Ref<{[key: string]: string}> = ref({});
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
const inParameters = computed(() => {
|
||||||
},
|
return props.localRoutine.parameters.filter(param => param.context === 'IN');
|
||||||
methods: {
|
});
|
||||||
typeClass (type) {
|
|
||||||
|
const typeClass = (type: string) => {
|
||||||
if (type)
|
if (type)
|
||||||
return `type-${type.toLowerCase().replaceAll(' ', '_').replaceAll('"', '')}`;
|
return `type-${type.toLowerCase().replaceAll(' ', '_').replaceAll('"', '')}`;
|
||||||
return '';
|
return '';
|
||||||
},
|
};
|
||||||
runRoutine () {
|
|
||||||
const valArr = Object.keys(this.values).reduce((acc, curr, i) => {
|
const runRoutine = () => {
|
||||||
|
const valArr = Object.keys(values.value).reduce((acc, curr, i) => {
|
||||||
let qc;
|
let qc;
|
||||||
switch (this.client) {
|
switch (props.client) {
|
||||||
case 'maria':
|
case 'maria':
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
qc = '"';
|
qc = '"';
|
||||||
|
@ -102,28 +91,34 @@ export default {
|
||||||
qc = '"';
|
qc = '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
const param = this.localRoutine.parameters.find(param => `${i}-${param.name}` === curr);
|
const param = props.localRoutine.parameters.find(param => `${i}-${param.name}` === curr);
|
||||||
|
|
||||||
const value = [...NUMBER, ...FLOAT].includes(param.type) ? this.values[curr] : `${qc}${this.values[curr]}${qc}`;
|
const value = [...NUMBER, ...FLOAT].includes(param.type) ? values.value[curr] : `${qc}${values.value[curr]}${qc}`;
|
||||||
acc.push(value);
|
acc.push(value);
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
this.$emit('confirm', valArr);
|
|
||||||
},
|
emit('confirm', valArr);
|
||||||
closeModal () {
|
};
|
||||||
this.$emit('close');
|
|
||||||
},
|
const closeModal = () => emit('close');
|
||||||
onKey (e) {
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
this.closeModal();
|
closeModal();
|
||||||
},
|
};
|
||||||
wrapNumber (num) {
|
|
||||||
|
const wrapNumber = (num: number) => {
|
||||||
if (!num) return '';
|
if (!num) return '';
|
||||||
return `(${num})`;
|
return `(${num})`;
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
firstInput.value[0].focus();
|
||||||
|
}, 20);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
:confirm-text="$t('word.discard')"
|
:confirm-text="$t('word.discard')"
|
||||||
:cancel-text="$t('word.stay')"
|
:cancel-text="$t('word.stay')"
|
||||||
@confirm="$emit('confirm')"
|
@confirm="emit('confirm')"
|
||||||
@hide="$emit('close')"
|
@hide="emit('close')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
|
@ -18,29 +18,23 @@
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
import { onBeforeUnmount } from 'vue';
|
||||||
|
|
||||||
export default {
|
const emit = defineEmits(['confirm', 'close']);
|
||||||
name: 'ModalDiscardChanges',
|
|
||||||
components: {
|
const onKey = (e: KeyboardEvent) => {
|
||||||
ConfirmModal
|
|
||||||
},
|
|
||||||
emits: ['confirm', 'close'],
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
this.closeModal();
|
emit('close');
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', onKey);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -67,19 +67,19 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'ModalEditSchema',
|
|
||||||
props: {
|
|
||||||
selectedSchema: String
|
selectedSchema: String
|
||||||
},
|
});
|
||||||
emits: ['close'],
|
|
||||||
setup () {
|
const emit = defineEmits(['close']);
|
||||||
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
|
@ -87,92 +87,78 @@ export default {
|
||||||
|
|
||||||
const { getWorkspace, getDatabaseVariable } = workspacesStore;
|
const { getWorkspace, getDatabaseVariable } = workspacesStore;
|
||||||
|
|
||||||
return {
|
const firstInput: Ref<HTMLInputElement> = ref(null);
|
||||||
addNotification,
|
const database = ref({
|
||||||
selectedWorkspace,
|
|
||||||
getWorkspace,
|
|
||||||
getDatabaseVariable
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
database: {
|
|
||||||
name: '',
|
name: '',
|
||||||
prevName: '',
|
prevName: '',
|
||||||
collation: ''
|
collation: '',
|
||||||
|
prevCollation: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const collations = computed(() => getWorkspace(selectedWorkspace.value).collations);
|
||||||
|
const defaultCollation = computed(() => (getDatabaseVariable(selectedWorkspace.value, 'collation_server').value || ''));
|
||||||
|
|
||||||
|
const updateSchema = async () => {
|
||||||
|
if (database.value.collation !== database.value.prevCollation) {
|
||||||
|
try {
|
||||||
|
const { status, response } = await Schema.updateSchema({
|
||||||
|
uid: selectedWorkspace.value,
|
||||||
|
...database.value
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status === 'success')
|
||||||
|
closeModal();
|
||||||
|
else
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else closeModal();
|
||||||
};
|
};
|
||||||
},
|
|
||||||
computed: {
|
const closeModal = () => emit('close');
|
||||||
collations () {
|
|
||||||
return this.getWorkspace(this.selectedWorkspace).collations;
|
const onKey =(e: KeyboardEvent) => {
|
||||||
},
|
e.stopPropagation();
|
||||||
defaultCollation () {
|
if (e.key === 'Escape')
|
||||||
return this.getDatabaseVariable(this.selectedWorkspace, 'collation_server').value || '';
|
closeModal();
|
||||||
}
|
};
|
||||||
},
|
|
||||||
async created () {
|
(async () => {
|
||||||
let actualCollation;
|
let actualCollation;
|
||||||
try {
|
try {
|
||||||
const { status, response } = await Schema.getDatabaseCollation({ uid: this.selectedWorkspace, database: this.selectedSchema });
|
const { status, response } = await Schema.getDatabaseCollation({ uid: selectedWorkspace.value, database: props.selectedSchema });
|
||||||
|
|
||||||
if (status === 'success')
|
if (status === 'success')
|
||||||
actualCollation = response;
|
actualCollation = response;
|
||||||
|
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.database = {
|
database.value = {
|
||||||
name: this.selectedSchema,
|
name: props.selectedSchema,
|
||||||
prevName: this.selectedSchema,
|
prevName: props.selectedSchema,
|
||||||
collation: actualCollation || this.defaultCollation,
|
collation: actualCollation || defaultCollation.value,
|
||||||
prevCollation: actualCollation || this.defaultCollation
|
prevCollation: actualCollation || defaultCollation.value
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.firstInput.focus();
|
firstInput.value.focus();
|
||||||
}, 20);
|
}, 20);
|
||||||
},
|
})();
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
onBeforeUnmount(() => {
|
||||||
},
|
window.removeEventListener('keydown', onKey);
|
||||||
methods: {
|
|
||||||
async updateSchema () {
|
|
||||||
if (this.database.collation !== this.database.prevCollation) {
|
|
||||||
try {
|
|
||||||
const { status, response } = await Schema.updateSchema({
|
|
||||||
uid: this.selectedWorkspace,
|
|
||||||
...this.database
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (status === 'success')
|
|
||||||
this.closeModal();
|
|
||||||
else
|
|
||||||
this.addNotification({ status: 'error', message: response });
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.closeModal();
|
|
||||||
},
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('close');
|
|
||||||
},
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (e.key === 'Escape')
|
|
||||||
this.closeModal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -146,7 +146,7 @@
|
||||||
<div class="tbody">
|
<div class="tbody">
|
||||||
<div
|
<div
|
||||||
v-for="item in tables"
|
v-for="item in tables"
|
||||||
:key="item.name"
|
:key="item.table"
|
||||||
class="tr"
|
class="tr"
|
||||||
>
|
>
|
||||||
<div class="td">
|
<div class="td">
|
||||||
|
@ -193,7 +193,7 @@
|
||||||
>
|
>
|
||||||
<input v-model="options.includes[key]" type="checkbox"><i class="form-icon" /> {{ $tc(`word.${key}`, 2) }}
|
<input v-model="options.includes[key]" type="checkbox"><i class="form-icon" /> {{ $tc(`word.${key}`, 2) }}
|
||||||
</label>
|
</label>
|
||||||
<div v-if="customizations.exportByChunks">
|
<div v-if="clientCustoms.exportByChunks">
|
||||||
<div class="h6 mt-4 mb-2">
|
<div class="h6 mt-4 mb-2">
|
||||||
{{ $t('message.newInserStmtEvery') }}:
|
{{ $t('message.newInserStmtEvery') }}:
|
||||||
</div>
|
</div>
|
||||||
|
@ -269,23 +269,27 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import moment from 'moment';
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
|
import * as moment from 'moment';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { SchemaInfos } from 'common/interfaces/antares';
|
||||||
|
import { ExportState, TableParams } from 'common/interfaces/exporter';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import customizations from 'common/customizations';
|
|
||||||
import Application from '@/ipc-api/Application';
|
import Application from '@/ipc-api/Application';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
|
import { Customizations } from 'common/interfaces/customizations';
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'ModalExportSchema',
|
|
||||||
props: {
|
|
||||||
selectedSchema: String
|
selectedSchema: String
|
||||||
},
|
});
|
||||||
emits: ['close'],
|
|
||||||
setup () {
|
const emit = defineEmits(['close']);
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
|
@ -293,78 +297,153 @@ export default {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getWorkspace,
|
getWorkspace,
|
||||||
getDatabaseVariable,
|
|
||||||
refreshSchema
|
refreshSchema
|
||||||
} = workspacesStore;
|
} = workspacesStore;
|
||||||
|
|
||||||
return {
|
const isExporting = ref(false);
|
||||||
addNotification,
|
const isRefreshing = ref(false);
|
||||||
selectedWorkspace,
|
const progressPercentage = ref(0);
|
||||||
getWorkspace,
|
const progressStatus = ref('');
|
||||||
getDatabaseVariable,
|
const tables: Ref<TableParams[]> = ref([]);
|
||||||
refreshSchema
|
const options = ref({
|
||||||
};
|
includes: {} as {[key: string]: boolean},
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
isExporting: false,
|
|
||||||
isRefreshing: false,
|
|
||||||
progressPercentage: 0,
|
|
||||||
progressStatus: '',
|
|
||||||
tables: [],
|
|
||||||
options: {
|
|
||||||
includes: {},
|
|
||||||
outputFormat: 'sql',
|
outputFormat: 'sql',
|
||||||
sqlInsertAfter: 250,
|
sqlInsertAfter: 250,
|
||||||
sqlInsertDivider: 'bytes'
|
sqlInsertDivider: 'bytes'
|
||||||
},
|
});
|
||||||
basePath: ''
|
const basePath = ref('');
|
||||||
};
|
|
||||||
},
|
const currentWorkspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||||
computed: {
|
const clientCustoms: Ref<Customizations> = computed(() => currentWorkspace.value.customizations);
|
||||||
currentWorkspace () {
|
const schemaItems = computed(() => {
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
const db: SchemaInfos = currentWorkspace.value.structure.find((db: SchemaInfos) => db.name === props.selectedSchema);
|
||||||
},
|
|
||||||
customizations () {
|
|
||||||
return this.currentWorkspace.customizations;
|
|
||||||
},
|
|
||||||
schemaItems () {
|
|
||||||
const db = this.currentWorkspace.structure.find(db => db.name === this.selectedSchema);
|
|
||||||
if (db)
|
if (db)
|
||||||
return db.tables.filter(table => table.type === 'table');
|
return db.tables.filter(table => table.type === 'table');
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
},
|
});
|
||||||
filename () {
|
const filename = computed(() => {
|
||||||
const date = moment().format('YYYY-MM-DD');
|
const date = moment().format('YYYY-MM-DD');
|
||||||
return `${this.selectedSchema}_${date}.${this.options.outputFormat}`;
|
return `${props.selectedSchema}_${date}.${options.value.outputFormat}`;
|
||||||
},
|
});
|
||||||
dumpFilePath () {
|
const dumpFilePath = computed(() => `${basePath.value}/${filename.value}`);
|
||||||
return `${this.basePath}/${this.filename}`;
|
const includeStructureStatus = computed(() => {
|
||||||
},
|
if (tables.value.every(item => item.includeStructure)) return 1;
|
||||||
includeStructureStatus () {
|
else if (tables.value.some(item => item.includeStructure)) return 2;
|
||||||
if (this.tables.every(item => item.includeStructure)) return 1;
|
|
||||||
else if (this.tables.some(item => item.includeStructure)) return 2;
|
|
||||||
else return 0;
|
else return 0;
|
||||||
},
|
});
|
||||||
includeContentStatus () {
|
const includeContentStatus = computed(() => {
|
||||||
if (this.tables.every(item => item.includeContent)) return 1;
|
if (tables.value.every(item => item.includeContent)) return 1;
|
||||||
else if (this.tables.some(item => item.includeContent)) return 2;
|
else if (tables.value.some(item => item.includeContent)) return 2;
|
||||||
else return 0;
|
else return 0;
|
||||||
},
|
});
|
||||||
includeDropStatementStatus () {
|
const includeDropStatementStatus = computed(() => {
|
||||||
if (this.tables.every(item => item.includeDropStatement)) return 1;
|
if (tables.value.every(item => item.includeDropStatement)) return 1;
|
||||||
else if (this.tables.some(item => item.includeDropStatement)) return 2;
|
else if (tables.value.some(item => item.includeDropStatement)) return 2;
|
||||||
else return 0;
|
else return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const startExport = async () => {
|
||||||
|
isExporting.value = true;
|
||||||
|
const { uid, client } = currentWorkspace.value;
|
||||||
|
const params = {
|
||||||
|
uid,
|
||||||
|
type: client,
|
||||||
|
schema: props.selectedSchema,
|
||||||
|
outputFile: dumpFilePath.value,
|
||||||
|
tables: [...tables.value],
|
||||||
|
...options.value
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status, response } = await Schema.export(params);
|
||||||
|
if (status === 'success')
|
||||||
|
progressStatus.value = response.cancelled ? t('word.aborted') : t('word.completed');
|
||||||
|
else {
|
||||||
|
progressStatus.value = response;
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
},
|
|
||||||
async created () {
|
|
||||||
if (!this.schemaItems.length) await this.refresh();
|
|
||||||
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
isExporting.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
this.basePath = await Application.getDownloadPathDirectory();
|
const updateProgress = (event: Event, state: ExportState) => {
|
||||||
this.tables = this.schemaItems.map(item => ({
|
progressPercentage.value = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
||||||
|
switch (state.op) {
|
||||||
|
case 'PROCESSING':
|
||||||
|
progressStatus.value = t('message.processingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
case 'FETCH':
|
||||||
|
progressStatus.value = t('message.fechingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
case 'WRITE':
|
||||||
|
progressStatus.value = t('message.writingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeModal = async () => {
|
||||||
|
let willClose = true;
|
||||||
|
if (isExporting.value) {
|
||||||
|
willClose = false;
|
||||||
|
const { response } = await Schema.abortExport();
|
||||||
|
willClose = response.willAbort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (willClose)
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (e.key === 'Escape')
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkAllTables = () => {
|
||||||
|
tables.value = tables.value.map(item => ({ ...item, includeStructure: true, includeContent: true, includeDropStatement: true }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const uncheckAllTables = () => {
|
||||||
|
tables.value = tables.value.map(item => ({ ...item, includeStructure: false, includeContent: false, includeDropStatement: false }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleAllTablesOption = (option: 'includeStructure' | 'includeContent' |'includeDropStatement') => {
|
||||||
|
const options = {
|
||||||
|
includeStructure: includeStructureStatus.value,
|
||||||
|
includeContent: includeContentStatus.value,
|
||||||
|
includeDropStatement: includeDropStatementStatus.value
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options[option] !== 1)
|
||||||
|
tables.value = tables.value.map(item => ({ ...item, [option]: true }));
|
||||||
|
else
|
||||||
|
tables.value = tables.value.map(item => ({ ...item, [option]: false }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const refresh = async () => {
|
||||||
|
isRefreshing.value = true;
|
||||||
|
await refreshSchema({ uid: currentWorkspace.value.uid, schema: props.selectedSchema });
|
||||||
|
isRefreshing.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const openPathDialog = async () => {
|
||||||
|
const result = await Application.showOpenDialog({ properties: ['openDirectory'] });
|
||||||
|
if (result && !result.canceled)
|
||||||
|
basePath.value = result.filePaths[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
if (!schemaItems.value.length) await refresh();
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
|
basePath.value = await Application.getDownloadPathDirectory();
|
||||||
|
tables.value = schemaItems.value.map(item => ({
|
||||||
table: item.name,
|
table: item.name,
|
||||||
includeStructure: true,
|
includeStructure: true,
|
||||||
includeContent: true,
|
includeContent: true,
|
||||||
|
@ -373,103 +452,20 @@ export default {
|
||||||
|
|
||||||
const structure = ['functions', 'views', 'triggers', 'routines', 'schedulers'];
|
const structure = ['functions', 'views', 'triggers', 'routines', 'schedulers'];
|
||||||
|
|
||||||
structure.forEach(feat => {
|
structure.forEach((feat: keyof Customizations) => {
|
||||||
const val = customizations[this.currentWorkspace.client][feat];
|
const val = clientCustoms.value[feat];
|
||||||
if (val)
|
if (val)
|
||||||
this.options.includes[feat] = true;
|
options.value.includes[feat] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('export-progress', this.updateProgress);
|
ipcRenderer.on('export-progress', updateProgress);
|
||||||
},
|
})();
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
ipcRenderer.off('export-progress', this.updateProgress);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async startExport () {
|
|
||||||
this.isExporting = true;
|
|
||||||
const { uid, client } = this.currentWorkspace;
|
|
||||||
const params = {
|
|
||||||
uid,
|
|
||||||
type: client,
|
|
||||||
schema: this.selectedSchema,
|
|
||||||
outputFile: this.dumpFilePath,
|
|
||||||
tables: [...this.tables],
|
|
||||||
...this.options
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
onBeforeUnmount(() => {
|
||||||
const { status, response } = await Schema.export(params);
|
window.removeEventListener('keydown', onKey);
|
||||||
if (status === 'success')
|
ipcRenderer.off('export-progress', updateProgress);
|
||||||
this.progressStatus = response.cancelled ? this.$t('word.aborted') : this.$t('word.completed');
|
});
|
||||||
else {
|
|
||||||
this.progressStatus = response;
|
|
||||||
this.addNotification({ status: 'error', message: response });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isExporting = false;
|
|
||||||
},
|
|
||||||
updateProgress (event, state) {
|
|
||||||
this.progressPercentage = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
|
||||||
switch (state.op) {
|
|
||||||
case 'PROCESSING':
|
|
||||||
this.progressStatus = this.$t('message.processingTableExport', { table: state.currentItem });
|
|
||||||
break;
|
|
||||||
case 'FETCH':
|
|
||||||
this.progressStatus = this.$t('message.fechingTableExport', { table: state.currentItem });
|
|
||||||
break;
|
|
||||||
case 'WRITE':
|
|
||||||
this.progressStatus = this.$t('message.writingTableExport', { table: state.currentItem });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async closeModal () {
|
|
||||||
let willClose = true;
|
|
||||||
if (this.isExporting) {
|
|
||||||
willClose = false;
|
|
||||||
const { response } = await Schema.abortExport();
|
|
||||||
willClose = response.willAbort;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (willClose)
|
|
||||||
this.$emit('close');
|
|
||||||
},
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (e.key === 'Escape')
|
|
||||||
this.closeModal();
|
|
||||||
},
|
|
||||||
checkAllTables () {
|
|
||||||
this.tables = this.tables.map(item => ({ ...item, includeStructure: true, includeContent: true, includeDropStatement: true }));
|
|
||||||
},
|
|
||||||
uncheckAllTables () {
|
|
||||||
this.tables = this.tables.map(item => ({ ...item, includeStructure: false, includeContent: false, includeDropStatement: false }));
|
|
||||||
},
|
|
||||||
toggleAllTablesOption (option) {
|
|
||||||
const options = ['includeStructure', 'includeContent', 'includeDropStatement'];
|
|
||||||
if (!options.includes(option)) return;
|
|
||||||
|
|
||||||
if (this[`${option}Status`] !== 1)
|
|
||||||
this.tables = this.tables.map(item => ({ ...item, [option]: true }));
|
|
||||||
else
|
|
||||||
this.tables = this.tables.map(item => ({ ...item, [option]: false }));
|
|
||||||
},
|
|
||||||
async refresh () {
|
|
||||||
this.isRefreshing = true;
|
|
||||||
await this.refreshSchema({ uid: this.currentWorkspace.uid, schema: this.selectedSchema });
|
|
||||||
this.isRefreshing = false;
|
|
||||||
},
|
|
||||||
async openPathDialog () {
|
|
||||||
const result = await Application.showOpenDialog({ properties: ['openDirectory'] });
|
|
||||||
if (result && !result.canceled)
|
|
||||||
this.basePath = result.filePaths[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -185,76 +185,133 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import moment from 'moment';
|
import { computed, onBeforeMount, onMounted, Prop, Ref, ref, watch } from 'vue';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { TableField, TableForeign } from 'common/interfaces/antares';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes';
|
import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import Tables from '@/ipc-api/Tables';
|
import Tables from '@/ipc-api/Tables';
|
||||||
import FakerSelect from '@/components/FakerSelect';
|
import FakerSelect from '@/components/FakerSelect.vue';
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'ModalFakerRows',
|
|
||||||
components: {
|
|
||||||
FakerSelect
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
tabUid: [String, Number],
|
tabUid: [String, Number],
|
||||||
fields: Array,
|
fields: Array as Prop<TableField[]>,
|
||||||
keyUsage: Array
|
keyUsage: Array as Prop<TableForeign[]>
|
||||||
},
|
});
|
||||||
emits: ['reload', 'hide'],
|
|
||||||
setup () {
|
const emit = defineEmits(['reload', 'hide']);
|
||||||
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
|
||||||
const { getWorkspace, getWorkspaceTab } = workspacesStore;
|
const { getWorkspace } = workspacesStore;
|
||||||
|
|
||||||
return {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
addNotification,
|
const localRow: Ref<{[key: string]: any}> = ref({});
|
||||||
selectedWorkspace,
|
const fieldsToExclude = ref([]);
|
||||||
getWorkspace,
|
const nInserts = ref(1);
|
||||||
getWorkspaceTab
|
const isInserting = ref(false);
|
||||||
};
|
const fakerLocale = ref('en');
|
||||||
},
|
|
||||||
data () {
|
const workspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||||
return {
|
const foreignKeys = computed(() => props.keyUsage.map(key => key.field));
|
||||||
localRow: {},
|
const hasFakes = computed(() => Object.keys(localRow.value).some(field => 'group' in localRow.value[field] && localRow.value[field].group !== 'manual'));
|
||||||
fieldsToExclude: [],
|
|
||||||
nInserts: 1,
|
watch(nInserts, (val) => {
|
||||||
isInserting: false,
|
|
||||||
fakerLocale: 'en'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
workspace () {
|
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
|
||||||
},
|
|
||||||
foreignKeys () {
|
|
||||||
return this.keyUsage.map(key => key.field);
|
|
||||||
},
|
|
||||||
hasFakes () {
|
|
||||||
return Object.keys(this.localRow).some(field => 'group' in this.localRow[field] && this.localRow[field].group !== 'manual');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
nInserts (val) {
|
|
||||||
if (!val || val < 1)
|
if (!val || val < 1)
|
||||||
this.nInserts = 1;
|
nInserts.value = 1;
|
||||||
else if (val > 1000)
|
else if (val > 1000)
|
||||||
this.nInserts = 1000;
|
nInserts.value = 1000;
|
||||||
}
|
});
|
||||||
},
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
const rowObj = {};
|
|
||||||
|
|
||||||
for (const field of this.fields) {
|
const typeClass = (type: string) => {
|
||||||
|
if (type)
|
||||||
|
return `type-${type.toLowerCase().replaceAll(' ', '_').replaceAll('"', '')}`;
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertRows = async () => {
|
||||||
|
isInserting.value = true;
|
||||||
|
const rowToInsert = localRow.value;
|
||||||
|
|
||||||
|
Object.keys(rowToInsert).forEach(key => {
|
||||||
|
if (fieldsToExclude.value.includes(key))
|
||||||
|
delete rowToInsert[key];
|
||||||
|
|
||||||
|
if (typeof rowToInsert[key] === 'undefined')
|
||||||
|
delete rowToInsert[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
const fieldTypes: {[key: string]: string} = {};
|
||||||
|
props.fields.forEach(field => {
|
||||||
|
fieldTypes[field.name] = field.type;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status, response } = await Tables.insertTableFakeRows({
|
||||||
|
uid: selectedWorkspace.value,
|
||||||
|
schema: workspace.value.breadcrumbs.schema,
|
||||||
|
table: workspace.value.breadcrumbs.table,
|
||||||
|
row: rowToInsert,
|
||||||
|
repeat: nInserts.value,
|
||||||
|
fields: fieldTypes,
|
||||||
|
locale: fakerLocale.value
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status === 'success') {
|
||||||
|
closeModal();
|
||||||
|
emit('reload');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
|
||||||
|
isInserting.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
emit('hide');
|
||||||
|
};
|
||||||
|
|
||||||
|
const fieldLength = (field: TableField) => {
|
||||||
|
if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null;
|
||||||
|
else if (TEXT.includes(field.type)) return Number(field.charLength);
|
||||||
|
return Number(field.length);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const toggleFields = (event: any, field: TableField) => {
|
||||||
|
if (event.target.checked)
|
||||||
|
fieldsToExclude.value = fieldsToExclude.value.filter(f => f !== field.name);
|
||||||
|
else
|
||||||
|
fieldsToExclude.value = [...fieldsToExclude.value, field.name];
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (e.key === 'Escape')
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapNumber = (num: number) => {
|
||||||
|
if (!num) return '';
|
||||||
|
return `(${num})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const rowObj: {[key: string]: unknown} = {};
|
||||||
|
|
||||||
|
for (const field of props.fields) {
|
||||||
let fieldDefault;
|
let fieldDefault;
|
||||||
|
|
||||||
if (field.default === 'NULL') fieldDefault = null;
|
if (field.default === 'NULL') fieldDefault = null;
|
||||||
|
@ -291,95 +348,15 @@ export default {
|
||||||
rowObj[field.name] = { value: fieldDefault };
|
rowObj[field.name] = { value: fieldDefault };
|
||||||
|
|
||||||
if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields
|
if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields
|
||||||
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
fieldsToExclude.value = [...fieldsToExclude.value, field.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localRow = { ...rowObj };
|
localRow.value = { ...rowObj };
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
typeClass (type) {
|
|
||||||
if (type)
|
|
||||||
return `type-${type.toLowerCase().replaceAll(' ', '_').replaceAll('"', '')}`;
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
async insertRows () {
|
|
||||||
this.isInserting = true;
|
|
||||||
const rowToInsert = this.localRow;
|
|
||||||
|
|
||||||
Object.keys(rowToInsert).forEach(key => {
|
|
||||||
if (this.fieldsToExclude.includes(key))
|
|
||||||
delete rowToInsert[key];
|
|
||||||
|
|
||||||
if (typeof rowToInsert[key] === 'undefined')
|
|
||||||
delete rowToInsert[key];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const fieldTypes = {};
|
onBeforeMount(() => {
|
||||||
this.fields.forEach(field => {
|
window.removeEventListener('keydown', onKey);
|
||||||
fieldTypes[field.name] = field.type;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
|
||||||
const { status, response } = await Tables.insertTableFakeRows({
|
|
||||||
uid: this.selectedWorkspace,
|
|
||||||
schema: this.workspace.breadcrumbs.schema,
|
|
||||||
table: this.workspace.breadcrumbs.table,
|
|
||||||
row: rowToInsert,
|
|
||||||
repeat: this.nInserts,
|
|
||||||
fields: fieldTypes,
|
|
||||||
locale: this.fakerLocale
|
|
||||||
});
|
|
||||||
|
|
||||||
if (status === 'success') {
|
|
||||||
this.closeModal();
|
|
||||||
this.$emit('reload');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.addNotification({ status: 'error', message: response });
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isInserting = false;
|
|
||||||
},
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('hide');
|
|
||||||
},
|
|
||||||
fieldLength (field) {
|
|
||||||
if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null;
|
|
||||||
else if (TEXT.includes(field.type)) return Number(field.charLength);
|
|
||||||
return Number(field.length);
|
|
||||||
},
|
|
||||||
toggleFields (event, field) {
|
|
||||||
if (event.target.checked)
|
|
||||||
this.fieldsToExclude = this.fieldsToExclude.filter(f => f !== field.name);
|
|
||||||
else
|
|
||||||
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
|
||||||
},
|
|
||||||
filesChange (event, field) {
|
|
||||||
const { files } = event.target;
|
|
||||||
if (!files.length) return;
|
|
||||||
|
|
||||||
this.localRow[field] = files[0].path;
|
|
||||||
},
|
|
||||||
getKeyUsage (keyName) {
|
|
||||||
return this.keyUsage.find(key => key.field === keyName);
|
|
||||||
},
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (e.key === 'Escape')
|
|
||||||
this.closeModal();
|
|
||||||
},
|
|
||||||
wrapNumber (num) {
|
|
||||||
if (!num) return '';
|
|
||||||
return `(${num})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -97,129 +97,115 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import moment from 'moment';
|
import { Component, computed, ComputedRef, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref, watch } from 'vue';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
import { useHistoryStore } from '@/stores/history';
|
import { useHistoryStore } from '@/stores/history';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
|
||||||
|
interface HistoryRow {
|
||||||
|
uid:string;
|
||||||
|
sql: string;
|
||||||
|
schema: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ModalHistory',
|
|
||||||
components: {
|
|
||||||
BaseVirtualScroll
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
connection: Object
|
|
||||||
},
|
|
||||||
emits: ['select-query', 'close'],
|
|
||||||
setup () {
|
|
||||||
const { getHistoryByWorkspace, deleteQueryFromHistory } = useHistoryStore();
|
const { getHistoryByWorkspace, deleteQueryFromHistory } = useHistoryStore();
|
||||||
const { getConnectionName } = useConnectionsStore();
|
const { getConnectionName } = useConnectionsStore();
|
||||||
const { addNotification } = useNotificationsStore();
|
|
||||||
|
|
||||||
return {
|
const props = defineProps({
|
||||||
getHistoryByWorkspace,
|
connection: Object as Prop<ConnectionParams>
|
||||||
deleteQueryFromHistory,
|
});
|
||||||
getConnectionName,
|
|
||||||
addNotification
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
resultsSize: 1000,
|
|
||||||
isQuering: false,
|
|
||||||
scrollElement: null,
|
|
||||||
searchTermInterval: null,
|
|
||||||
searchTerm: '',
|
|
||||||
localSearchTerm: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
connectionName () {
|
|
||||||
return this.getConnectionName(this.connection.uid);
|
|
||||||
},
|
|
||||||
history () {
|
|
||||||
return this.getHistoryByWorkspace(this.connection.uid) || [];
|
|
||||||
},
|
|
||||||
filteredHistory () {
|
|
||||||
return this.history.filter(q => q.sql.toLowerCase().search(this.searchTerm.toLowerCase()) >= 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
searchTerm () {
|
|
||||||
clearTimeout(this.searchTermInterval);
|
|
||||||
|
|
||||||
this.searchTermInterval = setTimeout(() => {
|
const emit = defineEmits(['select-query', 'close']);
|
||||||
this.localSearchTerm = this.searchTerm;
|
|
||||||
|
const table: Ref<HTMLDivElement> = ref(null);
|
||||||
|
const resultTable: Ref<Component & { updateWindow: () => void }> = ref(null);
|
||||||
|
const tableWrapper: Ref<HTMLDivElement> = ref(null);
|
||||||
|
const searchForm: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const resultsSize = ref(1000);
|
||||||
|
const scrollElement: Ref<HTMLDivElement> = ref(null);
|
||||||
|
const searchTermInterval: Ref<NodeJS.Timeout> = ref(null);
|
||||||
|
const searchTerm = ref('');
|
||||||
|
const localSearchTerm = ref('');
|
||||||
|
|
||||||
|
const connectionName = computed(() => getConnectionName(props.connection.uid));
|
||||||
|
const history: ComputedRef<HistoryRow[]> = computed(() => (getHistoryByWorkspace(props.connection.uid) || []));
|
||||||
|
const filteredHistory = computed(() => history.value.filter(q => q.sql.toLowerCase().search(searchTerm.value.toLowerCase()) >= 0));
|
||||||
|
|
||||||
|
watch(searchTerm, () => {
|
||||||
|
clearTimeout(searchTermInterval.value);
|
||||||
|
|
||||||
|
searchTermInterval.value = setTimeout(() => {
|
||||||
|
localSearchTerm.value = searchTerm.value;
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
});
|
||||||
},
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey, { capture: true });
|
|
||||||
},
|
|
||||||
updated () {
|
|
||||||
if (this.$refs.table)
|
|
||||||
this.refreshScroller();
|
|
||||||
|
|
||||||
if (this.$refs.tableWrapper)
|
const copyQuery = (sql: string) => {
|
||||||
this.scrollElement = this.$refs.tableWrapper;
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.resizeResults();
|
|
||||||
window.addEventListener('resize', this.resizeResults);
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey, { capture: true });
|
|
||||||
window.removeEventListener('resize', this.resizeResults);
|
|
||||||
clearInterval(this.refreshInterval);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
copyQuery (sql) {
|
|
||||||
navigator.clipboard.writeText(sql);
|
navigator.clipboard.writeText(sql);
|
||||||
},
|
};
|
||||||
deleteQuery (query) {
|
|
||||||
this.deleteQueryFromHistory({
|
const deleteQuery = (query: HistoryRow[]) => {
|
||||||
workspace: this.connection.uid,
|
deleteQueryFromHistory({
|
||||||
|
workspace: props.connection.uid,
|
||||||
...query
|
...query
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
resizeResults () {
|
|
||||||
if (this.$refs.resultTable) {
|
const resizeResults = () => {
|
||||||
const el = this.$refs.tableWrapper.parentElement;
|
if (resultTable.value) {
|
||||||
|
const el = tableWrapper.value.parentElement;
|
||||||
|
|
||||||
if (el)
|
if (el)
|
||||||
this.resultsSize = el.offsetHeight - this.$refs.searchForm.offsetHeight;
|
resultsSize.value = el.offsetHeight - searchForm.value.offsetHeight;
|
||||||
|
|
||||||
this.$refs.resultTable.updateWindow();
|
resultTable.value.updateWindow();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
formatDate (date) {
|
|
||||||
return moment(date).isValid() ? moment(date).format('HH:mm:ss - YYYY/MM/DD') : date;
|
const formatDate = (date: Date) => moment(date).isValid() ? moment(date).format('HH:mm:ss - YYYY/MM/DD') : date;
|
||||||
},
|
const refreshScroller = () => resizeResults();
|
||||||
refreshScroller () {
|
const closeModal = () => emit('close');
|
||||||
this.resizeResults();
|
|
||||||
},
|
const highlightWord = (string: string) => {
|
||||||
closeModal () {
|
|
||||||
this.$emit('close');
|
|
||||||
},
|
|
||||||
highlightWord (string) {
|
|
||||||
string = string.replaceAll('<', '<').replaceAll('>', '>');
|
string = string.replaceAll('<', '<').replaceAll('>', '>');
|
||||||
|
|
||||||
if (this.searchTerm) {
|
if (searchTerm.value) {
|
||||||
const regexp = new RegExp(`(${this.searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
const regexp = new RegExp(`(${searchTerm.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
||||||
return string.replace(regexp, '<span class="text-primary text-bold">$1</span>');
|
return string.replace(regexp, '<span class="text-primary text-bold">$1</span>');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return string;
|
return string;
|
||||||
},
|
};
|
||||||
onKey (e) {
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
this.closeModal();
|
closeModal();
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey, { capture: true });
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
if (table.value)
|
||||||
|
refreshScroller();
|
||||||
|
|
||||||
|
if (tableWrapper.value)
|
||||||
|
scrollElement.value = tableWrapper.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resizeResults();
|
||||||
|
window.addEventListener('resize', resizeResults);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', onKey, { capture: true });
|
||||||
|
window.removeEventListener('resize', resizeResults);
|
||||||
|
clearInterval(searchTermInterval.value);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -49,22 +49,19 @@
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import moment from 'moment';
|
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
import { storeToRefs } from 'pinia';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { ImportState } from 'common/interfaces/importer';
|
||||||
|
|
||||||
export default {
|
const { t } = useI18n();
|
||||||
name: 'ModalImportSchema',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
selectedSchema: String
|
|
||||||
},
|
|
||||||
emits: ['close'],
|
|
||||||
setup () {
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
|
@ -72,101 +69,99 @@ export default {
|
||||||
|
|
||||||
const { getWorkspace, refreshSchema } = workspacesStore;
|
const { getWorkspace, refreshSchema } = workspacesStore;
|
||||||
|
|
||||||
return {
|
const props = defineProps({
|
||||||
addNotification,
|
selectedSchema: String
|
||||||
selectedWorkspace,
|
});
|
||||||
getWorkspace,
|
|
||||||
refreshSchema
|
const emit = defineEmits(['close']);
|
||||||
};
|
|
||||||
},
|
const sqlFile = ref('');
|
||||||
data () {
|
const isImporting = ref(false);
|
||||||
return {
|
const progressPercentage = ref(0);
|
||||||
sqlFile: '',
|
const queryCount = ref(0);
|
||||||
isImporting: false,
|
const completed = ref(false);
|
||||||
progressPercentage: 0,
|
const progressStatus = ref('Reading');
|
||||||
queryCount: 0,
|
const queryErrors: Ref<{time: string; message: string}[]> = ref([]);
|
||||||
completed: false,
|
|
||||||
progressStatus: 'Reading',
|
const currentWorkspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||||
queryErrors: []
|
|
||||||
};
|
const formattedQueryErrors = computed(() => {
|
||||||
},
|
return queryErrors.value.map(err =>
|
||||||
computed: {
|
|
||||||
currentWorkspace () {
|
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
|
||||||
},
|
|
||||||
formattedQueryErrors () {
|
|
||||||
return this.queryErrors.map(err =>
|
|
||||||
`Time: ${moment(err.time).format('HH:mm:ss.S')} (${err.time})\nError: ${err.message}`
|
`Time: ${moment(err.time).format('HH:mm:ss.S')} (${err.time})\nError: ${err.message}`
|
||||||
).join('\n\n');
|
).join('\n\n');
|
||||||
}
|
});
|
||||||
},
|
|
||||||
async created () {
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
|
|
||||||
ipcRenderer.on('import-progress', this.updateProgress);
|
const startImport = async (file: string) => {
|
||||||
ipcRenderer.on('query-error', this.handleQueryError);
|
isImporting.value = true;
|
||||||
},
|
sqlFile.value = file;
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
ipcRenderer.off('import-progress', this.updateProgress);
|
|
||||||
ipcRenderer.off('query-error', this.handleQueryError);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async startImport (sqlFile) {
|
|
||||||
this.isImporting = true;
|
|
||||||
this.sqlFile = sqlFile;
|
|
||||||
|
|
||||||
const { uid, client } = this.currentWorkspace;
|
const { uid, client } = currentWorkspace.value;
|
||||||
const params = {
|
const params = {
|
||||||
uid,
|
uid,
|
||||||
type: client,
|
type: client,
|
||||||
schema: this.selectedSchema,
|
schema: props.selectedSchema,
|
||||||
file: sqlFile
|
file: sqlFile.value
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.completed = false;
|
completed.value = false;
|
||||||
const { status, response } = await Schema.import(params);
|
const { status, response } = await Schema.import(params);
|
||||||
|
|
||||||
if (status === 'success')
|
if (status === 'success')
|
||||||
this.progressStatus = response.cancelled ? this.$t('word.aborted') : this.$t('word.completed');
|
progressStatus.value = response.cancelled ? t('word.aborted') : t('word.completed');
|
||||||
else {
|
else {
|
||||||
this.progressStatus = response;
|
progressStatus.value = response;
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
this.refreshSchema({ uid, schema: this.selectedSchema });
|
refreshSchema({ uid, schema: props.selectedSchema });
|
||||||
this.completed = true;
|
completed.value = true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isImporting = false;
|
isImporting.value = false;
|
||||||
},
|
};
|
||||||
updateProgress (event, state) {
|
|
||||||
this.progressPercentage = Number(state.percentage).toFixed(1);
|
const updateProgress = (event: Event, state: ImportState) => {
|
||||||
this.queryCount = Number(state.queryCount);
|
progressPercentage.value = parseFloat(Number(state.percentage).toFixed(1));
|
||||||
},
|
queryCount.value = Number(state.queryCount);
|
||||||
handleQueryError (event, err) {
|
};
|
||||||
this.queryErrors.push(err);
|
|
||||||
},
|
const handleQueryError = (event: Event, err: { time: string; message: string }) => {
|
||||||
async closeModal () {
|
queryErrors.value.push(err);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeModal = async () => {
|
||||||
let willClose = true;
|
let willClose = true;
|
||||||
if (this.isImporting) {
|
if (isImporting.value) {
|
||||||
willClose = false;
|
willClose = false;
|
||||||
const { response } = await Schema.abortImport();
|
const { response } = await Schema.abortImport();
|
||||||
willClose = response.willAbort;
|
willClose = response.willAbort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (willClose)
|
if (willClose)
|
||||||
this.$emit('close');
|
emit('close');
|
||||||
},
|
};
|
||||||
onKey (e) {
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
this.closeModal();
|
closeModal();
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
|
||||||
|
ipcRenderer.on('import-progress', updateProgress);
|
||||||
|
ipcRenderer.on('query-error', handleQueryError);
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', onKey);
|
||||||
|
ipcRenderer.off('import-progress', updateProgress);
|
||||||
|
ipcRenderer.off('query-error', handleQueryError);
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({ startImport });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -67,16 +67,13 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ModalNewSchema',
|
|
||||||
emits: ['reload', 'close'],
|
|
||||||
setup () {
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
|
@ -84,74 +81,60 @@ export default {
|
||||||
|
|
||||||
const { getWorkspace, getDatabaseVariable } = workspacesStore;
|
const { getWorkspace, getDatabaseVariable } = workspacesStore;
|
||||||
|
|
||||||
return {
|
const emit = defineEmits(['reload', 'close']);
|
||||||
addNotification,
|
|
||||||
selectedWorkspace,
|
const firstInput: Ref<HTMLInputElement> = ref(null);
|
||||||
getWorkspace,
|
const isLoading = ref(false);
|
||||||
getDatabaseVariable
|
const database = ref({
|
||||||
};
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
isLoading: false,
|
|
||||||
database: {
|
|
||||||
name: '',
|
name: '',
|
||||||
collation: ''
|
collation: ''
|
||||||
}
|
});
|
||||||
};
|
|
||||||
},
|
const collations = computed(() => getWorkspace(selectedWorkspace.value).collations);
|
||||||
computed: {
|
const customizations = computed(() => getWorkspace(selectedWorkspace.value).customizations);
|
||||||
collations () {
|
const defaultCollation = computed(() => getDatabaseVariable(selectedWorkspace.value, 'collation_server') ? getDatabaseVariable(selectedWorkspace.value, 'collation_server').value : '');
|
||||||
return this.getWorkspace(this.selectedWorkspace).collations;
|
|
||||||
},
|
database.value = { ...database.value, collation: defaultCollation.value };
|
||||||
customizations () {
|
|
||||||
return this.getWorkspace(this.selectedWorkspace).customizations;
|
const createSchema = async () => {
|
||||||
},
|
isLoading.value = true;
|
||||||
defaultCollation () {
|
|
||||||
return this.getDatabaseVariable(this.selectedWorkspace, 'collation_server') ? this.getDatabaseVariable(this.selectedWorkspace, 'collation_server').value : '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.database = { ...this.database, collation: this.defaultCollation };
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.$refs.firstInput.focus();
|
|
||||||
}, 20);
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async createSchema () {
|
|
||||||
this.isLoading = true;
|
|
||||||
try {
|
try {
|
||||||
const { status, response } = await Schema.createSchema({
|
const { status, response } = await Schema.createSchema({
|
||||||
uid: this.selectedWorkspace,
|
uid: selectedWorkspace.value,
|
||||||
...this.database
|
...database.value
|
||||||
});
|
});
|
||||||
|
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
this.closeModal();
|
closeModal();
|
||||||
this.$emit('reload');
|
emit('reload');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
this.isLoading = false;
|
isLoading.value = false;
|
||||||
},
|
};
|
||||||
closeModal () {
|
|
||||||
this.$emit('close');
|
const closeModal = () => {
|
||||||
},
|
emit('close');
|
||||||
onKey (e) {
|
};
|
||||||
|
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
this.closeModal();
|
closeModal();
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey);
|
||||||
|
setTimeout(() => {
|
||||||
|
firstInput.value.focus();
|
||||||
|
}, 20);
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', onKey);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,366 +0,0 @@
|
||||||
<template>
|
|
||||||
<Teleport to="#window-content">
|
|
||||||
<div class="modal active">
|
|
||||||
<a class="modal-overlay" @click.stop="closeModal" />
|
|
||||||
<div class="modal-container p-0">
|
|
||||||
<div class="modal-header pl-2">
|
|
||||||
<div class="modal-title h6">
|
|
||||||
<div class="d-flex">
|
|
||||||
<i class="mdi mdi-24px mdi-playlist-plus mr-1" />
|
|
||||||
<span class="cut-text">{{ $t('message.addNewRow') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
|
|
||||||
</div>
|
|
||||||
<div class="modal-body pb-0">
|
|
||||||
<div class="content">
|
|
||||||
<form class="form-horizontal">
|
|
||||||
<fieldset :disabled="isInserting">
|
|
||||||
<div
|
|
||||||
v-for="(field, key) in fields"
|
|
||||||
:key="field.name"
|
|
||||||
class="form-group"
|
|
||||||
>
|
|
||||||
<div class="col-4 col-sm-12">
|
|
||||||
<label class="form-label" :title="field.name">{{ field.name }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="input-group col-8 col-sm-12">
|
|
||||||
<ForeignKeySelect
|
|
||||||
v-if="foreignKeys.includes(field.name)"
|
|
||||||
ref="formInput"
|
|
||||||
v-model="localRow[field.name]"
|
|
||||||
class="form-select"
|
|
||||||
:key-usage="getKeyUsage(field.name)"
|
|
||||||
:disabled="fieldsToExclude.includes(field.name)"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
v-else-if="inputProps(field).mask"
|
|
||||||
ref="formInput"
|
|
||||||
v-model="localRow[field.name]"
|
|
||||||
v-mask="inputProps(field).mask"
|
|
||||||
class="form-input"
|
|
||||||
:type="inputProps(field).type"
|
|
||||||
:disabled="fieldsToExclude.includes(field.name)"
|
|
||||||
:tabindex="key+1"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-else-if="inputProps(field).type === 'file'"
|
|
||||||
ref="formInput"
|
|
||||||
class="form-input"
|
|
||||||
type="file"
|
|
||||||
:disabled="fieldsToExclude.includes(field.name)"
|
|
||||||
:tabindex="key+1"
|
|
||||||
@change="filesChange($event,field.name)"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-else-if="inputProps(field).type === 'number'"
|
|
||||||
ref="formInput"
|
|
||||||
v-model="localRow[field.name]"
|
|
||||||
class="form-input"
|
|
||||||
step="any"
|
|
||||||
:type="inputProps(field).type"
|
|
||||||
:disabled="fieldsToExclude.includes(field.name)"
|
|
||||||
:tabindex="key+1"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-else
|
|
||||||
ref="formInput"
|
|
||||||
v-model="localRow[field.name]"
|
|
||||||
class="form-input"
|
|
||||||
:type="inputProps(field).type"
|
|
||||||
:disabled="fieldsToExclude.includes(field.name)"
|
|
||||||
:tabindex="key+1"
|
|
||||||
>
|
|
||||||
<span class="input-group-addon" :class="typeCLass(field.type)">
|
|
||||||
{{ field.type }} {{ wrapNumber(fieldLength(field)) }}
|
|
||||||
</span>
|
|
||||||
<label class="form-checkbox ml-3" :title="$t('word.insert')">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
:checked="!field.autoIncrement"
|
|
||||||
@change.prevent="toggleFields($event, field)"
|
|
||||||
><i class="form-icon" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<div class="input-group col-3 tooltip tooltip-right" :data-tooltip="$t('message.numberOfInserts')">
|
|
||||||
<input
|
|
||||||
v-model="nInserts"
|
|
||||||
type="number"
|
|
||||||
class="form-input"
|
|
||||||
min="1"
|
|
||||||
:disabled="isInserting"
|
|
||||||
>
|
|
||||||
<span class="input-group-addon">
|
|
||||||
<i class="mdi mdi-24px mdi-repeat" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary mr-2"
|
|
||||||
:class="{'loading': isInserting}"
|
|
||||||
@click.stop="insertRows"
|
|
||||||
>
|
|
||||||
{{ $t('word.insert') }}
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-link" @click.stop="closeModal">
|
|
||||||
{{ $t('word.close') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Teleport>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import moment from 'moment';
|
|
||||||
import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes';
|
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
|
||||||
import Tables from '@/ipc-api/Tables';
|
|
||||||
import ForeignKeySelect from '@/components/ForeignKeySelect';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ModalNewTableRow',
|
|
||||||
components: {
|
|
||||||
ForeignKeySelect
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
tabUid: [String, Number],
|
|
||||||
fields: Array,
|
|
||||||
keyUsage: Array
|
|
||||||
},
|
|
||||||
emits: ['reload', 'hide'],
|
|
||||||
setup () {
|
|
||||||
const { addNotification } = useNotificationsStore();
|
|
||||||
const workspacesStore = useWorkspacesStore();
|
|
||||||
|
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
|
||||||
|
|
||||||
const { getWorkspace, getWorkspaceTab } = workspacesStore;
|
|
||||||
|
|
||||||
return {
|
|
||||||
addNotification,
|
|
||||||
selectedWorkspace,
|
|
||||||
getWorkspace,
|
|
||||||
getWorkspaceTab
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
localRow: {},
|
|
||||||
fieldsToExclude: [],
|
|
||||||
nInserts: 1,
|
|
||||||
isInserting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
workspace () {
|
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
|
||||||
},
|
|
||||||
foreignKeys () {
|
|
||||||
return this.keyUsage.map(key => key.field);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
nInserts (val) {
|
|
||||||
if (!val || val < 1)
|
|
||||||
this.nInserts = 1;
|
|
||||||
else if (val > 1000)
|
|
||||||
this.nInserts = 1000;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
const rowObj = {};
|
|
||||||
|
|
||||||
for (const field of this.fields) {
|
|
||||||
let fieldDefault;
|
|
||||||
|
|
||||||
if (field.default === 'NULL') fieldDefault = null;
|
|
||||||
else {
|
|
||||||
if ([...NUMBER, ...FLOAT].includes(field.type))
|
|
||||||
fieldDefault = +field.default;
|
|
||||||
|
|
||||||
if ([...TEXT, ...LONG_TEXT].includes(field.type))
|
|
||||||
fieldDefault = field.default ? field.default.substring(1, field.default.length - 1) : '';
|
|
||||||
|
|
||||||
if ([...TIME, ...DATE].includes(field.type))
|
|
||||||
fieldDefault = field.default;
|
|
||||||
|
|
||||||
if (DATETIME.includes(field.type)) {
|
|
||||||
if (field.default && field.default.toLowerCase().includes('current_timestamp')) {
|
|
||||||
let datePrecision = '';
|
|
||||||
for (let i = 0; i < field.datePrecision; i++)
|
|
||||||
datePrecision += i === 0 ? '.S' : 'S';
|
|
||||||
fieldDefault = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rowObj[field.name] = fieldDefault;
|
|
||||||
|
|
||||||
if (field.autoIncrement)// Disable by default auto increment fields
|
|
||||||
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.localRow = { ...rowObj };
|
|
||||||
|
|
||||||
// Auto focus
|
|
||||||
setTimeout(() => {
|
|
||||||
const firstSelectableInput = this.$refs.formInput.find(input => !input.disabled);
|
|
||||||
firstSelectableInput.focus();
|
|
||||||
}, 20);
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
typeClass (type) {
|
|
||||||
if (type)
|
|
||||||
return `type-${type.toLowerCase().replaceAll(' ', '_').replaceAll('"', '')}`;
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
async insertRows () {
|
|
||||||
this.isInserting = true;
|
|
||||||
const rowToInsert = this.localRow;
|
|
||||||
Object.keys(rowToInsert).forEach(key => {
|
|
||||||
if (this.fieldsToExclude.includes(key))
|
|
||||||
delete rowToInsert[key];
|
|
||||||
if (typeof rowToInsert[key] === 'undefined')
|
|
||||||
delete rowToInsert[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
const fieldTypes = {};
|
|
||||||
this.fields.forEach(field => {
|
|
||||||
fieldTypes[field.name] = field.type;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { status, response } = await Tables.insertTableRows({
|
|
||||||
uid: this.selectedWorkspace,
|
|
||||||
schema: this.workspace.breadcrumbs.schema,
|
|
||||||
table: this.workspace.breadcrumbs.table,
|
|
||||||
row: rowToInsert,
|
|
||||||
repeat: this.nInserts,
|
|
||||||
fields: fieldTypes
|
|
||||||
});
|
|
||||||
|
|
||||||
if (status === 'success') {
|
|
||||||
this.closeModal();
|
|
||||||
this.$emit('reload');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.addNotification({ status: 'error', message: response });
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isInserting = false;
|
|
||||||
},
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('hide');
|
|
||||||
},
|
|
||||||
fieldLength (field) {
|
|
||||||
if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null;
|
|
||||||
else if (TEXT.includes(field.type)) return field.charLength;
|
|
||||||
return field.length;
|
|
||||||
},
|
|
||||||
inputProps (field) {
|
|
||||||
if ([...TEXT, ...LONG_TEXT].includes(field.type))
|
|
||||||
return { type: 'text', mask: false };
|
|
||||||
|
|
||||||
if ([...NUMBER, ...FLOAT].includes(field.type))
|
|
||||||
return { type: 'number', mask: false };
|
|
||||||
|
|
||||||
if (TIME.includes(field.type)) {
|
|
||||||
let timeMask = '##:##:##';
|
|
||||||
const precision = this.fieldLength(field);
|
|
||||||
|
|
||||||
for (let i = 0; i < precision; i++)
|
|
||||||
timeMask += i === 0 ? '.#' : '#';
|
|
||||||
|
|
||||||
return { type: 'text', mask: timeMask };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DATE.includes(field.type))
|
|
||||||
return { type: 'text', mask: '####-##-##' };
|
|
||||||
|
|
||||||
if (DATETIME.includes(field.type)) {
|
|
||||||
let datetimeMask = '####-##-## ##:##:##';
|
|
||||||
const precision = this.fieldLength(field);
|
|
||||||
|
|
||||||
for (let i = 0; i < precision; i++)
|
|
||||||
datetimeMask += i === 0 ? '.#' : '#';
|
|
||||||
|
|
||||||
return { type: 'text', mask: datetimeMask };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BLOB.includes(field.type))
|
|
||||||
return { type: 'file', mask: false };
|
|
||||||
|
|
||||||
if (BIT.includes(field.type))
|
|
||||||
return { type: 'text', mask: false };
|
|
||||||
|
|
||||||
return { type: 'text', mask: false };
|
|
||||||
},
|
|
||||||
toggleFields (event, field) {
|
|
||||||
if (event.target.checked)
|
|
||||||
this.fieldsToExclude = this.fieldsToExclude.filter(f => f !== field.name);
|
|
||||||
else
|
|
||||||
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
|
||||||
},
|
|
||||||
filesChange (event, field) {
|
|
||||||
const { files } = event.target;
|
|
||||||
if (!files.length) return;
|
|
||||||
|
|
||||||
this.localRow[field] = files[0].path;
|
|
||||||
},
|
|
||||||
getKeyUsage (keyName) {
|
|
||||||
return this.keyUsage.find(key => key.field === keyName);
|
|
||||||
},
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (e.key === 'Escape')
|
|
||||||
this.closeModal();
|
|
||||||
},
|
|
||||||
wrapNumber (num) {
|
|
||||||
if (!num) return '';
|
|
||||||
return `(${num})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.modal-container {
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label {
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: normal;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group-addon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -133,218 +133,218 @@
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { Component, computed, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref } from 'vue';
|
||||||
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
import { arrayToFile } from '../libs/arrayToFile';
|
import { arrayToFile } from '../libs/arrayToFile';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
|
||||||
import ModalProcessesListRow from '@/components/ModalProcessesListRow';
|
import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue';
|
||||||
import ModalProcessesListContext from '@/components/ModalProcessesListContext';
|
import ModalProcessesListContext from '@/components/ModalProcessesListContext.vue';
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ModalProcessesList',
|
|
||||||
components: {
|
|
||||||
BaseVirtualScroll,
|
|
||||||
ModalProcessesListRow,
|
|
||||||
ModalProcessesListContext
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
connection: Object
|
|
||||||
},
|
|
||||||
emits: ['close'],
|
|
||||||
setup () {
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const { getConnectionName } = useConnectionsStore();
|
const { getConnectionName } = useConnectionsStore();
|
||||||
|
|
||||||
return { addNotification, getConnectionName };
|
const props = defineProps({
|
||||||
},
|
connection: Object as Prop<ConnectionParams>
|
||||||
data () {
|
});
|
||||||
return {
|
|
||||||
resultsSize: 1000,
|
const emit = defineEmits(['close']);
|
||||||
isQuering: false,
|
|
||||||
isContext: false,
|
const tableWrapper: Ref<HTMLDivElement> = ref(null);
|
||||||
autorefreshTimer: 0,
|
const table: Ref<HTMLDivElement> = ref(null);
|
||||||
refreshInterval: null,
|
const resultTable: Ref<Component & {updateWindow: () => void}> = ref(null);
|
||||||
contextEvent: null,
|
const resultsSize = ref(1000);
|
||||||
selectedCell: null,
|
const isQuering = ref(false);
|
||||||
selectedRow: null,
|
const isContext = ref(false);
|
||||||
results: [],
|
const autorefreshTimer = ref(0);
|
||||||
fields: [],
|
const refreshInterval: Ref<NodeJS.Timeout> = ref(null);
|
||||||
currentSort: '',
|
const contextEvent = ref(null);
|
||||||
currentSortDir: 'asc',
|
const selectedCell = ref(null);
|
||||||
scrollElement: null
|
const selectedRow: Ref<number> = ref(null);
|
||||||
};
|
const results = ref([]);
|
||||||
},
|
const fields = ref([]);
|
||||||
computed: {
|
const currentSort = ref('');
|
||||||
connectionName () {
|
const currentSortDir = ref('asc');
|
||||||
return this.getConnectionName(this.connection.uid);
|
const scrollElement = ref(null);
|
||||||
},
|
|
||||||
sortedResults () {
|
const connectionName = computed(() => getConnectionName(props.connection.uid));
|
||||||
if (this.currentSort) {
|
|
||||||
return [...this.results].sort((a, b) => {
|
const sortedResults = computed(() => {
|
||||||
|
if (currentSort.value) {
|
||||||
|
return [...results.value].sort((a, b) => {
|
||||||
let modifier = 1;
|
let modifier = 1;
|
||||||
const valA = typeof a[this.currentSort] === 'string' ? a[this.currentSort].toLowerCase() : a[this.currentSort];
|
const valA = typeof a[currentSort.value] === 'string' ? a[currentSort.value].toLowerCase() : a[currentSort.value];
|
||||||
const valB = typeof b[this.currentSort] === 'string' ? b[this.currentSort].toLowerCase() : b[this.currentSort];
|
const valB = typeof b[currentSort.value] === 'string' ? b[currentSort.value].toLowerCase() : b[currentSort.value];
|
||||||
if (this.currentSortDir === 'desc') modifier = -1;
|
if (currentSortDir.value === 'desc') modifier = -1;
|
||||||
if (valA < valB) return -1 * modifier;
|
if (valA < valB) return -1 * modifier;
|
||||||
if (valA > valB) return 1 * modifier;
|
if (valA > valB) return 1 * modifier;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return this.results;
|
return results.value;
|
||||||
}
|
});
|
||||||
},
|
|
||||||
created () {
|
|
||||||
window.addEventListener('keydown', this.onKey, { capture: true });
|
|
||||||
},
|
|
||||||
updated () {
|
|
||||||
if (this.$refs.table)
|
|
||||||
this.refreshScroller();
|
|
||||||
|
|
||||||
if (this.$refs.tableWrapper)
|
const getProcessesList = async () => {
|
||||||
this.scrollElement = this.$refs.tableWrapper;
|
isQuering.value = true;
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.getProcessesList();
|
|
||||||
window.addEventListener('resize', this.resizeResults);
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
|
||||||
window.removeEventListener('keydown', this.onKey, { capture: true });
|
|
||||||
window.removeEventListener('resize', this.resizeResults);
|
|
||||||
clearInterval(this.refreshInterval);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async getProcessesList () {
|
|
||||||
this.isQuering = true;
|
|
||||||
|
|
||||||
// if table changes clear cached values
|
|
||||||
if (this.lastTable !== this.table)
|
|
||||||
this.results = [];
|
|
||||||
|
|
||||||
try { // Table data
|
try { // Table data
|
||||||
const { status, response } = await Schema.getProcesses(this.connection.uid);
|
const { status, response } = await Schema.getProcesses(props.connection.uid);
|
||||||
|
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
this.results = response;
|
results.value = response;
|
||||||
this.fields = response.length ? Object.keys(response[0]) : [];
|
fields.value = response.length ? Object.keys(response[0]) : [];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isQuering = false;
|
isQuering.value = false;
|
||||||
},
|
};
|
||||||
setRefreshInterval () {
|
|
||||||
this.clearRefresh();
|
|
||||||
|
|
||||||
if (+this.autorefreshTimer) {
|
const setRefreshInterval = () => {
|
||||||
this.refreshInterval = setInterval(() => {
|
clearRefresh();
|
||||||
if (!this.isQuering)
|
|
||||||
this.getProcessesList();
|
if (+autorefreshTimer.value) {
|
||||||
}, this.autorefreshTimer * 1000);
|
refreshInterval.value = setInterval(() => {
|
||||||
|
if (!isQuering.value)
|
||||||
|
getProcessesList();
|
||||||
|
}, autorefreshTimer.value * 1000);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
clearRefresh () {
|
|
||||||
if (this.refreshInterval)
|
const clearRefresh = () => {
|
||||||
clearInterval(this.refreshInterval);
|
if (refreshInterval.value)
|
||||||
},
|
clearInterval(refreshInterval.value);
|
||||||
resizeResults () {
|
};
|
||||||
if (this.$refs.resultTable) {
|
|
||||||
const el = this.$refs.tableWrapper.parentElement;
|
const resizeResults = () => {
|
||||||
|
if (resultTable.value) {
|
||||||
|
const el = tableWrapper.value.parentElement;
|
||||||
|
|
||||||
if (el) {
|
if (el) {
|
||||||
const size = el.offsetHeight;
|
const size = el.offsetHeight;
|
||||||
this.resultsSize = size;
|
resultsSize.value = size;
|
||||||
}
|
|
||||||
this.$refs.resultTable.updateWindow();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
refreshScroller () {
|
|
||||||
this.resizeResults();
|
|
||||||
},
|
|
||||||
sort (field) {
|
|
||||||
if (field === this.currentSort) {
|
|
||||||
if (this.currentSortDir === 'asc')
|
|
||||||
this.currentSortDir = 'desc';
|
|
||||||
else
|
|
||||||
this.resetSort();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.currentSortDir = 'asc';
|
|
||||||
this.currentSort = field;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetSort () {
|
|
||||||
this.currentSort = '';
|
|
||||||
this.currentSortDir = 'asc';
|
|
||||||
},
|
|
||||||
stopRefresh () {
|
|
||||||
this.autorefreshTimer = 0;
|
|
||||||
this.clearRefresh();
|
|
||||||
},
|
|
||||||
selectRow (row) {
|
|
||||||
this.selectedRow = Number(row);
|
|
||||||
},
|
|
||||||
contextMenu (event, cell) {
|
|
||||||
if (event.target.localName === 'input') return;
|
|
||||||
this.stopRefresh();
|
|
||||||
|
|
||||||
this.selectedCell = cell;
|
|
||||||
this.selectedRow = Number(cell.id);
|
|
||||||
this.contextEvent = event;
|
|
||||||
this.isContext = true;
|
|
||||||
},
|
|
||||||
async killProcess () {
|
|
||||||
try { // Table data
|
|
||||||
const { status, response } = await Schema.killProcess({ uid: this.connection.uid, pid: this.selectedRow });
|
|
||||||
|
|
||||||
if (status === 'success')
|
|
||||||
this.getProcessesList();
|
|
||||||
else
|
|
||||||
this.addNotification({ status: 'error', message: response });
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
closeContext () {
|
|
||||||
this.isContext = false;
|
|
||||||
},
|
|
||||||
copyCell () {
|
|
||||||
const row = this.results.find(row => row.id === this.selectedRow);
|
|
||||||
const valueToCopy = row[this.selectedCell.field];
|
|
||||||
navigator.clipboard.writeText(valueToCopy);
|
|
||||||
},
|
|
||||||
copyRow () {
|
|
||||||
const row = this.results.find(row => row.id === this.selectedRow);
|
|
||||||
const rowToCopy = JSON.parse(JSON.stringify(row));
|
|
||||||
navigator.clipboard.writeText(JSON.stringify(rowToCopy));
|
|
||||||
},
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('close');
|
|
||||||
},
|
|
||||||
downloadTable (format) {
|
|
||||||
if (!this.sortedResults) return;
|
|
||||||
arrayToFile({
|
|
||||||
type: format,
|
|
||||||
content: this.sortedResults,
|
|
||||||
filename: 'processes'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onKey (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (e.key === 'Escape')
|
|
||||||
this.closeModal();
|
|
||||||
if (e.key === 'F5')
|
|
||||||
this.getProcessesList();
|
|
||||||
}
|
}
|
||||||
|
resultTable.value.updateWindow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const refreshScroller = () => resizeResults();
|
||||||
|
|
||||||
|
const sort = (field: string) => {
|
||||||
|
if (field === currentSort.value) {
|
||||||
|
if (currentSortDir.value === 'asc')
|
||||||
|
currentSortDir.value = 'desc';
|
||||||
|
else
|
||||||
|
resetSort();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentSortDir.value = 'asc';
|
||||||
|
currentSort.value = field;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetSort = () => {
|
||||||
|
currentSort.value = '';
|
||||||
|
currentSortDir.value = 'asc';
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopRefresh = () => {
|
||||||
|
autorefreshTimer.value = 0;
|
||||||
|
clearRefresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectRow = (row: number) => {
|
||||||
|
selectedRow.value = Number(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextMenu = (event: MouseEvent, cell: { id: number; field: string }) => {
|
||||||
|
if ((event.target as HTMLElement).localName === 'input') return;
|
||||||
|
stopRefresh();
|
||||||
|
|
||||||
|
selectedCell.value = cell;
|
||||||
|
selectedRow.value = Number(cell.id);
|
||||||
|
contextEvent.value = event;
|
||||||
|
isContext.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const killProcess = async () => {
|
||||||
|
try { // Table data
|
||||||
|
const { status, response } = await Schema.killProcess({ uid: props.connection.uid, pid: selectedRow.value });
|
||||||
|
|
||||||
|
if (status === 'success')
|
||||||
|
getProcessesList();
|
||||||
|
else
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeContext = () => {
|
||||||
|
isContext.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyCell = () => {
|
||||||
|
const row = results.value.find(row => row.id === selectedRow.value);
|
||||||
|
const valueToCopy = row[selectedCell.value.field];
|
||||||
|
navigator.clipboard.writeText(valueToCopy);
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyRow = () => {
|
||||||
|
const row = results.value.find(row => row.id === selectedRow.value);
|
||||||
|
const rowToCopy = JSON.parse(JSON.stringify(row));
|
||||||
|
navigator.clipboard.writeText(JSON.stringify(rowToCopy));
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeModal = () => emit('close');
|
||||||
|
|
||||||
|
const downloadTable = (format: 'csv' | 'json') => {
|
||||||
|
if (!sortedResults.value) return;
|
||||||
|
arrayToFile({
|
||||||
|
type: format,
|
||||||
|
content: sortedResults.value,
|
||||||
|
filename: 'processes'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKey = (e:KeyboardEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (e.key === 'Escape')
|
||||||
|
closeModal();
|
||||||
|
if (e.key === 'F5')
|
||||||
|
getProcessesList();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', onKey, { capture: true });
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getProcessesList();
|
||||||
|
window.addEventListener('resize', resizeResults);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
if (table.value)
|
||||||
|
refreshScroller();
|
||||||
|
if (tableWrapper.value)
|
||||||
|
scrollElement.value = tableWrapper.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', onKey, { capture: true });
|
||||||
|
window.removeEventListener('resize', resizeResults);
|
||||||
|
clearInterval(refreshInterval.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({ refreshScroller });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, Ref } from 'vue';
|
import { ref, Ref, computed } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useApplicationStore } from '@/stores/application';
|
import { useApplicationStore } from '@/stores/application';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
|
@ -64,7 +64,6 @@ import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import * as Draggable from 'vuedraggable';
|
import * as Draggable from 'vuedraggable';
|
||||||
import SettingBarContext from '@/components/SettingBarContext.vue';
|
import SettingBarContext from '@/components/SettingBarContext.vue';
|
||||||
import { ConnectionParams } from 'common/interfaces/antares';
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
import { computed } from '@vue/reactivity';
|
|
||||||
|
|
||||||
const applicationStore = useApplicationStore();
|
const applicationStore = useApplicationStore();
|
||||||
const connectionsStore = useConnectionsStore();
|
const connectionsStore = useConnectionsStore();
|
||||||
|
@ -80,7 +79,7 @@ const { getWorkspace, selectWorkspace } = workspacesStore;
|
||||||
|
|
||||||
const isContext: Ref<boolean> = ref(false);
|
const isContext: Ref<boolean> = ref(false);
|
||||||
const isDragging: Ref<boolean> = ref(false);
|
const isDragging: Ref<boolean> = ref(false);
|
||||||
const contextEvent: Ref<Event> = ref(null);
|
const contextEvent: Ref<MouseEvent> = ref(null);
|
||||||
const contextConnection: Ref<ConnectionParams> = ref(null);
|
const contextConnection: Ref<ConnectionParams> = ref(null);
|
||||||
|
|
||||||
const connections = computed({
|
const connections = computed({
|
||||||
|
@ -94,7 +93,7 @@ const connections = computed({
|
||||||
|
|
||||||
const hasUpdates = computed(() => ['available', 'downloading', 'downloaded', 'link'].includes(updateStatus.value));
|
const hasUpdates = computed(() => ['available', 'downloading', 'downloaded', 'link'].includes(updateStatus.value));
|
||||||
|
|
||||||
const contextMenu = (event: Event, connection: ConnectionParams) => {
|
const contextMenu = (event: MouseEvent, connection: ConnectionParams) => {
|
||||||
contextEvent.value = event;
|
contextEvent.value = event;
|
||||||
contextConnection.value = connection;
|
contextConnection.value = connection;
|
||||||
isContext.value = true;
|
isContext.value = true;
|
||||||
|
@ -133,110 +132,6 @@ const dragStop = (e: any) => { // TODO: temp
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <script>
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useApplicationStore } from '@/stores/application';
|
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
|
||||||
import Draggable from 'vuedraggable';
|
|
||||||
import SettingBarContext from '@/components/SettingBarContext';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TheSettingBar',
|
|
||||||
components: {
|
|
||||||
Draggable,
|
|
||||||
SettingBarContext
|
|
||||||
},
|
|
||||||
setup () {
|
|
||||||
const applicationStore = useApplicationStore();
|
|
||||||
const connectionsStore = useConnectionsStore();
|
|
||||||
const workspacesStore = useWorkspacesStore();
|
|
||||||
|
|
||||||
const { updateStatus } = storeToRefs(applicationStore);
|
|
||||||
const { connections: getConnections } = storeToRefs(connectionsStore);
|
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
|
||||||
|
|
||||||
const { showSettingModal, showScratchpad } = applicationStore;
|
|
||||||
const { getConnectionName, updateConnections } = connectionsStore;
|
|
||||||
const { getWorkspace, selectWorkspace } = workspacesStore;
|
|
||||||
|
|
||||||
return {
|
|
||||||
applicationStore,
|
|
||||||
updateStatus,
|
|
||||||
showSettingModal,
|
|
||||||
showScratchpad,
|
|
||||||
getConnections,
|
|
||||||
getConnectionName,
|
|
||||||
updateConnections,
|
|
||||||
selectedWorkspace,
|
|
||||||
getWorkspace,
|
|
||||||
selectWorkspace
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
dragElement: null,
|
|
||||||
isContext: false,
|
|
||||||
isDragging: false,
|
|
||||||
contextEvent: null,
|
|
||||||
contextConnection: {},
|
|
||||||
scale: 0
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
connections: {
|
|
||||||
get () {
|
|
||||||
return this.getConnections;
|
|
||||||
},
|
|
||||||
set (value) {
|
|
||||||
this.updateConnections(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasUpdates () {
|
|
||||||
return ['available', 'downloading', 'downloaded', 'link'].includes(this.updateStatus);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
contextMenu (event, connection) {
|
|
||||||
this.contextEvent = event;
|
|
||||||
this.contextConnection = connection;
|
|
||||||
this.isContext = true;
|
|
||||||
},
|
|
||||||
workspaceName (connection) {
|
|
||||||
return connection.ask ? '' : `${connection.user + '@'}${connection.host}:${connection.port}`;
|
|
||||||
},
|
|
||||||
tooltipPosition (e) {
|
|
||||||
const el = e.target ? e.target : e;
|
|
||||||
const fromTop = window.pageYOffset + el.getBoundingClientRect().top - (el.offsetHeight / 4);
|
|
||||||
el.querySelector('.ex-tooltip-content').style.top = `${fromTop}px`;
|
|
||||||
},
|
|
||||||
getStatusBadge (uid) {
|
|
||||||
if (this.getWorkspace(uid)) {
|
|
||||||
const status = this.getWorkspace(uid).connectionStatus;
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 'connected':
|
|
||||||
return 'badge badge-connected';
|
|
||||||
case 'connecting':
|
|
||||||
return 'badge badge-connecting';
|
|
||||||
case 'failed':
|
|
||||||
return 'badge badge-failed';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dragStop (e) {
|
|
||||||
this.isDragging = false;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.tooltipPosition(e.originalEvent.target.parentNode);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script> -->
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#settingbar {
|
#settingbar {
|
||||||
width: $settingbar-width;
|
width: $settingbar-width;
|
||||||
|
|
|
@ -53,13 +53,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed, onUnmounted, ref } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { getCurrentWindow } from '@electron/remote';
|
import { getCurrentWindow } from '@electron/remote';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import { onUnmounted, ref } from 'vue';
|
|
||||||
import { computed } from '@vue/reactivity';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
|
@ -326,7 +326,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabTable
|
<WorkspaceTabTable
|
||||||
v-else-if="['temp-data', 'data'].includes(tab.type)"
|
v-else-if="['temp-data', 'data'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_data'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -336,7 +336,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewTable
|
<WorkspaceTabNewTable
|
||||||
v-else-if="tab.type === 'new-table'"
|
v-else-if="tab.type === 'new-table'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-table'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -345,7 +345,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsTable
|
<WorkspaceTabPropsTable
|
||||||
v-else-if="tab.type === 'table-props'"
|
v-else-if="tab.type === 'table-props'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_table-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -354,7 +354,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewView
|
<WorkspaceTabNewView
|
||||||
v-else-if="tab.type === 'new-view'"
|
v-else-if="tab.type === 'new-view'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-view'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -363,7 +363,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsView
|
<WorkspaceTabPropsView
|
||||||
v-else-if="tab.type === 'view-props'"
|
v-else-if="tab.type === 'view-props'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_view-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -372,7 +372,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewTrigger
|
<WorkspaceTabNewTrigger
|
||||||
v-else-if="tab.type === 'new-trigger'"
|
v-else-if="tab.type === 'new-trigger'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-trigger'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -382,7 +382,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsTrigger
|
<WorkspaceTabPropsTrigger
|
||||||
v-else-if="['temp-trigger-props', 'trigger-props'].includes(tab.type)"
|
v-else-if="['temp-trigger-props', 'trigger-props'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_trigger-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -391,7 +391,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewTriggerFunction
|
<WorkspaceTabNewTriggerFunction
|
||||||
v-else-if="tab.type === 'new-trigger-function'"
|
v-else-if="tab.type === 'new-trigger-function'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-trigger-function'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -401,7 +401,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsTriggerFunction
|
<WorkspaceTabPropsTriggerFunction
|
||||||
v-else-if="['temp-trigger-function-props', 'trigger-function-props'].includes(tab.type)"
|
v-else-if="['temp-trigger-function-props', 'trigger-function-props'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_trigger-function-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -410,7 +410,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewRoutine
|
<WorkspaceTabNewRoutine
|
||||||
v-else-if="tab.type === 'new-routine'"
|
v-else-if="tab.type === 'new-routine'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-routine'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -420,7 +420,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsRoutine
|
<WorkspaceTabPropsRoutine
|
||||||
v-else-if="['temp-routine-props', 'routine-props'].includes(tab.type)"
|
v-else-if="['temp-routine-props', 'routine-props'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_routine-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -429,7 +429,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewFunction
|
<WorkspaceTabNewFunction
|
||||||
v-else-if="tab.type === 'new-function'"
|
v-else-if="tab.type === 'new-function'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-function'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -439,7 +439,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsFunction
|
<WorkspaceTabPropsFunction
|
||||||
v-else-if="['temp-function-props', 'function-props'].includes(tab.type)"
|
v-else-if="['temp-function-props', 'function-props'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_function-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
@ -448,7 +448,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabNewScheduler
|
<WorkspaceTabNewScheduler
|
||||||
v-else-if="tab.type === 'new-scheduler'"
|
v-else-if="tab.type === 'new-scheduler'"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_new-scheduler'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
|
@ -458,7 +458,7 @@
|
||||||
/>
|
/>
|
||||||
<WorkspaceTabPropsScheduler
|
<WorkspaceTabPropsScheduler
|
||||||
v-else-if="['temp-scheduler-props', 'scheduler-props'].includes(tab.type)"
|
v-else-if="['temp-scheduler-props', 'scheduler-props'].includes(tab.type)"
|
||||||
:key="tab.uid"
|
:key="tab.uid+'_scheduler-props'"
|
||||||
:tab-uid="tab.uid"
|
:tab-uid="tab.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="selectedTab === tab.uid"
|
:is-selected="selectedTab === tab.uid"
|
||||||
|
|
|
@ -272,7 +272,13 @@ export default {
|
||||||
sql = `CALL \`${this.localElement.name}\`(${params.join(',')})`;
|
sql = `CALL \`${this.localElement.name}\`(${params.join(',')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
this.newTab({
|
||||||
|
uid: this.workspace.uid,
|
||||||
|
content: sql,
|
||||||
|
type: 'query',
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
autorun: true
|
||||||
|
});
|
||||||
this.closeContext();
|
this.closeContext();
|
||||||
},
|
},
|
||||||
async runFunctionCheck () {
|
async runFunctionCheck () {
|
||||||
|
@ -317,7 +323,13 @@ export default {
|
||||||
sql = `SELECT \`${this.localElement.name}\` (${params.join(',')})`;
|
sql = `SELECT \`${this.localElement.name}\` (${params.join(',')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
this.newTab({
|
||||||
|
uid: this.workspace.uid,
|
||||||
|
content: sql,
|
||||||
|
type: 'query',
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
autorun: true
|
||||||
|
});
|
||||||
this.closeContext();
|
this.closeContext();
|
||||||
},
|
},
|
||||||
async toggleTrigger () {
|
async toggleTrigger () {
|
||||||
|
|
|
@ -156,14 +156,6 @@
|
||||||
@hard-sort="hardSort"
|
@hard-sort="hardSort"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ModalNewTableRow
|
|
||||||
v-if="isAddModal"
|
|
||||||
:fields="fields"
|
|
||||||
:key-usage="keyUsage"
|
|
||||||
:tab-uid="tabUid"
|
|
||||||
@hide="hideAddModal"
|
|
||||||
@reload="reloadTable"
|
|
||||||
/>
|
|
||||||
<ModalFakerRows
|
<ModalFakerRows
|
||||||
v-if="isFakerModal"
|
v-if="isFakerModal"
|
||||||
:fields="fields"
|
:fields="fields"
|
||||||
|
@ -184,7 +176,6 @@ import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import BaseLoader from '@/components/BaseLoader';
|
import BaseLoader from '@/components/BaseLoader';
|
||||||
import WorkspaceTabQueryTable from '@/components/WorkspaceTabQueryTable';
|
import WorkspaceTabQueryTable from '@/components/WorkspaceTabQueryTable';
|
||||||
import WorkspaceTabTableFilters from '@/components/WorkspaceTabTableFilters';
|
import WorkspaceTabTableFilters from '@/components/WorkspaceTabTableFilters';
|
||||||
import ModalNewTableRow from '@/components/ModalNewTableRow';
|
|
||||||
import ModalFakerRows from '@/components/ModalFakerRows';
|
import ModalFakerRows from '@/components/ModalFakerRows';
|
||||||
import tableTabs from '@/mixins/tableTabs';
|
import tableTabs from '@/mixins/tableTabs';
|
||||||
|
|
||||||
|
@ -194,7 +185,6 @@ export default {
|
||||||
BaseLoader,
|
BaseLoader,
|
||||||
WorkspaceTabQueryTable,
|
WorkspaceTabQueryTable,
|
||||||
WorkspaceTabTableFilters,
|
WorkspaceTabTableFilters,
|
||||||
ModalNewTableRow,
|
|
||||||
ModalFakerRows
|
ModalFakerRows
|
||||||
},
|
},
|
||||||
mixins: [tableTabs],
|
mixins: [tableTabs],
|
||||||
|
@ -231,7 +221,6 @@ export default {
|
||||||
isSearch: false,
|
isSearch: false,
|
||||||
results: [],
|
results: [],
|
||||||
lastTable: null,
|
lastTable: null,
|
||||||
isAddModal: false,
|
|
||||||
isFakerModal: false,
|
isFakerModal: false,
|
||||||
autorefreshTimer: 0,
|
autorefreshTimer: 0,
|
||||||
refreshInterval: null,
|
refreshInterval: null,
|
||||||
|
@ -410,12 +399,6 @@ export default {
|
||||||
else if (direction === 'prev' && this.page > 1)
|
else if (direction === 'prev' && this.page > 1)
|
||||||
this.page--;
|
this.page--;
|
||||||
},
|
},
|
||||||
showAddModal () {
|
|
||||||
this.isAddModal = true;
|
|
||||||
},
|
|
||||||
hideAddModal () {
|
|
||||||
this.isAddModal = false;
|
|
||||||
},
|
|
||||||
showFakerModal () {
|
showFakerModal () {
|
||||||
if (this.isQuering) return;
|
if (this.isQuering) return;
|
||||||
this.isFakerModal = true;
|
this.isFakerModal = true;
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
import formatter from 'pg-connection-string'; // parses a connection string
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
|
import * as formatter from 'pg-connection-string'; // parses a connection string
|
||||||
|
|
||||||
const formatHost = host => {
|
const formatHost = (host: string) => {
|
||||||
const results = host === 'localhost' ? '127.0.0.1' : host;
|
const results = host === 'localhost' ? '127.0.0.1' : host;
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkForSSl = conn => {
|
const checkForSSl = (conn: string) => {
|
||||||
return conn.includes('ssl=true');
|
return conn.includes('ssl=true');
|
||||||
};
|
};
|
||||||
|
|
||||||
const connStringConstruct = (args) => {
|
const connStringConstruct = (args: ConnectionParams & { pgConnString: string }): ConnectionParams => {
|
||||||
if (!args.pgConnString)
|
if (!args.pgConnString)
|
||||||
return args;
|
return args;
|
||||||
|
|
||||||
if (typeof args.pgConnString !== 'string')
|
if (typeof args.pgConnString !== 'string')
|
||||||
return args;
|
return args;
|
||||||
|
|
||||||
const stringArgs = formatter.parse(args.pgConnString);
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const stringArgs: any = formatter.parse(args.pgConnString);
|
||||||
|
|
||||||
const client = args.client || 'pg';
|
const client = args.client || 'pg';
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable */
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
||||||
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
||||||
/* eslint-disable no-labels */
|
|
||||||
/* eslint-disable no-return-assign */
|
|
||||||
/* eslint-disable no-cond-assign */
|
|
||||||
/* eslint-disable no-prototype-builtins */
|
|
||||||
/* eslint-disable no-mixed-operators */
|
|
||||||
/*
|
/*
|
||||||
Got from 'ace-builds/src-noconflict/ext-language_tools' and edited to support icons.
|
Got from 'ace-builds/src-noconflict/ext-language_tools' and edited to support icons.
|
||||||
I'm not responsible of this crazy code.
|
I'm not responsible of this crazy code 🤯.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ace.define('ace/snippets', ['require', 'exports', 'module', 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/lib/lang', 'ace/range', 'ace/range_list', 'ace/keyboard/hash_handler', 'ace/tokenizer', 'ace/clipboard', 'ace/lib/dom', 'ace/editor'], function (require, exports, module) {
|
ace.define('ace/snippets', ['require', 'exports', 'module', 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/lib/lang', 'ace/range', 'ace/range_list', 'ace/keyboard/hash_handler', 'ace/tokenizer', 'ace/clipboard', 'ace/lib/dom', 'ace/editor'], function (require, exports, module) {
|
||||||
|
|
Loading…
Reference in New Issue