mirror of
https://github.com/Fabio286/antares.git
synced 2025-02-17 12:10:39 +01:00
feat: new unsaved change reminder
This commit is contained in:
parent
003c02b1fb
commit
f7a74df009
@ -16,7 +16,6 @@
|
|||||||
<TheNotificationsBoard />
|
<TheNotificationsBoard />
|
||||||
<TheScratchpad v-if="isScratchpad" />
|
<TheScratchpad v-if="isScratchpad" />
|
||||||
<ModalSettings v-if="isSettingModal" />
|
<ModalSettings v-if="isSettingModal" />
|
||||||
<ModalDiscardChanges v-if="isUnsavedDiscardModal" />
|
|
||||||
<BaseTextEditor class="d-none" value="" />
|
<BaseTextEditor class="d-none" value="" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -39,7 +38,6 @@ export default {
|
|||||||
WorkspaceAddConnectionPanel: () => import(/* webpackChunkName: "WorkspaceAddConnectionPanel" */'@/components/WorkspaceAddConnectionPanel'),
|
WorkspaceAddConnectionPanel: () => import(/* webpackChunkName: "WorkspaceAddConnectionPanel" */'@/components/WorkspaceAddConnectionPanel'),
|
||||||
ModalSettings: () => import(/* webpackChunkName: "ModalSettings" */'@/components/ModalSettings'),
|
ModalSettings: () => import(/* webpackChunkName: "ModalSettings" */'@/components/ModalSettings'),
|
||||||
TheScratchpad: () => import(/* webpackChunkName: "TheScratchpad" */'@/components/TheScratchpad'),
|
TheScratchpad: () => import(/* webpackChunkName: "TheScratchpad" */'@/components/TheScratchpad'),
|
||||||
ModalDiscardChanges: () => import(/* webpackChunkName: "ModalDiscardChanges" */'@/components/ModalDiscardChanges'),
|
|
||||||
BaseTextEditor: () => import(/* webpackChunkName: "BaseTextEditor" */'@/components/BaseTextEditor')
|
BaseTextEditor: () => import(/* webpackChunkName: "BaseTextEditor" */'@/components/BaseTextEditor')
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
@ -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="discardUnsavedChanges"
|
@confirm="$emit('confirm')"
|
||||||
@hide="closeUnsavedChangesModal"
|
@hide="$emit('close')"
|
||||||
>
|
>
|
||||||
<template slot="header">
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
@ -19,7 +19,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapActions } from 'vuex';
|
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -34,13 +33,6 @@ export default {
|
|||||||
window.removeEventListener('keydown', this.onKey);
|
window.removeEventListener('keydown', this.onKey);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
|
||||||
discardUnsavedChanges: 'workspaces/discardUnsavedChanges',
|
|
||||||
closeUnsavedChangesModal: 'workspaces/closeUnsavedChangesModal'
|
|
||||||
}),
|
|
||||||
closeModal () {
|
|
||||||
this.$emit('close');
|
|
||||||
},
|
|
||||||
onKey (e) {
|
onKey (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === 'Escape')
|
if (e.key === 'Escape')
|
||||||
|
@ -87,7 +87,11 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a v-else-if="tab.type === 'table-props'" class="tab-link">
|
<a
|
||||||
|
v-else-if="tab.type === 'table-props'"
|
||||||
|
class="tab-link"
|
||||||
|
:class="{'badge': tab.isChanged}"
|
||||||
|
>
|
||||||
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
||||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||||
{{ tab.elementName }}
|
{{ tab.elementName }}
|
||||||
@ -99,7 +103,11 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a v-else-if="tab.type === 'view-props'" class="tab-link">
|
<a
|
||||||
|
v-else-if="tab.type === 'view-props'"
|
||||||
|
class="tab-link"
|
||||||
|
:class="{'badge': tab.isChanged}"
|
||||||
|
>
|
||||||
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
||||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||||
{{ tab.elementName }}
|
{{ tab.elementName }}
|
||||||
@ -230,6 +238,12 @@
|
|||||||
:connection="connection"
|
:connection="connection"
|
||||||
@close="hideProcessesModal"
|
@close="hideProcessesModal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ModalDiscardChanges
|
||||||
|
v-if="unsavedTab"
|
||||||
|
@confirm="closeTab(unsavedTab, true)"
|
||||||
|
@close="unsavedTab = null"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -249,6 +263,7 @@ import WorkspacePropsTabView from '@/components/WorkspacePropsTabView';
|
|||||||
// import WorkspacePropsTabTriggerFunction from '@/components/WorkspacePropsTabTriggerFunction';
|
// import WorkspacePropsTabTriggerFunction from '@/components/WorkspacePropsTabTriggerFunction';
|
||||||
// import WorkspacePropsTabScheduler from '@/components/WorkspacePropsTabScheduler';
|
// import WorkspacePropsTabScheduler from '@/components/WorkspacePropsTabScheduler';
|
||||||
import ModalProcessesList from '@/components/ModalProcessesList';
|
import ModalProcessesList from '@/components/ModalProcessesList';
|
||||||
|
import ModalDiscardChanges from '@/components/ModalDiscardChanges';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Workspace',
|
name: 'Workspace',
|
||||||
@ -265,7 +280,8 @@ export default {
|
|||||||
// WorkspacePropsTabFunction,
|
// WorkspacePropsTabFunction,
|
||||||
// WorkspacePropsTabTriggerFunction,
|
// WorkspacePropsTabTriggerFunction,
|
||||||
// WorkspacePropsTabScheduler,
|
// WorkspacePropsTabScheduler,
|
||||||
ModalProcessesList
|
ModalProcessesList,
|
||||||
|
ModalDiscardChanges
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
connection: Object
|
connection: Object
|
||||||
@ -273,7 +289,8 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
hasWheelEvent: false,
|
hasWheelEvent: false,
|
||||||
isProcessesModal: false
|
isProcessesModal: false,
|
||||||
|
unsavedTab: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -365,8 +382,13 @@ export default {
|
|||||||
openAsDataTab (tab) {
|
openAsDataTab (tab) {
|
||||||
this.newTab({ uid: this.connection.uid, schema: tab.schema, elementName: tab.elementName, type: 'data', elementType: tab.elementType });
|
this.newTab({ uid: this.connection.uid, schema: tab.schema, elementName: tab.elementName, type: 'data', elementType: tab.elementType });
|
||||||
},
|
},
|
||||||
closeTab (tab) {
|
closeTab (tab, force) {
|
||||||
|
this.unsavedTab = null;
|
||||||
if (tab.type === 'query' && this.queryTabs.length === 1) return;
|
if (tab.type === 'query' && this.queryTabs.length === 1) return;
|
||||||
|
if (!force && tab.isChanged) {
|
||||||
|
this.unsavedTab = tab;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.removeTab({ uid: this.connection.uid, tab: tab.uid });
|
this.removeTab({ uid: this.connection.uid, tab: tab.uid });
|
||||||
if (this.selectedTab === tab.uid && this.workspace.tabs.length)
|
if (this.selectedTab === tab.uid && this.workspace.tabs.length)
|
||||||
@ -426,6 +448,12 @@ export default {
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
|
&.badge::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 35px;
|
||||||
|
top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-clear {
|
.btn-clear {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -137,7 +137,6 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
tabUid: 'prop', // ???
|
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
isOptionsModal: false,
|
isOptionsModal: false,
|
||||||
@ -164,6 +163,9 @@ export default {
|
|||||||
workspace () {
|
workspace () {
|
||||||
return this.getWorkspace(this.connection.uid);
|
return this.getWorkspace(this.connection.uid);
|
||||||
},
|
},
|
||||||
|
tabUid () {
|
||||||
|
return this.$vnode.key;
|
||||||
|
},
|
||||||
tableOptions () {
|
tableOptions () {
|
||||||
const db = this.workspace.structure.find(db => db.name === this.schema);
|
const db = this.workspace.structure.find(db => db.name === this.schema);
|
||||||
return db && this.table ? db.tables.find(table => table.name === this.table) : {};
|
return db && this.table ? db.tables.find(table => table.name === this.table) : {};
|
||||||
@ -207,8 +209,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
isChanged (val) {
|
isChanged (val) {
|
||||||
if (this.isSelected && this.lastTable === this.table && this.table !== null)
|
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||||
this.setUnsavedChanges(val);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
<span>{{ $t('word.clear') }}</span>
|
<span>{{ $t('word.clear') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="workspace-query-info">
|
||||||
|
<div class="d-flex" :title="$t('word.schema')">
|
||||||
|
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -192,7 +197,6 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
tabUid: 'prop',
|
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
originalView: null,
|
originalView: null,
|
||||||
@ -210,6 +214,9 @@ export default {
|
|||||||
workspace () {
|
workspace () {
|
||||||
return this.getWorkspace(this.connection.uid);
|
return this.getWorkspace(this.connection.uid);
|
||||||
},
|
},
|
||||||
|
tabUid () {
|
||||||
|
return this.$vnode.key;
|
||||||
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.originalView) !== JSON.stringify(this.localView);
|
return JSON.stringify(this.originalView) !== JSON.stringify(this.localView);
|
||||||
},
|
},
|
||||||
@ -241,8 +248,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
isChanged (val) {
|
isChanged (val) {
|
||||||
if (this.isSelected && this.lastView === this.view && this.view !== null)
|
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||||
this.setUnsavedChanges(val);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created () {
|
async created () {
|
||||||
|
@ -169,7 +169,7 @@ module.exports = {
|
|||||||
deleteTable: 'Delete table',
|
deleteTable: 'Delete table',
|
||||||
emptyCorfirm: 'Do you confirm to empty',
|
emptyCorfirm: 'Do you confirm to empty',
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
discardUnsavedChanges: 'You have some unsaved changes. By leaving this tab these changes will be discarded.',
|
discardUnsavedChanges: 'You have some unsaved changes. Closing this tab these changes will be discarded.',
|
||||||
thereAreNoIndexes: 'There are no indexes',
|
thereAreNoIndexes: 'There are no indexes',
|
||||||
thereAreNoForeign: 'There are no foreign keys',
|
thereAreNoForeign: 'There are no foreign keys',
|
||||||
createNewForeign: 'Create new foreign key',
|
createNewForeign: 'Create new foreign key',
|
||||||
|
@ -11,10 +11,7 @@ export default {
|
|||||||
strict: true,
|
strict: true,
|
||||||
state: {
|
state: {
|
||||||
workspaces: [],
|
workspaces: [],
|
||||||
selected_workspace: null,
|
selected_workspace: null
|
||||||
has_unsaved_changes: false,
|
|
||||||
is_unsaved_discard_modal: false,
|
|
||||||
pending_breadcrumbs: {}
|
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
getSelected: state => {
|
getSelected: state => {
|
||||||
@ -45,9 +42,6 @@ export default {
|
|||||||
},
|
},
|
||||||
getSearchTerm: state => uid => {
|
getSearchTerm: state => uid => {
|
||||||
return state.workspaces.find(workspace => workspace.uid === uid).search_term;
|
return state.workspaces.find(workspace => workspace.uid === uid).search_term;
|
||||||
},
|
|
||||||
isUnsavedDiscardModal: state => {
|
|
||||||
return state.is_unsaved_discard_modal;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -296,12 +290,26 @@ export default {
|
|||||||
return workspace;
|
return workspace;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
SET_UNSAVED_CHANGES (state, val) {
|
SET_UNSAVED_CHANGES (state, { uid, tUid, isChanged }) {
|
||||||
state.has_unsaved_changes = !!val;
|
state.workspaces = state.workspaces.map(workspace => {
|
||||||
},
|
if (workspace.uid === uid) {
|
||||||
SET_UNSAVED_DISCARD_MODAL (state, val) {
|
return {
|
||||||
state.is_unsaved_discard_modal = !!val;
|
...workspace,
|
||||||
|
tabs: workspace.tabs.map(tab => {
|
||||||
|
if (tab.uid === tUid)
|
||||||
|
return { ...tab, isChanged };
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return workspace;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
// SET_UNSAVED_DISCARD_MODAL (state, val) {
|
||||||
|
// state.is_unsaved_discard_modal = !!val;
|
||||||
|
// },
|
||||||
SET_PENDING_BREADCRUMBS (state, payload) {
|
SET_PENDING_BREADCRUMBS (state, payload) {
|
||||||
state.pending_breadcrumbs = payload;
|
state.pending_breadcrumbs = payload;
|
||||||
},
|
},
|
||||||
@ -483,11 +491,11 @@ export default {
|
|||||||
dispatch('setUnsavedChanges', false);
|
dispatch('setUnsavedChanges', false);
|
||||||
},
|
},
|
||||||
changeBreadcrumbs ({ state, commit, getters }, payload) {
|
changeBreadcrumbs ({ state, commit, getters }, payload) {
|
||||||
if (state.has_unsaved_changes) {
|
// if (state.has_unsaved_changes) {
|
||||||
commit('SET_UNSAVED_DISCARD_MODAL', true);
|
// commit('SET_UNSAVED_DISCARD_MODAL', true);
|
||||||
commit('SET_PENDING_BREADCRUMBS', payload);
|
// commit('SET_PENDING_BREADCRUMBS', payload);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const breadcrumbsObj = {
|
const breadcrumbsObj = {
|
||||||
schema: null,
|
schema: null,
|
||||||
@ -607,17 +615,8 @@ export default {
|
|||||||
setTabKeyUsage ({ commit }, payload) {
|
setTabKeyUsage ({ commit }, payload) {
|
||||||
commit('SET_TAB_KEY_USAGE', payload);
|
commit('SET_TAB_KEY_USAGE', payload);
|
||||||
},
|
},
|
||||||
setUnsavedChanges ({ commit }, val) {
|
setUnsavedChanges ({ commit }, payload) {
|
||||||
commit('SET_UNSAVED_CHANGES', val);
|
commit('SET_UNSAVED_CHANGES', payload);
|
||||||
},
|
|
||||||
discardUnsavedChanges ({ state, commit, dispatch }) {
|
|
||||||
dispatch('setUnsavedChanges', false);
|
|
||||||
dispatch('changeBreadcrumbs', state.pending_breadcrumbs);
|
|
||||||
commit('SET_UNSAVED_DISCARD_MODAL', false);
|
|
||||||
commit('SET_PENDING_BREADCRUMBS', {});
|
|
||||||
},
|
|
||||||
closeUnsavedChangesModal ({ commit }) {
|
|
||||||
commit('SET_UNSAVED_DISCARD_MODAL', false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user