invited.page.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import React from 'react';
  2. import type {
  3. GetServerSideProps,
  4. GetServerSidePropsContext,
  5. NextPage,
  6. } from 'next';
  7. import dynamic from 'next/dynamic';
  8. import Head from 'next/head';
  9. import type { IUser } from '@growi/core';
  10. import { USER_STATUS } from '@growi/core';
  11. import { useTranslation } from 'next-i18next';
  12. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  13. import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
  14. import type { CrowiRequest } from '~/interfaces/crowi-request';
  15. import {
  16. useCsrfToken,
  17. useCurrentPathname,
  18. useCurrentUser,
  19. } from '~/stores-universal/context';
  20. import type { CommonProps } from './utils/commons';
  21. import {
  22. generateCustomTitle,
  23. getNextI18NextConfig,
  24. getServerSideCommonProps,
  25. } from './utils/commons';
  26. const InvitedForm = dynamic(
  27. () =>
  28. import('~/client/components/InvitedForm').then((mod) => mod.InvitedForm),
  29. { ssr: false },
  30. );
  31. type Props = CommonProps & {
  32. currentUser: IUser;
  33. invitedFormUsername: string;
  34. invitedFormName: string;
  35. };
  36. const InvitedPage: NextPage<Props> = (props: Props) => {
  37. const { t } = useTranslation();
  38. useCsrfToken(props.csrfToken);
  39. useCurrentPathname(props.currentPathname);
  40. useCurrentUser(props.currentUser);
  41. const title = generateCustomTitle(props, t('invited.title'));
  42. const classNames: string[] = ['invited-page'];
  43. return (
  44. <NoLoginLayout className={classNames.join(' ')}>
  45. <Head>
  46. <title>{title}</title>
  47. </Head>
  48. <InvitedForm
  49. invitedFormUsername={props.invitedFormUsername}
  50. invitedFormName={props.invitedFormName}
  51. />
  52. </NoLoginLayout>
  53. );
  54. };
  55. async function injectServerConfigurations(
  56. context: GetServerSidePropsContext,
  57. props: Props,
  58. ): Promise<void> {
  59. const req: CrowiRequest = context.req as CrowiRequest;
  60. const { body: invitedForm } = req;
  61. if (props.invitedFormUsername != null) {
  62. props.invitedFormUsername = invitedForm.username;
  63. }
  64. if (props.invitedFormName != null) {
  65. props.invitedFormName = invitedForm.name;
  66. }
  67. }
  68. /**
  69. * for Server Side Translations
  70. * @param context
  71. * @param props
  72. * @param namespacesRequired
  73. */
  74. async function injectNextI18NextConfigurations(
  75. context: GetServerSidePropsContext,
  76. props: Props,
  77. namespacesRequired?: string[] | undefined,
  78. ): Promise<void> {
  79. const nextI18NextConfig = await getNextI18NextConfig(
  80. serverSideTranslations,
  81. context,
  82. namespacesRequired,
  83. );
  84. props._nextI18Next = nextI18NextConfig._nextI18Next;
  85. }
  86. export const getServerSideProps: GetServerSideProps = async (
  87. context: GetServerSidePropsContext,
  88. ) => {
  89. const req = context.req as CrowiRequest;
  90. const { user } = req;
  91. const result = await getServerSideCommonProps(context);
  92. // check for presence
  93. // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
  94. if (!('props' in result)) {
  95. throw new Error('invalid getSSP result');
  96. }
  97. const props: Props = result.props as Props;
  98. if (user != null) {
  99. props.currentUser = user.toObject();
  100. // Only invited user can access to /invited page
  101. if (props.currentUser.status !== USER_STATUS.INVITED) {
  102. return {
  103. redirect: {
  104. permanent: false,
  105. destination: '/',
  106. },
  107. };
  108. }
  109. }
  110. await injectServerConfigurations(context, props);
  111. await injectNextI18NextConfigurations(context, props, ['translation']);
  112. return { props };
  113. };
  114. export default InvitedPage;