| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||||
| <g id="file-upload"> | |||||
| <path id="Icon" d="M20 10.5V6.8C20 5.11984 20 4.27976 19.673 3.63803C19.3854 3.07354 18.9265 2.6146 18.362 2.32698C17.7202 2 16.8802 2 15.2 2H8.8C7.11984 2 6.27976 2 5.63803 2.32698C5.07354 2.6146 4.6146 3.07354 4.32698 3.63803C4 4.27976 4 5.11984 4 6.8V17.2C4 18.8802 4 19.7202 4.32698 20.362C4.6146 20.9265 5.07354 21.3854 5.63803 21.673C6.27976 22 7.11984 22 8.8 22H12M14 11H8M10 15H8M16 7H8" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||||
| <path id="Icon_2" d="M15 18L18 15M18 15L21 18M18 15L18 21" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||||
| </g> | |||||
| </svg> |
| { | |||||
| "icon": { | |||||
| "type": "element", | |||||
| "isRootNode": true, | |||||
| "name": "svg", | |||||
| "attributes": { | |||||
| "width": "24", | |||||
| "height": "24", | |||||
| "viewBox": "0 0 24 24", | |||||
| "fill": "none", | |||||
| "xmlns": "http://www.w3.org/2000/svg" | |||||
| }, | |||||
| "children": [ | |||||
| { | |||||
| "type": "element", | |||||
| "name": "g", | |||||
| "attributes": { | |||||
| "id": "file-upload" | |||||
| }, | |||||
| "children": [ | |||||
| { | |||||
| "type": "element", | |||||
| "name": "path", | |||||
| "attributes": { | |||||
| "id": "Icon", | |||||
| "d": "M20 10.5V6.8C20 5.11984 20 4.27976 19.673 3.63803C19.3854 3.07354 18.9265 2.6146 18.362 2.32698C17.7202 2 16.8802 2 15.2 2H8.8C7.11984 2 6.27976 2 5.63803 2.32698C5.07354 2.6146 4.6146 3.07354 4.32698 3.63803C4 4.27976 4 5.11984 4 6.8V17.2C4 18.8802 4 19.7202 4.32698 20.362C4.6146 20.9265 5.07354 21.3854 5.63803 21.673C6.27976 22 7.11984 22 8.8 22H12M14 11H8M10 15H8M16 7H8", | |||||
| "stroke": "currentColor", | |||||
| "stroke-width": "2", | |||||
| "stroke-linecap": "round", | |||||
| "stroke-linejoin": "round" | |||||
| }, | |||||
| "children": [] | |||||
| }, | |||||
| { | |||||
| "type": "element", | |||||
| "name": "path", | |||||
| "attributes": { | |||||
| "id": "Icon_2", | |||||
| "d": "M15 18L18 15M18 15L21 18M18 15L18 21", | |||||
| "stroke": "currentColor", | |||||
| "stroke-width": "2", | |||||
| "stroke-linecap": "round", | |||||
| "stroke-linejoin": "round" | |||||
| }, | |||||
| "children": [] | |||||
| } | |||||
| ] | |||||
| } | |||||
| ] | |||||
| }, | |||||
| "name": "FileUpload" | |||||
| } |
| // GENERATE BY script | |||||
| // DON NOT EDIT IT MANUALLY | |||||
| import * as React from 'react' | |||||
| import data from './FileUpload.json' | |||||
| import IconBase from '@/app/components/base/icons/IconBase' | |||||
| import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' | |||||
| const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( | |||||
| props, | |||||
| ref, | |||||
| ) => <IconBase {...props} ref={ref} data={data as IconData} />) | |||||
| Icon.displayName = 'FileUpload' | |||||
| export default Icon |
| export { default as FilePlus01 } from './FilePlus01' | export { default as FilePlus01 } from './FilePlus01' | ||||
| export { default as FilePlus02 } from './FilePlus02' | export { default as FilePlus02 } from './FilePlus02' | ||||
| export { default as FileText } from './FileText' | export { default as FileText } from './FileText' | ||||
| export { default as FileUpload } from './FileUpload' | |||||
| export { default as Folder } from './Folder' | export { default as Folder } from './Folder' |
| buildApps: 1, | buildApps: 1, | ||||
| teamMembers: 1, | teamMembers: 1, | ||||
| annotatedResponse: 1, | annotatedResponse: 1, | ||||
| documentsUploadQuota: 1, | |||||
| }, | }, | ||||
| total: { | total: { | ||||
| vectorSpace: 10, | vectorSpace: 10, | ||||
| buildApps: 10, | buildApps: 10, | ||||
| teamMembers: 1, | teamMembers: 1, | ||||
| annotatedResponse: 10, | annotatedResponse: 10, | ||||
| documentsUploadQuota: 50, | |||||
| }, | }, | ||||
| } | } |
| import VectorSpaceInfo from '../usage-info/vector-space-info' | import VectorSpaceInfo from '../usage-info/vector-space-info' | ||||
| import AppsInfo from '../usage-info/apps-info' | import AppsInfo from '../usage-info/apps-info' | ||||
| import UpgradeBtn from '../upgrade-btn' | import UpgradeBtn from '../upgrade-btn' | ||||
| import { User01 } from '../../base/icons/src/vender/line/users' | |||||
| import { MessageFastPlus } from '../../base/icons/src/vender/line/communication' | |||||
| import { FileUpload } from '../../base/icons/src/vender/line/files' | |||||
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| import UsageInfo from '@/app/components/billing/usage-info' | |||||
| const typeStyle = { | const typeStyle = { | ||||
| [Plan.sandbox]: { | [Plan.sandbox]: { | ||||
| type, | type, | ||||
| } = plan | } = plan | ||||
| const { | |||||
| usage, | |||||
| total, | |||||
| } = plan | |||||
| const isInHeader = loc === 'header' | const isInHeader = loc === 'header' | ||||
| return ( | return ( | ||||
| {/* Plan detail */} | {/* Plan detail */} | ||||
| <div className='rounded-xl bg-white px-6 py-3'> | <div className='rounded-xl bg-white px-6 py-3'> | ||||
| <VectorSpaceInfo className='py-3' /> | |||||
| <UsageInfo | |||||
| className='py-3' | |||||
| Icon={User01} | |||||
| name={t('billing.plansCommon.teamMembers')} | |||||
| usage={usage.teamMembers} | |||||
| total={total.teamMembers} | |||||
| /> | |||||
| <AppsInfo className='py-3' /> | <AppsInfo className='py-3' /> | ||||
| <VectorSpaceInfo className='py-3' /> | |||||
| <UsageInfo | |||||
| className='py-3' | |||||
| Icon={MessageFastPlus} | |||||
| name={t('billing.plansCommon.annotationQuota')} | |||||
| usage={usage.annotatedResponse} | |||||
| total={total.annotatedResponse} | |||||
| /> | |||||
| <UsageInfo | |||||
| className='py-3' | |||||
| Icon={FileUpload} | |||||
| name={t('billing.plansCommon.documentsUploadQuota')} | |||||
| usage={usage.documentsUploadQuota} | |||||
| total={total.documentsUploadQuota} | |||||
| /> | |||||
| {isInHeader && type === Plan.sandbox && ( | {isInHeader && type === Plan.sandbox && ( | ||||
| <UpgradeBtn | <UpgradeBtn | ||||
| className='flex-shrink-0 my-3' | className='flex-shrink-0 my-3' |
| annotatedResponse: number | annotatedResponse: number | ||||
| } | } | ||||
| export type UsagePlanInfo = Pick<PlanInfo, 'vectorSpace' | 'buildApps' | 'teamMembers' | 'annotatedResponse'> | |||||
| export type UsagePlanInfo = Pick<PlanInfo, 'vectorSpace' | 'buildApps' | 'teamMembers' | 'annotatedResponse' | 'documentsUploadQuota'> | |||||
| export enum DocumentProcessingPriority { | export enum DocumentProcessingPriority { | ||||
| standard = 'standard', | standard = 'standard', | ||||
| size: number | size: number | ||||
| limit: number // total. 0 means unlimited | limit: number // total. 0 means unlimited | ||||
| } | } | ||||
| documents_upload_quota: { | |||||
| size: number | |||||
| limit: number // total. 0 means unlimited | |||||
| } | |||||
| docs_processing: DocumentProcessingPriority | docs_processing: DocumentProcessingPriority | ||||
| can_replace_logo: boolean | can_replace_logo: boolean | ||||
| } | } |
| buildApps: data.apps?.size || 0, | buildApps: data.apps?.size || 0, | ||||
| teamMembers: data.members.size, | teamMembers: data.members.size, | ||||
| annotatedResponse: data.annotation_quota_limit.size, | annotatedResponse: data.annotation_quota_limit.size, | ||||
| documentsUploadQuota: data.documents_upload_quota.size, | |||||
| }, | }, | ||||
| total: { | total: { | ||||
| vectorSpace: parseLimit(data.vector_space.limit), | vectorSpace: parseLimit(data.vector_space.limit), | ||||
| buildApps: parseLimit(data.apps?.limit) || 0, | buildApps: parseLimit(data.apps?.limit) || 0, | ||||
| teamMembers: parseLimit(data.members.limit), | teamMembers: parseLimit(data.members.limit), | ||||
| annotatedResponse: parseLimit(data.annotation_quota_limit.limit), | annotatedResponse: parseLimit(data.annotation_quota_limit.limit), | ||||
| documentsUploadQuota: parseLimit(data.documents_upload_quota.limit), | |||||
| }, | }, | ||||
| } | } | ||||
| } | } |
| 'use client' | 'use client' | ||||
| import { useEffect, useRef, useState } from 'react' | |||||
| import { useCallback, useEffect } from 'react' | |||||
| import Link from 'next/link' | import Link from 'next/link' | ||||
| import { useBoolean, useClickAway } from 'ahooks' | |||||
| import { useBoolean } from 'ahooks' | |||||
| import { useSelectedLayoutSegment } from 'next/navigation' | import { useSelectedLayoutSegment } from 'next/navigation' | ||||
| import { Bars3Icon } from '@heroicons/react/20/solid' | import { Bars3Icon } from '@heroicons/react/20/solid' | ||||
| import HeaderBillingBtn from '../billing/header-billing-btn' | import HeaderBillingBtn from '../billing/header-billing-btn' | ||||
| import { WorkspaceProvider } from '@/context/workspace-context' | import { WorkspaceProvider } from '@/context/workspace-context' | ||||
| import { useAppContext } from '@/context/app-context' | import { useAppContext } from '@/context/app-context' | ||||
| import LogoSite from '@/app/components/base/logo/logo-site' | import LogoSite from '@/app/components/base/logo/logo-site' | ||||
| import PlanComp from '@/app/components/billing/plan' | |||||
| import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | ||||
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| import { useModalContext } from '@/context/modal-context' | |||||
| const navClassName = ` | const navClassName = ` | ||||
| flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl | flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl | ||||
| ` | ` | ||||
| const Header = () => { | const Header = () => { | ||||
| const { isCurrentWorkspaceManager, langeniusVersionInfo } = useAppContext() | |||||
| const [showUpgradePanel, setShowUpgradePanel] = useState(false) | |||||
| const upgradeBtnRef = useRef<HTMLElement>(null) | |||||
| useClickAway(() => { | |||||
| setShowUpgradePanel(false) | |||||
| }, upgradeBtnRef) | |||||
| const { isCurrentWorkspaceManager } = useAppContext() | |||||
| const selectedSegment = useSelectedLayoutSegment() | const selectedSegment = useSelectedLayoutSegment() | ||||
| const media = useBreakpoints() | const media = useBreakpoints() | ||||
| const isMobile = media === MediaType.mobile | const isMobile = media === MediaType.mobile | ||||
| const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false) | const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false) | ||||
| const { enableBilling } = useProviderContext() | |||||
| const { enableBilling, plan } = useProviderContext() | |||||
| const { setShowPricingModal, setShowAccountSettingModal } = useModalContext() | |||||
| const isFreePlan = plan.type === 'sandbox' | |||||
| const handlePlanClick = useCallback(() => { | |||||
| if (isFreePlan) | |||||
| setShowPricingModal() | |||||
| else | |||||
| setShowAccountSettingModal({ payload: 'billing' }) | |||||
| }, [isFreePlan, setShowAccountSettingModal, setShowPricingModal]) | |||||
| useEffect(() => { | useEffect(() => { | ||||
| hideNavMenu() | hideNavMenu() | ||||
| <EnvNav /> | <EnvNav /> | ||||
| {enableBilling && ( | {enableBilling && ( | ||||
| <div className='mr-3 select-none'> | <div className='mr-3 select-none'> | ||||
| <HeaderBillingBtn onClick={() => setShowUpgradePanel(true)} /> | |||||
| {showUpgradePanel && ( | |||||
| <div | |||||
| ref={upgradeBtnRef as any} | |||||
| className='fixed z-10 top-12 right-1 w-[360px]' | |||||
| > | |||||
| <PlanComp loc='header' /> | |||||
| </div> | |||||
| )} | |||||
| <HeaderBillingBtn onClick={handlePlanClick} /> | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| <WorkspaceProvider> | <WorkspaceProvider> |
| setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>> | setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>> | ||||
| setShowModerationSettingModal: Dispatch<SetStateAction<ModalState<ModerationConfig> | null>> | setShowModerationSettingModal: Dispatch<SetStateAction<ModalState<ModerationConfig> | null>> | ||||
| setShowExternalDataToolModal: Dispatch<SetStateAction<ModalState<ExternalDataTool> | null>> | setShowExternalDataToolModal: Dispatch<SetStateAction<ModalState<ExternalDataTool> | null>> | ||||
| setShowPricingModal: Dispatch<SetStateAction<any>> | |||||
| setShowPricingModal: () => void | |||||
| setShowAnnotationFullModal: () => void | setShowAnnotationFullModal: () => void | ||||
| setShowModelModal: Dispatch<SetStateAction<ModalState<ModelModalType> | null>> | setShowModelModal: Dispatch<SetStateAction<ModalState<ModelModalType> | null>> | ||||
| }>({ | }>({ | ||||
| setShowExternalDataToolModal: () => { }, | setShowExternalDataToolModal: () => { }, | ||||
| setShowPricingModal: () => { }, | setShowPricingModal: () => { }, | ||||
| setShowAnnotationFullModal: () => { }, | setShowAnnotationFullModal: () => { }, | ||||
| setShowModelModal: () => {}, | |||||
| setShowModelModal: () => { }, | |||||
| }) | }) | ||||
| export const useModalContext = () => useContext(ModalContext) | export const useModalContext = () => useContext(ModalContext) |
| talkToSales: 'Talk to Sales', | talkToSales: 'Talk to Sales', | ||||
| modelProviders: 'Model Providers', | modelProviders: 'Model Providers', | ||||
| teamMembers: 'Team Members', | teamMembers: 'Team Members', | ||||
| annotationQuota: 'Annotation Quota', | |||||
| buildApps: 'Build Apps', | buildApps: 'Build Apps', | ||||
| vectorSpace: 'Vector Space', | vectorSpace: 'Vector Space', | ||||
| vectorSpaceBillingTooltip: 'Each 1MB can store about 1.2million characters of vectorized data(estimated using OpenAI Embeddings, varies across models).', | vectorSpaceBillingTooltip: 'Each 1MB can store about 1.2million characters of vectorized data(estimated using OpenAI Embeddings, varies across models).', |
| modelProviders: '支持的模型提供商', | modelProviders: '支持的模型提供商', | ||||
| teamMembers: '团队成员', | teamMembers: '团队成员', | ||||
| buildApps: '构建应用程序数', | buildApps: '构建应用程序数', | ||||
| annotationQuota: '标注回复数', | |||||
| vectorSpace: '向量空间', | vectorSpace: '向量空间', | ||||
| vectorSpaceTooltip: '向量空间是 LLMs 理解您的数据所需的长期记忆系统。', | vectorSpaceTooltip: '向量空间是 LLMs 理解您的数据所需的长期记忆系统。', | ||||
| vectorSpaceBillingTooltip: '向量存储是将知识库向量化处理后为让 LLMs 理解数据而使用的长期记忆存储,1MB 大约能满足1.2 million character 的向量化后数据存储(以 OpenAI Embedding 模型估算,不同模型计算方式有差异)。在向量化过程中,实际的压缩或尺寸减小取决于内容的复杂性和冗余性。', | vectorSpaceBillingTooltip: '向量存储是将知识库向量化处理后为让 LLMs 理解数据而使用的长期记忆存储,1MB 大约能满足1.2 million character 的向量化后数据存储(以 OpenAI Embedding 模型估算,不同模型计算方式有差异)。在向量化过程中,实际的压缩或尺寸减小取决于内容的复杂性和冗余性。', |