import React from "react" import classnames from "classnames" import * as antd from "antd" import { createIconRender } from "components/Icons" import NavMenu from "./components/NavMenu" import "./index.less" export const Panel = (props) => { return
{props.children}
} export class PagePanelWithNavMenu extends React.Component { state = { activeTab: this.props.defaultTab ?? new URLSearchParams(window.location.search).get("type") ?? this.props.tabs[0].key, renders: [], } primaryPanelRef = React.createRef() interface = { attachComponent: (id, component, options) => { const renders = this.state.renders renders.push({ id: id, component: component, options: options, ref: React.createRef() }) this.setState({ renders: renders, }) }, detachComponent: (id) => { const renders = this.state.renders const index = renders.findIndex((render) => render.id === id) renders.splice(index, 1) this.setState({ renders: renders, }) } } componentDidMount() { app.layout.page_panels = this.interface if (app.isMobile) { app.layout.top_bar.shouldUseTopBarSpacer(true) app.layout.toggleCenteredContent(false) } app.layout.toggleCenteredContent(true) } componentWillUnmount() { delete app.layout.page_panels if (!app.isMobile) { app.layout.header.render(null) } else { app.layout.top_bar.renderDefault() } } renderActiveTab() { if (!Array.isArray(this.props.tabs)) { console.error("PagePanelWithNavMenu: tabs must be an array") return <> } // slip the active tab by splitting on "." if (!this.state.activeTab) { console.error("PagePanelWithNavMenu: activeTab is not defined") return <> } let tab = null const activeTabDirectory = this.state.activeTab.split(".") activeTabDirectory.forEach((key, index) => { if (!tab) { tab = this.props.tabs.find((children) => children.key === key) } else { if (!tab.children) { console.error("PagePanelWithNavMenu: tab.children is not defined") return tab = null } tab = tab.children.find((children) => children.key === `${activeTabDirectory[index - 1]}.${key}`) } }) if (!tab) { if (this.props.onNotFound) { return this.props.onNotFound() } return } const componentProps = tab.props ?? this.props.tabProps return React.createElement(tab.component, { ...componentProps, ref: this.primaryPanelRef, }) } replaceQueryTypeToCurrentTab = () => { app.history.replace(`${window.location.pathname}?type=${this.state.activeTab}`) } tabChange = async (key) => { if (this.props.beforeTabChange) { await this.props.beforeTabChange(key) } await this.setState({ activeTab: key }) if (this.props.useSetQueryType) { this.replaceQueryTypeToCurrentTab() } if (this.props.onTabChange) { this.props.onTabChange(key) } } handleTabChange = async (key) => { if (this.state.activeTab === key) return if (this.props.transition) { if (document.startViewTransition) { return document.startViewTransition(() => { this.tabChange(key) }) } console.warn("PagePanelWithNavMenu: transition is enabled but document.startViewTransition is not compatible with your browser") // set to primary panel fade-opacity-leave class this.primaryPanelRef.current.classList.add("fade-opacity-leave") // remove fade-opacity-leave class after animation setTimeout(() => { this.primaryPanelRef.current.classList.remove("fade-opacity-leave") }, 300) await new Promise(resolve => setTimeout(resolve, 200)) } return this.tabChange(key) } getItems = (items) => { if (!Array.isArray(items)) { console.error(`[items] is not an (array), received (${typeof items})`) return [] } items = items.map((item) => { return { key: item.key, icon: createIconRender(item.icon), label: item.label, children: item.children && this.getItems(item.children), disabled: item.disabled, props: item.props ?? {}, } }) return items } render() { return <> { app.isMobile && app.layout.top_bar.render( this.handleTabChange(key)} />) } { !app.isMobile && app.layout.header.render( this.handleTabChange(key)} renderNames > { Array.isArray(this.state.renders) && [ this.state.renders.map((render, index) => { return React.createElement(render.component, { ...render.options.props, ref: render.ref }) }) ] } ) }
{ this.renderActiveTab() }
} } export default PagePanelWithNavMenu