fix unmount

This commit is contained in:
SrGooglo 2025-02-05 02:39:10 +00:00
parent dacca7021c
commit ac93563a5e

View File

@ -9,261 +9,287 @@ import NavMenu from "./components/NavMenu"
import "./index.less"
export class Tab extends React.Component {
state = {
error: null
}
state = {
error: null,
}
// handle on error
componentDidCatch(err) {
this.setState({ error: err })
}
// handle on error
componentDidCatch(err) {
this.setState({ error: err })
}
render() {
if (this.state.error) {
return <antd.Result
status="error"
title="Error"
subTitle={this.state.error}
/>
}
render() {
if (this.state.error) {
return (
<antd.Result
status="error"
title="Error"
subTitle={this.state.error}
/>
)
}
return <>
{this.props.children}
</>
}
return <>{this.props.children}</>
}
}
export const Panel = (props) => {
return <div
{...props.props ?? {}}
className={classnames(
"panel",
props.align,
props.className
)}
>
{props.children}
</div>
return (
<div
{...(props.props ?? {})}
className={classnames("panel", props.align, props.className)}
>
{props.children}
</div>
)
}
export class PagePanelWithNavMenu extends React.Component {
state = {
activeTab: new URLSearchParams(window.location.search).get("type") ?? this.props.defaultTab ?? this.props.tabs[0].key,
renders: [],
}
state = {
activeTab:
new URLSearchParams(window.location.search).get("type") ??
this.props.defaultTab ??
this.props.tabs[0].key,
renders: [],
}
primaryPanelRef = React.createRef()
primaryPanelRef = React.createRef()
interface = {
attachComponent: (id, component, options) => {
const renders = this.state.renders
interface = {
attachComponent: (id, component, options) => {
const renders = this.state.renders
renders.push({
id: id,
component: component,
options: options,
ref: React.createRef()
})
renders.push({
id: id,
component: component,
options: options,
ref: React.createRef(),
})
this.setState({
renders: renders,
})
},
detachComponent: (id) => {
const renders = this.state.renders
this.setState({
renders: renders,
})
},
detachComponent: (id) => {
const renders = this.state.renders
const index = renders.findIndex((render) => render.id === id)
const index = renders.findIndex((render) => render.id === id)
renders.splice(index, 1)
renders.splice(index, 1)
this.setState({
renders: renders,
})
}
}
this.setState({
renders: renders,
})
},
}
componentDidMount() {
app.layout.page_panels = this.interface
componentDidMount() {
app.layout.page_panels = this.interface
if (app.isMobile) {
app.layout.top_bar.shouldUseTopBarSpacer(true)
app.layout.toggleCenteredContent(false)
}
if (app.isMobile) {
app.layout.top_bar.shouldUseTopBarSpacer(true)
app.layout.toggleCenteredContent(false)
}
app.layout.toggleCenteredContent(true)
}
app.layout.toggleCenteredContent(true)
}
componentWillUnmount() {
delete app.layout.page_panels
componentWillUnmount() {
delete app.layout.page_panels
if (!app.isMobile) {
app.layout.header.render(null)
} else {
app.layout.top_bar.renderDefault()
}
}
if (!app.isMobile) {
if (app.layout.header) {
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 <></>
}
renderActiveTab() {
if (!Array.isArray(this.props.tabs)) {
console.error("PagePanelWithNavMenu: tabs must be an array")
return <></>
}
if (this.props.tabs.length === 0) {
return <></>
}
if (this.props.tabs.length === 0) {
return <></>
}
// slip the active tab by splitting on "."
if (!this.state.activeTab) {
console.error("PagePanelWithNavMenu: activeTab is not defined")
return <></>
}
// slip the active tab by splitting on "."
if (!this.state.activeTab) {
console.error("PagePanelWithNavMenu: activeTab is not defined")
return <></>
}
let tab = null
let tab = null
const activeTabDirectory = this.state.activeTab.split(".")
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")
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
}
return (tab = null)
}
tab = tab.children.find((children) => children.key === `${activeTabDirectory[index - 1]}.${key}`)
}
})
tab = tab.children.find(
(children) =>
children.key ===
`${activeTabDirectory[index - 1]}.${key}`,
)
}
})
if (!tab) {
if (this.props.onNotFound) {
return this.props.onNotFound()
}
if (!tab) {
if (this.props.onNotFound) {
return this.props.onNotFound()
}
return <antd.Result
status="404"
title="404"
subTitle="Sorry, the tab you visited does not exist."
/>
}
return (
<antd.Result
status="404"
title="404"
subTitle="Sorry, the tab you visited does not exist."
/>
)
}
const componentProps = tab.props ?? this.props.tabProps
const componentProps = tab.props ?? this.props.tabProps
return React.createElement(tab.component, {
...componentProps,
})
}
return React.createElement(tab.component, {
...componentProps,
})
}
replaceQueryTypeToCurrentTab = (key) => {
history.pushState(undefined, "", `?type=${key ?? this.state.activeTab}`)
}
replaceQueryTypeToCurrentTab = (key) => {
history.pushState(undefined, "", `?type=${key ?? this.state.activeTab}`)
}
tabChange = async (key) => {
if (this.props.beforeTabChange) {
await this.props.beforeTabChange(key)
}
tabChange = async (key) => {
if (this.props.beforeTabChange) {
await this.props.beforeTabChange(key)
}
await this.setState({ activeTab: key })
await this.setState({ activeTab: key })
if (this.props.useSetQueryType) {
this.replaceQueryTypeToCurrentTab(key)
}
if (this.props.useSetQueryType) {
this.replaceQueryTypeToCurrentTab(key)
}
if (this.props.onTabChange) {
this.props.onTabChange(key)
}
}
if (this.props.onTabChange) {
this.props.onTabChange(key)
}
}
handleTabChange = async (key) => {
if (this.state.activeTab === key) return
handleTabChange = async (key) => {
if (this.state.activeTab === key) return
if (this.props.transition) {
if (document.startViewTransition) {
return document.startViewTransition(() => {
this.tabChange(key)
})
}
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")
console.warn(
"PagePanelWithNavMenu: transition is enabled but document.startViewTransition is not compatible with your browser",
)
if (this.primaryPanelRef.current && this.primaryPanelRef.current?.classList) {
// set to primary panel fade-opacity-leave class
this.primaryPanelRef.current.classList.add("fade-opacity-leave")
if (
this.primaryPanelRef.current &&
this.primaryPanelRef.current?.classList
) {
// 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)
}
// remove fade-opacity-leave class after animation
setTimeout(() => {
this.primaryPanelRef.current.classList.remove(
"fade-opacity-leave",
)
}, 300)
}
await new Promise(resolve => setTimeout(resolve, 200))
}
await new Promise((resolve) => setTimeout(resolve, 200))
}
return this.tabChange(key)
}
return this.tabChange(key)
}
getItems = (items) => {
if (!Array.isArray(items)) {
console.error(`[items] is not an (array), received (${typeof items})`)
return []
}
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 ?? {},
}
})
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
}
return items
}
render() {
return <>
{
app.isMobile && app.layout.top_bar.render(<NavMenu
activeKey={this.state.activeTab}
items={this.getItems(this.props.tabs)}
onClickItem={(key) => this.handleTabChange(key)}
/>)
}
render() {
return (
<>
{app.isMobile &&
app.layout.top_bar.render(
<NavMenu
activeKey={this.state.activeTab}
items={this.getItems(this.props.tabs)}
onClickItem={(key) => this.handleTabChange(key)}
/>,
)}
{
!app.isMobile && app.layout.header.render(<NavMenu
header={this.props.navMenuHeader}
activeKey={this.state.activeTab}
items={this.getItems([...this.props.tabs ?? [], ...this.props.extraItems ?? []])}
onClickItem={(key) => 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
})
})
]
}
</NavMenu>)
}
{!app.isMobile &&
app.layout.header.render(
<NavMenu
header={this.props.navMenuHeader}
activeKey={this.state.activeTab}
items={this.getItems([
...(this.props.tabs ?? []),
...(this.props.extraItems ?? []),
])}
onClickItem={(key) => 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,
},
)
}),
]}
</NavMenu>,
)}
<div className="pagePanels">
<div className="panel" ref={this.primaryPanelRef}>
{
this.renderActiveTab()
}
</div>
</div>
</>
}
<div className="pagePanels">
<div className="panel" ref={this.primaryPanelRef}>
{this.renderActiveTab()}
</div>
</div>
</>
)
}
}
export default PagePanelWithNavMenu
export default PagePanelWithNavMenu