Просмотр исходного кода

Merge pull request #8119 from overleaf/msm-refactor-settings

[Settings] Type refactoring

GitOrigin-RevId: c2b5e76bda463508aa3a1d7ee22fd7839ec26075
Miguel Serrano 4 лет назад
Родитель
Сommit
082a333773

+ 9 - 9
services/web/frontend/js/features/settings/components/emails/add-email.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
 import { Col } from 'react-bootstrap'
 import Cell from './cell'
 import Layout from './add-email/layout'
-import Input, { InstitutionInfo } from './add-email/input'
+import Input, { DomainInfo } from './add-email/input'
 import AddAnotherEmailBtn from './add-email/add-another-email-btn'
 import InstitutionFields from './add-email/institution-fields'
 import SsoLinkingInfo from './add-email/sso-linking-info'
@@ -21,8 +21,8 @@ function AddEmail() {
     () => window.location.hash === '#add-email'
   )
   const [newEmail, setNewEmail] = useState('')
-  const [newEmailMatchedInstitution, setNewEmailMatchedInstitution] =
-    useState<InstitutionInfo | null>(null)
+  const [newEmailMatchedDomain, setNewEmailMatchedDomain] =
+    useState<DomainInfo | null>(null)
   const [countryCode, setCountryCode] = useState<CountryCode | null>(null)
   const [universities, setUniversities] = useState<
     Partial<Record<CountryCode, University[]>>
@@ -45,9 +45,9 @@ function AddEmail() {
     setIsFormVisible(true)
   }
 
