mirror of https://github.com/Fabio286/antares.git
feat: new table empty state
This commit is contained in:
parent
6cef02bebb
commit
0842e00098
|
@ -119,8 +119,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="workspace-query-results column col-12 p-relative">
|
<div class="workspace-query-results column col-12 p-relative">
|
||||||
<BaseLoader v-if="isLoading" />
|
<BaseLoader v-if="isLoading" />
|
||||||
<WorkspaceTabPropsTableFIelds
|
<WorkspaceTabNewTableEmptyState v-if="!localFields.length" @new-field="addField" />
|
||||||
v-if="localFields"
|
<WorkspaceTabPropsTableFields
|
||||||
|
v-if="localFields.length"
|
||||||
ref="indexTable"
|
ref="indexTable"
|
||||||
:fields="localFields"
|
:fields="localFields"
|
||||||
:indexes="localIndexes"
|
:indexes="localIndexes"
|
||||||
|
@ -168,17 +169,19 @@ import { mapGetters, mapActions } from 'vuex';
|
||||||
import { uidGen } from 'common/libs/uidGen';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import Tables from '@/ipc-api/Tables';
|
import Tables from '@/ipc-api/Tables';
|
||||||
import BaseLoader from '@/components/BaseLoader';
|
import BaseLoader from '@/components/BaseLoader';
|
||||||
import WorkspaceTabPropsTableFIelds from '@/components/WorkspaceTabPropsTableFIelds';
|
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields';
|
||||||
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal';
|
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal';
|
||||||
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal';
|
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal';
|
||||||
|
import WorkspaceTabNewTableEmptyState from '@/components/WorkspaceTabNewTableEmptyState';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'WorkspaceTabNewTable',
|
name: 'WorkspaceTabNewTable',
|
||||||
components: {
|
components: {
|
||||||
BaseLoader,
|
BaseLoader,
|
||||||
WorkspaceTabPropsTableFIelds,
|
WorkspaceTabPropsTableFields,
|
||||||
WorkspaceTabPropsTableIndexesModal,
|
WorkspaceTabPropsTableIndexesModal,
|
||||||
WorkspaceTabPropsTableForeignModal
|
WorkspaceTabPropsTableForeignModal,
|
||||||
|
WorkspaceTabNewTableEmptyState
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
connection: Object,
|
connection: Object,
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<template>
|
||||||
|
<div class="column col-12 empty">
|
||||||
|
<p class="h6 empty-subtitle">
|
||||||
|
{{ $t('message.thereAreNoTableFields') }}
|
||||||
|
</p>
|
||||||
|
<div class="empty-action">
|
||||||
|
<button class="btn btn-gray d-flex" @click="$emit('new-field')">
|
||||||
|
<i class="mdi mdi-24px mdi-playlist-plus mr-2" />
|
||||||
|
{{ $t('message.addNewField') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'WorkspaceTabNewTableEmptyState'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.empty {
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,263 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="tableWrapper"
|
||||||
|
class="vscroll"
|
||||||
|
:style="{'height': resultsSize+'px'}"
|
||||||
|
>
|
||||||
|
<TableContext
|
||||||
|
v-if="isContext"
|
||||||
|
:context-event="contextEvent"
|
||||||
|
:selected-field="selectedField"
|
||||||
|
:index-types="indexTypes"
|
||||||
|
:indexes="indexes"
|
||||||
|
@delete-selected="removeField"
|
||||||
|
@duplicate-selected="duplicateField"
|
||||||
|
@close-context="isContext = false"
|
||||||
|
@add-new-index="$emit('add-new-index', $event)"
|
||||||
|
@add-to-index="$emit('add-to-index', $event)"
|
||||||
|
/>
|
||||||
|
<div ref="propTable" class="table table-hover">
|
||||||
|
<div class="thead">
|
||||||
|
<div class="tr">
|
||||||
|
<div class="th">
|
||||||
|
<div class="text-right">
|
||||||
|
{{ $t('word.order') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $tc('word.key', 2) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th">
|
||||||
|
<div class="column-resizable min-100">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.name') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th">
|
||||||
|
<div class="column-resizable min-100">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.type') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.tableArray" class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.array') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.length') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.unsigned" class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.unsigned') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.nullable" class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('message.allowNull') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.zerofill" class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('message.zeroFill') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.default') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.comment" class="th">
|
||||||
|
<div class="column-resizable">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.comment') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="customizations.collation" class="th">
|
||||||
|
<div class="column-resizable min-100">
|
||||||
|
<div class="table-column-title">
|
||||||
|
{{ $t('word.collation') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Draggable
|
||||||
|
ref="resultTable"
|
||||||
|
:list="fields"
|
||||||
|
class="tbody"
|
||||||
|
handle=".row-draggable"
|
||||||
|
>
|
||||||
|
<TableRow
|
||||||
|
v-for="row in fields"
|
||||||
|
:key="row._id"
|
||||||
|
:row="row"
|
||||||
|
:indexes="getIndexes(row.name)"
|
||||||
|
:foreigns="getForeigns(row.name)"
|
||||||
|
:data-types="dataTypes"
|
||||||
|
:customizations="customizations"
|
||||||
|
@contextmenu="contextMenu"
|
||||||
|
@rename-field="$emit('rename-field', $event)"
|
||||||
|
/>
|
||||||
|
</Draggable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapGetters } from 'vuex';
|
||||||
|
import Draggable from 'vuedraggable';
|
||||||
|
import TableRow from '@/components/WorkspaceTabPropsTableRow';
|
||||||
|
import TableContext from '@/components/WorkspaceTabPropsTableContext';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WorkspaceTabPropsTableFIelds',
|
||||||
|
components: {
|
||||||
|
TableRow,
|
||||||
|
TableContext,
|
||||||
|
Draggable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
fields: Array,
|
||||||
|
indexes: Array,
|
||||||
|
foreigns: Array,
|
||||||
|
indexTypes: Array,
|
||||||
|
tabUid: [String, Number],
|
||||||
|
connUid: String,
|
||||||
|
table: String,
|
||||||
|
schema: String,
|
||||||
|
mode: String
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
resultsSize: 1000,
|
||||||
|
isContext: false,
|
||||||
|
contextEvent: null,
|
||||||
|
selectedField: null,
|
||||||
|
scrollElement: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getWorkspaceTab: 'workspaces/getWorkspaceTab',
|
||||||
|
getWorkspace: 'workspaces/getWorkspace'
|
||||||
|
}),
|
||||||
|
workspaceSchema () {
|
||||||
|
return this.getWorkspace(this.connUid).breadcrumbs.schema;
|
||||||
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.getWorkspace(this.connUid).customizations;
|
||||||
|
},
|
||||||
|
dataTypes () {
|
||||||
|
return this.getWorkspace(this.connUid).dataTypes;
|
||||||
|
},
|
||||||
|
primaryField () {
|
||||||
|
return this.fields.filter(field => ['pri', 'uni'].includes(field.key))[0] || false;
|
||||||
|
},
|
||||||
|
tabProperties () {
|
||||||
|
return this.getWorkspaceTab(this.tabUid);
|
||||||
|
},
|
||||||
|
fieldsLength () {
|
||||||
|
return this.fields.length;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
fieldsLength () {
|
||||||
|
this.refreshScroller();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updated () {
|
||||||
|
if (this.$refs.propTable)
|
||||||
|
this.refreshScroller();
|
||||||
|
|
||||||
|
if (this.$refs.tableWrapper)
|
||||||
|
this.scrollElement = this.$refs.tableWrapper;
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
window.addEventListener('resize', this.resizeResults);
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
window.removeEventListener('resize', this.resizeResults);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
addNotification: 'notifications/addNotification'
|
||||||
|
}),
|
||||||
|
resizeResults () {
|
||||||
|
if (this.$refs.resultTable) {
|
||||||
|
const el = this.$refs.tableWrapper;
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
const footer = document.getElementById('footer');
|
||||||
|
const size = window.innerHeight - el.getBoundingClientRect().top - footer.offsetHeight;
|
||||||
|
this.resultsSize = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
refreshScroller () {
|
||||||
|
this.resizeResults();
|
||||||
|
},
|
||||||
|
contextMenu (event, uid) {
|
||||||
|
this.selectedField = this.fields.find(field => field._id === uid);
|
||||||
|
this.contextEvent = event;
|
||||||
|
this.isContext = true;
|
||||||
|
},
|
||||||
|
duplicateField () {
|
||||||
|
this.$emit('duplicate-field', this.selectedField._id);
|
||||||
|
},
|
||||||
|
removeField () {
|
||||||
|
this.$emit('remove-field', this.selectedField._id);
|
||||||
|
},
|
||||||
|
getIndexes (field) {
|
||||||
|
return this.indexes.reduce((acc, curr) => {
|
||||||
|
acc.push(...curr.fields.map(f => ({ name: f, type: curr.type })));
|
||||||
|
return acc;
|
||||||
|
}, []).filter(f => f.name === field);
|
||||||
|
},
|
||||||
|
getForeigns (field) {
|
||||||
|
return this.foreigns.reduce((acc, curr) => {
|
||||||
|
if (curr.field === field)
|
||||||
|
acc.push(`${curr.refTable}.${curr.refField}`);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.column-resizable {
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
resize: horizontal;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vscroll {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-100 {
|
||||||
|
min-width: 100px !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -231,7 +231,8 @@ module.exports = {
|
||||||
noSchema: 'No schema',
|
noSchema: 'No schema',
|
||||||
restorePreviourSession: 'Restore previous session',
|
restorePreviourSession: 'Restore previous session',
|
||||||
runQuery: 'Run query',
|
runQuery: 'Run query',
|
||||||
newTable: 'New table'
|
newTable: 'New table',
|
||||||
|
thereAreNoTableFields: 'There are no table fields'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
|
Loading…
Reference in New Issue