Commit 139adcbb authored by Joel's avatar Joel

chore: enchance app config

parent 97d3a627
# 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).
## Set App Info
Set app info in `config/index.ts`. Includes:
## Config App
Config app in `config/index.ts`.Please config:
- APP_ID
- 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
First, install dependencies:
......
......@@ -9,26 +9,18 @@ import Toast from '@/app/components/base/toast'
import Sidebar from '@/app/components/sidebar'
import ConfigSence from '@/app/components/config-scence'
import Header from '@/app/components/header'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service'
import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, SiteInfo } from '@/types/app'
import { fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service'
import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, AppInfo } from '@/types/app'
import Chat from '@/app/components/chat'
import { setLocaleOnClient } from '@/i18n/client'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import Loading from '@/app/components/base/loading'
import { replaceVarWithValues } from '@/utils/prompt'
import AppUnavailable from '@/app/components/app-unavailable'
import { APP_ID, API_KEY } from '@/config'
export type IMainProps = {
params: {
locale: string
appId: string
conversationId: string
token: string
}
}
import { APP_ID, API_KEY, APP_INFO, isShowPrompt, promptTemplate } from '@/config'
const Main: FC<IMainProps> = () => {
const Main: FC = () => {
const { t } = useTranslation()
const media = useBreakpoints()
const isMobile = media === MediaType.mobile
......@@ -39,23 +31,16 @@ const Main: FC<IMainProps> = () => {
*/
const [appUnavailable, setAppUnavailable] = 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 [inited, setInited] = useState<boolean>(false)
const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
// in mobile, show sidebar by click button
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
useEffect(() => {
if (siteInfo?.title) {
if (plan !== 'basic')
document.title = `${siteInfo.title}`
else
document.title = `${siteInfo.title} - Powered by LangGenius`
if (APP_INFO?.title) {
document.title = `${APP_INFO.title} - Powered by LangGenius`
}
}, [siteInfo?.title, plan])
}, [APP_INFO?.title])
/*
* conversation info
......@@ -97,11 +82,6 @@ const Main: FC<IMainProps> = () => {
const handleConversationSwitch = () => {
if (!inited)
return
if (!appId) {
// wait for appId
setTimeout(handleConversationSwitch, 100)
return
}
// update inputs of current conversation
let notSyncToStateIntroduction = ''
......@@ -160,7 +140,7 @@ const Main: FC<IMainProps> = () => {
setConversationIdChangeBecauseOfNew(false)
}
// trigger handleConversationSwitch
setCurrConversationId(id, appId)
setCurrConversationId(id, APP_ID)
hideSidebar()
}
......@@ -203,7 +183,7 @@ const Main: FC<IMainProps> = () => {
content: caculatedIntroduction,
isAnswer: true,
feedbackDisabled: true,
isOpeningStatement: isPublicVersion,
isOpeningStatement: isShowPrompt,
}
if (caculatedIntroduction)
return [openstatement]
......@@ -219,37 +199,30 @@ const Main: FC<IMainProps> = () => {
}
(async () => {
try {
const [appData, conversationData, appParams] = await Promise.all([fetchAppInfo(), 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 : ''
const [conversationData, appParams] = await Promise.all([fetchConversations(), fetchAppParams()])
// handle current conversation id
const { data: conversations } = conversationData as { data: ConversationItem[] }
const _conversationId = getConversationIdFromStorage(appId)
const _conversationId = getConversationIdFromStorage(APP_ID)
const isNotNewConversation = conversations.some(item => item.id === _conversationId)
// fetch new conversation info
const { variables: prompt_variables, introduction }: any = appParams
setLocaleOnClient(siteInfo.default_language, true)
setLocaleOnClient(APP_INFO.default_language, true)
setNewConversationInfo({
name: t('app.chat.newChatDefaultName'),
introduction,
})
setSiteInfo(siteInfo as SiteInfo)
setPromptConfig({
prompt_template,
prompt_template: promptTemplate,
prompt_variables,
} as PromptConfig)
setConversationList(conversations as ConversationItem[])
if (isNotNewConversation)
setCurrConversationId(_conversationId, appId, false)
setCurrConversationId(_conversationId, APP_ID, false)
setInited(true)
}
......@@ -355,7 +328,7 @@ const Main: FC<IMainProps> = () => {
setConversationIdChangeBecauseOfNew(false)
resetNewConversationInputs()
setChatNotStarted()
setCurrConversationId(tempNewConversationId, appId, true)
setCurrConversationId(tempNewConversationId, APP_ID, true)
},
onError() {
setResponsingFalse()
......@@ -383,28 +356,28 @@ const Main: FC<IMainProps> = () => {
}
const renderSidebar = () => {
if (!appId || !siteInfo || !promptConfig)
if (!APP_ID || !APP_INFO || !promptConfig)
return null
return (
<Sidebar
list={conversationList}
onCurrentIdChange={handleConversationIdChange}
currentId={currConversationId}
copyRight={siteInfo.copyright || siteInfo.title}
copyRight={APP_INFO.copyright || APP_INFO.title}
/>
)
}
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 (
<div className='bg-gray-100'>
<Header
title={siteInfo.title}
title={APP_INFO.title}
isMobile={isMobile}
onShowSideBar={showSidebar}
onCreateNewChat={() => handleConversationIdChange('-1')}
......@@ -427,14 +400,13 @@ const Main: FC<IMainProps> = () => {
<ConfigSence
conversationName={conversationName}
hasSetInputs={hasSetInputs}
isPublicVersion={isPublicVersion}
siteInfo={siteInfo}
isPublicVersion={isShowPrompt}
siteInfo={APP_INFO}
promptConfig={promptConfig}
onStartChat={handleStartChat}
canEidtInpus={canEditInpus}
savedInputs={currInputs as Record<string, any>}
onInputsChange={setCurrInputs}
plan={plan}
></ConfigSence>
{
......
......@@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel'
import s from './style.module.css'
import { AppInfo, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
import type { PromptConfig, SiteInfo } from '@/types/app'
import { AppInfoComp, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
import type { PromptConfig, AppInfo } from '@/types/app'
import Toast from '@/app/components/base/toast'
import Select from '@/app/components/base/select'
import { DEFAULT_VALUE_MAX_LEN } from '@/config'
......@@ -17,13 +17,12 @@ export type IWelcomeProps = {
conversationName: string
hasSetInputs: boolean
isPublicVersion: boolean
siteInfo: SiteInfo
siteInfo: AppInfo
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> = ({
......@@ -31,7 +30,6 @@ const Welcome: FC<IWelcomeProps> = ({
hasSetInputs,
isPublicVersion,
siteInfo,
plan,
promptConfig,
onStartChat,
canEidtInpus,
......@@ -144,7 +142,7 @@ const Welcome: FC<IWelcomeProps> = ({
if (isPublicVersion) {
return (
<div>
<AppInfo siteInfo={siteInfo} />
<AppInfoComp siteInfo={siteInfo} />
<TemplateVarPanel
isFold={false}
header={
......@@ -167,7 +165,7 @@ const Welcome: FC<IWelcomeProps> = ({
<TemplateVarPanel
isFold={false}
header={
<AppInfo siteInfo={siteInfo} />
<AppInfoComp siteInfo={siteInfo} />
}
>
<ChatBtn onClick={handleChat} />
......@@ -180,7 +178,7 @@ const Welcome: FC<IWelcomeProps> = ({
<TemplateVarPanel
isFold={false}
header={
<AppInfo siteInfo={siteInfo} />
<AppInfoComp siteInfo={siteInfo} />
}
>
{renderInputs()}
......@@ -325,10 +323,10 @@ const Welcome: FC<IWelcomeProps> = ({
</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>
<FootLogo />
</a>}
</a>
</div>
)}
</div>
......
......@@ -7,10 +7,10 @@ import {
PencilIcon,
} from '@heroicons/react/24/solid'
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'
export const AppInfo: FC<{ siteInfo: SiteInfo }> = ({ siteInfo }) => {
export const AppInfoComp: FC<{ siteInfo: AppInfo }> = ({ siteInfo }) => {
const { t } = useTranslation()
return (
<div>
......
import { AppInfo } from "@/types/app"
export const APP_ID = ''
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';
......
......@@ -66,7 +66,7 @@ export type ConversationItem = {
introduction: string,
}
export type SiteInfo = {
export type AppInfo = {
title: string
description: string
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