mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
fix unmount
This commit is contained in:
parent
dacca7021c
commit
ac93563a5e
@ -9,261 +9,287 @@ import NavMenu from "./components/NavMenu"
|
|||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
export class Tab extends React.Component {
|
export class Tab extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
error: null
|
error: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle on error
|
// handle on error
|
||||||
componentDidCatch(err) {
|
componentDidCatch(err) {
|
||||||
this.setState({ error: err })
|
this.setState({ error: err })
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
return <antd.Result
|
return (
|
||||||
status="error"
|
<antd.Result
|
||||||
title="Error"
|
status="error"
|
||||||
subTitle={this.state.error}
|
title="Error"
|
||||||
/>
|
subTitle={this.state.error}
|
||||||
}
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return <>
|
return <>{this.props.children}</>
|
||||||
{this.props.children}
|
}
|
||||||
</>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Panel = (props) => {
|
export const Panel = (props) => {
|
||||||
return <div
|
return (
|
||||||
{...props.props ?? {}}
|
<div
|
||||||
className={classnames(
|
{...(props.props ?? {})}
|
||||||
"panel",
|
className={classnames("panel", props.align, props.className)}
|
||||||
props.align,
|
>
|
||||||
props.className
|
{props.children}
|
||||||
)}
|
</div>
|
||||||
>
|
)
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PagePanelWithNavMenu extends React.Component {
|
export class PagePanelWithNavMenu extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
activeTab: new URLSearchParams(window.location.search).get("type") ?? this.props.defaultTab ?? this.props.tabs[0].key,
|
activeTab:
|
||||||
renders: [],
|
new URLSearchParams(window.location.search).get("type") ??
|
||||||
}
|
this.props.defaultTab ??
|
||||||
|
this.props.tabs[0].key,
|
||||||
|
renders: [],
|
||||||
|
}
|
||||||
|
|
||||||
primaryPanelRef = React.createRef()
|
primaryPanelRef = React.createRef()
|
||||||
|
|
||||||
interface = {
|
interface = {
|
||||||
attachComponent: (id, component, options) => {
|
attachComponent: (id, component, options) => {
|
||||||
const renders = this.state.renders
|
const renders = this.state.renders
|
||||||
|
|
||||||
renders.push({
|
renders.push({
|
||||||
id: id,
|
id: id,
|
||||||
component: component,
|
component: component,
|
||||||
options: options,
|
options: options,
|
||||||
ref: React.createRef()
|
ref: React.createRef(),
|
||||||
})
|
})
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
renders: renders,
|
renders: renders,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
detachComponent: (id) => {
|
detachComponent: (id) => {
|
||||||
const renders = this.state.renders
|
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({
|
this.setState({
|
||||||
renders: renders,
|
renders: renders,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
app.layout.page_panels = this.interface
|
app.layout.page_panels = this.interface
|
||||||
|
|
||||||
if (app.isMobile) {
|
if (app.isMobile) {
|
||||||
app.layout.top_bar.shouldUseTopBarSpacer(true)
|
app.layout.top_bar.shouldUseTopBarSpacer(true)
|
||||||
app.layout.toggleCenteredContent(false)
|
app.layout.toggleCenteredContent(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.layout.toggleCenteredContent(true)
|
app.layout.toggleCenteredContent(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
delete app.layout.page_panels
|
delete app.layout.page_panels
|
||||||
|
|
||||||
if (!app.isMobile) {
|
if (!app.isMobile) {
|
||||||
app.layout.header.render(null)
|
if (app.layout.header) {
|
||||||
} else {
|
app.layout.header.render(null)
|
||||||
app.layout.top_bar.renderDefault()
|
}
|
||||||
}
|
} else {
|
||||||
}
|
app.layout.top_bar.renderDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderActiveTab() {
|
renderActiveTab() {
|
||||||
if (!Array.isArray(this.props.tabs)) {
|
if (!Array.isArray(this.props.tabs)) {
|
||||||
console.error("PagePanelWithNavMenu: tabs must be an array")
|
console.error("PagePanelWithNavMenu: tabs must be an array")
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.tabs.length === 0) {
|
if (this.props.tabs.length === 0) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
// slip the active tab by splitting on "."
|
// slip the active tab by splitting on "."
|
||||||
if (!this.state.activeTab) {
|
if (!this.state.activeTab) {
|
||||||
console.error("PagePanelWithNavMenu: activeTab is not defined")
|
console.error("PagePanelWithNavMenu: activeTab is not defined")
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
let tab = null
|
let tab = null
|
||||||
|
|
||||||
const activeTabDirectory = this.state.activeTab.split(".")
|
const activeTabDirectory = this.state.activeTab.split(".")
|
||||||
|
|
||||||
activeTabDirectory.forEach((key, index) => {
|
activeTabDirectory.forEach((key, index) => {
|
||||||
if (!tab) {
|
if (!tab) {
|
||||||
tab = this.props.tabs.find((children) => children.key === key)
|
tab = this.props.tabs.find((children) => children.key === key)
|
||||||
} else {
|
} else {
|
||||||
if (!tab.children) {
|
if (!tab.children) {
|
||||||
console.error("PagePanelWithNavMenu: tab.children is not defined")
|
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 (!tab) {
|
||||||
if (this.props.onNotFound) {
|
if (this.props.onNotFound) {
|
||||||
return this.props.onNotFound()
|
return this.props.onNotFound()
|
||||||
}
|
}
|
||||||
|
|
||||||
return <antd.Result
|
return (
|
||||||
status="404"
|
<antd.Result
|
||||||
title="404"
|
status="404"
|
||||||
subTitle="Sorry, the tab you visited does not exist."
|
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, {
|
return React.createElement(tab.component, {
|
||||||
...componentProps,
|
...componentProps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceQueryTypeToCurrentTab = (key) => {
|
replaceQueryTypeToCurrentTab = (key) => {
|
||||||
history.pushState(undefined, "", `?type=${key ?? this.state.activeTab}`)
|
history.pushState(undefined, "", `?type=${key ?? this.state.activeTab}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
tabChange = async (key) => {
|
tabChange = async (key) => {
|
||||||
if (this.props.beforeTabChange) {
|
if (this.props.beforeTabChange) {
|
||||||
await this.props.beforeTabChange(key)
|
await this.props.beforeTabChange(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.setState({ activeTab: key })
|
await this.setState({ activeTab: key })
|
||||||
|
|
||||||
if (this.props.useSetQueryType) {
|
if (this.props.useSetQueryType) {
|
||||||
this.replaceQueryTypeToCurrentTab(key)
|
this.replaceQueryTypeToCurrentTab(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.onTabChange) {
|
if (this.props.onTabChange) {
|
||||||
this.props.onTabChange(key)
|
this.props.onTabChange(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTabChange = async (key) => {
|
handleTabChange = async (key) => {
|
||||||
if (this.state.activeTab === key) return
|
if (this.state.activeTab === key) return
|
||||||
|
|
||||||
if (this.props.transition) {
|
if (this.props.transition) {
|
||||||
if (document.startViewTransition) {
|
if (document.startViewTransition) {
|
||||||
return document.startViewTransition(() => {
|
return document.startViewTransition(() => {
|
||||||
this.tabChange(key)
|
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) {
|
if (
|
||||||
// set to primary panel fade-opacity-leave class
|
this.primaryPanelRef.current &&
|
||||||
this.primaryPanelRef.current.classList.add("fade-opacity-leave")
|
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
|
// remove fade-opacity-leave class after animation
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.primaryPanelRef.current.classList.remove("fade-opacity-leave")
|
this.primaryPanelRef.current.classList.remove(
|
||||||
}, 300)
|
"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) => {
|
getItems = (items) => {
|
||||||
if (!Array.isArray(items)) {
|
if (!Array.isArray(items)) {
|
||||||
console.error(`[items] is not an (array), received (${typeof items})`)
|
console.error(
|
||||||
return []
|
`[items] is not an (array), received (${typeof items})`,
|
||||||
}
|
)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
items = items.map((item) => {
|
items = items.map((item) => {
|
||||||
return {
|
return {
|
||||||
key: item.key,
|
key: item.key,
|
||||||
icon: createIconRender(item.icon),
|
icon: createIconRender(item.icon),
|
||||||
label: item.label,
|
label: item.label,
|
||||||
children: item.children && this.getItems(item.children),
|
children: item.children && this.getItems(item.children),
|
||||||
disabled: item.disabled,
|
disabled: item.disabled,
|
||||||
props: item.props ?? {},
|
props: item.props ?? {},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <>
|
return (
|
||||||
{
|
<>
|
||||||
app.isMobile && app.layout.top_bar.render(<NavMenu
|
{app.isMobile &&
|
||||||
activeKey={this.state.activeTab}
|
app.layout.top_bar.render(
|
||||||
items={this.getItems(this.props.tabs)}
|
<NavMenu
|
||||||
onClickItem={(key) => this.handleTabChange(key)}
|
activeKey={this.state.activeTab}
|
||||||
/>)
|
items={this.getItems(this.props.tabs)}
|
||||||
}
|
onClickItem={(key) => this.handleTabChange(key)}
|
||||||
|
/>,
|
||||||
|
)}
|
||||||
|
|
||||||
{
|
{!app.isMobile &&
|
||||||
!app.isMobile && app.layout.header.render(<NavMenu
|
app.layout.header.render(
|
||||||
header={this.props.navMenuHeader}
|
<NavMenu
|
||||||
activeKey={this.state.activeTab}
|
header={this.props.navMenuHeader}
|
||||||
items={this.getItems([...this.props.tabs ?? [], ...this.props.extraItems ?? []])}
|
activeKey={this.state.activeTab}
|
||||||
onClickItem={(key) => this.handleTabChange(key)}
|
items={this.getItems([
|
||||||
renderNames
|
...(this.props.tabs ?? []),
|
||||||
>
|
...(this.props.extraItems ?? []),
|
||||||
{
|
])}
|
||||||
Array.isArray(this.state.renders) && [
|
onClickItem={(key) => this.handleTabChange(key)}
|
||||||
this.state.renders.map((render, index) => {
|
renderNames
|
||||||
return React.createElement(render.component, {
|
>
|
||||||
...render.options.props,
|
{Array.isArray(this.state.renders) && [
|
||||||
ref: render.ref
|
this.state.renders.map((render, index) => {
|
||||||
})
|
return React.createElement(
|
||||||
})
|
render.component,
|
||||||
]
|
{
|
||||||
}
|
...render.options.props,
|
||||||
</NavMenu>)
|
ref: render.ref,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
</NavMenu>,
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="pagePanels">
|
<div className="pagePanels">
|
||||||
<div className="panel" ref={this.primaryPanelRef}>
|
<div className="panel" ref={this.primaryPanelRef}>
|
||||||
{
|
{this.renderActiveTab()}
|
||||||
this.renderActiveTab()
|
</div>
|
||||||
}
|
</div>
|
||||||
</div>
|
</>
|
||||||
</div>
|
)
|
||||||
</>
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PagePanelWithNavMenu
|
export default PagePanelWithNavMenu
|
Loading…
x
Reference in New Issue
Block a user