import { defineStore } from 'pinia'; import { getAvailableTermsForSpecies, } from "../components/SimulatedData.js"; /* eslint-disable no-alert, no-console */ const presetLayouts = (view) => { switch (view) { case "2horpanel": return { "split-1": {content: false, horizontal: true, children: ["pane-1", "pane-2"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, }; case "2vertpanel": return { "split-1": {content: false, horizontal: false, children: ["pane-1", "pane-2"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, } case "3panel": return { "split-1": {content: false, horizontal: false, children: ["pane-1", "split-2"]}, "split-2": {content: false, horizontal: true, children: ["pane-2", "pane-3"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, } case "4panel": return { "split-1": {content: false, horizontal: false, children: ["split-3", "split-2"]}, "split-2": {content: false, horizontal: true, children: ["pane-2", "pane-3"]}, "split-3": {content: false, horizontal: true, children: ["pane-1", "pane-4"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, "pane-4": {content: true, id: 4}, } case "5panel": return { "split-1": {content: false, horizontal: true, children: ["split-3", "split-2"]}, "split-2": {content: false, horizontal: false, children: ["pane-2", "pane-3"]}, "split-3": {content: false, horizontal: false, children: ["pane-1","pane-4", "pane-5"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, "pane-4": {content: true, id: 4}, "pane-5": {content: true, id: 5}, } case "6panel": return { "split-1": {content: false, horizontal: true, children: ["split-3", "split-2"]}, "split-2": {content: false, horizontal: false, children: ["pane-2", "pane-3", "pane-5"]}, "split-3": {content: false, horizontal: false, children: ["pane-1","pane-4", "pane-6"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, "pane-4": {content: true, id: 4}, "pane-5": {content: true, id: 5}, "pane-6": {content: true, id: 6}, } case "6panelVertical": return { "split-1": {content: false, horizontal: false, children: ["split-3", "split-2"]}, "split-2": {content: false, horizontal: true, children: ["pane-2", "pane-3", "pane-5"]}, "split-3": {content: false, horizontal: true, children: ["pane-1","pane-4", "pane-6"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, "pane-4": {content: true, id: 4}, "pane-5": {content: true, id: 5}, "pane-6": {content: true, id: 6}, } case "singlepanel": default: return { "split-1": {content: false, horizontal: false, children: ["pane-1"]}, "pane-1": {content: true, id: 1}, } } } //A method to assign unused entry to pane with duplicated id const autoAssignEntryIdsToPane = (entries, layout) => { const assignedIds = []; const invalidIdKeys = []; for (const [key, value] of Object.entries(layout)) { if (value.content) { if (assignedIds.includes(value.id)) { //id has got an assigned pane, cache it and find one //later invalidIdKeys.push(key); } else { assignedIds.push(value.id); } } } invalidIdKeys.forEach((key) => { let done = false; for (let i = 0; i < entries.length && !done; i++) { if (!(assignedIds.includes(entries[i].id))) { layout[key].id = entries[i].id; assignedIds.push(entries.id); done = true; } } }); } const extractPaneInfo = (layout) => { const panes = {}; for (const [key, value] of Object.entries(layout)) { if (value.content) { panes[key] = value; } } return panes; } const newLayoutWithOrigInfo = (original, activeView) => { const panes = extractPaneInfo(original); const customLayout = presetLayouts(activeView); for (const [key, value] of Object.entries(panes)) { customLayout[key] = value; } return customLayout; } const findKeyWithId = (layout, id) => { return Object.keys(layout).find(key => layout[key]["id"] === id); } const getOriginalState = () => { return { activeView: "singlepanel", idNamePair: {}, viewIcons: [ { icon: "singlepanel", name: "Single view", min: 1 }, { icon: "2horpanel", name: "Horizontal split", min: 2 }, { icon: "2vertpanel", name: "Vertical split", min: 2 }, { icon: "3panel", name: "Three panes", min: 3 }, { icon: "4panel", name: "Four panes", min: 4 }, { icon: "5panel", name: "Five panes", min: 5 }, { icon: "6panel", name: "Six (horizontal)", min: 6 }, { icon: "6panelVertical", name: "Six (vertical)", min: 6 }, //{ icon: "customise", name: "Customise", min: 2 } ], customLayout: { "split-1": {content: false, horizontal: false, children: ["pane-1"]}, "pane-1": {content: true, id: 1}, /* Example layout "split-1": {content: false, horizontal: true, children: ["split-2", "pane-1"]}, "split-2": {content: false, horizontal: false, children: ["pane-2", "pane-3"]}, "pane-1": {content: true, id: 1}, "pane-2": {content: true, id: 2}, "pane-3": {content: true, id: 3}, */ }, splitters: { "first": 50, "second": 50, "third": 50 }, globalCallback: false, syncMode: false, }; } export const useSplitFlowStore = defineStore('splitFlow', { state: () => { return getOriginalState(); }, getters: { getPaneNameById: (state) => (id) => { return findKeyWithId(state.customLayout, id); }, getState: (state) => () => { return { activeView: state.activeView, splitters: state.splitters, globalCallback: state.globalCallback, customLayout: state.customLayout, syncMode: state.syncMode, }; }, }, actions: { assignOrSwapPaneWithIds(payload) { let sourceKey = findKeyWithId(this.customLayout, payload.source); let targetKey = findKeyWithId(this.customLayout, payload.target); // Check if it is on syncMode if (this.syncMode && (!(targetKey || sourceKey))) { //exit syncMod if the two panel in sync mode are not swapping this.syncMode = false; this.globalCallback = false; } if (targetKey) { this.customLayout[targetKey].id = payload.source; } if (sourceKey) { this.customLayout[sourceKey].id = payload.target; } }, getAvailableTerms(apiLocation) { let terms = getAvailableTermsForSpecies(); for (let i = 0; i < terms.length; i++) { this.idNamePair[terms[i].id] = terms[i].name; } if (apiLocation) { if (this._controller) this._controller.abort(); this._controller = new AbortController(); let signal = this._controller.signal; // console.log("getAvailableTerms") fetch(`${apiLocation}get-organ-curies`, { signal, }) .then(response => response.json()) .then(data => { this._controller = undefined; data.uberon.array.forEach(pair => { this.idNamePair[pair.id.toUpperCase()] = pair.name.charAt(0).toUpperCase() + pair.name.slice(1); }); return; }); } }, toggleGlobalCallback(flag) { this.globalCallback = flag; }, updateActiveView(payload) { //Deactivate sync mode if current or future view //is not in 2 split panels/ if (this.syncMode) { const view1 = this.viewIcons.find( view => this.activeView === view.icon); const view2 = this.viewIcons.find( view => payload.view === view.icon); if (!(view1.min == 2 && view2.min == 2)) { this.syncMode = false; this.globalCallback = false; } } this.activeView = payload.view; const customLayout = newLayoutWithOrigInfo( this.customLayout, this.activeView); autoAssignEntryIdsToPane(payload.entries, customLayout); for (const [key, value] of Object.entries(customLayout)) { this.customLayout[key] = value; } }, setSplitter(payload) { if (this.splitters[payload.name]) this.splitters[payload.name] = payload.value; }, setState(newState) { if (newState) { let customLayout = undefined; if (newState.activeView) { this.activeView = newState.activeView; } if (newState.customLayout) { customLayout = newState.customLayout; } else { customLayout = presetLayouts(this.activeView); if (newState.slotInfo) { for (let i = 0; i < newState.slotInfo.length; i++) { switch (newState.slotInfo[i].name) { case "first": { customLayout["pane-1"].id = newState.slotInfo[i].id; } break; case "second": { if("pane-2" in customLayout) customLayout["pane-2"].id = newState.slotInfo[i].id; } break; case "thrid": { if("pane-3" in customLayout) customLayout["pane-3"].id = newState.slotInfo[i].id; } break; case "fourth": { if("pane-4" in customLayout) customLayout["pane-4"].id = newState.slotInfo[i].id; } break; case "fifth": { if("pane-5" in customLayout) customLayout["pane-5"].id = newState.slotInfo[i].id; } break; case "sixth": { if("pane-6" in customLayout) customLayout["pane-6"].id = newState.slotInfo[i].id; } break; default: break; } } } } for (const [key, value] of Object.entries(customLayout)) { this.customLayout[key] = value; } if (newState.globalCallback) { this.globalCallback = newState.globalCallback; } for (const [key, value] of Object.entries(newState.splitters)) { this.splitters[key] = value; } if (newState.syncMode) { this.syncMode = newState.syncMode; } } }, setIdToPrimaryPane(id) { const currentKey = findKeyWithId(this.customLayout, id); const firstPaneId = this.customLayout["pane-1"].id; this.customLayout["pane-1"].id = id; if (currentKey) { this.customLayout[currentKey].id = firstPaneId; } }, setSyncMode(payload) { if (payload) { //Force the second slot to be the new viewer in payload and change the //view to the payload's layout //this.customLayout["pane-2"].id = id; if (payload.flag === true) { this.activeView = payload.layout; //Extract pane info form original state and copy to the new layout const customLayout = newLayoutWithOrigInfo( this.customLayout, this.activeView); const originalKey = findKeyWithId(customLayout, 1); const firstPaneId = customLayout["pane-1"].id; if (originalKey !== "pane-1") { customLayout["pane-1"].id = firstPaneId; } customLayout["pane-1"].id = 1; customLayout["pane-2"].id = payload.newId; for (const [key, value] of Object.entries(customLayout)) { this.customLayout[key] = value; } this.syncMode = true; this.globalCallback = true; } else { this.activeView = "singlepanel"; const customLayout = newLayoutWithOrigInfo( this.customLayout, this.activeView); for (const [key, value] of Object.entries(customLayout)) { this.customLayout[key] = value; } this.syncMode = false; this.globalCallback = false; } } }, reset() { const original = getOriginalState(); this.activeView = original.activeView; this.customLayout = original.customLayout; this.splitters = original.splitters; this.globalCallback = original.globalCallback; this.syncMode = original.syncMode; }, closeSlot(payload) { if (payload) { this.syncMode = false; this.globalCallback = false; let availableId = 0; //Primary id cannot be changed if (payload.id === 1) { availableId = 1; } else if (payload.entries) { for (let i = 0; i < payload.entries.length && availableId == 0; i++) { //Find the first entry not currently in use if (findKeyWithId(payload.entries[i].id) === undefined) { availableId = payload.entries[i].id; } } } //Switch the view if (this.activeView !== "customise") { //closePaneWithStandardLayout const pView = this.activeView; switch (this.activeView) { case "2horpanel": case "2vertpanel": this.activeView = "singlepanel"; break; case "3panel": this.activeView = "2vertpanel"; break; case "4panel": this.activeView = "3panel"; break; case "5panel": this.activeView = "4panel"; break; case "6panelVertical": case "6panel": this.activeView = "5panel"; break; default: break; } const customLayout = newLayoutWithOrigInfo( this.customLayout, this.activeView); const key = findKeyWithId(customLayout, payload.id); // The following move the entry id to the appropriate slot // and remove the target id switch (key) { case "pane-1": { switch (pView) { case "2horpanel": case "2vertpanel": { customLayout["pane-1"].id = customLayout["pane-2"].id; customLayout["pane-2"].id = availableId; } break; case "3panel": { customLayout["pane-1"].id = customLayout["pane-2"].id; customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = availableId; } break; case "4panel": { customLayout["pane-1"].id = customLayout["pane-2"].id; customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = availableId; } break; case "5panel": { customLayout["pane-1"].id = customLayout["pane-2"].id; customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = availableId; } break; case "6panelVertical": case "6panel": { customLayout["pane-1"].id = customLayout["pane-2"].id; customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = customLayout["pane-6"].id; customLayout["pane-6"].id = availableId; } break; default: break; } } break; case "pane-2": { switch (pView) { case "2horpanel": case "2vertpanel": { customLayout["pane-2"].id = availableId; } break; case "3panel": { customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = availableId; } break; case "4panel": { customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = availableId; } break; case "5panel": { customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = availableId; } break; case "6panelVertical": case "6panel": { customLayout["pane-2"].id = customLayout["pane-3"].id; customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = customLayout["pane-6"].id; customLayout["pane-6"].id = availableId; } break; default: break; } } break; case "pane-3": { switch (pView) { case "3panel": { customLayout["pane-3"].id = availableId; } break; case "4panel": { customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = availableId; } break; case "5panel": { customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = availableId; } break; case "6panelVertical": case "6panel": { customLayout["pane-3"].id = customLayout["pane-4"].id; customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = customLayout["pane-6"].id; customLayout["pane-6"].id = availableId; } break; default: break; } } break; case "pane-4": { switch (pView) { case "4panel": { customLayout["pane-4"].id = availableId; } break; case "5panel": { customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = availableId; } break; case "6panelVertical": case "6panel": { customLayout["pane-4"].id = customLayout["pane-5"].id; customLayout["pane-5"].id = customLayout["pane-6"].id; customLayout["pane-6"].id = availableId; } break; default: break; } } break; case "pane-5": { switch (pView) { case "5panel": { customLayout["pane-5"].id = availableId; } break; case "6panelVertical": case "6panel": { customLayout["pane-5"].id = customLayout["pane-6"].id; customLayout["pane-6"].id = availableId; } break; default: break; } } break; case "pane-6" : { switch (pView) { case "6panelVertical": case "6panel": { customLayout["pane-6"].id = availableId; } break; default: break; } } break; default: break; } for (const [key, value] of Object.entries(customLayout)) { this.customLayout[key] = value; } } } } } });