-  const handleEmailChange = (value: string, institution?: InstitutionInfo) => {
+  const handleEmailChange = (value: string, domain?: DomainInfo) => {
     setNewEmail(value)
-    setNewEmailMatchedInstitution(institution || null)
+    setNewEmailMatchedDomain(domain || null)
   }
 
   const getSelectedKnownUniversityId = (): number | undefined => {
@@ -57,7 +57,7 @@ function AddEmail() {
       )?.id
     }
 
-    return newEmailMatchedInstitution?.university.id
+    return newEmailMatchedDomain?.university.id
   }
 
   const handleAddNewEmail = () => {
@@ -120,12 +120,12 @@ function AddEmail() {
             />
           </Cell>
         </Col>
-        {ssoAvailableForDomain(newEmailMatchedInstitution) ? (
+        {ssoAvailableForDomain(newEmailMatchedDomain) ? (
           <Col md={8}>
             <Cell>
               <SsoLinkingInfo
                 email={newEmail}
-                institutionInfo={newEmailMatchedInstitution}
+                domainInfo={newEmailMatchedDomain}
               />
             </Cell>
           </Col>
@@ -144,7 +144,7 @@ function AddEmail() {
                   setRole={setRole}
                   department={department}
                   setDepartment={setDepartment}
-                  newEmailMatchedInstitution={newEmailMatchedInstitution}
+                  newEmailMatchedDomain={newEmailMatchedDomain}
                 />
               </Cell>
             </Col>

+ 17 - 19
services/web/frontend/js/features/settings/components/emails/add-email/input.tsx

@@ -21,7 +21,7 @@ function matchLocalAndDomain(emailHint: string) {
   }
 }
 
-export type InstitutionInfo = {
+export type DomainInfo = {
   hostname: string
   confirmed?: boolean
   university: {
@@ -32,14 +32,14 @@ export type InstitutionInfo = {
   }
 }
 
-let domainCache = new Map<string, InstitutionInfo>()
+let domainCache = new Map<string, DomainInfo>()
 
 export function clearDomainCache() {
-  domainCache = new Map<string, InstitutionInfo>()
+  domainCache = new Map<string, DomainInfo>()
 }
 
 type InputProps = {
-  onChange: (value: string, institution?: InstitutionInfo) => void
+  onChange: (value: string, domain?: DomainInfo) => void
   handleAddNewEmail: () => void
 }
 
@@ -49,8 +49,7 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
   const inputRef = useRef<HTMLInputElement | null>(null)
   const [suggestion, setSuggestion] = useState<string | null>(null)
   const [inputValue, setInputValue] = useState<string | null>(null)
-  const [matchedInstitution, setMatchedInstitution] =
-    useState<InstitutionInfo | null>(null)
+  const [matchedDomain, setMatchedDomain] = useState<DomainInfo | null>(null)
 
   useEffect(() => {
     inputRef.current?.focus()
@@ -60,22 +59,19 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
     if (inputValue == null) {
       return
     }
-    if (
-      matchedInstitution &&
-      inputValue.endsWith(matchedInstitution.hostname)
-    ) {
-      onChange(inputValue, matchedInstitution)
+    if (matchedDomain && inputValue.endsWith(matchedDomain.hostname)) {
+      onChange(inputValue, matchedDomain)
     } else {
       onChange(inputValue)
     }
-  }, [onChange, inputValue, suggestion, matchedInstitution])
+  }, [onChange, inputValue, suggestion, matchedDomain])
 
   const handleEmailChange = useCallback(
     (event: ChangeEvent<HTMLInputElement>) => {
       const hint = event.target.value
       setInputValue(hint)
       const match = matchLocalAndDomain(hint)
-      if (!matchedInstitution?.hostname.startsWith(match.domain)) {
+      if (!matchedDomain?.hostname.startsWith(match.domain)) {
         setSuggestion(null)
       }
       if (!match.domain) {
@@ -84,11 +80,13 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
       if (domainCache.has(match.domain)) {
         const cachedDomain = domainCache.get(match.domain)
         setSuggestion(`${match.local}@${cachedDomain.hostname}`)
-        setMatchedInstitution(cachedDomain)
+        setMatchedDomain(cachedDomain)
         return
       }
       const query = `?hostname=${match.domain}&limit=1`
-      getJSON(`/institutions/domains${query}`, { signal })
+      getJSON<Nullable<DomainInfo[]>>(`/institutions/domains${query}`, {
+        signal,
+      })
         .then(data => {
           if (!(data && data[0])) {
             return
@@ -100,19 +98,19 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
           if (hostname) {
             domainCache.set(match.domain, data[0])
             setSuggestion(`${match.local}@${hostname}`)
-            setMatchedInstitution(data[0])
+            setMatchedDomain(data[0])
           } else {
             setSuggestion(null)
-            setMatchedInstitution(null)
+            setMatchedDomain(null)
           }
         })
         .catch(error => {
           setSuggestion(null)
-          setMatchedInstitution(null)
+          setMatchedDomain(null)
           console.error(error)
         })
     },
-    [signal, matchedInstitution]
+    [signal, matchedDomain]
   )
 
   const handleKeyDownEvent = useCallback(

+ 8 - 8
services/web/frontend/js/features/settings/components/emails/add-email/institution-fields.tsx

@@ -7,7 +7,7 @@ import defaultRoles from '../../../data/roles'
 import defaultDepartments from '../../../data/departments'
 import { CountryCode } from '../../../data/countries-list'
 import { University } from '../../../../../../../types/university'
-import { InstitutionInfo } from './input'
+import { DomainInfo } from './input'
 import { getJSON } from '../../../../../infrastructure/fetch-json'
 import useAsync from '../../../../../shared/hooks/use-async'
 import UniversityName from './university-name'
@@ -25,7 +25,7 @@ type InstitutionFieldsProps = {
   setRole: React.Dispatch<React.SetStateAction<string>>
   department: string
   setDepartment: React.Dispatch<React.SetStateAction<string>>
-  newEmailMatchedInstitution: InstitutionInfo | null
+  newEmailMatchedDomain: DomainInfo | null
 }
 
 function InstitutionFields({
@@ -39,7 +39,7 @@ function InstitutionFields({
   setRole,
   department,
   setDepartment,
-  newEmailMatchedInstitution,
+  newEmailMatchedDomain,
 }: InstitutionFieldsProps) {
   const { t } = useTranslation()
   const countryRef = useRef<HTMLInputElement | null>(null)
@@ -66,12 +66,12 @@ function InstitutionFields({
   // If the institution selected by autocompletion has changed
   // hide the fields visibility and reset values
   useEffect(() => {
-    if (!newEmailMatchedInstitution) {
+    if (!newEmailMatchedDomain) {
       setIsInstitutionFieldsVisible(false)
       setRole('')
       setDepartment('')
     }
-  }, [newEmailMatchedInstitution, setRole, setDepartment])
+  }, [newEmailMatchedDomain, setRole, setDepartment])
 
   useEffect(() => {
     const selectedKnownUniversity = countryCode
@@ -121,9 +121,9 @@ function InstitutionFields({
   }
 
   const isLetUsKnowVisible =
-    !newEmailMatchedInstitution && !isInstitutionFieldsVisible
+    !newEmailMatchedDomain && !isInstitutionFieldsVisible
   const isAutocompletedInstitutionVisible =
-    newEmailMatchedInstitution && !isInstitutionFieldsVisible
+    newEmailMatchedDomain && !isInstitutionFieldsVisible
   const isRoleAndDepartmentVisible =
     isAutocompletedInstitutionVisible || isUniversityDirty
 
@@ -139,7 +139,7 @@ function InstitutionFields({
       {isAutocompletedInstitutionVisible ? (
         // Display the institution name after autocompletion
         <UniversityName
-          name={newEmailMatchedInstitution.university.name}
+          name={newEmailMatchedDomain.university.name}
           onClick={handleSelectUniversityManually}
         />
       ) : (

+ 7 - 9
services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx

@@ -1,34 +1,32 @@
 import { Trans, useTranslation } from 'react-i18next'
-import { InstitutionInfo } from './input'
+import { DomainInfo } from './input'
 import { ExposedSettings } from '../../../../../../../types/exposed-settings'
 import getMeta from '../../../../../utils/meta'
 
 type SSOLinkingInfoProps = {
-  institutionInfo: InstitutionInfo
+  domainInfo: DomainInfo
   email: string
 }
 
-function SsoLinkingInfo({ institutionInfo, email }: SSOLinkingInfoProps) {
+function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) {
   const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
   const { t } = useTranslation()
 
   return (
     <>
-      <p className="affiliations-table-label">
-        {institutionInfo.university.name}
-      </p>
+      <p className="affiliations-table-label">{domainInfo.university.name}</p>
       <p>
         <Trans
           i18nKey="to_add_email_accounts_need_to_be_linked_2"
           components={[<strong />]} // eslint-disable-line react/jsx-key
-          values={{ institutionName: institutionInfo.university.name }}
+          values={{ institutionName: domainInfo.university.name }}
         />
       </p>
       <p>
         <Trans
           i18nKey="doing_this_will_verify_affiliation_and_allow_log_in_2"
           components={[<strong />]} // eslint-disable-line react/jsx-key
-          values={{ institutionName: institutionInfo.university.name }}
+          values={{ institutionName: domainInfo.university.name }}
         />{' '}
         <a
           href="/learn/how-to/Institutional_Login"
@@ -40,7 +38,7 @@ function SsoLinkingInfo({ institutionInfo, email }: SSOLinkingInfoProps) {
       </p>
       <a
         className="btn-sm btn btn-primary btn-link-accounts"
-        href={`${samlInitPath}?university_id=${institutionInfo.university.id}&auto=/user/settings&email=${email}`}
+        href={`${samlInitPath}?university_id=${domainInfo.university.id}&auto=/user/settings&email=${email}`}
       >
         {t('link_accounts_and_add_email')}
       </a>

+ 2 - 2
services/web/frontend/js/features/settings/utils/sso.ts

@@ -1,9 +1,9 @@
 import getMeta from '../../../utils/meta'
-import { InstitutionInfo } from '../components/emails/add-email/input'
+import { DomainInfo } from '../components/emails/add-email/input'
 import { ExposedSettings } from '../../../../../types/exposed-settings'
 import { Institution } from '../../../../../types/institution'
 
-export const ssoAvailableForDomain = (domain: InstitutionInfo | null) => {
+export const ssoAvailableForDomain = (domain: DomainInfo | null) => {
   const { hasSamlBeta, hasSamlFeature } = getMeta(
     'ol-ExposedSettings'
   ) as ExposedSettings