Files
DiceCloud/app/imports/client/ui/dialogStack/dialogStackStore.js
2022-11-19 17:51:50 +02:00

127 lines
3.7 KiB
JavaScript

import Vue from 'vue';
import { clone } from 'lodash';
let dialogStack = {};
dialogStack.dialogs = [];
const dialogStackStore = {
state: {
dialogs: [],
currentResult: null,
currentReturnElement: null,
},
mutations: {
pushDialogStack(state, { component, data, elementId, callback }) {
// Generate a new _id so that Vue knows how to shuffle the array
const _id = Random.id();
state.dialogs.push({
_id,
component,
data,
elementId,
callback,
});
updateHistory();
},
replaceDialog(state, { component, data }) {
if (!state.dialogs.length) {
throw new Meteor.Error('can\'t replace dialog if no dialogs are open');
}
let currentDialog = state.dialogs[state.dialogs.length - 1]
Vue.set(state.dialogs, state.dialogs.length - 1, {
_id: currentDialog._id,
component,
data,
elementId: currentDialog.elementId,
callback: currentDialog.callback,
});
},
popDialogStackMutation(state, result) {
const dialog = state.dialogs.pop();
state.currentResult = null;
updateHistory();
if (!dialog) return;
if (dialog.callback) {
let returnElementId = dialog.callback(result);
state.currentReturnElement = returnElementId;
} else {
state.currentReturnElement = null;
}
},
setCurrentResult(state, result) {
state.currentResult = result;
},
},
actions: {
popDialogStack(context, result) {
if (history && history.state && history.state.openDialogs) {
context.commit('setCurrentResult', result);
history.back();
} else {
context.commit('popDialogStackMutation', result);
}
},
popDialogStacks(context, quantity) {
if (quantity <= 0) return;
let iterationsLeft = quantity;
let intervalId = setInterval(() => {
if (history && history.state && history.state.openDialogs) {
context.commit('setCurrentResult');
history.back();
} else {
context.commit('popDialogStackMutation');
}
iterationsLeft -= 1;
if (iterationsLeft === 0) {
clearInterval(intervalId);
}
}, 150);
},
},
};
export default dialogStackStore;
const updateHistory = function () {
// history should looks like: [{openDialogs: 0}, {openDialogs: n}] where
// n is the number of open dialogs
// If we can't access the history object, give up
if (!history) return;
// Make sure that there is a state tracking open dialogs
// replace the state without bashing it in the process
if (!history.state || !Number.isFinite(history.state.openDialogs)) {
let newState = clone(history.state) || {};
newState.openDialogs = 0;
history.replaceState(newState, '');
}
const numDialogs = dialogStackStore.state.dialogs.length;
const stateDialogs = history.state.openDialogs;
// If the number of dialogs and state dialogs are equal, we don't need to do
// anything
if (numDialogs === stateDialogs) return;
if (stateDialogs > 0) {
// On a dialog count
if (numDialogs === 0) {
// but shouldn't be
history.back();
} else {
// but should replace with correct count
let newState = clone(history.state) || {};
newState.openDialogs = dialogStackStore.state.dialogs.length;
history.replaceState(newState, '');
}
} else if (numDialogs > 0 && stateDialogs === 0) {
// On the zero state, push a dialog count
history.pushState({ openDialogs: numDialogs }, '');
} else {
console.warn(
'History could not be updated correctly, unexpected case',
{ stateDialogs, numDialogs },
)
}
};