mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
chore(web): new lint setup (#30020)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
@@ -16,18 +16,19 @@ const ApiServer: FC<ApiServerProps> = ({
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex flex-wrap items-center gap-y-2'>
|
||||
<div className='mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-components-input-border-active bg-components-input-bg-normal pl-1.5 pr-1 leading-5'>
|
||||
<div className='mr-0.5 h-5 shrink-0 rounded-md border border-divider-subtle px-1.5 text-[11px] text-text-tertiary'>{t('appApi.apiServer')}</div>
|
||||
<div className='w-fit truncate px-1 text-[13px] font-medium text-text-secondary sm:w-[248px]'>{apiBaseUrl}</div>
|
||||
<div className='mx-1 h-[14px] w-[1px] bg-divider-regular'></div>
|
||||
<CopyFeedback content={apiBaseUrl}/>
|
||||
<div className="flex flex-wrap items-center gap-y-2">
|
||||
<div className="mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-components-input-border-active bg-components-input-bg-normal pl-1.5 pr-1 leading-5">
|
||||
<div className="mr-0.5 h-5 shrink-0 rounded-md border border-divider-subtle px-1.5 text-[11px] text-text-tertiary">{t('appApi.apiServer')}</div>
|
||||
<div className="w-fit truncate px-1 text-[13px] font-medium text-text-secondary sm:w-[248px]">{apiBaseUrl}</div>
|
||||
<div className="mx-1 h-[14px] w-[1px] bg-divider-regular"></div>
|
||||
<CopyFeedback content={apiBaseUrl} />
|
||||
</div>
|
||||
<div className='mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-[#D1FADF] bg-[#ECFDF3] px-3 text-xs font-semibold text-[#039855]'>
|
||||
<div className="mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-[#D1FADF] bg-[#ECFDF3] px-3 text-xs font-semibold text-[#039855]">
|
||||
{t('appApi.ok')}
|
||||
</div>
|
||||
<SecretKeyButton
|
||||
className='!h-8 shrink-0' appId={appId}
|
||||
className="!h-8 shrink-0"
|
||||
appId={appId}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
'use client'
|
||||
import type { PropsWithChildren, ReactElement, ReactNode } from 'react'
|
||||
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react'
|
||||
import {
|
||||
Children,
|
||||
createContext,
|
||||
@@ -7,11 +9,9 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react'
|
||||
import { Tag } from './tag'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { writeTextToClipboard } from '@/utils/clipboard'
|
||||
import type { PropsWithChildren, ReactElement, ReactNode } from 'react'
|
||||
import { Tag } from './tag'
|
||||
|
||||
type IChildrenProps = {
|
||||
children: React.ReactNode
|
||||
@@ -50,10 +50,9 @@ function CopyButton({ code }: { code: string }) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={cn('group/button absolute right-4 top-1.5 overflow-hidden rounded-full py-1 pl-2 pr-3 text-2xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100',
|
||||
copied
|
||||
? 'bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20'
|
||||
: 'hover:bg-white/7.5 dark:bg-white/2.5 bg-white/5 dark:hover:bg-white/5')}
|
||||
className={cn('group/button absolute right-4 top-1.5 overflow-hidden rounded-full py-1 pl-2 pr-3 text-2xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100', copied
|
||||
? 'bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20'
|
||||
: 'hover:bg-white/7.5 dark:bg-white/2.5 bg-white/5 dark:hover:bg-white/5')}
|
||||
onClick={() => {
|
||||
writeTextToClipboard(code).then(() => {
|
||||
setCopyCount(count => count + 1)
|
||||
@@ -62,16 +61,14 @@ function CopyButton({ code }: { code: string }) {
|
||||
>
|
||||
<span
|
||||
aria-hidden={copied}
|
||||
className={cn('pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300',
|
||||
copied && '-translate-y-1.5 opacity-0')}
|
||||
className={cn('pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300', copied && '-translate-y-1.5 opacity-0')}
|
||||
>
|
||||
<ClipboardIcon className="h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" />
|
||||
Copy
|
||||
</span>
|
||||
<span
|
||||
aria-hidden={!copied}
|
||||
className={cn('pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300',
|
||||
!copied && 'translate-y-1.5 opacity-0')}
|
||||
className={cn('pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300', !copied && 'translate-y-1.5 opacity-0')}
|
||||
>
|
||||
Copied!
|
||||
</span>
|
||||
@@ -79,7 +76,7 @@ function CopyButton({ code }: { code: string }) {
|
||||
)
|
||||
}
|
||||
|
||||
function CodePanelHeader({ tag, label }: { tag?: string; label?: string }) {
|
||||
function CodePanelHeader({ tag, label }: { tag?: string, label?: string }) {
|
||||
if (!tag && !label)
|
||||
return null
|
||||
|
||||
@@ -129,11 +126,13 @@ function CodePanel({ tag, label, children, targetCode }: ICodePanelProps) {
|
||||
{/* <CopyButton code={child.props.code ?? code} /> */}
|
||||
{/* <CopyButton code={child.props.children.props.children} /> */}
|
||||
<pre className="overflow-x-auto p-4 text-xs text-white">
|
||||
{targetCode?.code ? (
|
||||
<code>{targetCode?.code}</code>
|
||||
) : (
|
||||
child
|
||||
)}
|
||||
{targetCode?.code
|
||||
? (
|
||||
<code>{targetCode?.code}</code>
|
||||
)
|
||||
: (
|
||||
child
|
||||
)}
|
||||
</pre>
|
||||
<CopyButton code={targetCode?.code ?? child.props.children.props.children} />
|
||||
</div>
|
||||
@@ -162,10 +161,9 @@ function CodeGroupHeader({ title, tabTitles, selectedIndex }: CodeGroupHeaderPro
|
||||
{tabTitles!.map((tabTitle, tabIndex) => (
|
||||
<Tab
|
||||
key={tabIndex}
|
||||
className={cn('border-b py-3 transition focus:[&:not(:focus-visible)]:outline-none',
|
||||
tabIndex === selectedIndex
|
||||
? 'border-emerald-500 text-emerald-400'
|
||||
: 'border-transparent text-zinc-400 hover:text-zinc-300')}
|
||||
className={cn('border-b py-3 transition focus:[&:not(:focus-visible)]:outline-none', tabIndex === selectedIndex
|
||||
? 'border-emerald-500 text-emerald-400'
|
||||
: 'border-transparent text-zinc-400 hover:text-zinc-300')}
|
||||
>
|
||||
{tabTitle}
|
||||
</Tab>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
'use client'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiCloseLine, RiListUnordered } from '@remixicon/react'
|
||||
import TemplateEn from './template/template.en.mdx'
|
||||
import TemplateZh from './template/template.zh.mdx'
|
||||
import TemplateJa from './template/template.ja.mdx'
|
||||
import TemplateAdvancedChatEn from './template/template_advanced_chat.en.mdx'
|
||||
import TemplateAdvancedChatZh from './template/template_advanced_chat.zh.mdx'
|
||||
import TemplateAdvancedChatJa from './template/template_advanced_chat.ja.mdx'
|
||||
import TemplateWorkflowEn from './template/template_workflow.en.mdx'
|
||||
import TemplateWorkflowZh from './template/template_workflow.zh.mdx'
|
||||
import TemplateWorkflowJa from './template/template_workflow.ja.mdx'
|
||||
import TemplateChatEn from './template/template_chat.en.mdx'
|
||||
import TemplateChatZh from './template/template_chat.zh.mdx'
|
||||
import TemplateChatJa from './template/template_chat.ja.mdx'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import I18n from '@/context/i18n'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import { AppModeEnum, Theme } from '@/types/app'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import TemplateEn from './template/template.en.mdx'
|
||||
import TemplateJa from './template/template.ja.mdx'
|
||||
import TemplateZh from './template/template.zh.mdx'
|
||||
import TemplateAdvancedChatEn from './template/template_advanced_chat.en.mdx'
|
||||
import TemplateAdvancedChatJa from './template/template_advanced_chat.ja.mdx'
|
||||
import TemplateAdvancedChatZh from './template/template_advanced_chat.zh.mdx'
|
||||
import TemplateChatEn from './template/template_chat.en.mdx'
|
||||
import TemplateChatJa from './template/template_chat.ja.mdx'
|
||||
import TemplateChatZh from './template/template_chat.zh.mdx'
|
||||
import TemplateWorkflowEn from './template/template_workflow.en.mdx'
|
||||
import TemplateWorkflowJa from './template/template_workflow.ja.mdx'
|
||||
import TemplateWorkflowZh from './template/template_workflow.zh.mdx'
|
||||
|
||||
type IDocProps = {
|
||||
appDetail: any
|
||||
@@ -28,7 +28,7 @@ type IDocProps = {
|
||||
const Doc = ({ appDetail }: IDocProps) => {
|
||||
const { locale } = useContext(I18n)
|
||||
const { t } = useTranslation()
|
||||
const [toc, setToc] = useState<Array<{ href: string; text: string }>>([])
|
||||
const [toc, setToc] = useState<Array<{ href: string, text: string }>>([])
|
||||
const [isTocExpanded, setIsTocExpanded] = useState(false)
|
||||
const [activeSection, setActiveSection] = useState<string>('')
|
||||
const { theme } = useTheme()
|
||||
@@ -58,7 +58,7 @@ const Doc = ({ appDetail }: IDocProps) => {
|
||||
}
|
||||
}
|
||||
return null
|
||||
}).filter((item): item is { href: string; text: string } => item !== null)
|
||||
}).filter((item): item is { href: string, text: string } => item !== null)
|
||||
setToc(tocItems)
|
||||
if (tocItems.length > 0)
|
||||
setActiveSection(tocItems[0].href.replace('#', ''))
|
||||
@@ -97,7 +97,7 @@ const Doc = ({ appDetail }: IDocProps) => {
|
||||
}
|
||||
}, [toc, activeSection])
|
||||
|
||||
const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string; text: string }) => {
|
||||
const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string, text: string }) => {
|
||||
e.preventDefault()
|
||||
const targetId = item.href.replace('#', '')
|
||||
const element = document.getElementById(targetId)
|
||||
@@ -163,75 +163,79 @@ const Doc = ({ appDetail }: IDocProps) => {
|
||||
<div className={`fixed right-20 top-32 z-10 transition-all duration-150 ease-out ${isTocExpanded ? 'w-[280px]' : 'w-11'}`}>
|
||||
{isTocExpanded
|
||||
? (
|
||||
<nav className="toc flex max-h-[calc(100vh-150px)] w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-background-default-hover shadow-xl">
|
||||
<div className="relative z-10 flex items-center justify-between border-b border-components-panel-border-subtle bg-background-default-hover px-4 py-2.5">
|
||||
<span className="text-xs font-medium uppercase tracking-wide text-text-tertiary">
|
||||
{t('appApi.develop.toc')}
|
||||
</span>
|
||||
<button type="button"
|
||||
onClick={() => setIsTocExpanded(false)}
|
||||
className="group flex h-6 w-6 items-center justify-center rounded-md transition-colors hover:bg-state-base-hover"
|
||||
aria-label="Close"
|
||||
>
|
||||
<RiCloseLine className="h-3 w-3 text-text-quaternary transition-colors group-hover:text-text-secondary" />
|
||||
</button>
|
||||
</div>
|
||||
<nav className="toc flex max-h-[calc(100vh-150px)] w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-background-default-hover shadow-xl">
|
||||
<div className="relative z-10 flex items-center justify-between border-b border-components-panel-border-subtle bg-background-default-hover px-4 py-2.5">
|
||||
<span className="text-xs font-medium uppercase tracking-wide text-text-tertiary">
|
||||
{t('appApi.develop.toc')}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsTocExpanded(false)}
|
||||
className="group flex h-6 w-6 items-center justify-center rounded-md transition-colors hover:bg-state-base-hover"
|
||||
aria-label="Close"
|
||||
>
|
||||
<RiCloseLine className="h-3 w-3 text-text-quaternary transition-colors group-hover:text-text-secondary" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="from-components-panel-border-subtle/20 pointer-events-none absolute left-0 right-0 top-[41px] z-10 h-2 bg-gradient-to-b to-transparent"></div>
|
||||
<div className="pointer-events-none absolute left-0 right-0 top-[43px] z-10 h-3 bg-gradient-to-b from-background-default-hover to-transparent"></div>
|
||||
<div className="from-components-panel-border-subtle/20 pointer-events-none absolute left-0 right-0 top-[41px] z-10 h-2 bg-gradient-to-b to-transparent"></div>
|
||||
<div className="pointer-events-none absolute left-0 right-0 top-[43px] z-10 h-3 bg-gradient-to-b from-background-default-hover to-transparent"></div>
|
||||
|
||||
<div className="relative flex-1 overflow-y-auto px-3 py-3 pt-1">
|
||||
{toc.length === 0 ? (
|
||||
<div className="px-2 py-8 text-center text-xs text-text-quaternary">
|
||||
{t('appApi.develop.noContent')}
|
||||
</div>
|
||||
) : (
|
||||
<ul className="space-y-0.5">
|
||||
{toc.map((item, index) => {
|
||||
const isActive = activeSection === item.href.replace('#', '')
|
||||
return (
|
||||
<li key={index}>
|
||||
<a
|
||||
href={item.href}
|
||||
onClick={e => handleTocClick(e, item)}
|
||||
className={cn(
|
||||
'group relative flex items-center rounded-md px-3 py-2 text-[13px] transition-all duration-200',
|
||||
isActive
|
||||
? 'bg-state-base-hover font-medium text-text-primary'
|
||||
: 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'mr-2 h-1.5 w-1.5 rounded-full transition-all duration-200',
|
||||
isActive
|
||||
? 'scale-100 bg-text-accent'
|
||||
: 'scale-75 bg-components-panel-border',
|
||||
)}
|
||||
/>
|
||||
<span className="flex-1 truncate">
|
||||
{item.text}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<div className="relative flex-1 overflow-y-auto px-3 py-3 pt-1">
|
||||
{toc.length === 0
|
||||
? (
|
||||
<div className="px-2 py-8 text-center text-xs text-text-quaternary">
|
||||
{t('appApi.develop.noContent')}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
: (
|
||||
<ul className="space-y-0.5">
|
||||
{toc.map((item, index) => {
|
||||
const isActive = activeSection === item.href.replace('#', '')
|
||||
return (
|
||||
<li key={index}>
|
||||
<a
|
||||
href={item.href}
|
||||
onClick={e => handleTocClick(e, item)}
|
||||
className={cn(
|
||||
'group relative flex items-center rounded-md px-3 py-2 text-[13px] transition-all duration-200',
|
||||
isActive
|
||||
? 'bg-state-base-hover font-medium text-text-primary'
|
||||
: 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'mr-2 h-1.5 w-1.5 rounded-full transition-all duration-200',
|
||||
isActive
|
||||
? 'scale-100 bg-text-accent'
|
||||
: 'scale-75 bg-components-panel-border',
|
||||
)}
|
||||
/>
|
||||
<span className="flex-1 truncate">
|
||||
{item.text}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-4 rounded-b-xl bg-gradient-to-t from-background-default-hover to-transparent"></div>
|
||||
</nav>
|
||||
)
|
||||
<div className="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-4 rounded-b-xl bg-gradient-to-t from-background-default-hover to-transparent"></div>
|
||||
</nav>
|
||||
)
|
||||
: (
|
||||
<button type="button"
|
||||
onClick={() => setIsTocExpanded(true)}
|
||||
className="group flex h-11 w-11 items-center justify-center rounded-full border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg transition-all duration-150 hover:bg-background-default-hover hover:shadow-xl"
|
||||
aria-label="Open table of contents"
|
||||
>
|
||||
<RiListUnordered className="h-5 w-5 text-text-tertiary transition-colors group-hover:text-text-secondary" />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsTocExpanded(true)}
|
||||
className="group flex h-11 w-11 items-center justify-center rounded-full border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg transition-all duration-150 hover:bg-background-default-hover hover:shadow-xl"
|
||||
aria-label="Open table of contents"
|
||||
>
|
||||
<RiListUnordered className="h-5 w-5 text-text-tertiary transition-colors group-hover:text-text-secondary" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<article className={cn('prose-xl prose', theme === Theme.dark && 'prose-invert')}>
|
||||
{Template}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import Doc from '@/app/components/develop/doc'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import ApiServer from '@/app/components/develop/ApiServer'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Doc from '@/app/components/develop/doc'
|
||||
|
||||
type IDevelopMainProps = {
|
||||
appId: string
|
||||
@@ -13,19 +13,19 @@ const DevelopMain = ({ appId }: IDevelopMainProps) => {
|
||||
|
||||
if (!appDetail) {
|
||||
return (
|
||||
<div className='flex h-full items-center justify-center bg-background-default'>
|
||||
<div className="flex h-full items-center justify-center bg-background-default">
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='relative flex h-full flex-col overflow-hidden'>
|
||||
<div className='flex shrink-0 items-center justify-between border-b border-solid border-b-divider-regular px-6 py-2'>
|
||||
<div className='text-lg font-medium text-text-primary'></div>
|
||||
<div className="relative flex h-full flex-col overflow-hidden">
|
||||
<div className="flex shrink-0 items-center justify-between border-b border-solid border-b-divider-regular px-6 py-2">
|
||||
<div className="text-lg font-medium text-text-primary"></div>
|
||||
<ApiServer apiBaseUrl={appDetail.api_base_url} appId={appId} />
|
||||
</div>
|
||||
<div className='grow overflow-auto px-4 py-4 sm:px-10'>
|
||||
<div className="grow overflow-auto px-4 py-4 sm:px-10">
|
||||
<Doc appDetail={appDetail} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,14 +43,14 @@ export const Heading = function H2({
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<span id={name?.replace(/^#/, '')} className='relative -top-28' />
|
||||
<div className="flex items-center gap-x-3" >
|
||||
<span id={name?.replace(/^#/, '')} className="relative -top-28" />
|
||||
<div className="flex items-center gap-x-3">
|
||||
<span className={`rounded-lg px-1.5 font-mono text-[0.625rem] font-semibold leading-6 ring-1 ring-inset ${style}`}>{method}</span>
|
||||
{/* <span className="h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600"></span> */}
|
||||
<span className="font-mono text-xs text-zinc-400">{url}</span>
|
||||
</div>
|
||||
<h2 className='mt-2 scroll-mt-32'>
|
||||
<a href={name} className='group text-inherit no-underline hover:text-inherit'>{title}</a>
|
||||
<h2 className="mt-2 scroll-mt-32">
|
||||
<a href={name} className="group text-inherit no-underline hover:text-inherit">{title}</a>
|
||||
</h2>
|
||||
</>
|
||||
|
||||
@@ -71,8 +71,7 @@ type IColProps = IChildrenProps & {
|
||||
export function Col({ children, sticky = false }: IColProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn('[&>:first-child]:mt-0 [&>:last-child]:mb-0',
|
||||
sticky && 'xl:sticky xl:top-24')}
|
||||
className={cn('[&>:first-child]:mt-0 [&>:last-child]:mb-0', sticky && 'xl:sticky xl:top-24')}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { t } from 'i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type IInputCopyProps = {
|
||||
value?: string
|
||||
@@ -34,21 +34,24 @@ const InputCopy = ({
|
||||
<div className={`flex items-center rounded-lg bg-components-input-bg-normal py-2 hover:bg-state-base-hover ${className}`}>
|
||||
<div className="flex h-5 grow items-center">
|
||||
{children}
|
||||
<div className='relative h-full grow text-[13px]'>
|
||||
<div className='r-0 absolute left-0 top-0 w-full cursor-pointer truncate pl-2 pr-2' onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}>
|
||||
<div className="relative h-full grow text-[13px]">
|
||||
<div
|
||||
className="r-0 absolute left-0 top-0 w-full cursor-pointer truncate pl-2 pr-2"
|
||||
onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
|
||||
position='bottom'
|
||||
position="bottom"
|
||||
>
|
||||
<span className='text-text-secondary'>{value}</span>
|
||||
<span className="text-text-secondary">{value}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-4 w-px shrink-0 bg-divider-regular" />
|
||||
<div className='mx-1'><CopyFeedback content={value} /></div>
|
||||
<div className="mx-1"><CopyFeedback content={value} /></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import { RiKey2Line } from '@remixicon/react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiKey2Line } from '@remixicon/react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal'
|
||||
|
||||
@@ -19,11 +19,11 @@ const SecretKeyButton = ({ className, appId, textCls }: ISecretKeyButtonProps) =
|
||||
<Button
|
||||
className={`px-3 ${className}`}
|
||||
onClick={() => setVisible(true)}
|
||||
size='small'
|
||||
variant='ghost'
|
||||
size="small"
|
||||
variant="ghost"
|
||||
>
|
||||
<div className={'flex h-3.5 w-3.5 items-center justify-center'}>
|
||||
<RiKey2Line className='h-3.5 w-3.5 text-text-tertiary' />
|
||||
<div className="flex h-3.5 w-3.5 items-center justify-center">
|
||||
<RiKey2Line className="h-3.5 w-3.5 text-text-tertiary" />
|
||||
</div>
|
||||
<div className={`system-xs-medium px-[3px] text-text-tertiary ${textCls}`}>{t('appApi.apiKey')}</div>
|
||||
</Button>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import InputCopy from './input-copy'
|
||||
import s from './style.module.css'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import InputCopy from './input-copy'
|
||||
import s from './style.module.css'
|
||||
|
||||
type ISecretKeyGenerateModalProps = {
|
||||
isShow: boolean
|
||||
@@ -26,17 +26,17 @@ const SecretKeyGenerateModal = ({
|
||||
<div className="-mr-2 -mt-6 mb-4 flex justify-end">
|
||||
<XMarkIcon className="h-6 w-6 cursor-pointer text-text-tertiary" onClick={onClose} />
|
||||
</div>
|
||||
<p className='mt-1 text-[13px] font-normal leading-5 text-text-tertiary'>{t('appApi.apiKeyModal.generateTips')}</p>
|
||||
<div className='my-4'>
|
||||
<InputCopy className='w-full' value={newKey?.token} />
|
||||
<p className="mt-1 text-[13px] font-normal leading-5 text-text-tertiary">{t('appApi.apiKeyModal.generateTips')}</p>
|
||||
<div className="my-4">
|
||||
<InputCopy className="w-full" value={newKey?.token} />
|
||||
</div>
|
||||
<div className='my-4 flex justify-end'>
|
||||
<div className="my-4 flex justify-end">
|
||||
<Button className={`shrink-0 ${s.w64}`} onClick={onClose}>
|
||||
<span className='text-xs font-medium text-text-secondary'>{t('appApi.actionMsg.ok')}</span>
|
||||
<span className="text-xs font-medium text-text-secondary">{t('appApi.actionMsg.ok')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</Modal >
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
'use client'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import { PlusIcon, XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import { RiDeleteBinLine } from '@remixicon/react'
|
||||
import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiDeleteBinLine } from '@remixicon/react'
|
||||
import { PlusIcon, XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import SecretKeyGenerateModal from './secret-key-generate'
|
||||
import s from './style.module.css'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import {
|
||||
createApikey as createAppApikey,
|
||||
delApikey as delAppApikey,
|
||||
@@ -19,13 +22,10 @@ import {
|
||||
createApikey as createDatasetApikey,
|
||||
delApikey as delDatasetApikey,
|
||||
} from '@/service/datasets'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useAppApiKeys, useInvalidateAppApiKeys } from '@/service/use-apps'
|
||||
import { useDatasetApiKeys, useInvalidateDatasetApiKeys } from '@/service/knowledge/use-dataset'
|
||||
import { useAppApiKeys, useInvalidateAppApiKeys } from '@/service/use-apps'
|
||||
import SecretKeyGenerateModal from './secret-key-generate'
|
||||
import s from './style.module.css'
|
||||
|
||||
type ISecretKeyModalProps = {
|
||||
isShow: boolean
|
||||
@@ -92,24 +92,24 @@ const SecretKeyModal = ({
|
||||
<div className="-mr-2 -mt-6 mb-4 flex justify-end">
|
||||
<XMarkIcon className="h-6 w-6 cursor-pointer text-text-tertiary" onClick={onClose} />
|
||||
</div>
|
||||
<p className='mt-1 shrink-0 text-[13px] font-normal leading-5 text-text-tertiary'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
|
||||
{isApiKeysLoading && <div className='mt-4'><Loading /></div>}
|
||||
<p className="mt-1 shrink-0 text-[13px] font-normal leading-5 text-text-tertiary">{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
|
||||
{isApiKeysLoading && <div className="mt-4"><Loading /></div>}
|
||||
{
|
||||
!!apiKeysList?.data?.length && (
|
||||
<div className='mt-4 flex grow flex-col overflow-hidden'>
|
||||
<div className='flex h-9 shrink-0 items-center border-b border-divider-regular text-xs font-semibold text-text-tertiary'>
|
||||
<div className='w-64 shrink-0 px-3'>{t('appApi.apiKeyModal.secretKey')}</div>
|
||||
<div className='w-[200px] shrink-0 px-3'>{t('appApi.apiKeyModal.created')}</div>
|
||||
<div className='w-[200px] shrink-0 px-3'>{t('appApi.apiKeyModal.lastUsed')}</div>
|
||||
<div className='grow px-3'></div>
|
||||
<div className="mt-4 flex grow flex-col overflow-hidden">
|
||||
<div className="flex h-9 shrink-0 items-center border-b border-divider-regular text-xs font-semibold text-text-tertiary">
|
||||
<div className="w-64 shrink-0 px-3">{t('appApi.apiKeyModal.secretKey')}</div>
|
||||
<div className="w-[200px] shrink-0 px-3">{t('appApi.apiKeyModal.created')}</div>
|
||||
<div className="w-[200px] shrink-0 px-3">{t('appApi.apiKeyModal.lastUsed')}</div>
|
||||
<div className="grow px-3"></div>
|
||||
</div>
|
||||
<div className='grow overflow-auto'>
|
||||
<div className="grow overflow-auto">
|
||||
{apiKeysList.data.map(api => (
|
||||
<div className='flex h-9 items-center border-b border-divider-regular text-sm font-normal text-text-secondary' key={api.id}>
|
||||
<div className='w-64 shrink-0 truncate px-3 font-mono'>{generateToken(api.token)}</div>
|
||||
<div className='w-[200px] shrink-0 truncate px-3'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div>
|
||||
<div className='w-[200px] shrink-0 truncate px-3'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div>
|
||||
<div className='flex grow space-x-2 px-3'>
|
||||
<div className="flex h-9 items-center border-b border-divider-regular text-sm font-normal text-text-secondary" key={api.id}>
|
||||
<div className="w-64 shrink-0 truncate px-3 font-mono">{generateToken(api.token)}</div>
|
||||
<div className="w-[200px] shrink-0 truncate px-3">{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div>
|
||||
<div className="w-[200px] shrink-0 truncate px-3">{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div>
|
||||
<div className="flex grow space-x-2 px-3">
|
||||
<CopyFeedback content={api.token} />
|
||||
{isCurrentWorkspaceManager && (
|
||||
<ActionButton
|
||||
@@ -118,7 +118,7 @@ const SecretKeyModal = ({
|
||||
setShowConfirmDelete(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
<RiDeleteBinLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
@@ -128,13 +128,13 @@ const SecretKeyModal = ({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='flex'>
|
||||
<div className="flex">
|
||||
<Button className={`mt-4 flex shrink-0 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}>
|
||||
<PlusIcon className='mr-1 flex h-4 w-4 shrink-0' />
|
||||
<div className='text-xs font-medium text-text-secondary'>{t('appApi.apiKeyModal.createNewSecretKey')}</div>
|
||||
<PlusIcon className="mr-1 flex h-4 w-4 shrink-0" />
|
||||
<div className="text-xs font-medium text-text-secondary">{t('appApi.apiKeyModal.createNewSecretKey')}</div>
|
||||
</Button>
|
||||
</div>
|
||||
<SecretKeyGenerateModal className='shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
|
||||
<SecretKeyGenerateModal className="shrink-0" isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
|
||||
{showConfirmDelete && (
|
||||
<Confirm
|
||||
title={`${t('appApi.actionMsg.deleteConfirmTitle')}`}
|
||||
@@ -147,7 +147,7 @@ const SecretKeyModal = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Modal >
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@ export function Tag({
|
||||
}: ITagProps) {
|
||||
return (
|
||||
<span
|
||||
className={cn('font-mono text-[0.625rem] font-semibold leading-6',
|
||||
variantStyles[variant],
|
||||
colorStyles[color][variant])}
|
||||
className={cn('font-mono text-[0.625rem] font-semibold leading-6', variantStyles[variant], colorStyles[color][variant])}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user