diff --git a/scm-ui/ui-webapp/src/admin/containers/Admin.tsx b/scm-ui/ui-webapp/src/admin/containers/Admin.tsx index 23b1a58c65..82b564a607 100644 --- a/scm-ui/ui-webapp/src/admin/containers/Admin.tsx +++ b/scm-ui/ui-webapp/src/admin/containers/Admin.tsx @@ -2,11 +2,18 @@ import React from "react"; import { connect } from "react-redux"; import { compose } from "redux"; import { WithTranslation, withTranslation } from "react-i18next"; -import { Redirect, Route, Switch } from "react-router-dom"; -import { History } from "history"; +import { Redirect, Route, RouteComponentProps, Switch } from "react-router-dom"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { Links } from "@scm-manager/ui-types"; -import { Navigation, NavLink, Page, Section, SubNavigation } from "@scm-manager/ui-components"; +import { + Navigation, + NavLink, + Page, + Section, + SubNavigation, + isMenuCollapsed, + MenuContext +} from "@scm-manager/ui-components"; import { getAvailablePluginsLink, getInstalledPluginsLink, getLinks } from "../../modules/indexResource"; import AdminDetails from "./AdminDetails"; import PluginsOverview from "../plugins/containers/PluginsOverview"; @@ -14,18 +21,44 @@ import GlobalConfig from "./GlobalConfig"; import RepositoryRoles from "../roles/containers/RepositoryRoles"; import SingleRepositoryRole from "../roles/containers/SingleRepositoryRole"; import CreateRepositoryRole from "../roles/containers/CreateRepositoryRole"; +import { storeMenuCollapsed } from "@scm-manager/ui-components/src"; -type Props = WithTranslation & { - links: Links; - availablePluginsLink: string; - installedPluginsLink: string; +type Props = RouteComponentProps & + WithTranslation & { + links: Links; + availablePluginsLink: string; + installedPluginsLink: string; + }; - // context objects - match: any; - history: History; +type State = { + menuCollapsed: boolean; + setMenuCollapsed: (collapsed: boolean) => void; }; -class Admin extends React.Component { +class Admin extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + menuCollapsed: isMenuCollapsed(), + setMenuCollapsed: (collapsed: boolean) => this.setState({ menuCollapsed: collapsed }) + }; + } + + componentDidUpdate() { + if (this.state.menuCollapsed && this.isCollapseForbidden()) { + this.setState({ menuCollapsed: false }); + } + } + + isCollapseForbidden = () => { + return this.props.location.pathname.includes("/settings/") || this.props.location.pathname.includes("/plugins/"); + }; + + onCollapseAdminMenu = (collapsed: boolean) => { + this.setState({ menuCollapsed: collapsed }, () => storeMenuCollapsed(collapsed)); + }; + stripEndingSlash = (url: string) => { if (url.endsWith("/")) { if (url.includes("role")) { @@ -48,6 +81,7 @@ class Admin extends React.Component { render() { const { links, availablePluginsLink, installedPluginsLink, t } = this.props; + const { menuCollapsed } = this.state; const url = this.matchedUrl(); const extensionProps = { @@ -56,82 +90,99 @@ class Admin extends React.Component { }; return ( - -
-
- - - - - - } - /> - } - /> - } - /> - } - /> - } - /> - } /> - } - /> - } /> - - -
-
- -
- - {(availablePluginsLink || installedPluginsLink) && ( - - {installedPluginsLink && ( - - )} - {availablePluginsLink && ( - - )} - - )} - + +
+
+ + + + + + } /> - - - - - -
-
+ } + /> + } + /> + } + /> + } + /> + } /> + } + /> + } /> + + +
+
+ +
this.onCollapseAdminMenu(!menuCollapsed)} + collapsed={menuCollapsed} + > + + {(availablePluginsLink || installedPluginsLink) && ( + + {installedPluginsLink && ( + + )} + {availablePluginsLink && ( + + )} + + )} + + + + + + +
+
+
- -
+ + ); } } diff --git a/scm-ui/ui-webapp/src/groups/containers/SingleGroup.tsx b/scm-ui/ui-webapp/src/groups/containers/SingleGroup.tsx index 90e15b5e43..c80a3225c9 100644 --- a/scm-ui/ui-webapp/src/groups/containers/SingleGroup.tsx +++ b/scm-ui/ui-webapp/src/groups/containers/SingleGroup.tsx @@ -1,38 +1,73 @@ import React from "react"; import { connect } from "react-redux"; -import { Route } from "react-router-dom"; +import { Route, RouteComponentProps } from "react-router-dom"; import { WithTranslation, withTranslation } from "react-i18next"; -import { History } from "history"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { Group } from "@scm-manager/ui-types"; -import { ErrorPage, Loading, Navigation, NavLink, Page, Section, SubNavigation } from "@scm-manager/ui-components"; +import { + ErrorPage, + Loading, + Navigation, + NavLink, + Page, + Section, + SubNavigation, + isMenuCollapsed, + MenuContext +} from "@scm-manager/ui-components"; import { getGroupsLink } from "../../modules/indexResource"; import { fetchGroupByName, getFetchGroupFailure, getGroupByName, isFetchGroupPending } from "../modules/groups"; import { Details } from "./../components/table"; import { EditGroupNavLink, SetPermissionsNavLink } from "./../components/navLinks"; import EditGroup from "./EditGroup"; import SetPermissions from "../../permissions/components/SetPermissions"; +import { storeMenuCollapsed } from "@scm-manager/ui-components/src"; -type Props = WithTranslation & { - name: string; - group: Group; - loading: boolean; - error: Error; - groupLink: string; +type Props = RouteComponentProps & + WithTranslation & { + name: string; + group: Group; + loading: boolean; + error: Error; + groupLink: string; - // dispatcher functions - fetchGroupByName: (p1: string, p2: string) => void; + // dispatcher functions + fetchGroupByName: (p1: string, p2: string) => void; + }; - // context objects - match: any; - history: History; +type State = { + menuCollapsed: boolean; + setMenuCollapsed: (collapsed: boolean) => void; }; -class SingleGroup extends React.Component { +class SingleGroup extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + menuCollapsed: isMenuCollapsed(), + setMenuCollapsed: (collapsed: boolean) => this.setState({ menuCollapsed: collapsed }) + }; + } + componentDidMount() { this.props.fetchGroupByName(this.props.groupLink, this.props.name); } + componentDidUpdate() { + if (this.state.menuCollapsed && this.isCollapseForbidden()) { + this.setState({ menuCollapsed: false }); + } + } + + isCollapseForbidden = () => { + return this.props.location.pathname.includes("/settings/"); + }; + + onCollapseGroupMenu = (collapsed: boolean) => { + this.setState({ menuCollapsed: collapsed }, () => storeMenuCollapsed(collapsed)); + }; + stripEndingSlash = (url: string) => { if (url.endsWith("/")) { return url.substring(0, url.length - 2); @@ -46,6 +81,7 @@ class SingleGroup extends React.Component { render() { const { t, loading, error, group } = this.props; + const { menuCollapsed } = this.state; if (error) { return ; @@ -63,33 +99,48 @@ class SingleGroup extends React.Component { }; return ( - -
-
-
} /> - } /> - } - /> - + + +
+
+
} /> + } /> + } + /> + +
+
+ +
this.onCollapseGroupMenu(!menuCollapsed)} + collapsed={menuCollapsed} + > + + + + + + + +
+
+
-
- -
- - - - - - - -
-
-
-
- + + ); } } diff --git a/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx b/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx index 06184842ff..c436219e8b 100644 --- a/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx +++ b/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx @@ -4,16 +4,19 @@ import { Redirect, Route, Switch, RouteComponentProps } from "react-router-dom"; import { WithTranslation, withTranslation } from "react-i18next"; import { binder, ExtensionPoint } from "@scm-manager/ui-extensions"; import { Repository } from "@scm-manager/ui-types"; -import { ErrorPage, Loading, Navigation, NavLink, Page, Section, SubNavigation } from "@scm-manager/ui-components"; import { - fetchRepoByName, - getFetchRepoFailure, - getRepository, - isFetchRepoPending, - isRepositoryMenuCollapsed, - switchRepositoryMenuCollapsed, - RepositoryContext -} from "../modules/repos"; + ErrorPage, + Loading, + Navigation, + NavLink, + Page, + Section, + SubNavigation, + MenuContext, + storeMenuCollapsed, + isMenuCollapsed +} from "@scm-manager/ui-components"; +import { fetchRepoByName, getFetchRepoFailure, getRepository, isFetchRepoPending } from "../modules/repos"; import RepositoryDetails from "../components/RepositoryDetails"; import EditRepo from "./EditRepo"; import BranchesOverview from "../branches/containers/BranchesOverview"; @@ -43,24 +46,28 @@ type Props = RouteComponentProps & }; type State = { - collapsedRepositoryMenu: boolean; + menuCollapsed: boolean; + setMenuCollapsed: (collapsed: boolean) => void; }; class RepositoryRoot extends React.Component { constructor(props: Props) { super(props); + this.state = { - collapsedRepositoryMenu: isRepositoryMenuCollapsed() + menuCollapsed: isMenuCollapsed(), + setMenuCollapsed: (collapsed: boolean) => this.setState({ menuCollapsed: collapsed }) }; } + componentDidMount() { const { fetchRepoByName, namespace, name, repoLink } = this.props; fetchRepoByName(repoLink, namespace, name); } componentDidUpdate() { - if (this.state.collapsedRepositoryMenu && this.isCollapseForbidden()) { - this.onCollapseRepositoryMenu(false); + if (this.state.menuCollapsed && this.isCollapseForbidden()) { + this.setState({ menuCollapsed: false }); } } @@ -111,13 +118,13 @@ class RepositoryRoot extends React.Component { return `${url}/changesets`; }; - onCollapseRepositoryMenu = (status: boolean) => { - this.setState({ collapsedRepositoryMenu: status }, () => switchRepositoryMenuCollapsed(status)); + onCollapseRepositoryMenu = (collapsed: boolean) => { + this.setState({ menuCollapsed: collapsed }, () => storeMenuCollapsed(collapsed)); }; render() { const { loading, error, indexLinks, repository, t } = this.props; - const { collapsedRepositoryMenu } = this.state; + const { menuCollapsed } = this.state; if (error) { return ( @@ -135,7 +142,7 @@ class RepositoryRoot extends React.Component { repository, url, indexLinks, - collapsedRepositoryMenu + collapsedRepositoryMenu: menuCollapsed }; const redirectUrlFactory = binder.getExtension("repository.redirect", this.props); @@ -147,15 +154,10 @@ class RepositoryRoot extends React.Component { } return ( - this.setState({ collapsedRepositoryMenu: !this.state.collapsedRepositoryMenu }) - }} - > - -
-
+ +
+
+ @@ -204,61 +206,59 @@ class RepositoryRoot extends React.Component { } /> -
-
- -
this.onCollapseRepositoryMenu(!collapsedRepositoryMenu) - } - collapsed={collapsedRepositoryMenu} - > - - - - - - - - - - -
-
-
+
-
- +
+ +
this.onCollapseRepositoryMenu(!menuCollapsed) + } + collapsed={menuCollapsed} + > + + + + + + + + + + +
+
+
+
+ ); } } diff --git a/scm-ui/ui-webapp/src/users/containers/SingleUser.tsx b/scm-ui/ui-webapp/src/users/containers/SingleUser.tsx index 8b0826ee6b..9d0dd2b9c5 100644 --- a/scm-ui/ui-webapp/src/users/containers/SingleUser.tsx +++ b/scm-ui/ui-webapp/src/users/containers/SingleUser.tsx @@ -1,10 +1,20 @@ import React from "react"; import { connect } from "react-redux"; -import { Route } from "react-router-dom"; +import { Route, RouteComponentProps } from "react-router-dom"; import { History } from "history"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { User } from "@scm-manager/ui-types"; -import { ErrorPage, Loading, Navigation, NavLink, Page, Section, SubNavigation } from "@scm-manager/ui-components"; +import { + ErrorPage, + Loading, + Navigation, + NavLink, + Page, + Section, + SubNavigation, + MenuContext, + isMenuCollapsed +} from "@scm-manager/ui-components"; import { Details } from "./../components/table"; import EditUser from "./EditUser"; import { fetchUserByName, getFetchUserFailure, getUserByName, isFetchUserPending } from "../modules/users"; @@ -13,27 +23,45 @@ import { WithTranslation, withTranslation } from "react-i18next"; import { getUsersLink } from "../../modules/indexResource"; import SetUserPassword from "../components/SetUserPassword"; import SetPermissions from "../../permissions/components/SetPermissions"; +import { storeMenuCollapsed } from "@scm-manager/ui-components/src"; -type Props = WithTranslation & { - name: string; - user: User; - loading: boolean; - error: Error; - usersLink: string; +type Props = RouteComponentProps & + WithTranslation & { + name: string; + user: User; + loading: boolean; + error: Error; + usersLink: string; - // dispatcher function - fetchUserByName: (p1: string, p2: string) => void; + // dispatcher function + fetchUserByName: (p1: string, p2: string) => void; + }; - // context objects - match: any; - history: History; +type State = { + menuCollapsed: boolean; + setMenuCollapsed: (collapsed: boolean) => void; }; -class SingleUser extends React.Component { +class SingleUser extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + menuCollapsed: isMenuCollapsed(), + setMenuCollapsed: (collapsed: boolean) => this.setState({ menuCollapsed: collapsed }) + }; + } + componentDidMount() { this.props.fetchUserByName(this.props.usersLink, this.props.name); } + componentDidUpdate() { + if (this.state.menuCollapsed && this.isCollapseForbidden()) { + this.setState({ menuCollapsed: false }); + } + } + stripEndingSlash = (url: string) => { if (url.endsWith("/")) { return url.substring(0, url.length - 2); @@ -41,12 +69,21 @@ class SingleUser extends React.Component { return url; }; + isCollapseForbidden = () => { + return this.props.location.pathname.includes("/settings/"); + }; + + onCollapseUserMenu = (collapsed: boolean) => { + this.setState({ menuCollapsed: collapsed }, () => storeMenuCollapsed(collapsed)); + }; + matchedUrl = () => { return this.stripEndingSlash(this.props.match.url); }; render() { const { t, loading, error, user } = this.props; + const { menuCollapsed } = this.state; if (error) { return ; @@ -64,33 +101,48 @@ class SingleUser extends React.Component { }; return ( - -
-
-
} /> - } /> - } /> - } - /> - + + +
+
+
} /> + } /> + } /> + } + /> + +
+
+ +
this.onCollapseUserMenu(!menuCollapsed)} + collapsed={menuCollapsed} + > + + + + + + + +
+
+
-
- -
- - - - - - - -
-
-
-
- + + ); } }