feat: views creation

This commit is contained in:
Fabio Di Stasio 2020-12-27 16:16:48 +01:00
parent b7053bdf80
commit 8c4aaec167
9 changed files with 262 additions and 6 deletions

View File

@ -30,4 +30,14 @@ export default (connections) => {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('create-view', async (event, params) => {
try {
await connections[params.uid].createView(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@ -311,6 +311,17 @@ export class MySQLClient extends AntaresCore {
return await this.raw(sql);
}
/**
* CREATE VIEW
*
* @returns {Array.<Object>} parameters
* @memberof MySQLClient
*/
async createView (view) {
const sql = `CREATE ALGORITHM = ${view.algorithm} ${view.definer ? `DEFINER=${view.definer} ` : ''}SQL SECURITY ${view.security} VIEW \`${view.name}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
return await this.raw(sql);
}
/**
* SHOW COLLATION
*

View File

@ -0,0 +1,188 @@
<template>
<ConfirmModal
:confirm-text="$t('word.confirm')"
size="medium"
@confirm="confirmOptionsChange"
@hide="$emit('close')"
>
<template :slot="'header'">
<div class="d-flex">
<i class="mdi mdi-24px mdi-eye-plus mr-1" /> {{ $t('message.createNewView') }}
</div>
</template>
<div :slot="'body'">
<div class="container">
<div class="columns mb-4">
<div class="column col-6">
<div class="form-group">
<label class="form-label">{{ $t('word.name') }}</label>
<input
ref="firstInput"
v-model="localView.name"
class="form-input"
type="text"
>
</div>
</div>
<div class="column col-6">
<div class="form-group">
<label class="form-label">{{ $t('word.definer') }}</label>
<input
v-model="localView.definer"
class="form-input"
type="text"
:placeholder="$t('message.currentUser')"
readonly
>
</div>
</div>
</div>
<div class="columns">
<div class="column col-4">
<div class="form-group">
<label class="form-label">{{ $t('message.sqlSecurity') }}</label>
<label class="form-radio">
<input
v-model="localView.security"
type="radio"
name="security"
value="DEFINER"
>
<i class="form-icon" /> DEFINER
</label>
<label class="form-radio">
<input
v-model="localView.security"
type="radio"
name="security"
value="INVOKER"
>
<i class="form-icon" /> INVOKER
</label>
</div>
</div>
<div class="column col-4">
<div class="form-group">
<label class="form-label">{{ $t('word.algorithm') }}</label>
<label class="form-radio">
<input
v-model="localView.algorithm"
type="radio"
name="algorithm"
value="UNDEFINED"
>
<i class="form-icon" /> UNDEFINED
</label>
<label class="form-radio">
<input
v-model="localView.algorithm"
type="radio"
value="MERGE"
name="algorithm"
>
<i class="form-icon" /> MERGE
</label>
<label class="form-radio">
<input
v-model="localView.algorithm"
type="radio"
value="TEMPTABLE"
name="algorithm"
>
<i class="form-icon" /> TEMPTABLE
</label>
</div>
</div>
<div class="column col-4">
<div class="form-group">
<label class="form-label">{{ $t('message.updateOption') }}</label>
<label class="form-radio">
<input
v-model="localView.updateOption"
type="radio"
name="update"
value=""
>
<i class="form-icon" /> None
</label>
<label class="form-radio">
<input
v-model="localView.updateOption"
type="radio"
name="update"
value="CASCADED"
>
<i class="form-icon" /> CASCADED
</label>
<label class="form-radio">
<input
v-model="localView.updateOption"
type="radio"
name="update"
value="LOCAL"
>
<i class="form-icon" /> LOCAL
</label>
</div>
</div>
</div>
</div>
<div class="workspace-query-results column col-12 mt-2">
<label class="form-label ml-2">{{ $t('message.selectStatement') }}</label>
<QueryEditor
ref="queryEditor"
:value.sync="localView.sql"
:workspace="workspace"
:schema="schema"
:height="editorHeight"
/>
</div>
</div>
</ConfirmModal>
</template>
<script>
import ConfirmModal from '@/components/BaseConfirmModal';
import QueryEditor from '@/components/QueryEditor';
export default {
name: 'ModalNewView',
components: {
ConfirmModal,
QueryEditor
},
props: {
table: String,
workspace: Object
},
data () {
return {
localView: {
algorithm: 'UNDEFINED',
definer: '',
security: 'DEFINER',
updateOption: '',
sql: '',
name: ''
},
isOptionsChanging: false,
editorHeight: 300
};
},
computed: {
schema () {
return this.workspace.breadcrumbs.schema;
}
},
mounted () {
setTimeout(() => {
this.$refs.firstInput.focus();
}, 20);
},
methods: {
confirmOptionsChange () {
this.$emit('open-create-view-editor', this.localView);
}
}
};
</script>

View File

@ -54,12 +54,19 @@
@close="hideCreateTableModal"
@open-create-table-editor="openCreateTableEditor"
/>
<ModalNewView
v-if="isNewViewModal"
:workspace="workspace"
@close="hideCreateViewModal"
@open-create-view-editor="openCreateViewEditor"
/>
<DatabaseContext
v-if="isDatabaseContext"
:selected-database="selectedDatabase"
:context-event="databaseContextEvent"
@close-context="closeDatabaseContext"
@show-create-table-modal="showCreateTableModal"
@show-create-view-modal="showCreateViewModal"
@reload="refresh"
/>
<TableContext
@ -76,12 +83,14 @@
import { mapGetters, mapActions } from 'vuex';
import _ from 'lodash';
import Tables from '@/ipc-api/Tables';
import Views from '@/ipc-api/Views';
import WorkspaceConnectPanel from '@/components/WorkspaceConnectPanel';
import WorkspaceExploreBarDatabase from '@/components/WorkspaceExploreBarDatabase';
import DatabaseContext from '@/components/WorkspaceExploreBarDatabaseContext';
import TableContext from '@/components/WorkspaceExploreBarTableContext';
import ModalNewDatabase from '@/components/ModalNewDatabase';
import ModalNewTable from '@/components/ModalNewTable';
import ModalNewView from '@/components/ModalNewView';
export default {
name: 'WorkspaceExploreBar',
@ -91,7 +100,8 @@ export default {
DatabaseContext,
TableContext,
ModalNewDatabase,
ModalNewTable
ModalNewTable,
ModalNewView
},
props: {
connection: Object,
@ -102,6 +112,7 @@ export default {
isRefreshing: false,
isNewDBModal: false,
isNewTableModal: false,
isNewViewModal: false,
localWidth: null,
isDatabaseContext: false,
isTableContext: false,
@ -215,6 +226,29 @@ export default {
},
closeTableContext () {
this.isTableContext = false;
},
showCreateViewModal () {
this.closeDatabaseContext();
this.isNewViewModal = true;
},
hideCreateViewModal () {
this.isNewViewModal = false;
},
async openCreateViewEditor (payload) {
const params = {
uid: this.connection.uid,
...payload
};
const { status, response } = await Views.createView(params);
if (status === 'success') {
await this.refresh();
this.changeBreadcrumbs({ schema: this.selectedDatabase, view: payload.name });
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
}
else
this.addNotification({ status: 'error', message: response });
}
}
};

View File

@ -25,7 +25,11 @@
<i class="table-icon mdi mdi-18px mr-1" :class="table.type === 'view' ? 'mdi-table-eye' : 'mdi-table'" />
<span>{{ table.name }}</span>
</a>
<div class="table-size tooltip tooltip-left mr-1" :data-tooltip="formatBytes(table.size)">
<div
v-if="table.type === 'table'"
class="table-size tooltip tooltip-left mr-1"
:data-tooltip="formatBytes(table.size)"
>
<div class="pie" :style="piePercentage(table.size)" />
</div>
</li>

View File

@ -10,7 +10,7 @@
<div class="context-element" @click="showCreateTableModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-table text-light pr-1" /> {{ $t('word.table') }}</span>
</div>
<div class="context-element" @click="showCreateTableModal">
<div class="context-element" @click="showCreateViewModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-table-eye text-light pr-1" /> {{ $t('word.view') }}</span>
</div>
<div class="context-element d-none" @click="false">
@ -96,6 +96,9 @@ export default {
showCreateTableModal () {
this.$emit('show-create-table-modal');
},
showCreateViewModal () {
this.$emit('show-create-view-modal');
},
showDeleteModal () {
this.isDeleteModal = true;
},

View File

@ -145,8 +145,8 @@ export default {
const { status, response } = res;
if (status === 'success') {
if (this.selectedTable.name === this.workspace.breadcrumbs.table)
this.changeBreadcrumbs({ table: null });
if (this.selectedTable.name === this.workspace.breadcrumbs.table || this.selectedTable.name === this.workspace.breadcrumbs.view)
this.changeBreadcrumbs({ table: null, view: null });
this.closeContext();
this.$emit('reload');

View File

@ -142,7 +142,9 @@ module.exports = {
selectStatement: 'Select statement',
sqlSecurity: 'SQL security',
updateOption: 'Update option',
deleteView: 'Delete view'
deleteView: 'Delete view',
createNewView: 'Create new view',
currentUser: 'Current user'
},
// Date and Time
short: {

View File

@ -13,4 +13,8 @@ export default class {
static alterView (params) {
return ipcRenderer.invoke('alter-view', params);
}
static createView (params) {
return ipcRenderer.invoke('create-view', params);
}
}