2022-05-10 13:02:01 +02:00
|
|
|
import customizations from 'common/customizations';
|
2022-05-28 18:43:56 +02:00
|
|
|
import {
|
2022-06-09 20:08:32 +02:00
|
|
|
ClientCode,
|
2022-05-28 18:43:56 +02:00
|
|
|
CollationInfos,
|
|
|
|
ConnectionParams,
|
|
|
|
EventInfos,
|
|
|
|
FunctionInfos,
|
|
|
|
RoutineInfos,
|
|
|
|
TableInfos,
|
2022-06-09 20:08:32 +02:00
|
|
|
TriggerFunctionInfos,
|
2022-05-28 18:43:56 +02:00
|
|
|
TriggerInfos,
|
|
|
|
TypesGroup
|
|
|
|
} from 'common/interfaces/antares';
|
|
|
|
import { Customizations } from 'common/interfaces/customizations';
|
2023-08-18 15:57:31 +02:00
|
|
|
import { uidGen } from 'common/libs/uidGen';
|
|
|
|
import * as Store from 'electron-store';
|
|
|
|
import { defineStore } from 'pinia';
|
|
|
|
|
|
|
|
import Connection from '@/ipc-api/Connection';
|
|
|
|
import Schema from '@/ipc-api/Schema';
|
|
|
|
import Users from '@/ipc-api/Users';
|
|
|
|
import { useConnectionsStore } from '@/stores/connections';
|
|
|
|
import { useNotificationsStore } from '@/stores/notifications';
|
|
|
|
import { useSettingsStore } from '@/stores/settings';
|
2022-05-28 18:43:56 +02:00
|
|
|
|
|
|
|
export interface WorkspaceTab {
|
|
|
|
uid: string;
|
|
|
|
tab?: string;
|
2022-06-04 18:37:16 +02:00
|
|
|
index?: number;
|
|
|
|
selected?: boolean;
|
|
|
|
type?: string;
|
2023-06-13 18:10:52 +02:00
|
|
|
database?: string;
|
2022-05-28 18:43:56 +02:00
|
|
|
schema?: string;
|
|
|
|
elementName?: string;
|
|
|
|
elementNewName?: string;
|
|
|
|
elementType?: string;
|
|
|
|
isChanged?: boolean;
|
|
|
|
content?: string;
|
2022-06-04 18:37:16 +02:00
|
|
|
autorun?: boolean;
|
2024-04-06 09:34:42 +02:00
|
|
|
filePath?: string;
|
2022-05-28 18:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface WorkspaceStructure {
|
|
|
|
name: string;
|
|
|
|
functions: FunctionInfos[];
|
|
|
|
procedures: RoutineInfos[];
|
|
|
|
schedulers: EventInfos[];
|
|
|
|
tables: TableInfos[];
|
|
|
|
triggers: TriggerInfos[];
|
2022-06-09 20:08:32 +02:00
|
|
|
triggerFunctions: TriggerFunctionInfos[];
|
2022-05-28 18:43:56 +02:00
|
|
|
size: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Breadcrumb {
|
|
|
|
function?: string;
|
2022-06-09 20:08:32 +02:00
|
|
|
routine?: string;
|
2022-05-28 18:43:56 +02:00
|
|
|
query?: string;
|
|
|
|
scheduler?: string;
|
|
|
|
schema?: string;
|
|
|
|
table?: string;
|
|
|
|
trigger?: string;
|
|
|
|
triggerFunction?: string;
|
|
|
|
view?: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Workspace {
|
|
|
|
uid: string;
|
2022-06-09 20:08:32 +02:00
|
|
|
client?: ClientCode;
|
2023-06-13 18:10:52 +02:00
|
|
|
database?: string;
|
2024-03-23 18:45:38 +01:00
|
|
|
connectionStatus: 'connected' | 'connecting' | 'disconnected' | 'failed';
|
2023-12-25 10:54:41 +01:00
|
|
|
selectedTab: string;
|
2022-05-28 18:43:56 +02:00
|
|
|
searchTerm: string;
|
|
|
|
tabs: WorkspaceTab[];
|
|
|
|
structure: WorkspaceStructure[];
|
|
|
|
variables: { name: string; value: string }[];
|
|
|
|
collations: CollationInfos[];
|
2022-06-14 20:02:17 +02:00
|
|
|
users: { host: string; name: string; password?: string }[];
|
2022-06-04 18:37:16 +02:00
|
|
|
breadcrumbs: Breadcrumb;
|
2022-05-28 18:43:56 +02:00
|
|
|
loadingElements: { name: string; schema: string; type: string }[];
|
|
|
|
loadedSchemas: Set<string>;
|
|
|
|
dataTypes?: { [key: string]: TypesGroup[] };
|
|
|
|
indexTypes?: string[];
|
|
|
|
customizations?: Customizations;
|
|
|
|
version?: {
|
|
|
|
number: string;
|
|
|
|
name: string;
|
|
|
|
arch: string;
|
|
|
|
os: string;
|
|
|
|
};
|
2024-01-19 18:03:20 +01:00
|
|
|
engines?: Record<string, string | boolean | number>[];
|
2022-05-28 18:43:56 +02:00
|
|
|
}
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
const persistentStore = new Store({ name: 'tabs' });
|
2024-01-19 18:03:20 +01:00
|
|
|
const tabIndex: Record<string, number> = {};
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
export const useWorkspacesStore = defineStore('workspaces', {
|
|
|
|
state: () => ({
|
2022-05-28 18:43:56 +02:00
|
|
|
workspaces: [] as Workspace[],
|
|
|
|
selectedWorkspace: null as string
|
2022-04-30 00:47:37 +02:00
|
|
|
}),
|
|
|
|
getters: {
|
|
|
|
getSelected: state => {
|
|
|
|
if (!state.workspaces.length) return 'NEW';
|
|
|
|
if (state.selectedWorkspace) return state.selectedWorkspace;
|
2022-07-17 12:36:37 +02:00
|
|
|
const connectionsStore = useConnectionsStore();
|
|
|
|
if (connectionsStore.lastConnections.length) {
|
|
|
|
return connectionsStore.lastConnections.sort((a, b) => {
|
|
|
|
if (a.time < b.time) return 1;
|
|
|
|
else if (a.time > b.time) return -1;
|
|
|
|
return 0;
|
|
|
|
})[0].uid;
|
|
|
|
}
|
|
|
|
|
2022-04-30 00:47:37 +02:00
|
|
|
return state.workspaces[0].uid;
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
getWorkspace: state => (uid: string) => {
|
2022-04-30 00:47:37 +02:00
|
|
|
return state.workspaces.find(workspace => workspace.uid === uid);
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
getDatabaseVariable: state => (uid: string, name: string) => {
|
2022-04-30 00:47:37 +02:00
|
|
|
return state.workspaces.find(workspace => workspace.uid === uid).variables.find(variable => variable.name === name);
|
|
|
|
},
|
|
|
|
getWorkspaceTab (state) {
|
2023-12-25 10:54:41 +01:00
|
|
|
return (tUid: string): WorkspaceTab => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (!this.getSelected) return;
|
|
|
|
const workspace = state.workspaces.find(workspace => workspace.uid === this.getSelected);
|
|
|
|
if ('tabs' in workspace)
|
|
|
|
return workspace.tabs.find(tab => tab.uid === tUid);
|
2023-12-25 10:54:41 +01:00
|
|
|
return null;
|
2022-04-30 00:47:37 +02:00
|
|
|
};
|
|
|
|
},
|
|
|
|
getConnected: state => {
|
|
|
|
return state.workspaces
|
|
|
|
.filter(workspace => workspace.connectionStatus === 'connected')
|
|
|
|
.map(workspace => workspace.uid);
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
getLoadedSchemas: state => (uid: string) => {
|
2022-04-30 00:47:37 +02:00
|
|
|
return state.workspaces.find(workspace => workspace.uid === uid).loadedSchemas;
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
getSearchTerm: state => (uid: string) => {
|
2022-04-30 00:47:37 +02:00
|
|
|
return state.workspaces.find(workspace => workspace.uid === uid).searchTerm;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
actions: {
|
2022-05-28 18:43:56 +02:00
|
|
|
selectWorkspace (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (!uid)
|
|
|
|
this.selectedWorkspace = this.workspaces.length ? this.workspaces[0].uid : 'NEW';
|
|
|
|
else
|
|
|
|
this.selectedWorkspace = uid;
|
|
|
|
},
|
2023-06-13 18:10:52 +02:00
|
|
|
async connectWorkspace (connection: ConnectionParams & { pgConnString?: string }, mode?: string) {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
2023-06-13 18:10:52 +02:00
|
|
|
structure: [],
|
2022-04-30 00:47:37 +02:00
|
|
|
breadcrumbs: {},
|
|
|
|
loadedSchemas: new Set(),
|
2023-06-13 18:10:52 +02:00
|
|
|
database: connection.database,
|
|
|
|
connectionStatus: mode === 'switch' ? 'connected' : 'connecting'
|
2022-04-30 00:47:37 +02:00
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
|
|
|
|
const connectionsStore = useConnectionsStore();
|
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
const settingsStore = useSettingsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Connection.connect(connection);
|
|
|
|
|
|
|
|
if (status === 'error') {
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
2023-06-13 18:10:52 +02:00
|
|
|
structure: [],
|
2022-04-30 00:47:37 +02:00
|
|
|
breadcrumbs: {},
|
|
|
|
loadedSchemas: new Set(),
|
|
|
|
connectionStatus: 'failed'
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
let clientCustomizations: Customizations;
|
2022-06-29 19:05:45 +02:00
|
|
|
const { updateLastConnection } = connectionsStore;
|
|
|
|
|
|
|
|
updateLastConnection(connection.uid);
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
switch (connection.client) {
|
|
|
|
case 'mysql':
|
|
|
|
case 'maria':
|
2022-05-10 13:02:01 +02:00
|
|
|
clientCustomizations = customizations.mysql;
|
2022-04-30 00:47:37 +02:00
|
|
|
break;
|
|
|
|
case 'pg':
|
2022-05-10 13:02:01 +02:00
|
|
|
clientCustomizations = customizations.pg;
|
2022-04-30 00:47:37 +02:00
|
|
|
break;
|
|
|
|
case 'sqlite':
|
2022-05-10 13:02:01 +02:00
|
|
|
clientCustomizations = customizations.sqlite;
|
2022-04-30 00:47:37 +02:00
|
|
|
break;
|
2022-11-04 16:31:10 +01:00
|
|
|
case 'firebird':
|
|
|
|
clientCustomizations = customizations.firebird;
|
|
|
|
break;
|
2022-04-30 00:47:37 +02:00
|
|
|
}
|
2022-11-15 16:46:12 +01:00
|
|
|
const dataTypes = clientCustomizations.dataTypes;
|
|
|
|
const indexTypes = clientCustomizations.indexTypes;
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
const { status, response: version } = await Schema.getVersion(connection.uid);
|
|
|
|
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: version });
|
|
|
|
|
|
|
|
// Check if Maria or MySQL
|
|
|
|
const isMySQL = version.name.includes('MySQL');
|
2022-06-02 09:50:16 +02:00
|
|
|
const isMaria = version.name.includes('Maria');
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
if (isMySQL && connection.client !== 'mysql') {
|
|
|
|
const connProxy = Object.assign({}, connection);
|
|
|
|
connProxy.client = 'mysql';
|
|
|
|
connectionsStore.editConnection(connProxy);
|
|
|
|
}
|
2022-06-02 09:50:16 +02:00
|
|
|
else if (isMaria && connection.client === 'mysql') {
|
2022-04-30 00:47:37 +02:00
|
|
|
const connProxy = Object.assign({}, connection);
|
|
|
|
connProxy.client = 'maria';
|
|
|
|
connectionsStore.editConnection(connProxy);
|
|
|
|
}
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
const cachedTabs: WorkspaceTab[] = settingsStore.restoreTabs ? persistentStore.get(connection.uid, []) as WorkspaceTab[] : [];
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
if (cachedTabs.length) {
|
2022-05-28 18:43:56 +02:00
|
|
|
tabIndex[connection.uid] = cachedTabs.reduce((acc: number, curr) => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (curr.index > acc) acc = curr.index;
|
|
|
|
return acc;
|
|
|
|
}, null);
|
|
|
|
}
|
|
|
|
|
2023-06-13 18:10:52 +02:00
|
|
|
const selectedTab = cachedTabs.length
|
|
|
|
? connection.database
|
2023-07-06 22:01:41 +02:00
|
|
|
? cachedTabs.filter(tab => tab.type === 'query' || tab.database === connection.database)[0]?.uid
|
2023-06-13 18:10:52 +02:00
|
|
|
: cachedTabs[0].uid
|
|
|
|
: null;
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
client: connection.client,
|
|
|
|
dataTypes,
|
|
|
|
indexTypes,
|
2022-05-10 13:02:01 +02:00
|
|
|
customizations: clientCustomizations,
|
2022-04-30 00:47:37 +02:00
|
|
|
structure: response,
|
|
|
|
connectionStatus: 'connected',
|
|
|
|
tabs: cachedTabs,
|
2023-06-13 18:10:52 +02:00
|
|
|
selectedTab,
|
2022-04-30 00:47:37 +02:00
|
|
|
version
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
|
|
|
|
this.refreshCollations(connection.uid);
|
|
|
|
this.refreshVariables(connection.uid);
|
|
|
|
this.refreshEngines(connection.uid);
|
|
|
|
this.refreshUsers(connection.uid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshStructure (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Schema.getStructure({ uid, schemas: this.getLoadedSchemas(uid) });
|
|
|
|
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
structure: response
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshSchema ({ uid, schema }: {uid: string; schema: string}) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Schema.getStructure({ uid, schemas: new Set([schema]) });
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
const schemaElements = (response as WorkspaceStructure[]).find(_schema => _schema.name === schema);
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
const schemaIndex = workspace.structure.findIndex(s => s.name === schema);
|
|
|
|
|
|
|
|
if (schemaIndex !== -1)
|
|
|
|
workspace.structure[schemaIndex] = schemaElements;
|
|
|
|
else
|
|
|
|
workspace.structure.push(schemaElements);
|
|
|
|
}
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshCollations (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Schema.getCollations(uid);
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
collations: response
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshVariables (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Schema.getVariables(uid);
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
variables: response
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshEngines (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Schema.getEngines(uid);
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
engines: response
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
async refreshUsers (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
const notificationsStore = useNotificationsStore();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { status, response } = await Users.getUsers(uid);
|
|
|
|
if (status === 'error')
|
|
|
|
notificationsStore.addNotification({ status, message: response });
|
|
|
|
else {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
users: response
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
notificationsStore.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
removeConnected (uid: string) {
|
2022-04-30 00:47:37 +02:00
|
|
|
Connection.disconnect(uid);
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
2023-06-13 18:10:52 +02:00
|
|
|
structure: [],
|
2022-04-30 00:47:37 +02:00
|
|
|
breadcrumbs: {},
|
|
|
|
loadedSchemas: new Set(),
|
|
|
|
connectionStatus: 'disconnected'
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
|
|
|
|
this.selectTab({ uid, tab: 0 });
|
|
|
|
},
|
2023-06-13 18:10:52 +02:00
|
|
|
async switchConnection (connection: ConnectionParams & { pgConnString?: string }) {
|
|
|
|
await Connection.disconnect(connection.uid);
|
|
|
|
return this.connectWorkspace(connection, 'switch');
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
addWorkspace (uid: string) {
|
|
|
|
const workspace: Workspace = {
|
2022-04-30 00:47:37 +02:00
|
|
|
uid,
|
|
|
|
connectionStatus: 'disconnected',
|
2023-12-25 10:54:41 +01:00
|
|
|
selectedTab: '0',
|
2022-04-30 00:47:37 +02:00
|
|
|
searchTerm: '',
|
|
|
|
tabs: [],
|
2022-05-28 18:43:56 +02:00
|
|
|
structure: [],
|
2022-04-30 00:47:37 +02:00
|
|
|
variables: [],
|
|
|
|
collations: [],
|
|
|
|
users: [],
|
2022-06-04 18:37:16 +02:00
|
|
|
breadcrumbs: {},
|
2022-04-30 00:47:37 +02:00
|
|
|
loadingElements: [],
|
|
|
|
loadedSchemas: new Set()
|
|
|
|
};
|
|
|
|
|
|
|
|
this.workspaces.push(workspace);
|
|
|
|
},
|
2023-09-11 18:02:19 +02:00
|
|
|
removeWorkspace (uid: string) {
|
|
|
|
this.workspaces = this.workspaces.filter((w: Workspace) => w.uid !== uid);
|
|
|
|
if (uid === this.selectedWorkspace) this.selectedWorkspace = 'NEW';
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
changeBreadcrumbs (payload: Breadcrumb) {
|
|
|
|
const breadcrumbsObj: Breadcrumb = {
|
2022-04-30 00:47:37 +02:00
|
|
|
schema: null,
|
|
|
|
table: null,
|
|
|
|
trigger: null,
|
|
|
|
triggerFunction: null,
|
2022-06-09 20:08:32 +02:00
|
|
|
routine: null,
|
2022-04-30 00:47:37 +02:00
|
|
|
function: null,
|
|
|
|
scheduler: null,
|
|
|
|
view: null,
|
|
|
|
query: null
|
|
|
|
};
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === this.getSelected
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
breadcrumbs: { ...breadcrumbsObj, ...payload }
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
addLoadedSchema (schema: string) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === this.getSelected)
|
|
|
|
workspace.loadedSchemas.add(schema);
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
addLoadingElement (element: { name: string; schema: string; type: string }) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === this.getSelected)
|
|
|
|
workspace.loadingElements.push(element);
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
removeLoadingElement (element: { name: string; schema: string; type: string }) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === this.getSelected) {
|
|
|
|
const loadingElements = workspace.loadingElements.filter(el =>
|
|
|
|
el.schema !== element.schema &&
|
|
|
|
el.name !== element.name &&
|
|
|
|
el.type !== element.type
|
|
|
|
);
|
|
|
|
|
|
|
|
workspace = { ...workspace, loadingElements };
|
|
|
|
}
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
setSearchTerm (term: string) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === this.getSelected
|
2022-04-30 00:47:37 +02:00
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
searchTerm: term
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
},
|
2023-06-13 18:10:52 +02:00
|
|
|
setDatabase (databaseName: string) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === this.getSelected
|
|
|
|
? {
|
|
|
|
...workspace,
|
|
|
|
database: databaseName
|
|
|
|
}
|
|
|
|
: workspace);
|
|
|
|
},
|
2024-04-06 09:34:42 +02:00
|
|
|
_addTab ({ uid, tab, content, type, autorun, schema, database, elementName, elementType, filePath }: WorkspaceTab) {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (type === 'query')
|
|
|
|
tabIndex[uid] = tabIndex[uid] ? ++tabIndex[uid] : 1;
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
const newTab: WorkspaceTab = {
|
2022-04-30 00:47:37 +02:00
|
|
|
uid: tab,
|
|
|
|
index: type === 'query' ? tabIndex[uid] : null,
|
|
|
|
selected: false,
|
|
|
|
type,
|
2023-06-13 18:10:52 +02:00
|
|
|
database,
|
2022-04-30 00:47:37 +02:00
|
|
|
schema,
|
|
|
|
elementName,
|
|
|
|
elementType,
|
|
|
|
content: content || '',
|
2024-04-06 09:34:42 +02:00
|
|
|
autorun: !!autorun,
|
|
|
|
filePath: filePath || ''
|
2022-04-30 00:47:37 +02:00
|
|
|
};
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: [...workspace.tabs, newTab]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
2022-04-30 00:47:37 +02:00
|
|
|
},
|
2024-04-06 09:34:42 +02:00
|
|
|
_replaceTab ({ uid, tab: tUid, type, schema, content, elementName, elementType, filePath }: WorkspaceTab) {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: workspace.tabs.map(tab => {
|
2024-04-30 18:07:08 +02:00
|
|
|
if (tab.uid === tUid) {
|
|
|
|
return {
|
|
|
|
...tab,
|
|
|
|
type,
|
|
|
|
schema,
|
|
|
|
content,
|
|
|
|
elementName,
|
|
|
|
elementType,
|
|
|
|
filePath
|
|
|
|
};
|
|
|
|
}
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
return tab;
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
2022-04-30 00:47:37 +02:00
|
|
|
},
|
2024-04-06 09:34:42 +02:00
|
|
|
newTab ({ uid, content, type, autorun, schema, elementName, elementType, filePath }: WorkspaceTab) {
|
2022-04-30 00:47:37 +02:00
|
|
|
let tabUid;
|
2022-05-28 18:43:56 +02:00
|
|
|
const workspaceTabs = (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid);
|
2022-04-30 00:47:37 +02:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 'new-table':
|
2024-06-14 18:05:29 +02:00
|
|
|
case 'new-view':
|
|
|
|
case 'new-materialized-view':
|
2022-04-30 00:47:37 +02:00
|
|
|
case 'new-trigger':
|
|
|
|
case 'new-trigger-function':
|
|
|
|
case 'new-function':
|
|
|
|
case 'new-routine':
|
|
|
|
case 'new-scheduler':
|
|
|
|
tabUid = uidGen('T');
|
|
|
|
this._addTab({
|
|
|
|
uid,
|
|
|
|
tab: tabUid,
|
|
|
|
content,
|
|
|
|
type,
|
|
|
|
autorun,
|
2023-06-13 18:10:52 +02:00
|
|
|
database: workspaceTabs.database,
|
2022-04-30 00:47:37 +02:00
|
|
|
schema,
|
|
|
|
elementName,
|
2024-04-06 09:34:42 +02:00
|
|
|
elementType,
|
|
|
|
filePath
|
2022-04-30 00:47:37 +02:00
|
|
|
});
|
|
|
|
break;
|
|
|
|
case 'temp-data':
|
|
|
|
case 'temp-trigger-props':
|
|
|
|
case 'temp-trigger-function-props':
|
|
|
|
case 'temp-function-props':
|
|
|
|
case 'temp-routine-props':
|
|
|
|
case 'temp-scheduler-props': {
|
|
|
|
const existentTab = workspaceTabs
|
|
|
|
? workspaceTabs.tabs.find(tab =>
|
|
|
|
tab.schema === schema &&
|
|
|
|
tab.elementName === elementName &&
|
|
|
|
tab.elementType === elementType &&
|
2024-04-18 18:22:29 +02:00
|
|
|
tab.database === workspaceTabs.database &&
|
2022-04-30 00:47:37 +02:00
|
|
|
[type, type.replace('temp-', '')].includes(tab.type))
|
|
|
|
: false;
|
|
|
|
|
|
|
|
if (existentTab) { // if tab exists
|
|
|
|
tabUid = existentTab.uid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const tempTabs = workspaceTabs ? workspaceTabs.tabs.filter(tab => tab.type.includes('temp-')) : false;
|
|
|
|
|
|
|
|
if (tempTabs && tempTabs.length) { // if temp tab already opened
|
|
|
|
for (const tab of tempTabs) {
|
|
|
|
if (tab.isChanged) {
|
|
|
|
this._replaceTab({ // make permanent a temp table with unsaved changes
|
|
|
|
uid,
|
|
|
|
tab: tab.uid,
|
|
|
|
type: tab.type.replace('temp-', ''),
|
|
|
|
schema: tab.schema,
|
|
|
|
elementName: tab.elementName,
|
2024-04-06 09:34:42 +02:00
|
|
|
elementType: tab.elementType,
|
|
|
|
filePath: tab.filePath
|
2022-04-30 00:47:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
tabUid = uidGen('T');
|
2024-04-30 18:07:08 +02:00
|
|
|
this._addTab({
|
|
|
|
uid,
|
|
|
|
tab: tabUid,
|
|
|
|
content,
|
|
|
|
type,
|
|
|
|
autorun,
|
|
|
|
database: workspaceTabs.database,
|
|
|
|
schema,
|
|
|
|
elementName,
|
|
|
|
elementType,
|
|
|
|
filePath
|
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
}
|
|
|
|
else {
|
2024-04-30 18:07:08 +02:00
|
|
|
this._replaceTab({
|
|
|
|
uid,
|
|
|
|
tab: tab.uid,
|
|
|
|
type,
|
|
|
|
schema,
|
|
|
|
elementName,
|
|
|
|
elementType,
|
|
|
|
filePath
|
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
tabUid = tab.uid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tabUid = uidGen('T');
|
2024-04-30 18:07:08 +02:00
|
|
|
this._addTab({
|
|
|
|
uid,
|
|
|
|
tab: tabUid,
|
|
|
|
content,
|
|
|
|
type,
|
|
|
|
autorun,
|
|
|
|
database: workspaceTabs.database,
|
|
|
|
schema,
|
|
|
|
elementName,
|
|
|
|
elementType,
|
|
|
|
filePath
|
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'data':
|
|
|
|
case 'table-props':
|
2024-06-14 18:05:29 +02:00
|
|
|
case 'view-props':
|
|
|
|
case 'materialized-view-props':
|
2022-04-30 00:47:37 +02:00
|
|
|
case 'trigger-props':
|
|
|
|
case 'trigger-function-props':
|
|
|
|
case 'function-props':
|
|
|
|
case 'routine-props':
|
|
|
|
case 'scheduler-props': {
|
|
|
|
const existentTab = workspaceTabs
|
|
|
|
? workspaceTabs.tabs.find(tab =>
|
|
|
|
tab.schema === schema &&
|
|
|
|
tab.elementName === elementName &&
|
|
|
|
tab.elementType === elementType &&
|
2024-04-18 18:22:29 +02:00
|
|
|
tab.database === workspaceTabs.database &&
|
2022-04-30 00:47:37 +02:00
|
|
|
[`temp-${type}`, type].includes(tab.type))
|
|
|
|
: false;
|
|
|
|
|
|
|
|
if (existentTab) {
|
2023-12-25 10:54:41 +01:00
|
|
|
this._replaceTab({ uid,
|
|
|
|
tab: existentTab.uid,
|
|
|
|
type,
|
|
|
|
database: workspaceTabs.database,
|
|
|
|
schema,
|
|
|
|
elementName,
|
2024-04-06 09:34:42 +02:00
|
|
|
elementType,
|
|
|
|
filePath
|
2023-12-25 10:54:41 +01:00
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
tabUid = existentTab.uid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tabUid = uidGen('T');
|
2023-12-25 10:54:41 +01:00
|
|
|
this._addTab({ uid,
|
|
|
|
tab: tabUid,
|
|
|
|
content,
|
|
|
|
type,
|
|
|
|
autorun,
|
|
|
|
database: workspaceTabs.database,
|
|
|
|
schema,
|
|
|
|
elementName,
|
2024-04-06 09:34:42 +02:00
|
|
|
elementType,
|
|
|
|
filePath
|
2023-12-25 10:54:41 +01:00
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tabUid = uidGen('T');
|
2023-12-25 10:54:41 +01:00
|
|
|
this._addTab({ uid,
|
|
|
|
tab: tabUid,
|
|
|
|
content,
|
|
|
|
type,
|
|
|
|
autorun,
|
|
|
|
database: workspaceTabs.database,
|
|
|
|
schema,
|
|
|
|
elementName,
|
2024-04-06 09:34:42 +02:00
|
|
|
elementType,
|
|
|
|
filePath
|
2023-12-25 10:54:41 +01:00
|
|
|
});
|
2022-04-30 00:47:37 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.selectTab({ uid, tab: tabUid });
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
checkSelectedTabExists (uid: string) {
|
|
|
|
const workspace = (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid);
|
2022-04-30 00:47:37 +02:00
|
|
|
const isSelectedExistent = workspace
|
|
|
|
? workspace.tabs.some(tab => tab.uid === workspace.selectedTab)
|
|
|
|
: false;
|
|
|
|
|
2023-06-13 18:10:52 +02:00
|
|
|
if (!isSelectedExistent && workspace.tabs.length) {
|
|
|
|
if (workspace.customizations.database) {
|
|
|
|
const databaseTabs = workspace.tabs.filter(tab => tab.type === 'query' || tab.database === workspace.database);
|
2023-12-28 10:44:11 +01:00
|
|
|
if (databaseTabs.length)
|
|
|
|
this.selectTab({ uid, tab: databaseTabs[databaseTabs.length - 1].uid });
|
2023-06-13 18:10:52 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
this.selectTab({ uid, tab: workspace.tabs[workspace.tabs.length - 1].uid });
|
|
|
|
}
|
2022-04-30 00:47:37 +02:00
|
|
|
},
|
2024-04-06 09:34:42 +02:00
|
|
|
updateTabContent ({ uid, tab, type, schema, content, elementName, filePath }: WorkspaceTab) {
|
|
|
|
this._replaceTab({ uid, tab, type, schema, content, elementName, filePath });
|
2022-04-30 00:47:37 +02:00
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
renameTabs ({ uid, schema, elementName, elementNewName }: WorkspaceTab) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: workspace.tabs.map(tab => {
|
|
|
|
if (tab.elementName === elementName && tab.schema === schema) {
|
|
|
|
return {
|
|
|
|
...tab,
|
|
|
|
elementName: elementNewName
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return tab;
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
2022-04-30 00:47:37 +02:00
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
removeTab ({ uid, tab: tUid }: {uid: string; tab: string}) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: workspace.tabs.filter(tab => tab.uid !== tUid)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
2022-04-30 00:47:37 +02:00
|
|
|
this.checkSelectedTabExists(uid);
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
removeTabs ({ uid, schema, elementName, elementType }: WorkspaceTab) { // Multiple tabs based on schema and element name
|
2022-04-30 00:47:37 +02:00
|
|
|
if (elementType === 'procedure') elementType = 'routine'; // TODO: pass directly "routine"
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: workspace.tabs.filter(tab =>
|
|
|
|
tab.schema !== schema ||
|
|
|
|
tab.elementName !== elementName ||
|
|
|
|
tab.elementType !== elementType
|
|
|
|
)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
2022-04-30 00:47:37 +02:00
|
|
|
this.checkSelectedTabExists(uid);
|
|
|
|
},
|
2022-05-28 18:43:56 +02:00
|
|
|
selectTab ({ uid, tab }: {uid: string; tab: string}) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? { ...workspace, selectedTab: tab }
|
|
|
|
: workspace
|
|
|
|
);
|
|
|
|
},
|
2022-06-13 09:29:05 +02:00
|
|
|
selectNextTab ({ uid }: {uid: string }) {
|
|
|
|
const workspace = (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid);
|
2022-06-03 18:56:19 +02:00
|
|
|
|
|
|
|
let newIndex = workspace.tabs.findIndex(tab => tab.selected || tab.uid === workspace.selectedTab) + 1;
|
|
|
|
|
|
|
|
if (newIndex > workspace.tabs.length -1)
|
|
|
|
newIndex = 0;
|
|
|
|
|
|
|
|
this.selectTab({ uid, tab: workspace.tabs[newIndex].uid });
|
|
|
|
},
|
2022-06-13 09:29:05 +02:00
|
|
|
selectPrevTab ({ uid }: {uid: string }) {
|
|
|
|
const workspace = (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid);
|
2022-06-03 18:56:19 +02:00
|
|
|
|
|
|
|
let newIndex = workspace.tabs.findIndex(tab => tab.selected || tab.uid === workspace.selectedTab) - 1;
|
|
|
|
|
|
|
|
if (newIndex < 0)
|
|
|
|
newIndex = workspace.tabs.length -1;
|
|
|
|
|
|
|
|
this.selectTab({ uid, tab: workspace.tabs[newIndex].uid });
|
|
|
|
},
|
2022-06-04 18:37:16 +02:00
|
|
|
updateTabs ({ uid, tabs }: {uid: string; tabs: WorkspaceTab[]}) {
|
2022-05-28 18:43:56 +02:00
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === uid
|
2022-04-30 00:47:37 +02:00
|
|
|
? { ...workspace, tabs }
|
|
|
|
: workspace
|
|
|
|
);
|
2022-05-28 18:43:56 +02:00
|
|
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
|
|
|
},
|
|
|
|
setUnsavedChanges ({ uid, tUid, isChanged }: { uid: string; tUid: string; isChanged: boolean }) {
|
|
|
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
2022-04-30 00:47:37 +02:00
|
|
|
if (workspace.uid === uid) {
|
|
|
|
return {
|
|
|
|
...workspace,
|
|
|
|
tabs: workspace.tabs.map(tab => {
|
|
|
|
if (tab.uid === tUid)
|
|
|
|
return { ...tab, isChanged };
|
|
|
|
|
|
|
|
return tab;
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return workspace;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|