1
1
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:
Fabio Di Stasio 2021-07-16 23:24:55 +02:00
parent 003c02b1fb
commit f7a74df009
7 changed files with 76 additions and 52 deletions

View File

@ -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 () {

View File

@ -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')

View File

@ -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;

View File

@ -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 () {

View File

@ -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 () {

View File

@ -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',

View File

@ -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);
} }
} }
}; };