trash.page.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import React, { ReactNode } from 'react';
  2. import type { IUser, IUserHasId } from '@growi/core';
  3. import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
  4. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  5. import dynamic from 'next/dynamic';
  6. import Head from 'next/head';
  7. import { PagePathNavSticky } from '~/components/Common/PagePathNav';
  8. import type { CrowiRequest } from '~/interfaces/crowi-request';
  9. import type { RendererConfig } from '~/interfaces/services/renderer';
  10. import { useCurrentPageId } from '~/stores/page';
  11. import { BasicLayout } from '../components/Layout/BasicLayout';
  12. import {
  13. useCurrentUser, useCurrentPathname, useGrowiCloudUri,
  14. useIsSearchServiceConfigured, useIsSearchServiceReachable,
  15. useIsSearchScopeChildrenAsDefault, useIsSearchPage, useShowPageLimitationXL,
  16. } from '../stores/context';
  17. import type { NextPageWithLayout } from './_app.page';
  18. import type { CommonProps } from './utils/commons';
  19. import {
  20. getServerSideCommonProps, getNextI18NextConfig, generateCustomTitleForPage, useInitSidebarConfig,
  21. } from './utils/commons';
  22. const TrashPageList = dynamic(() => import('~/components/TrashPageList').then(mod => mod.TrashPageList), { ssr: false });
  23. const EmptyTrashModal = dynamic(() => import('~/components/EmptyTrashModal'), { ssr: false });
  24. type Props = CommonProps & {
  25. currentUser: IUser,
  26. isSearchServiceConfigured: boolean,
  27. isSearchServiceReachable: boolean,
  28. isSearchScopeChildrenAsDefault: boolean,
  29. showPageLimitationXL: number,
  30. rendererConfig: RendererConfig,
  31. };
  32. const TrashPage: NextPageWithLayout<CommonProps> = (props: Props) => {
  33. useCurrentUser(props.currentUser ?? null);
  34. useGrowiCloudUri(props.growiCloudUri);
  35. useIsSearchServiceConfigured(props.isSearchServiceConfigured);
  36. useIsSearchServiceReachable(props.isSearchServiceReachable);
  37. useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
  38. useIsSearchPage(false);
  39. useCurrentPageId(null);
  40. useCurrentPathname('/trash');
  41. // init sidebar config with UserUISettings and sidebarConfig
  42. useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
  43. useShowPageLimitationXL(props.showPageLimitationXL);
  44. const title = generateCustomTitleForPage(props, '/trash');
  45. return (
  46. <>
  47. <Head>
  48. <title>{title}</title>
  49. </Head>
  50. <div className="dynamic-layout-root">
  51. <nav className="sticky-top">
  52. TODO: implement navigation for /trash
  53. </nav>
  54. <div className="content-main container-lg grw-container-convertible mb-5 pb-5">
  55. <PagePathNavSticky pagePath="/trash" />
  56. <TrashPageList />
  57. </div>
  58. <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
  59. </div>
  60. </>
  61. );
  62. };
  63. type LayoutProps = Props & {
  64. children?: ReactNode,
  65. }
  66. const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
  67. // init sidebar config with UserUISettings and sidebarConfig
  68. useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
  69. return <BasicLayout>{children}</BasicLayout>;
  70. };
  71. TrashPage.getLayout = function getLayout(page) {
  72. return (
  73. <>
  74. <Layout {...page.props}>
  75. {page}
  76. </Layout>
  77. <EmptyTrashModal />
  78. </>
  79. );
  80. };
  81. function injectServerConfigurations(context: GetServerSidePropsContext, props: Props): void {
  82. const req: CrowiRequest = context.req as CrowiRequest;
  83. const { crowi } = req;
  84. const {
  85. searchService, configManager,
  86. } = crowi;
  87. props.isSearchServiceConfigured = searchService.isConfigured;
  88. props.isSearchServiceReachable = searchService.isReachable;
  89. props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault');
  90. props.showPageLimitationXL = crowi.configManager.getConfig('crowi', 'customize:showPageLimitationXL');
  91. props.sidebarConfig = {
  92. isSidebarCollapsedMode: configManager.getConfig('crowi', 'customize:isSidebarCollapsedMode'),
  93. };
  94. }
  95. /**
  96. * for Server Side Translations
  97. * @param context
  98. * @param props
  99. * @param namespacesRequired
  100. */
  101. async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
  102. const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
  103. props._nextI18Next = nextI18NextConfig._nextI18Next;
  104. }
  105. export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
  106. const req = context.req as CrowiRequest<IUserHasId & any>;
  107. const { user } = req;
  108. const result = await getServerSideCommonProps(context);
  109. if (!('props' in result)) {
  110. throw new Error('invalid getSSP result');
  111. }
  112. const props: Props = result.props as Props;
  113. if (user != null) {
  114. props.currentUser = user.toObject();
  115. }
  116. injectServerConfigurations(context, props);
  117. await injectNextI18NextConfigurations(context, props, ['translation']);
  118. return {
  119. props,
  120. };
  121. };
  122. export default TrashPage;