/* * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). * * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import {Controller} from "@hotwired/stimulus"; import {default as TreeController} from "./tree_controller"; import {EVENT_INITIALIZED} from "@jbtronics/bs-treeview"; export default class extends TreeController { static targets = [ "tree", 'sourceText' ]; _storage_key; _lastUpdate; connect() { //Check if the tree is already initialized, if so then skip initialization (useful when going back) to in history using Turbo if(this._isInitialized()) { return; } const default_mode = this.element.dataset.defaultMode; this._storage_key = 'tree_' + this.element.id; //Check if we have a saved mode const stored_mode = localStorage.getItem(this._storage_key); this._frame = this.element.dataset.frame || "content"; //By default, navigate in the content frame, if a frame is defined //Use stored mode if possible, otherwise use default if(stored_mode) { try { this.setMode(stored_mode); } catch (e) { console.error(e); //If an error happenes, use the default mode this.setMode(default_mode); } } else { this.setMode(default_mode); } //Register an event listener which checks if the tree needs to be updated document.addEventListener('turbo:render', this.doUpdateIfNeeded.bind(this)); //Register an event listener, to check if we end up on a page we can highlight in the tree, if so then higlight it document.addEventListener('turbo:load', this._onTurboLoad.bind(this)); //On initial page load the tree is not available yet, so do another check after the tree is initialized this.treeTarget.addEventListener(EVENT_INITIALIZED, (event) => { this.selectNodeWithURL(document.location) }); } _onTurboLoad(event) { this.selectNodeWithURL(event.detail.url); } selectNodeWithURL(url) { //Get path from url const path = new URL(url).pathname; if (!this._tree) { return; } //Unselect all nodes this._tree.unselectAll({silent: true, ignorePreventUnselect: true}); //Try to find a node with this path as data-path const nodes = this._tree.findNodes(path, "href"); if (nodes.length !== 1) { return; //We can only work with exactly one node, if there are multiple nodes with the same path, we cannot know which one to select, so we do nothing } const node = nodes[0]; node.setSelected(true, {ignorePreventUnselect: true, silent: true}); this._tree.revealNode(node); } doUpdateIfNeeded() { const info_element = document.getElementById('sidebar-last-time-updated'); const date_str = info_element.dataset.lastUpdate; const server_last_update = new Date(date_str); if(this._lastUpdate < server_last_update) { console.log("Sidebar tree is outdated, reloading (last update: " + this._lastUpdate + ", server update: " + server_last_update + ")"); this._lastUpdate = new Date(); this.reinitTree(); } } setMode(mode) { //Find the button for this mode const modeButton = this.element.querySelector(`[data-mode="${mode}"]`); if(!modeButton) { throw new Error(`Could not find button for mode ${mode}`); } //Get the url and text from the button const url = modeButton.dataset.url; const text = modeButton.dataset.text; this.sourceTextTarget.innerText = text; this.setURL(url); //Update the last update time this._lastUpdate = new Date(); } changeDataSource(event) { const mode = event.params.mode ?? event.target.dataset.mode; const url = event.params.url ?? event.target.dataset.url; const text = event.params.text ?? event.target.dataset.text; this.sourceTextTarget.innerText = text; this.setURL(url); //Save the mode in local storage localStorage.setItem(this._storage_key, mode); this._lastUpdate = new Date(); } }