|
|
@@ -11,15 +11,19 @@ import PagePathHierarchicalLink from '@commons/components/PagePathHierarchicalLi
|
|
|
|
|
|
import { withUnstatedContainers } from '../UnstatedUtils';
|
|
|
import AppContainer from '../../services/AppContainer';
|
|
|
+import NavigationContainer from '../../services/NavigationContainer';
|
|
|
+import PageContainer from '../../services/PageContainer';
|
|
|
|
|
|
import RevisionPathControls from '../Page/RevisionPathControls';
|
|
|
-import PageContainer from '../../services/PageContainer';
|
|
|
import TagLabels from '../Page/TagLabels';
|
|
|
import LikeButton from '../LikeButton';
|
|
|
import BookmarkButton from '../BookmarkButton';
|
|
|
|
|
|
import PageCreator from './PageCreator';
|
|
|
import RevisionAuthor from './RevisionAuthor';
|
|
|
+import DrawerToggler from './DrawerToggler';
|
|
|
+import UserPicture from '../User/UserPicture';
|
|
|
+
|
|
|
|
|
|
// eslint-disable-next-line react/prop-types
|
|
|
const PagePathNav = ({ pageId, pagePath, isPageForbidden }) => {
|
|
|
@@ -57,64 +61,157 @@ const PagePathNav = ({ pageId, pagePath, isPageForbidden }) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
+// eslint-disable-next-line react/prop-types
|
|
|
+const UserPagePathNav = ({ pageId, pagePath }) => {
|
|
|
+ const linkedPagePath = new LinkedPagePath(pagePath);
|
|
|
+ const latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePath} />;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="grw-page-path-nav">
|
|
|
+ <span className="d-flex align-items-center flex-wrap">
|
|
|
+ <h4 className="grw-user-page-path">{latterLink}</h4>
|
|
|
+ <RevisionPathControls
|
|
|
+ pageId={pageId}
|
|
|
+ pagePath={pagePath}
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+/* eslint-disable react/prop-types */
|
|
|
+const UserInfo = ({ pageUser }) => {
|
|
|
+ return (
|
|
|
+ <div className="grw-users-info d-flex align-items-center d-edit-none">
|
|
|
+ <UserPicture user={pageUser} />
|
|
|
+
|
|
|
+ <div className="users-meta">
|
|
|
+ <h1 className="user-page-name">
|
|
|
+ {pageUser.name}
|
|
|
+ </h1>
|
|
|
+ <div className="user-page-meta mt-1 mb-0">
|
|
|
+ <span className="user-page-username mr-2"><i className="icon-user mr-1"></i>{pageUser.username}</span>
|
|
|
+ <span className="user-page-email mr-2">
|
|
|
+ <i className="icon-envelope mr-1"></i>
|
|
|
+ {pageUser.isEmailPublished ? pageUser.email : '*****'}
|
|
|
+ </span>
|
|
|
+ {pageUser.introduction && <span className="user-page-introduction">{pageUser.introduction}</span>}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+/* eslint-enable react/prop-types */
|
|
|
+
|
|
|
+/* eslint-disable react/prop-types */
|
|
|
+const PageReactionButtons = ({ appContainer, pageContainer }) => {
|
|
|
+
|
|
|
+ const { pageId, isLiked, pageUser } = pageContainer.state;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ {pageUser == null && (
|
|
|
+ <span className="mr-2">
|
|
|
+ <LikeButton pageId={pageId} isLiked={isLiked} />
|
|
|
+ </span>
|
|
|
+ )}
|
|
|
+ <span className="mr-2">
|
|
|
+ <BookmarkButton pageId={pageId} crowi={appContainer} />
|
|
|
+ </span>
|
|
|
+ </>
|
|
|
+ );
|
|
|
+};
|
|
|
+/* eslint-enable react/prop-types */
|
|
|
+
|
|
|
const GrowiSubNavigation = (props) => {
|
|
|
- const isPageForbidden = document.querySelector('#grw-subnav').getAttribute('data-is-forbidden-page') === 'true';
|
|
|
- const { appContainer, pageContainer } = props;
|
|
|
+ const {
|
|
|
+ appContainer, navigationContainer, pageContainer, isCompactMode,
|
|
|
+ } = props;
|
|
|
+ const { isDrawerMode } = navigationContainer.state;
|
|
|
const {
|
|
|
pageId, path, createdAt, creator, updatedAt, revisionAuthor,
|
|
|
+ isForbidden: isPageForbidden, pageUser,
|
|
|
} = pageContainer.state;
|
|
|
|
|
|
const isPageNotFound = pageId == null;
|
|
|
+ const isUserPage = pageUser != null;
|
|
|
const isPageInTrash = isTrashPage(path);
|
|
|
|
|
|
// Display only the RevisionPath
|
|
|
if (isPageNotFound || isPageForbidden) {
|
|
|
return (
|
|
|
- <div className="px-3 py-3 grw-subnavbar">
|
|
|
+ <div className="grw-subnav d-flex align-items-center justify-content-between">
|
|
|
<PagePathNav pageId={pageId} pagePath={path} isPageForbidden={isPageForbidden} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- const additionalClassNames = ['grw-subnavbar'];
|
|
|
-
|
|
|
return (
|
|
|
- <div className={`d-flex align-items-center justify-content-between px-3 py-1 ${additionalClassNames.join(' ')}`}>
|
|
|
+ <div className={`grw-subnav d-flex align-items-center justify-content-between ${isCompactMode ? 'grw-subnav-compact' : ''}`}>
|
|
|
|
|
|
- {/* Page Path */}
|
|
|
- <div>
|
|
|
- <PagePathNav pageId={pageId} pagePath={path} isPageForbidden={isPageForbidden} />
|
|
|
- { !isPageNotFound && !isPageForbidden && (
|
|
|
- <TagLabels />
|
|
|
+ {/* Left side */}
|
|
|
+ <div className="d-flex">
|
|
|
+ { isDrawerMode && (
|
|
|
+ <div className="d-none d-md-flex align-items-center border-right mr-3 pr-3">
|
|
|
+ <DrawerToggler />
|
|
|
+ </div>
|
|
|
) }
|
|
|
+
|
|
|
+ <div>
|
|
|
+ { !isCompactMode && !isPageNotFound && !isPageForbidden && !isUserPage && (
|
|
|
+ <div className="mb-2">
|
|
|
+ <TagLabels />
|
|
|
+ </div>
|
|
|
+ ) }
|
|
|
+
|
|
|
+ { isUserPage
|
|
|
+ ? (
|
|
|
+ <>
|
|
|
+ <UserPagePathNav pageId={pageId} pagePath={path} />
|
|
|
+ <UserInfo pageUser={pageUser} />
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ : (
|
|
|
+ <PagePathNav pageId={pageId} pagePath={path} isPageForbidden={isPageForbidden} />
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
- <div className="d-flex align-items-center">
|
|
|
- { !isPageInTrash && (
|
|
|
- /* Header Button */
|
|
|
- <div className="mr-2">
|
|
|
- <LikeButton pageId={pageId} isLiked={pageContainer.state.isLiked} />
|
|
|
- </div>
|
|
|
- ) }
|
|
|
- { !isPageInTrash && (
|
|
|
- <div>
|
|
|
- <BookmarkButton pageId={pageId} crowi={appContainer} />
|
|
|
+ {/* Right side */}
|
|
|
+ <div className="d-flex">
|
|
|
+
|
|
|
+ <div className="d-flex flex-column align-items-end justify-content-center">
|
|
|
+ <div className="d-flex">
|
|
|
+ { !isPageInTrash && <PageReactionButtons appContainer={appContainer} pageContainer={pageContainer} /> }
|
|
|
+ <div className="mt-2">
|
|
|
+ {/* TODO: impl View / Edit / HackMD button group */}
|
|
|
+ {/* <div className="btn-group" role="group" aria-label="Basic example">
|
|
|
+ <button type="button" className="btn btn-outline-primary">Left</button>
|
|
|
+ <button type="button" className="btn btn-outline-primary">Middle</button>
|
|
|
+ <button type="button" className="btn btn-outline-primary">Right</button>
|
|
|
+ </div> */}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- ) }
|
|
|
+ </div>
|
|
|
|
|
|
{/* Page Authors */}
|
|
|
- <ul className="authors text-nowrap d-none d-lg-block d-edit-none">
|
|
|
- { creator != null && (
|
|
|
- <li>
|
|
|
- <PageCreator creator={creator} createdAt={createdAt} />
|
|
|
- </li>
|
|
|
- ) }
|
|
|
- { revisionAuthor != null && (
|
|
|
- <li className="mt-1">
|
|
|
- <RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} />
|
|
|
- </li>
|
|
|
- ) }
|
|
|
- </ul>
|
|
|
+ { (!isCompactMode && !isUserPage) && (
|
|
|
+ <ul className="authors text-nowrap border-left d-none d-lg-block d-edit-none">
|
|
|
+ { creator != null && (
|
|
|
+ <li className="pb-1">
|
|
|
+ <PageCreator creator={creator} createdAt={createdAt} />
|
|
|
+ </li>
|
|
|
+ ) }
|
|
|
+ { revisionAuthor != null && (
|
|
|
+ <li className="mt-1 pt-1 border-top">
|
|
|
+ <RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} />
|
|
|
+ </li>
|
|
|
+ ) }
|
|
|
+ </ul>
|
|
|
+ ) }
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
@@ -125,13 +222,16 @@ const GrowiSubNavigation = (props) => {
|
|
|
/**
|
|
|
* Wrapper component for using unstated
|
|
|
*/
|
|
|
-const GrowiSubNavigationWrapper = withUnstatedContainers(GrowiSubNavigation, [AppContainer, PageContainer]);
|
|
|
+const GrowiSubNavigationWrapper = withUnstatedContainers(GrowiSubNavigation, [AppContainer, NavigationContainer, PageContainer]);
|
|
|
|
|
|
|
|
|
GrowiSubNavigation.propTypes = {
|
|
|
t: PropTypes.func.isRequired, // i18next
|
|
|
appContainer: PropTypes.instanceOf(AppContainer).isRequired,
|
|
|
+ navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
|
|
|
pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
|
|
|
+
|
|
|
+ isCompactMode: PropTypes.bool,
|
|
|
};
|
|
|
|
|
|
export default withTranslation()(GrowiSubNavigationWrapper);
|