1
0
Эх сурвалжийг харах

enhance(ui): export authentication and enhance UI components

charlie 1 долоо хоног өмнө
parent
commit
3447b8602e

+ 9 - 5
packages/ui/src/amplify/core.ts

@@ -2,10 +2,6 @@ import { Amplify } from 'aws-amplify'
 import { createContext, useContext } from 'react'
 import { translate, setNSDicts, setLocale } from '../i18n'
 
-// Amplify.configure({
-//   Auth: {}
-// })
-
 export const AuthFormRootContext = createContext<any>(null)
 export const useAuthFormState = () => {
   return useContext(AuthFormRootContext)
@@ -15,7 +11,15 @@ export function t(key: string, ...args: any) {
   return translate('amplify', key, ...args)
 }
 
-export function init() {
+export function init({ lang, authCognito }: any) {
   // Load default language
   setNSDicts('amplify', require('./lang').default)
+  if (lang) setLocale(lang)
+  Amplify.configure({
+    Auth: {
+      Cognito: {
+        ...authCognito, loginWith: { email: true }
+      }
+    }
+  })
 }

+ 8 - 0
packages/ui/src/amplify/index.ts

@@ -0,0 +1,8 @@
+import * as Auth from 'aws-amplify/auth'
+import { init } from './core'
+import { LSAuthenticator } from './ui'
+
+export {
+  init, Auth,
+  LSAuthenticator,
+}

+ 63 - 7
packages/ui/src/amplify/ui.tsx

@@ -5,9 +5,10 @@ import { cn } from '@/lib/utils'
 import { FormHTMLAttributes, useEffect, useState } from 'react'
 import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
 import { AlertCircleIcon, Loader2Icon, LucideEye, LucideEyeClosed, LucideX, LucideXCircle } from 'lucide-react'
-import { t, useAuthFormState } from './core'
+import { AuthFormRootContext, t, useAuthFormState } from './core'
 import * as Auth from 'aws-amplify/auth'
 import { Skeleton } from '@/components/ui/skeleton'
+import * as React from 'react'
 
 function ErrorTip({ error, removeError }: {
   error: string | { variant?: 'warning' | 'destructive', title?: string, message: string | any },
@@ -112,7 +113,7 @@ function useCountDown() {
 }
 
 export function LoginForm() {
-  const { setErrors, setCurrentTab, onSessionCallback } = useAuthFormState()
+  const { setErrors, setCurrentTab, onSessionCallback, userSessionRender } = useAuthFormState()
   const [loading, setLoading] = useState<boolean>(false)
   const [sessionUser, setSessionUser] = useState<any>(null)
   const loadSession = async () => {
@@ -142,15 +143,26 @@ export function LoginForm() {
       </div>)
   }
 
+  const signOut = async () => {
+    await Auth.signOut()
+    setSessionUser(false)
+    setErrors(null)
+  }
+
   if (sessionUser?.username) {
+    if (userSessionRender) {
+      if (typeof userSessionRender === 'function') {
+        return userSessionRender({ sessionUser, signOut })
+      }
+      return userSessionRender
+    }
+
     return (
       <div className={'w-full text-center'}>
         <p className={'mb-4'}>{t('You are already logged in as')} <strong>{sessionUser.username}</strong></p>
-        <Button variant={'secondary'} className={'w-full'} onClick={async () => {
-          await Auth.signOut()
-          setSessionUser(false)
-          setErrors(null)
-        }}>{t('Sign out')}</Button>
+        <Button variant={'secondary'} className={'w-full'} onClick={signOut}>
+          {t('Sign out')}
+        </Button>
       </div>
     )
   }
@@ -622,4 +634,48 @@ export function ConfirmWithCodeForm(
       </div>
     </FormGroup>
   )
+}
+
+export function LSAuthenticator(props: any) {
+  const [errors, setErrors] = React.useState<string | null>(null)
+  const [currentTab, setCurrentTab] = React.useState<'login' | 'reset' | 'signup' | 'confirm-code' | any>('login')
+  const onSessionCallback = React.useCallback((session: any) => {
+    props.onSessionCallback?.(session)
+  }, [props.onSessionCallback])
+
+  React.useEffect(() => {
+    setErrors(null)
+  }, [currentTab])
+
+  let content = null
+  // support passing object with type field
+  let _currentTab = currentTab?.type ? currentTab.type : currentTab
+  let _currentTabProps = currentTab?.props || {}
+
+  switch (_currentTab) {
+    case 'login':
+      content = <LoginForm/>
+      break
+    case 'reset':
+      content = <ResetPasswordForm/>
+      break
+    case 'signup':
+      content = <SignupForm/>
+      break
+    case 'confirm-code':
+      content = <ConfirmWithCodeForm {..._currentTabProps}/>
+      break
+  }
+
+  return (
+    <AuthFormRootContext.Provider value={{
+      errors, setErrors, setCurrentTab,
+      onSessionCallback, userSessionRender: props.children
+    }}>
+      {props.titleRender?.(_currentTab)}
+      <div className={'ls-authenticator-content'}>
+        {content}
+      </div>
+    </AuthFormRootContext.Provider>
+  )
 }

+ 4 - 0
packages/ui/src/ui.ts

@@ -94,11 +94,13 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
 import * as uniqolor from 'uniqolor'
 import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
 import { setLocale, setTranslate } from './i18n'
+import * as amplifyAuth from './amplify'
 
 declare global {
   var LSUI: any
   var LSUtils: any
   var LSI18N: any
+  var LSAuth: any
 }
 
 const shadui = {
@@ -206,6 +208,8 @@ function setupGlobals() {
     setTranslate,
     setLocale,
   }
+
+  window.LSAuth = amplifyAuth
 }
 
 // setup