Преглед изворни кода

Merge pull request #7761 from overleaf/ta-settings-loading-screen

Delay Settings Page Content Until Translations Are Ready

GitOrigin-RevId: 0537367f672bd2e88c95248d15c5638887ff3aee
Timothée Alby пре 4 година
родитељ
комит
e63c5565a6

+ 41 - 32
services/web/frontend/js/features/settings/components/root.tsx

@@ -11,49 +11,58 @@ import LeaveSection from './leave-section'
 import * as eventTracking from '../../../infrastructure/event-tracking'
 import { UserProvider } from '../../../shared/context/user-context'
 import { SSOProvider } from '../context/sso-context'
+import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
 
 function SettingsPageRoot() {
-  const { t } = useTranslation()
-  const ssoError = getMeta('ol-ssoError') as string
+  const { isReady } = useWaitForI18n()
 
   useEffect(() => {
     eventTracking.sendMB('settings-view')
   }, [])
 
+  return (
+    <div className="container">
+      <div className="row">
+        <div className="col-md-12 col-lg-10 col-lg-offset-1">
+          {isReady ? <SettingsPageContent /> : null}
+        </div>
+      </div>
+    </div>
+  )
+}
+
+function SettingsPageContent() {
+  const { t } = useTranslation()
+  const ssoError = getMeta('ol-ssoError') as string
+
   return (
     <UserProvider>
-      <div className="container">
-        <div className="row">
-          <div className="col-md-12 col-lg-10 col-lg-offset-1">
-            {ssoError ? (
-              <Alert bsStyle="danger">
-                {t('sso_link_error')}: {t(ssoError)}
-              </Alert>
-            ) : null}
-            <div className="card">
-              <div className="page-header">
-                <h1>{t('account_settings')}</h1>
-              </div>
-              <div>
-                <EmailsSection />
-                <div className="row">
-                  <div className="col-md-5">
-                    <AccountInfoSection />
-                  </div>
-                  <div className="col-md-5 col-md-offset-1">
-                    <PasswordSection />
-                  </div>
-                </div>
-                <hr />
-                <SSOProvider>
-                  <LinkingSection />
-                </SSOProvider>
-                <MiscSection />
-                <hr />
-                <LeaveSection />
-              </div>
+      {ssoError ? (
+        <Alert bsStyle="danger">
+          {t('sso_link_error')}: {t(ssoError)}
+        </Alert>
+      ) : null}
+      <div className="card">
+        <div className="page-header">
+          <h1>{t('account_settings')}</h1>
+        </div>
+        <div>
+          <EmailsSection />
+          <div className="row">
+            <div className="col-md-5">
+              <AccountInfoSection />
+            </div>
+            <div className="col-md-5 col-md-offset-1">
+              <PasswordSection />
             </div>
           </div>
+          <hr />
+          <SSOProvider>
+            <LinkingSection />
+          </SSOProvider>
+          <MiscSection />
+          <hr />
+          <LeaveSection />
         </div>
       </div>
     </UserProvider>

+ 20 - 0
services/web/frontend/js/shared/hooks/use-wait-for-i18n.ts

@@ -0,0 +1,20 @@
+import { useEffect, useState } from 'react'
+import i18n from '../../../js/i18n'
+import { useTranslation } from 'react-i18next'
+
+function useWaitForI18n() {
+  const { ready: isHookReady } = useTranslation()
+  const [isLocaleDataLoaded, setIsLocaleDataLoaded] = useState(false)
+
+  useEffect(() => {
+    i18n.then(() => {
+      setIsLocaleDataLoaded(true)
+    })
+  }, [])
+
+  return {
+    isReady: isHookReady && isLocaleDataLoaded,
+  }
+}
+
+export default useWaitForI18n

+ 5 - 1
services/web/test/frontend/features/settings/components/root.test.tsx

@@ -1,5 +1,5 @@
 import sinon from 'sinon'
-import { screen, render } from '@testing-library/react'
+import { screen, render, waitFor } from '@testing-library/react'
 import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking'
 import SettingsPageRoot from '../../../../../frontend/js/features/settings/components/root'
 
@@ -34,6 +34,10 @@ describe('<SettingsPageRoot />', function () {
   it('displays page', async function () {
     render(<SettingsPageRoot />)
 
+    await waitFor(() => {
+      screen.getByText('Account Settings')
+    })
+
     screen.getByRole('button', {
       name: 'Delete your account',
     })