/** * @author Martin Karkowski * @email m.karkowski@zema.de * @create date 2019-02-20 09:19:06 * @modify date 2020-10-29 09:55:30 * @desc [description] * * A Basic Layout. * It uses a Toolbar, Sidebar * * Toast are implemented by https://fkhadra.github.io/react-toastify/introduction */ import React from "react"; import { Nav } from "react-bootstrap"; import { FaTimesCircle } from "react-icons/fa"; import { deepClone } from "../../../lib/helpers/objectMethods"; import { ITab } from "./interfaces/ITab"; import { ITabEntry } from "./interfaces/ITabEntry"; export interface ITabProps { onMount?: (item: ITabEntry) => void; onNewTab?: () => Promise; onTabSelect?: (oldTabId: ITab, newTabId: ITab) => Promise; onTabEdit?: (tab: ITab) => Promise; onTabDelete?: (tabId: ITab, forced?: boolean) => Promise; onNoTabSelected?: () => Promise; onConfigChanged?: (config: ITabProps) => void; tabs: { allowNewTabs?: boolean; active: string; items: ITab[]; }; } class TabEntry extends React.Component implements ITabEntry { protected _handleResize: () => void; public hotkeysEnabled = true; public pressedKey: string = null; public currentMousePosition: MouseEvent; constructor(props) { super(props); this.state = Object.assign({}, this.props); } /** * Function will be called if the Item has been rendered sucessfully. */ componentDidMount() { const _this = this; if (typeof _this.state.onMount === "function") { _this.state.onMount(_this); } } protected _sendConfig() { if (typeof this.props.onConfigChanged === "function") { this.props.onConfigChanged(deepClone(this.state)); } } public get selectedTab() { for (const tab of this.state.tabs.items) { if (tab.id === this.state.tabs.active) { return tab; } } return null; } public async requestTab() { if (typeof this.state.onNewTab === "function") { const tab = await this.state.onNewTab(); if (typeof tab === "object") { this.state.tabs.items.push(tab); await this.selectTab(tab); } } } public async createTab(tab: ITab) { const tabs = this.tabs; tabs.push(tab); this.tabs = tabs; } public get tabs(): ITab[] { return this.state.tabs?.items || []; } public set tabs(value: ITab[]) { this.setState({ tabs: { active: this.activeTab, items: value, allowNewTabs: this.state.tabs.allowNewTabs, }, }); } public get activeTab(): string { return this.state.tabs.active; } public set activeTab(value: string) { this.setState({ tabs: { active: value, items: this.props.tabs.items, allowNewTabs: this.props.tabs.allowNewTabs, }, }); this._sendConfig(); } /** * Function to Select a Tab * @param tab */ public async selectTab(tab: ITab | string) { let newTabToDisplay: ITab; if (typeof tab === "string") { for (const _t of this.tabs) { if (_t.id === tab) { newTabToDisplay = _t; break; } } } else { newTabToDisplay = tab; } if (typeof this.state.onTabSelect === "function") { const currentlySelected = this.selectedTab; // Call the Async Function to select a Tab. if (await this.state.onTabSelect(currentlySelected, newTabToDisplay)) { this.activeTab = newTabToDisplay.id; return true; } return false; } else { // Assign the Tab ID this.activeTab = newTabToDisplay.id; return true; } } public async editTab(tab: ITab | string) { let tabToEdit: ITab; let idx = -1; const tabs = this.tabs; for (const [_idx, _tab] of this.tabs.entries()) { if (_tab.id === (typeof tab === "string" ? tab : tab.id)) { tabToEdit = _tab; idx = _idx; break; } } if (tabToEdit && typeof this.state.onTabEdit === "function") { const editedTab = await this.state.onTabEdit(tabToEdit); tabs[idx] = editedTab; this.tabs = tabs; } } public async delteTab(tab: ITab | string, forced = false) { let idx = -1; let _tab: ITab = null; const tabs = this.state.tabs.items; for (const [_idx, _t] of tabs.entries()) { if (_t.id === (typeof tab === "string" ? tab : tab.id)) { idx = _idx; _tab = _t; break; } } if (_tab != null) { let removed = false; if (typeof this.state.onTabDelete === "function") { // Call the Async Function to select a Tab. if (await this.state.onTabDelete(_tab, forced)) { removed = true; } } else { removed = true; } if (removed) { // Remove the Items. tabs.splice(idx, 1); // Check if the active element has been removed: if (_tab.id == this.state.tabs.active) { // Assign the ID of the Element. const _idx = tabs.length > idx ? idx : tabs.length - 1; if (_idx !== -1) { // Assign the First ID. const _newTab = tabs.length > _idx ? tabs[_idx] : null; if (_newTab !== null) { if ( !(await this.selectTab(_newTab)) && typeof this.state.onNoTabSelected === "function" ) { // Send a Warning, that no Tabs has been selected await this.state.onNoTabSelected(); } } else if (typeof this.state.onNoTabSelected === "function") { // Send a Warning, that no Tabs has been selected await this.state.onNoTabSelected(); } } else if (typeof this.state.onNoTabSelected === "function") { // Send a Warning, that no Tabs has been selected await this.state.onNoTabSelected(); } } this.tabs = tabs; this._sendConfig(); } } } public render() { return ( <> ); } } export default TabEntry;