| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 | 
							- 'use client'
 - import type { FC } from 'react'
 - import React, { useEffect, useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import { useContext } from 'use-context-selector'
 - import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel'
 - import s from './style.module.css'
 - import { AppInfo, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
 - import type { SiteInfo } from '@/models/share'
 - import type { PromptConfig } from '@/models/debug'
 - import { ToastContext } from '@/app/components/base/toast'
 - import Select from '@/app/components/base/select'
 - import { DEFAULT_VALUE_MAX_LEN } from '@/config'
 - 
 - // regex to match the {{}} and replace it with a span
 - const regex = /\{\{([^}]+)\}\}/g
 - 
 - export type IWelcomeProps = {
 -   conversationName: string
 -   hasSetInputs: boolean
 -   isPublicVersion: boolean
 -   siteInfo: SiteInfo
 -   promptConfig: PromptConfig
 -   onStartChat: (inputs: Record<string, any>) => void
 -   canEidtInpus: boolean
 -   savedInputs: Record<string, any>
 -   onInputsChange: (inputs: Record<string, any>) => void
 -   plan: string
 - }
 - 
 - const Welcome: FC<IWelcomeProps> = ({
 -   conversationName,
 -   hasSetInputs,
 -   isPublicVersion,
 -   siteInfo,
 -   plan,
 -   promptConfig,
 -   onStartChat,
 -   canEidtInpus,
 -   savedInputs,
 -   onInputsChange,
 - }) => {
 -   const { t } = useTranslation()
 -   const hasVar = promptConfig.prompt_variables.length > 0
 -   const [isFold, setIsFold] = useState<boolean>(true)
 -   const [inputs, setInputs] = useState<Record<string, any>>((() => {
 -     if (hasSetInputs)
 -       return savedInputs
 - 
 -     const res: Record<string, any> = {}
 -     if (promptConfig) {
 -       promptConfig.prompt_variables.forEach((item) => {
 -         res[item.key] = ''
 -       })
 -     }
 -     // debugger
 -     return res
 -   })())
 -   useEffect(() => {
 -     if (!savedInputs) {
 -       const res: Record<string, any> = {}
 -       if (promptConfig) {
 -         promptConfig.prompt_variables.forEach((item) => {
 -           res[item.key] = ''
 -         })
 -       }
 -       setInputs(res)
 -     }
 -     else {
 -       setInputs(savedInputs)
 -     }
 -   }, [savedInputs])
 - 
 -   const highLightPromoptTemplate = (() => {
 -     if (!promptConfig)
 -       return ''
 -     const res = promptConfig.prompt_template.replace(regex, (match, p1) => {
 -       return `<span class='text-gray-800 font-bold'>${inputs?.[p1] ? inputs?.[p1] : match}</span>`
 -     })
 -     return res
 -   })()
 - 
 -   const { notify } = useContext(ToastContext)
 -   const logError = (message: string) => {
 -     notify({ type: 'error', message, duration: 3000 })
 -   }
 - 
 -   const renderHeader = () => {
 -     return (
 -       <div className='absolute top-0 left-0 right-0 flex items-center justify-between border-b border-gray-100 mobile:h-12 tablet:h-16 px-8 bg-white'>
 -         <div className='text-gray-900'>{conversationName}</div>
 -       </div>
 -     )
 -   }
 - 
 -   const renderInputs = () => {
 -     return (
 -       <div className='space-y-3'>
 -         {promptConfig.prompt_variables.map(item => (
 -           <div className='tablet:flex tablet:!h-9 mobile:space-y-2 tablet:space-y-0 mobile:text-xs tablet:text-sm' key={item.key}>
 -             <label className={`flex-shrink-0 flex items-center mobile:text-gray-700 tablet:text-gray-900 mobile:font-medium pc:font-normal ${s.formLabel}`}>{item.name}</label>
 -             {item.type === 'select'
 -               ? (
 -                 <Select
 -                   className='w-full'
 -                   defaultValue={inputs?.[item.key]}
 -                   onSelect={(i) => { setInputs({ ...inputs, [item.key]: i.value }) }}
 -                   items={(item.options || []).map(i => ({ name: i, value: i }))}
 -                   allowSearch={false}
 -                   bgClassName='bg-gray-50'
 -                 />
 -               )
 -               : (
 -                 <input
 -                   placeholder={`${item.name}${!item.required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
 -                   value={inputs?.[item.key] || ''}
 -                   onChange={(e) => { setInputs({ ...inputs, [item.key]: e.target.value }) }}
 -                   className={'w-full flex-grow py-2 pl-3 pr-3 box-border rounded-lg bg-gray-50'}
 -                   maxLength={item.max_length || DEFAULT_VALUE_MAX_LEN}
 -                 />
 -               )}
 -           </div>
 -         ))}
 -       </div>
 -     )
 -   }
 - 
 -   const canChat = () => {
 -     const prompt_variables = promptConfig?.prompt_variables
 -     if (!inputs || !prompt_variables || prompt_variables?.length === 0)
 -       return true
 - 
 -     let hasEmptyInput = ''
 -     const requiredVars = prompt_variables?.filter(({ key, name, required }) => {
 -       const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null)
 -       return res
 -     }) || [] // compatible with old version
 -     requiredVars.forEach(({ key, name }) => {
 -       if (hasEmptyInput)
 -         return
 - 
 -       if (!inputs?.[key])
 -         hasEmptyInput = name
 -     })
 - 
 -     if (hasEmptyInput) {
 -       logError(t('appDebug.errorMessage.valueOfVarRequired', { key: hasEmptyInput }))
 -       return false
 -     }
 -     return !hasEmptyInput
 -   }
 - 
 -   const handleChat = () => {
 -     if (!canChat())
 -       return
 - 
 -     onStartChat(inputs)
 -   }
 - 
 -   const renderNoVarPanel = () => {
 -     if (isPublicVersion) {
 -       return (
 -         <div>
 -           <AppInfo siteInfo={siteInfo} />
 -           <TemplateVarPanel
 -             isFold={false}
 -             header={
 -               <>
 -                 <PanelTitle
 -                   title={t('share.chat.publicPromptConfigTitle')}
 -                   className='mb-1'
 -                 />
 -                 <PromptTemplate html={highLightPromoptTemplate} />
 -               </>
 -             }
 -           >
 -             <ChatBtn onClick={handleChat} />
 -           </TemplateVarPanel>
 -         </div>
 -       )
 -     }
 -     // private version
 -     return (
 -       <TemplateVarPanel
 -         isFold={false}
 -         header={
 -           <AppInfo siteInfo={siteInfo} />
 -         }
 -       >
 -         <ChatBtn onClick={handleChat} />
 -       </TemplateVarPanel>
 -     )
 -   }
 - 
 -   const renderVarPanel = () => {
 -     return (
 -       <TemplateVarPanel
 -         isFold={false}
 -         header={
 -           <AppInfo siteInfo={siteInfo} />
 -         }
 -       >
 -         {renderInputs()}
 -         <ChatBtn
 -           className='mt-3 mobile:ml-0 tablet:ml-[128px]'
 -           onClick={handleChat}
 -         />
 -       </TemplateVarPanel>
 -     )
 -   }
 - 
 -   const renderVarOpBtnGroup = () => {
 -     return (
 -       <VarOpBtnGroup
 -         onConfirm={() => {
 -           if (!canChat())
 -             return
 - 
 -           onInputsChange(inputs)
 -           setIsFold(true)
 -         }}
 -         onCancel={() => {
 -           setInputs(savedInputs)
 -           setIsFold(true)
 -         }}
 -       />
 -     )
 -   }
 - 
 -   const renderHasSetInputsPublic = () => {
 -     if (!canEidtInpus) {
 -       return (
 -         <TemplateVarPanel
 -           isFold={false}
 -           header={
 -             <>
 -               <PanelTitle
 -                 title={t('share.chat.publicPromptConfigTitle')}
 -                 className='mb-1'
 -               />
 -               <PromptTemplate html={highLightPromoptTemplate} />
 -             </>
 -           }
 -         />
 -       )
 -     }
 - 
 -     return (
 -       <TemplateVarPanel
 -         isFold={isFold}
 -         header={
 -           <>
 -             <PanelTitle
 -               title={t('share.chat.publicPromptConfigTitle')}
 -               className='mb-1'
 -             />
 -             <PromptTemplate html={highLightPromoptTemplate} />
 -             {isFold && (
 -               <div className='flex items-center justify-between mt-3 border-t border-indigo-100 pt-4 text-xs text-indigo-600'>
 -                 <span className='text-gray-700'>{t('share.chat.configStatusDes')}</span>
 -                 <EditBtn onClick={() => setIsFold(false)} />
 -               </div>
 -             )}
 -           </>
 -         }
 -       >
 -         {renderInputs()}
 -         {renderVarOpBtnGroup()}
 -       </TemplateVarPanel>
 -     )
 -   }
 - 
 -   const renderHasSetInputsPrivate = () => {
 -     if (!canEidtInpus || !hasVar)
 -       return null
 - 
 -     return (
 -       <TemplateVarPanel
 -         isFold={isFold}
 -         header={
 -           <div className='flex items-center justify-between text-indigo-600'>
 -             <PanelTitle
 -               title={!isFold ? t('share.chat.privatePromptConfigTitle') : t('share.chat.configStatusDes')}
 -             />
 -             {isFold && (
 -               <EditBtn onClick={() => setIsFold(false)} />
 -             )}
 -           </div>
 -         }
 -       >
 -         {renderInputs()}
 -         {renderVarOpBtnGroup()}
 -       </TemplateVarPanel>
 -     )
 -   }
 - 
 -   const renderHasSetInputs = () => {
 -     if ((!isPublicVersion && !canEidtInpus) || !hasVar)
 -       return null
 - 
 -     return (
 -       <div
 -         className='pt-[88px] mb-5'
 -       >
 -         {isPublicVersion ? renderHasSetInputsPublic() : renderHasSetInputsPrivate()}
 -       </div>)
 -   }
 - 
 -   return (
 -     <div className='relative mobile:min-h-[48px] tablet:min-h-[64px]'>
 -       {hasSetInputs && renderHeader()}
 -       <div className='mx-auto pc:w-[794px] max-w-full mobile:w-full px-3.5'>
 -         {/*  Has't set inputs  */}
 -         {
 -           !hasSetInputs && (
 -             <div className='mobile:pt-[72px] tablet:pt-[128px] pc:pt-[200px]'>
 -               {hasVar
 -                 ? (
 -                   renderVarPanel()
 -                 )
 -                 : (
 -                   renderNoVarPanel()
 -                 )}
 -             </div>
 -           )
 -         }
 - 
 -         {/* Has set inputs */}
 -         {hasSetInputs && renderHasSetInputs()}
 - 
 -         {/* foot */}
 -         {!hasSetInputs && (
 -           <div className='mt-4 flex justify-between items-center h-8 text-xs text-gray-400'>
 - 
 -             {siteInfo.privacy_policy
 -               ? <div>{t('share.chat.privacyPolicyLeft')}
 -                 <a
 -                   className='text-gray-500'
 -                   href={siteInfo.privacy_policy}
 -                   target='_blank'>{t('share.chat.privacyPolicyMiddle')}</a>
 -                 {t('share.chat.privacyPolicyRight')}
 -               </div>
 -               : <div>
 -               </div>}
 -             {plan === 'basic' && <a className='flex items-center pr-3 space-x-3' href="https://dify.ai/" target="_blank">
 -               <span className='uppercase'>{t('share.chat.powerBy')}</span>
 -               <FootLogo />
 -             </a>}
 -           </div>
 -         )}
 -       </div>
 -     </div >
 -   )
 - }
 - 
 - export default React.memo(Welcome)
 
 
  |