Commit 139adcbb authored by Joel's avatar Joel

chore: enchance app config

parent 97d3a627
# Conversion Web App Template # Conversion Web App Template
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Set App Info ## Config App
Set app info in `config/index.ts`. Includes: Config app in `config/index.ts`.Please config:
- APP_ID - APP_ID
- API_KEY - API_KEY
- APP_INFO
More config:
```js
export const APP_INFO: AppInfo = {
"title": 'Chat APP',
"description": '',
"copyright": '',
"privacy_policy": '',
"default_language": 'zh-Hans'
}
export const isShowPrompt = true
export const promptTemplate = ''
```
## Getting Started ## Getting Started
First, install dependencies: First, install dependencies:
......
...@@ -9,26 +9,18 @@ import Toast from '@/app/components/base/toast' ...@@ -9,26 +9,18 @@ import Toast from '@/app/components/base/toast'
import Sidebar from '@/app/components/sidebar' import Sidebar from '@/app/components/sidebar'
import ConfigSence from '@/app/components/config-scence' import ConfigSence from '@/app/components/config-scence'
import Header from '@/app/components/header' import Header from '@/app/components/header'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service' import { fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service'
import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, SiteInfo } from '@/types/app' import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, AppInfo } from '@/types/app'
import Chat from '@/app/components/chat' import Chat from '@/app/components/chat'
import { setLocaleOnClient } from '@/i18n/client' import { setLocaleOnClient } from '@/i18n/client'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import { replaceVarWithValues } from '@/utils/prompt' import { replaceVarWithValues } from '@/utils/prompt'
import AppUnavailable from '@/app/components/app-unavailable' import AppUnavailable from '@/app/components/app-unavailable'
import { APP_ID, API_KEY } from '@/config' import { APP_ID, API_KEY, APP_INFO, isShowPrompt, promptTemplate } from '@/config'
export type IMainProps = {
params: {
locale: string
appId: string
conversationId: string
token: string
}
}
const Main: FC<IMainProps> = () => { const Main: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const media = useBreakpoints() const media = useBreakpoints()
const isMobile = media === MediaType.mobile const isMobile = media === MediaType.mobile
...@@ -39,23 +31,16 @@ const Main: FC<IMainProps> = () => { ...@@ -39,23 +31,16 @@ const Main: FC<IMainProps> = () => {
*/ */
const [appUnavailable, setAppUnavailable] = useState<boolean>(false) const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false) const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
const [appId, setAppId] = useState<string>('')
const [isPublicVersion, setIsPublicVersion] = useState<boolean>(true)
const [siteInfo, setSiteInfo] = useState<SiteInfo | null>()
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null) const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
const [inited, setInited] = useState<boolean>(false) const [inited, setInited] = useState<boolean>(false)
const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
// in mobile, show sidebar by click button // in mobile, show sidebar by click button
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false) const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
useEffect(() => { useEffect(() => {
if (siteInfo?.title) { if (APP_INFO?.title) {
if (plan !== 'basic') document.title = `${APP_INFO.title} - Powered by LangGenius`
document.title = `${siteInfo.title}`
else
document.title = `${siteInfo.title} - Powered by LangGenius`
} }
}, [siteInfo?.title, plan]) }, [APP_INFO?.title])
/* /*
* conversation info * conversation info
...@@ -97,11 +82,6 @@ const Main: FC<IMainProps> = () => { ...@@ -97,11 +82,6 @@ const Main: FC<IMainProps> = () => {
const handleConversationSwitch = () => { const handleConversationSwitch = () => {
if (!inited) if (!inited)
return return
if (!appId) {
// wait for appId
setTimeout(handleConversationSwitch, 100)
return
}
// update inputs of current conversation // update inputs of current conversation
let notSyncToStateIntroduction = '' let notSyncToStateIntroduction = ''
...@@ -160,7 +140,7 @@ const Main: FC<IMainProps> = () => { ...@@ -160,7 +140,7 @@ const Main: FC<IMainProps> = () => {
setConversationIdChangeBecauseOfNew(false) setConversationIdChangeBecauseOfNew(false)
} }
// trigger handleConversationSwitch // trigger handleConversationSwitch
setCurrConversationId(id, appId) setCurrConversationId(id, APP_ID)
hideSidebar() hideSidebar()
} }
...@@ -203,7 +183,7 @@ const Main: FC<IMainProps> = () => { ...@@ -203,7 +183,7 @@ const Main: FC<IMainProps> = () => {
content: caculatedIntroduction, content: caculatedIntroduction,
isAnswer: true, isAnswer: true,
feedbackDisabled: true, feedbackDisabled: true,
isOpeningStatement: isPublicVersion, isOpeningStatement: isShowPrompt,
} }
if (caculatedIntroduction) if (caculatedIntroduction)
return [openstatement] return [openstatement]
...@@ -219,37 +199,30 @@ const Main: FC<IMainProps> = () => { ...@@ -219,37 +199,30 @@ const Main: FC<IMainProps> = () => {
} }
(async () => { (async () => {
try { try {
const [appData, conversationData, appParams] = await Promise.all([fetchAppInfo(), fetchConversations(), fetchAppParams()]) const [conversationData, appParams] = await Promise.all([fetchConversations(), fetchAppParams()])
const { app_id: appId, site: siteInfo, prompt_config, plan }: any = appData
setAppId(appId)
setPlan(plan)
const tempIsPublicVersion = !!prompt_config
setIsPublicVersion(tempIsPublicVersion)
const prompt_template = tempIsPublicVersion ? prompt_config.prompt_template : ''
// handle current conversation id // handle current conversation id
const { data: conversations } = conversationData as { data: ConversationItem[] } const { data: conversations } = conversationData as { data: ConversationItem[] }
const _conversationId = getConversationIdFromStorage(appId) const _conversationId = getConversationIdFromStorage(APP_ID)
const isNotNewConversation = conversations.some(item => item.id === _conversationId) const isNotNewConversation = conversations.some(item => item.id === _conversationId)
// fetch new conversation info // fetch new conversation info
const { variables: prompt_variables, introduction }: any = appParams const { variables: prompt_variables, introduction }: any = appParams
setLocaleOnClient(siteInfo.default_language, true) setLocaleOnClient(APP_INFO.default_language, true)
setNewConversationInfo({ setNewConversationInfo({
name: t('app.chat.newChatDefaultName'), name: t('app.chat.newChatDefaultName'),
introduction, introduction,
}) })
setSiteInfo(siteInfo as SiteInfo)
setPromptConfig({ setPromptConfig({
prompt_template, prompt_template: promptTemplate,
prompt_variables, prompt_variables,
} as PromptConfig) } as PromptConfig)
setConversationList(conversations as ConversationItem[]) setConversationList(conversations as ConversationItem[])
if (isNotNewConversation) if (isNotNewConversation)
setCurrConversationId(_conversationId, appId, false) setCurrConversationId(_conversationId, APP_ID, false)
setInited(true) setInited(true)
} }
...@@ -355,7 +328,7 @@ const Main: FC<IMainProps> = () => { ...@@ -355,7 +328,7 @@ const Main: FC<IMainProps> = () => {
setConversationIdChangeBecauseOfNew(false) setConversationIdChangeBecauseOfNew(false)
resetNewConversationInputs() resetNewConversationInputs()
setChatNotStarted() setChatNotStarted()
setCurrConversationId(tempNewConversationId, appId, true) setCurrConversationId(tempNewConversationId, APP_ID, true)
}, },
onError() { onError() {
setResponsingFalse() setResponsingFalse()
...@@ -383,28 +356,28 @@ const Main: FC<IMainProps> = () => { ...@@ -383,28 +356,28 @@ const Main: FC<IMainProps> = () => {
} }
const renderSidebar = () => { const renderSidebar = () => {
if (!appId || !siteInfo || !promptConfig) if (!APP_ID || !APP_INFO || !promptConfig)
return null return null
return ( return (
<Sidebar <Sidebar
list={conversationList} list={conversationList}
onCurrentIdChange={handleConversationIdChange} onCurrentIdChange={handleConversationIdChange}
currentId={currConversationId} currentId={currConversationId}
copyRight={siteInfo.copyright || siteInfo.title} copyRight={APP_INFO.copyright || APP_INFO.title}
/> />
) )
} }
if (appUnavailable) if (appUnavailable)
return <AppUnavailable isUnknwonReason={isUnknwonReason} errMessage={!hasSetAppConfig && 'Please set APP_ID and API_KEY in config/index.tsx'} /> return <AppUnavailable isUnknwonReason={isUnknwonReason} errMessage={!hasSetAppConfig ? 'Please set APP_ID and API_KEY in config/index.tsx' : ''} />
if (!appId || !siteInfo || !promptConfig) if (!APP_ID || !APP_INFO || !promptConfig)
return <Loading type='app' /> return <Loading type='app' />
return ( return (
<div className='bg-gray-100'> <div className='bg-gray-100'>
<Header <Header
title={siteInfo.title} title={APP_INFO.title}
isMobile={isMobile} isMobile={isMobile}
onShowSideBar={showSidebar} onShowSideBar={showSidebar}
onCreateNewChat={() => handleConversationIdChange('-1')} onCreateNewChat={() => handleConversationIdChange('-1')}
...@@ -427,14 +400,13 @@ const Main: FC<IMainProps> = () => { ...@@ -427,14 +400,13 @@ const Main: FC<IMainProps> = () => {
<ConfigSence <ConfigSence
conversationName={conversationName} conversationName={conversationName}
hasSetInputs={hasSetInputs} hasSetInputs={hasSetInputs}
isPublicVersion={isPublicVersion} isPublicVersion={isShowPrompt}
siteInfo={siteInfo} siteInfo={APP_INFO}
promptConfig={promptConfig} promptConfig={promptConfig}
onStartChat={handleStartChat} onStartChat={handleStartChat}
canEidtInpus={canEditInpus} canEidtInpus={canEditInpus}
savedInputs={currInputs as Record<string, any>} savedInputs={currInputs as Record<string, any>}
onInputsChange={setCurrInputs} onInputsChange={setCurrInputs}
plan={plan}
></ConfigSence> ></ConfigSence>
{ {
......
...@@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react' ...@@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel' import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel'
import s from './style.module.css' import s from './style.module.css'
import { AppInfo, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component' import { AppInfoComp, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
import type { PromptConfig, SiteInfo } from '@/types/app' import type { PromptConfig, AppInfo } from '@/types/app'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import Select from '@/app/components/base/select' import Select from '@/app/components/base/select'
import { DEFAULT_VALUE_MAX_LEN } from '@/config' import { DEFAULT_VALUE_MAX_LEN } from '@/config'
...@@ -17,13 +17,12 @@ export type IWelcomeProps = { ...@@ -17,13 +17,12 @@ export type IWelcomeProps = {
conversationName: string conversationName: string
hasSetInputs: boolean hasSetInputs: boolean
isPublicVersion: boolean isPublicVersion: boolean
siteInfo: SiteInfo siteInfo: AppInfo
promptConfig: PromptConfig promptConfig: PromptConfig
onStartChat: (inputs: Record<string, any>) => void onStartChat: (inputs: Record<string, any>) => void
canEidtInpus: boolean canEidtInpus: boolean
savedInputs: Record<string, any> savedInputs: Record<string, any>
onInputsChange: (inputs: Record<string, any>) => void onInputsChange: (inputs: Record<string, any>) => void
plan: string
} }
const Welcome: FC<IWelcomeProps> = ({ const Welcome: FC<IWelcomeProps> = ({
...@@ -31,7 +30,6 @@ const Welcome: FC<IWelcomeProps> = ({ ...@@ -31,7 +30,6 @@ const Welcome: FC<IWelcomeProps> = ({
hasSetInputs, hasSetInputs,
isPublicVersion, isPublicVersion,
siteInfo, siteInfo,
plan,
promptConfig, promptConfig,
onStartChat, onStartChat,
canEidtInpus, canEidtInpus,
...@@ -144,7 +142,7 @@ const Welcome: FC<IWelcomeProps> = ({ ...@@ -144,7 +142,7 @@ const Welcome: FC<IWelcomeProps> = ({
if (isPublicVersion) { if (isPublicVersion) {
return ( return (
<div> <div>
<AppInfo siteInfo={siteInfo} /> <AppInfoComp siteInfo={siteInfo} />
<TemplateVarPanel <TemplateVarPanel
isFold={false} isFold={false}
header={ header={
...@@ -167,7 +165,7 @@ const Welcome: FC<IWelcomeProps> = ({ ...@@ -167,7 +165,7 @@ const Welcome: FC<IWelcomeProps> = ({
<TemplateVarPanel <TemplateVarPanel
isFold={false} isFold={false}
header={ header={
<AppInfo siteInfo={siteInfo} /> <AppInfoComp siteInfo={siteInfo} />
} }
> >
<ChatBtn onClick={handleChat} /> <ChatBtn onClick={handleChat} />
...@@ -180,7 +178,7 @@ const Welcome: FC<IWelcomeProps> = ({ ...@@ -180,7 +178,7 @@ const Welcome: FC<IWelcomeProps> = ({
<TemplateVarPanel <TemplateVarPanel
isFold={false} isFold={false}
header={ header={
<AppInfo siteInfo={siteInfo} /> <AppInfoComp siteInfo={siteInfo} />
} }
> >
{renderInputs()} {renderInputs()}
...@@ -325,10 +323,10 @@ const Welcome: FC<IWelcomeProps> = ({ ...@@ -325,10 +323,10 @@ const Welcome: FC<IWelcomeProps> = ({
</div> </div>
: <div> : <div>
</div>} </div>}
{plan === 'basic' && <a className='flex items-center pr-3 space-x-3' href="https://langgenius.ai/" target="_blank"> <a className='flex items-center pr-3 space-x-3' href="https://langgenius.ai/" target="_blank">
<span className='uppercase'>{t('app.chat.powerBy')}</span> <span className='uppercase'>{t('app.chat.powerBy')}</span>
<FootLogo /> <FootLogo />
</a>} </a>
</div> </div>
)} )}
</div> </div>
......
...@@ -7,10 +7,10 @@ import { ...@@ -7,10 +7,10 @@ import {
PencilIcon, PencilIcon,
} from '@heroicons/react/24/solid' } from '@heroicons/react/24/solid'
import s from './style.module.css' import s from './style.module.css'
import type { SiteInfo } from '@/types/app' import type { AppInfo } from '@/types/app'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
export const AppInfo: FC<{ siteInfo: SiteInfo }> = ({ siteInfo }) => { export const AppInfoComp: FC<{ siteInfo: AppInfo }> = ({ siteInfo }) => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<div> <div>
......
import { AppInfo } from "@/types/app"
export const APP_ID = '' export const APP_ID = ''
export const API_KEY = '' export const API_KEY = ''
export const APP_INFO = {
"app_id": APP_ID,
"site": {
"title": "Chat APP",
"description": null,
"copyright": null,
"privacy_policy": null,
"default_language": "zh-Hans",
"prompt_public": true
},
"prompt_config": {
"introduction": "Chat APP",
"prompt_template": "{{a}}", "prompt_variables": [{ "key": "a", "name": "a", "type": "string", "max_length": 48 }], "completion_params": { "max_token": 256, "temperature": 1, "top_p": 1, "presence_penalty": 0, "frequency_penalty": 0 }
}
}
export const APP_INFO: AppInfo = {
"title": 'Chat APP',
"description": '',
"copyright": '',
"privacy_policy": '',
"default_language": 'zh-Hans'
}
export const isShowPrompt = false
export const promptTemplate = 'I want you to act as a javascript console.'
export const API_PREFIX = '/api'; export const API_PREFIX = '/api';
......
...@@ -66,7 +66,7 @@ export type ConversationItem = { ...@@ -66,7 +66,7 @@ export type ConversationItem = {
introduction: string, introduction: string,
} }
export type SiteInfo = { export type AppInfo = {
title: string title: string
description: string description: string
default_language: Locale default_language: Locale
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment