trash.page.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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, useSWRxCurrentPage } 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. // clear the cache for the current page
  35. const { mutate } = useSWRxCurrentPage();
  36. mutate(undefined, { revalidate: false });
  37. useGrowiCloudUri(props.growiCloudUri);
  38. useIsSearchServiceConfigured(props.isSearchServiceConfigured);
  39. useIsSearchServiceReachable(props.isSearchServiceReachable);
  40. useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
  41. useIsSearchPage(false);
  42. useCurrentPageId(null);
  43. useCurrentPathname('/trash');
  44. // init sidebar config with UserUISettings and sidebarConfig
  45. useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
  46. useShowPageLimitationXL(props.showPageLimitationXL);
  47. const title = generateCustomTitleForPage(props, '/trash');
  48. return (
  49. <>
  50. <Head>
  51. <title>{title}</title>
  52. </Head>
  53. <div className="dynamic-layout-root">
  54. <nav className="sticky-top">
  55. TODO: implement navigation for /trash
  56. </nav>
  57. <div className="content-main container-lg mb-5 pb-5">
  58. <PagePathNavSticky pagePath="/trash" />
  59. <TrashPageList />
  60. </div>
  61. <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
  62. </div>
  63. </>
  64. );
  65. };
  66. type LayoutProps = Props & {
  67. children?: ReactNode,
  68. }
  69. const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
  70. // init sidebar config with UserUISettings and sidebarConfig
  71. useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
  72. return <BasicLayout>{children}</BasicLayout>;
  73. };
  74. TrashPage.getLayout = function getLayout(page) {
  75. return (
  76. <>
  77. <Layout {...page.props}>
  78. {page}
  79. </Layout>
  80. <EmptyTrashModal />
  81. </>
  82. );
  83. };
  84. function injectServerConfigurations(context: GetServerSidePropsContext, props: Props): void {
  85. const req: CrowiRequest = context.req as CrowiRequest;
  86. const { crowi } = req;
  87. const {
  88. searchService, configManager,
  89. } = crowi;
  90. props.isSearchServiceConfigured = searchService.isConfigured;
  91. props.isSearchServiceReachable = searchService.isReachable;
  92. props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault');
  93. props.showPageLimitationXL = crowi.configManager.getConfig('crowi', 'customize:showPageLimitationXL');
  94. props.sidebarConfig = {
  95. isSidebarCollapsedMode: configManager.getConfig('crowi', 'customize:isSidebarCollapsedMode'),
  96. };
  97. }
  98. /**
  99. * for Server Side Translations
  100. * @param context
  101. * @param props
  102. * @param namespacesRequired
  103. */
  104. async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
  105. const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
  106. props._nextI18Next = nextI18NextConfig._nextI18Next;
  107. }
  108. export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
  109. const req = context.req as CrowiRequest;
  110. const { user } = req;
  111. const result = await getServerSideCommonProps(context);
  112. if (!('props' in result)) {
  113. throw new Error('invalid getSSP result');
  114. }
  115. const props: Props = result.props as Props;
  116. if (user != null) {
  117. props.currentUser = user.toObject();
  118. }
  119. injectServerConfigurations(context, props);
  120. await injectNextI18NextConfigurations(context, props, ['translation']);
  121. return {
  122. props,
  123. };
  124. };
  125. export default TrashPage;