jam411 3 лет назад
Родитель
Сommit
6f0049922d

+ 83 - 24
packages/app/src/components/Login/InvitedForm.tsx

@@ -1,20 +1,24 @@
 import React, { useEffect, useState } from 'react';
 
-import { useTranslation } from 'next-i18next';
+import { useTranslation, i18n } from 'next-i18next';
+
+import { i18n as i18nConfig } from '^/config/next-i18next.config';
 
 import { apiv3Get } from '~/client/util/apiv3-client';
-import { useCsrfToken } from '~/stores/context';
+import { usePersonalSettings } from '~/stores/personal-settings';
 
-import { toastError } from '../client/util/apiNotification';
+import { useCsrfToken, useCurrentUser } from '../../stores/context';
+// import { toastError, toastSuccess } from '../client/util/apiNotification';
 
 
 type InvitedFormProps = {
-  csrfToken: string,
+  // csrfToken: string,
   // isEmailAuthenticationEnabled: boolean,
   username: string,
   // isRegistering: boolean,
   name: string,
-  email: string,
+  // email: string,
+  // user: any,
   // isMailerSetup: boolean,
 
   // isLocalOrLdapStrategiesEnabled: boolean,
@@ -26,40 +30,95 @@ type InvitedFormProps = {
 export const InvitedForm = (props: InvitedFormProps): JSX.Element => {
   const { t } = useTranslation();
   const { data: csrfToken } = useCsrfToken();
+  const { data: user } = useCurrentUser();
+  const {
+    data: personalSettingsInfo, mutate: mutatePersonalSettings, sync, updateBasicInfo, error,
+  } = usePersonalSettings();
 
   const {
-    username, name, email,
+    username, name,
   } = props;
 
-  const registerAction = '/login/activateInvited';
+  if (user == null) {
+    return <></>;
+  }
 
-  // const [usernameAvailable, setUsernameAvailable] = useState(true);
+  const submitHandler = async() => {
+    try {
+      await updateBasicInfo();
+      sync();
+      // toastSuccess(t('toaster.update_successed', { target: t('Basic Info') }));
+    }
+    catch (err) {
+      // toastError(err);
+    }
+  };
 
-  // useEffect(() => {
-  //   const delayDebounceFn = setTimeout(async() => {
-  //     try {
-  //       const { data } = await apiv3Get('/check-username', { username });
-  //       if (data.ok) {
-  //         setUsernameAvailable(data.valid);
-  //       }
-  //     }
-  //     catch (error) {
-  //       toastError(error, 'Error occurred when checking username');
-  //     }
-  //   }, 500);
-
-  //   return () => clearTimeout(delayDebounceFn);
-  // }, [username]);
+  const changePersonalSettingsHandler = (updateData) => {
+    if (personalSettingsInfo == null) {
+      return;
+    }
+    mutatePersonalSettings({ ...personalSettingsInfo, ...updateData });
+  };
 
   // TODO: check flow
   // TODO: check noLoing-dialog
+  // TODO: Check loginForm[app:globalLang]
   return (
     <div className="noLogin-dialog p-3 mx-auto" id="noLogin-dialog">
       <p className="alert alert-success">
         <strong>{ t('invited.discription_heading') }</strong><br></br>
         <small>{ t('invited.discription') }</small>
       </p>
-      <form role="form" action={registerAction} method="post" id="invited-form">
+      <form role="form" action="/login/activateInvited" method="post" id="invited-form">
+        {/* Language Menu */}
+        <div className="dropdown mb-3">
+          <div className="d-flex dropdown-with-icon">
+            <i className="icon-bubbles border-0 rounded-0"></i>
+            <button
+              type="button"
+              className="btn btn-secondary dropdown-toggle text-right w-100 border-0 shadow-none"
+              id="dropdownLanguage"
+              data-testid="dropdownLanguage"
+              data-toggle="dropdown"
+              aria-haspopup="true"
+              aria-expanded="true"
+            >
+              <span className="float-left">{t('meta.display_name')}</span>
+            </button>
+            <input type="hidden" name="loginForm[app:globalLang]" />
+            <div className="dropdown-menu" aria-labelledby="dropdownLanguage">
+              { i18nConfig.locales.map((locale) => {
+                const fixedT = i18n.getFixedT(locale);
+
+                return (
+                  <button
+                    key={locale}
+                    data-testid={`dropdownLanguageMenu-${locale}`}
+                    className="dropdown-item"
+                    type="button"
+                    onClick={() => changePersonalSettingsHandler({ lang: locale })}
+                  >
+                    {fixedT('meta.display_name')}
+                  </button>
+                );
+              }) }
+            </div>
+          </div>
+        </div>
+        <div className="row my-3">
+          <div className="offset-4 col-5">
+            <button
+              data-testid="grw-besic-info-settings-update-button"
+              type="button"
+              className="btn btn-primary"
+              onClick={submitHandler}
+              disabled={error != null}
+            >
+              {t('Update')}
+            </button>
+          </div>
+        </div>
         {/* Email Form */}
         <div className="input-group">
           <div className="input-group-prepend">

+ 10 - 2
packages/app/src/pages/login/[[...path]].page.tsx

@@ -1,5 +1,6 @@
 import React from 'react';
 
+import { IUserHasId } from '@growi/core';
 import { NextPage, GetServerSideProps, GetServerSidePropsContext } from 'next';
 import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 import dynamic from 'next/dynamic';
@@ -8,11 +9,12 @@ import { useRouter } from 'next/router';
 import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
 import { CrowiRequest } from '~/interfaces/crowi-request';
 
-import { useCsrfToken, useCurrentPathname } from '../../stores/context';
+import { useCsrfToken, useCurrentPathname, useCurrentUser } from '../../stores/context';
 import {
   CommonProps, getServerSideCommonProps, useCustomTitle, getNextI18NextConfig,
 } from '../utils/commons';
 
+
 const LoginForm = dynamic(() => import('~/components/LoginForm'), { ssr: false });
 const InvitedForm = dynamic(() => import('~/components/Login/InvitedForm').then(mod => mod.InvitedForm), { ssr: false });
 
@@ -31,6 +33,7 @@ const LoginPage: NextPage<Props> = (props: Props) => {
 
   useCsrfToken(props.csrfToken);
   useCurrentPathname(props.currentPathname);
+  useCurrentUser(props.currentUser);
 
   const loginPagesMap = {
     login: {
@@ -105,6 +108,8 @@ async function injectNextI18NextConfigurations(context: GetServerSidePropsContex
 }
 
 export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
+  const req = context.req as CrowiRequest<IUserHasId & any>;
+  const { user } = req;
   const result = await getServerSideCommonProps(context);
 
   // check for presence
@@ -112,9 +117,12 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
   if (!('props' in result)) {
     throw new Error('invalid getSSP result');
   }
-
   const props: Props = result.props as Props;
 
+  if (user != null) {
+    props.currentUser = user.toObject();
+  }
+
   injectServerConfigurations(context, props);
   injectEnabledStrategies(context, props);
   await injectNextI18NextConfigurations(context, props, ['translation']);