From a4f79bf8c2a9ce4847f7d9d0b3945db5e91d0bab Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 31 Jul 2018 15:53:52 +0300 Subject: [PATCH] chore: refactor, separate active and expanded state for menu items --- src/components/SideMenu/MenuItem.tsx | 23 +++++++++++----------- src/components/SideMenu/MenuItems.tsx | 6 +++--- src/components/SideMenu/styled.elements.ts | 4 ++-- src/services/MenuStore.ts | 16 ++++++++++----- src/services/models/Group.model.ts | 20 ++++++++++++++++--- src/services/models/Operation.ts | 11 +++++++++++ 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/components/SideMenu/MenuItem.tsx b/src/components/SideMenu/MenuItem.tsx index fefc3a02..73e9a209 100644 --- a/src/components/SideMenu/MenuItem.tsx +++ b/src/components/SideMenu/MenuItem.tsx @@ -22,20 +22,15 @@ export class MenuItem extends React.Component { }; componentDidMount() { - const item = this.props.item; - if (item.type !== 'group' && item.active) { - this.scrollIntoView(); - } + this.scrollIntoViewIfActive(); } componentDidUpdate() { - if (this.props.item.active) { - this.scrollIntoView(); - } + this.scrollIntoViewIfActive(); } - scrollIntoView() { - if (this.ref) { + scrollIntoViewIfActive() { + if (this.props.item.active && this.ref) { this.ref.scrollIntoViewIfNeeded(); } } @@ -56,14 +51,14 @@ export class MenuItem extends React.Component { {item.type === 'operation' ? ( ) : ( - + {item.name} {this.props.children} {(item.depth > 0 && item.items.length > 0 && ( - + )) || null} @@ -71,7 +66,11 @@ export class MenuItem extends React.Component { {!withoutChildren && item.items && item.items.length > 0 && ( - + )} ); diff --git a/src/components/SideMenu/MenuItems.tsx b/src/components/SideMenu/MenuItems.tsx index f36a2c89..f8791343 100644 --- a/src/components/SideMenu/MenuItems.tsx +++ b/src/components/SideMenu/MenuItems.tsx @@ -8,7 +8,7 @@ import { MenuItemUl } from './styled.elements'; export interface MenuItemsProps { items: IMenuItem[]; - active?: boolean; + expanded?: boolean; onActivate?: (item: IMenuItem) => void; style?: React.CSSProperties; root?: boolean; @@ -20,12 +20,12 @@ export interface MenuItemsProps { export class MenuItems extends React.Component { render() { const { items, root, className } = this.props; - const active = this.props.active == null ? true : this.props.active; + const expanded = this.props.expanded == null ? true : this.props.expanded; return ( {items.map((item, idx) => ( diff --git a/src/components/SideMenu/styled.elements.ts b/src/components/SideMenu/styled.elements.ts index d44dd0a2..6e0c8794 100644 --- a/src/components/SideMenu/styled.elements.ts +++ b/src/components/SideMenu/styled.elements.ts @@ -75,7 +75,7 @@ function menuItemActiveBg(depth): string { } } -export const MenuItemUl = withProps<{ active: boolean }>(styled.ul)` +export const MenuItemUl = withProps<{ expanded: boolean }>(styled.ul)` margin: 0; padding: 0; @@ -83,7 +83,7 @@ export const MenuItemUl = withProps<{ active: boolean }>(styled.ul)` font-size: 0.929em; } - ${props => (props.active ? '' : 'display: none;')}; + ${props => (props.expanded ? '' : 'display: none;')}; `; export const MenuItemLi = withProps<{ depth: number }>(styled.li)` diff --git a/src/services/MenuStore.ts b/src/services/MenuStore.ts index 05dc5bd3..bee6c63e 100644 --- a/src/services/MenuStore.ts +++ b/src/services/MenuStore.ts @@ -19,6 +19,7 @@ export interface IMenuItem { description?: string; depth: number; active: boolean; + expanded: boolean; items: IMenuItem[]; parent?: IMenuItem; deprecated?: boolean; @@ -26,6 +27,9 @@ export interface IMenuItem { deactivate(): void; activate(): void; + + collapse(): void; + expand(): void; } export const SECTION_ATTR = 'data-section-id'; @@ -198,10 +202,8 @@ export class MenuStore { HistoryService.update(item.id, rewriteHistory); } - while (item !== undefined) { - item.activate(); - item = item.parent; - } + item.activate(); + item.expand(); } /** @@ -209,8 +211,12 @@ export class MenuStore { * @param item item to deactivate */ deactivate(item: IMenuItem | undefined) { + if (item === undefined) { + return; + } + item.deactivate(); while (item !== undefined) { - item.deactivate(); + item.collapse(); item = item.parent; } } diff --git a/src/services/models/Group.model.ts b/src/services/models/Group.model.ts index 328ae41f..52d9108b 100644 --- a/src/services/models/Group.model.ts +++ b/src/services/models/Group.model.ts @@ -22,6 +22,7 @@ export class GroupModel implements IMenuItem { externalDocs?: OpenAPIExternalDocumentation; @observable active: boolean = false; + @observable expanded: boolean = false; depth: number; //#endregion @@ -41,7 +42,7 @@ export class GroupModel implements IMenuItem { // groups are active (expanded) by default if (this.type === 'group') { - this.active = true; + this.expanded = true; } } @@ -51,11 +52,24 @@ export class GroupModel implements IMenuItem { } @action - deactivate() { - // disallow deactivating groups + expand() { + if (this.parent) { + this.parent.expand(); + } + this.expanded = true; + } + + @action + collapse() { + // disallow collapsing groups if (this.type === 'group') { return; } + this.expanded = false; + } + + @action + deactivate() { this.active = false; } } diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts index b589f108..797895e2 100644 --- a/src/services/models/Operation.ts +++ b/src/services/models/Operation.ts @@ -42,6 +42,7 @@ export class OperationModel implements IMenuItem { @observable ready?: boolean = true; @observable active: boolean = false; + @observable expanded: boolean = false; //#endregion pointer: string; @@ -105,6 +106,16 @@ export class OperationModel implements IMenuItem { this.active = false; } + expand() { + if (this.parent) { + this.parent.expand(); + } + } + + collapse() { + /* do nothing */ + } + @memoize get requestBody() { return (