chore: remove frontend changes

This commit is contained in:
Novice
2025-12-30 10:19:40 +08:00
parent f55faae31b
commit 56c8221b3f
4921 changed files with 308906 additions and 230467 deletions

View File

@ -1,5 +1,6 @@
import type { AutoUpdateConfig } from './types'
import { AUTO_UPDATE_MODE, AUTO_UPDATE_STRATEGY } from './types'
export const defaultValue: AutoUpdateConfig = {
strategy_setting: AUTO_UPDATE_STRATEGY.disabled,
upgrade_time_of_day: 0,

View File

@ -1,23 +1,25 @@
'use client'
import type { FC } from 'react'
import React, { useCallback, useMemo } from 'react'
import { AUTO_UPDATE_MODE, AUTO_UPDATE_STRATEGY, type AutoUpdateConfig } from './types'
import Label from '../label'
import StrategyPicker from './strategy-picker'
import { Trans, useTranslation } from 'react-i18next'
import TimePicker from '@/app/components/base/date-and-time-picker/time-picker'
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
import PluginsPicker from './plugins-picker'
import { convertLocalSecondsToUTCDaySeconds, convertUTCDaySecondsToLocalSeconds, dayjsToTimeOfDay, timeOfDayToDayjs } from './utils'
import { useAppContext } from '@/context/app-context'
import type { AutoUpdateConfig } from './types'
import type { TriggerParams } from '@/app/components/base/date-and-time-picker/types'
import { RiTimeLine } from '@remixicon/react'
import cn from '@/utils/classnames'
import * as React from 'react'
import { useCallback, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import TimePicker from '@/app/components/base/date-and-time-picker/time-picker'
import { convertTimezoneToOffsetStr } from '@/app/components/base/date-and-time-picker/utils/dayjs'
import { useModalContextSelector } from '@/context/modal-context'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
import { useAppContext } from '@/context/app-context'
import { useModalContextSelector } from '@/context/modal-context'
import { cn } from '@/utils/classnames'
import Label from '../label'
import PluginsPicker from './plugins-picker'
import StrategyPicker from './strategy-picker'
import { AUTO_UPDATE_MODE, AUTO_UPDATE_STRATEGY } from './types'
import { convertLocalSecondsToUTCDaySeconds, convertUTCDaySecondsToLocalSeconds, dayjsToTimeOfDay, timeOfDayToDayjs } from './utils'
const i18nPrefix = 'plugin.autoUpdate'
const i18nPrefix = 'autoUpdate'
type Props = {
payload: AutoUpdateConfig
@ -31,7 +33,7 @@ const SettingTimeZone: FC<{
}) => {
const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal)
return (
<span className='body-xs-regular cursor-pointer text-text-accent' onClick={() => setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.LANGUAGE })} >{children}</span>
<span className="body-xs-regular cursor-pointer text-text-accent" onClick={() => setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.LANGUAGE })}>{children}</span>
)
}
const AutoUpdateSetting: FC<Props> = ({
@ -58,9 +60,9 @@ const AutoUpdateSetting: FC<Props> = ({
const strategyDescription = useMemo(() => {
switch (strategy_setting) {
case AUTO_UPDATE_STRATEGY.fixOnly:
return t(`${i18nPrefix}.strategy.fixOnly.selectedDescription`)
return t(`${i18nPrefix}.strategy.fixOnly.selectedDescription`, { ns: 'plugin' })
case AUTO_UPDATE_STRATEGY.latest:
return t(`${i18nPrefix}.strategy.latest.selectedDescription`)
return t(`${i18nPrefix}.strategy.latest.selectedDescription`, { ns: 'plugin' })
default:
return ''
}
@ -103,50 +105,51 @@ const AutoUpdateSetting: FC<Props> = ({
const renderTimePickerTrigger = useCallback(({ inputElem, onClick, isOpen }: TriggerParams) => {
return (
<div
className='group float-right flex h-8 w-[160px] cursor-pointer items-center justify-between rounded-lg bg-components-input-bg-normal px-2 hover:bg-state-base-hover-alt'
className="group float-right flex h-8 w-[160px] cursor-pointer items-center justify-between rounded-lg bg-components-input-bg-normal px-2 hover:bg-state-base-hover-alt"
onClick={onClick}
>
<div className='flex w-0 grow items-center gap-x-1'>
<div className="flex w-0 grow items-center gap-x-1">
<RiTimeLine className={cn(
'h-4 w-4 shrink-0 text-text-tertiary',
isOpen ? 'text-text-secondary' : 'group-hover:text-text-secondary',
)} />
)}
/>
{inputElem}
</div>
<div className='system-sm-regular text-text-tertiary'>{convertTimezoneToOffsetStr(timezone)}</div>
<div className="system-sm-regular text-text-tertiary">{convertTimezoneToOffsetStr(timezone)}</div>
</div>
)
}, [timezone])
return (
<div className='self-stretch px-6'>
<div className='my-3 flex items-center'>
<div className='system-xs-medium-uppercase text-text-tertiary'>{t(`${i18nPrefix}.updateSettings`)}</div>
<div className='ml-2 h-px grow bg-divider-subtle'></div>
<div className="self-stretch px-6">
<div className="my-3 flex items-center">
<div className="system-xs-medium-uppercase text-text-tertiary">{t(`${i18nPrefix}.updateSettings`, { ns: 'plugin' })}</div>
<div className="ml-2 h-px grow bg-divider-subtle"></div>
</div>
<div className='space-y-4'>
<div className='flex items-center justify-between'>
<Label label={t(`${i18nPrefix}.automaticUpdates`)} description={strategyDescription} />
<div className="space-y-4">
<div className="flex items-center justify-between">
<Label label={t(`${i18nPrefix}.automaticUpdates`, { ns: 'plugin' })} description={strategyDescription} />
<StrategyPicker value={strategy_setting} onChange={handleChange('strategy_setting')} />
</div>
{strategy_setting !== AUTO_UPDATE_STRATEGY.disabled && (
<>
<div className='flex items-center justify-between'>
<Label label={t(`${i18nPrefix}.updateTime`)} />
<div className='flex flex-col justify-start'>
<div className="flex items-center justify-between">
<Label label={t(`${i18nPrefix}.updateTime`, { ns: 'plugin' })} />
<div className="flex flex-col justify-start">
<TimePicker
value={timeOfDayToDayjs(convertUTCDaySecondsToLocalSeconds(upgrade_time_of_day, timezone!))}
timezone={timezone}
onChange={v => handleChange('upgrade_time_of_day')(convertLocalSecondsToUTCDaySeconds(dayjsToTimeOfDay(v), timezone!))}
onClear={() => handleChange('upgrade_time_of_day')(convertLocalSecondsToUTCDaySeconds(0, timezone!))}
popupClassName='z-[99]'
title={t(`${i18nPrefix}.updateTime`)}
popupClassName="z-[99]"
title={t(`${i18nPrefix}.updateTime`, { ns: 'plugin' })}
minuteFilter={minuteFilter}
renderTrigger={renderTimePickerTrigger}
placement='bottom-end'
placement="bottom-end"
/>
<div className='body-xs-regular mt-1 text-right text-text-tertiary'>
<div className="body-xs-regular mt-1 text-right text-text-tertiary">
<Trans
i18nKey={`${i18nPrefix}.changeTimezone`}
components={{
@ -157,12 +160,12 @@ const AutoUpdateSetting: FC<Props> = ({
</div>
</div>
<div>
<Label label={t(`${i18nPrefix}.specifyPluginsToUpdate`)} />
<div className='mt-1 flex w-full items-start justify-between gap-2'>
<Label label={t(`${i18nPrefix}.specifyPluginsToUpdate`, { ns: 'plugin' })} />
<div className="mt-1 flex w-full items-start justify-between gap-2">
{[AUTO_UPDATE_MODE.update_all, AUTO_UPDATE_MODE.exclude, AUTO_UPDATE_MODE.partial].map(option => (
<OptionCard
key={option}
title={t(`${i18nPrefix}.upgradeMode.${option}`)}
title={t(`${i18nPrefix}.upgradeMode.${option}`, { ns: 'plugin' })}
onSelect={() => handleChange('upgrade_mode')(option)}
selected={upgrade_mode === option}
className="flex-1"

View File

@ -1,10 +1,10 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import cn from '@/utils/classnames'
import { Group } from '@/app/components/base/icons/src/vender/other'
import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
import { Group } from '@/app/components/base/icons/src/vender/other'
import { cn } from '@/utils/classnames'
type Props = {
className: string
@ -16,13 +16,13 @@ const NoDataPlaceholder: FC<Props> = ({
noPlugins,
}) => {
const { t } = useTranslation()
const icon = noPlugins ? (<Group className='size-6 text-text-quaternary' />) : (<SearchMenu className='size-8 text-text-tertiary' />)
const text = t(`plugin.autoUpdate.noPluginPlaceholder.${noPlugins ? 'noInstalled' : 'noFound'}`)
const icon = noPlugins ? (<Group className="size-6 text-text-quaternary" />) : (<SearchMenu className="size-8 text-text-tertiary" />)
const text = t(`autoUpdate.noPluginPlaceholder.${noPlugins ? 'noInstalled' : 'noFound'}`, { ns: 'plugin' })
return (
<div className={cn('flex items-center justify-center', className)}>
<div className='flex flex-col items-center'>
<div className="flex flex-col items-center">
{icon}
<div className='system-sm-regular mt-2 text-text-tertiary'>{text}</div>
<div className="system-sm-regular mt-2 text-text-tertiary">{text}</div>
</div>
</div>
)

View File

@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { AUTO_UPDATE_MODE } from './types'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { AUTO_UPDATE_MODE } from './types'
type Props = {
updateMode: AUTO_UPDATE_MODE
@ -12,9 +12,9 @@ const NoPluginSelected: FC<Props> = ({
updateMode,
}) => {
const { t } = useTranslation()
const text = `${t(`plugin.autoUpdate.upgradeModePlaceholder.${updateMode === AUTO_UPDATE_MODE.partial ? 'partial' : 'exclude'}`)}`
const text = `${t(`autoUpdate.upgradeModePlaceholder.${updateMode === AUTO_UPDATE_MODE.partial ? 'partial' : 'exclude'}`, { ns: 'plugin' })}`
return (
<div className='system-xs-regular rounded-[10px] border border-components-option-card-option-border bg-background-section p-3 text-center text-text-tertiary'>
<div className="system-xs-regular rounded-[10px] border border-components-option-card-option-border bg-background-section p-3 text-center text-text-tertiary">
{text}
</div>
)

View File

@ -1,16 +1,16 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import NoPluginSelected from './no-plugin-selected'
import { AUTO_UPDATE_MODE } from './types'
import PluginsSelected from './plugins-selected'
import Button from '@/app/components/base/button'
import { RiAddLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import NoPluginSelected from './no-plugin-selected'
import PluginsSelected from './plugins-selected'
import ToolPicker from './tool-picker'
import { AUTO_UPDATE_MODE } from './types'
const i18nPrefix = 'plugin.autoUpdate'
const i18nPrefix = 'autoUpdate'
type Props = {
updateMode: AUTO_UPDATE_MODE
@ -34,30 +34,32 @@ const PluginsPicker: FC<Props> = ({
set: setToolPicker,
}] = useBoolean(false)
return (
<div className='mt-2 rounded-[10px] bg-background-section-burn p-2.5'>
{hasSelected ? (
<div className='flex justify-between text-text-tertiary'>
<div className='system-xs-medium'>{t(`${i18nPrefix}.${isExcludeMode ? 'excludeUpdate' : 'partialUPdate'}`, { num: value.length })}</div>
<div className='system-xs-medium cursor-pointer' onClick={handleClear}>{t(`${i18nPrefix}.operation.clearAll`)}</div>
</div>
) : (
<NoPluginSelected updateMode={updateMode} />
)}
<div className="mt-2 rounded-[10px] bg-background-section-burn p-2.5">
{hasSelected
? (
<div className="flex justify-between text-text-tertiary">
<div className="system-xs-medium">{t(`${i18nPrefix}.${isExcludeMode ? 'excludeUpdate' : 'partialUPdate'}`, { ns: 'plugin', num: value.length })}</div>
<div className="system-xs-medium cursor-pointer" onClick={handleClear}>{t(`${i18nPrefix}.operation.clearAll`, { ns: 'plugin' })}</div>
</div>
)
: (
<NoPluginSelected updateMode={updateMode} />
)}
{hasSelected && (
<PluginsSelected
className='mt-2'
className="mt-2"
plugins={value}
/>
)}
<ToolPicker
trigger={
<Button className='mt-2 w-full' size='small' variant='secondary-accent'>
<RiAddLine className='size-3.5' />
{t(`${i18nPrefix}.operation.select`)}
trigger={(
<Button className="mt-2 w-full" size="small" variant="secondary-accent">
<RiAddLine className="size-3.5" />
{t(`${i18nPrefix}.operation.select`, { ns: 'plugin' })}
</Button>
}
)}
value={value}
onChange={onChange}
isShow={isShowToolPicker}

View File

@ -1,9 +1,9 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import cn from '@/utils/classnames'
import { MARKETPLACE_API_PREFIX } from '@/config'
import * as React from 'react'
import Icon from '@/app/components/plugins/card/base/card-icon'
import { MARKETPLACE_API_PREFIX } from '@/config'
import { cn } from '@/utils/classnames'
const MAX_DISPLAY_COUNT = 14
type Props = {
@ -20,9 +20,14 @@ const PluginsSelected: FC<Props> = ({
return (
<div className={cn('flex items-center space-x-1', className)}>
{displayPlugins.map(plugin => (
<Icon key={plugin} size='tiny' src={`${MARKETPLACE_API_PREFIX}/plugins/${plugin}/icon`} />
<Icon key={plugin} size="tiny" src={`${MARKETPLACE_API_PREFIX}/plugins/${plugin}/icon`} />
))}
{!isShowAll && <div className='system-xs-medium text-text-tertiary'>+{plugins.length - MAX_DISPLAY_COUNT}</div>}
{!isShowAll && (
<div className="system-xs-medium text-text-tertiary">
+
{plugins.length - MAX_DISPLAY_COUNT}
</div>
)}
</div>
)
}

View File

@ -1,17 +1,18 @@
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
RiArrowDownSLine,
RiCheckLine,
} from '@remixicon/react'
import { AUTO_UPDATE_STRATEGY } from './types'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import Button from '@/app/components/base/button'
const i18nPrefix = 'plugin.autoUpdate.strategy'
import { AUTO_UPDATE_STRATEGY } from './types'
const i18nPrefix = 'autoUpdate.strategy'
type Props = {
value: AUTO_UPDATE_STRATEGY
@ -26,18 +27,18 @@ const StrategyPicker = ({
const options = [
{
value: AUTO_UPDATE_STRATEGY.disabled,
label: t(`${i18nPrefix}.disabled.name`),
description: t(`${i18nPrefix}.disabled.description`),
label: t(`${i18nPrefix}.disabled.name`, { ns: 'plugin' }),
description: t(`${i18nPrefix}.disabled.description`, { ns: 'plugin' }),
},
{
value: AUTO_UPDATE_STRATEGY.fixOnly,
label: t(`${i18nPrefix}.fixOnly.name`),
description: t(`${i18nPrefix}.fixOnly.description`),
label: t(`${i18nPrefix}.fixOnly.name`, { ns: 'plugin' }),
description: t(`${i18nPrefix}.fixOnly.description`, { ns: 'plugin' }),
},
{
value: AUTO_UPDATE_STRATEGY.latest,
label: t(`${i18nPrefix}.latest.name`),
description: t(`${i18nPrefix}.latest.description`),
label: t(`${i18nPrefix}.latest.name`, { ns: 'plugin' }),
description: t(`${i18nPrefix}.latest.description`, { ns: 'plugin' }),
},
]
const selectedOption = options.find(option => option.value === value)
@ -46,28 +47,29 @@ const StrategyPicker = ({
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='top-end'
placement="top-end"
offset={4}
>
<PortalToFollowElemTrigger onClick={(e) => {
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
setOpen(v => !v)
}}>
}}
>
<Button
size='small'
size="small"
>
{selectedOption?.label}
<RiArrowDownSLine className='h-3.5 w-3.5' />
<RiArrowDownSLine className="h-3.5 w-3.5" />
</Button>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[99]'>
<div className='w-[280px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg'>
<PortalToFollowElemContent className="z-[99]">
<div className="w-[280px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
{
options.map(option => (
<div
key={option.value}
className='flex cursor-pointer rounded-lg p-2 pr-3 hover:bg-state-base-hover'
className="flex cursor-pointer rounded-lg p-2 pr-3 hover:bg-state-base-hover"
onClick={(e) => {
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
@ -75,16 +77,16 @@ const StrategyPicker = ({
setOpen(false)
}}
>
<div className='mr-1 w-4 shrink-0'>
<div className="mr-1 w-4 shrink-0">
{
value === option.value && (
<RiCheckLine className='h-4 w-4 text-text-accent' />
<RiCheckLine className="h-4 w-4 text-text-accent" />
)
}
</div>
<div className='grow'>
<div className='system-sm-semibold mb-0.5 text-text-secondary'>{option.label}</div>
<div className='system-xs-regular text-text-tertiary'>{option.description}</div>
<div className="grow">
<div className="system-sm-semibold mb-0.5 text-text-secondary">{option.label}</div>
<div className="system-xs-regular text-text-tertiary">{option.description}</div>
</div>
</div>
))

View File

@ -1,12 +1,12 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import type { PluginDetail } from '@/app/components/plugins/types'
import Icon from '@/app/components/plugins/card/base/card-icon'
import { renderI18nObject } from '@/i18n-config'
import { useGetLanguage } from '@/context/i18n'
import { MARKETPLACE_API_PREFIX } from '@/config'
import * as React from 'react'
import Checkbox from '@/app/components/base/checkbox'
import Icon from '@/app/components/plugins/card/base/card-icon'
import { MARKETPLACE_API_PREFIX } from '@/config'
import { useGetLanguage } from '@/context/i18n'
import { renderI18nObject } from '@/i18n-config'
type Props = {
payload: PluginDetail
@ -24,19 +24,19 @@ const ToolItem: FC<Props> = ({
const { plugin_id, declaration } = payload
const { label, author: org } = declaration
return (
<div className='p-1'>
<div className="p-1">
<div
className='flex w-full select-none items-center rounded-lg pr-2 hover:bg-state-base-hover'
className="flex w-full select-none items-center rounded-lg pr-2 hover:bg-state-base-hover"
>
<div className='flex h-8 grow items-center space-x-2 pl-3 pr-2'>
<Icon size='tiny' src={`${MARKETPLACE_API_PREFIX}/plugins/${plugin_id}/icon`} />
<div className='system-sm-medium max-w-[150px] shrink-0 truncate text-text-primary'>{renderI18nObject(label, language)}</div>
<div className='system-xs-regular max-w-[150px] shrink-0 truncate text-text-quaternary'>{org}</div>
<div className="flex h-8 grow items-center space-x-2 pl-3 pr-2">
<Icon size="tiny" src={`${MARKETPLACE_API_PREFIX}/plugins/${plugin_id}/icon`} />
<div className="system-sm-medium max-w-[150px] shrink-0 truncate text-text-primary">{renderI18nObject(label, language)}</div>
<div className="system-xs-regular max-w-[150px] shrink-0 truncate text-text-quaternary">{org}</div>
</div>
<Checkbox
checked={isChecked}
onCheck={onCheckChange}
className='shrink-0'
className="shrink-0"
/>
</div>
</div>

View File

@ -1,20 +1,21 @@
'use client'
import type { FC } from 'react'
import React, { useCallback, useMemo, useState } from 'react'
import * as React from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { useInstalledPluginList } from '@/service/use-plugins'
import { PLUGIN_TYPE_SEARCH_MAP } from '../../marketplace/plugin-type-switch'
import SearchBox from '@/app/components/plugins/marketplace/search-box'
import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames'
import ToolItem from './tool-item'
import Loading from '@/app/components/base/loading'
import NoDataPlaceholder from './no-data-placeholder'
import { useInstalledPluginList } from '@/service/use-plugins'
import { cn } from '@/utils/classnames'
import { PLUGIN_TYPE_SEARCH_MAP } from '../../marketplace/plugin-type-switch'
import { PluginSource } from '../../types'
import NoDataPlaceholder from './no-data-placeholder'
import ToolItem from './tool-item'
type Props = {
trigger: React.ReactNode
@ -40,35 +41,35 @@ const ToolPicker: FC<Props> = ({
const tabs = [
{
key: PLUGIN_TYPE_SEARCH_MAP.all,
name: t('plugin.category.all'),
name: t('category.all', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.model,
name: t('plugin.category.models'),
name: t('category.models', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.tool,
name: t('plugin.category.tools'),
name: t('category.tools', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.agent,
name: t('plugin.category.agents'),
name: t('category.agents', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.extension,
name: t('plugin.category.extensions'),
name: t('category.extensions', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.datasource,
name: t('plugin.category.datasources'),
name: t('category.datasources', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.trigger,
name: t('plugin.category.triggers'),
name: t('category.triggers', { ns: 'plugin' }),
},
{
key: PLUGIN_TYPE_SEARCH_MAP.bundle,
name: t('plugin.category.bundles'),
name: t('category.bundles', { ns: 'plugin' }),
},
]
@ -97,7 +98,7 @@ const ToolPicker: FC<Props> = ({
}, [onChange, value])
const listContent = (
<div className='max-h-[396px] overflow-y-auto'>
<div className="max-h-[396px] overflow-y-auto">
{filteredList.map(item => (
<ToolItem
key={item.plugin_id}
@ -110,42 +111,42 @@ const ToolPicker: FC<Props> = ({
)
const loadingContent = (
<div className='flex h-[396px] items-center justify-center'>
<div className="flex h-[396px] items-center justify-center">
<Loading />
</div>
)
const noData = (
<NoDataPlaceholder className='h-[396px]' noPlugins={!query} />
<NoDataPlaceholder className="h-[396px]" noPlugins={!query} />
)
return (
<PortalToFollowElem
placement='top'
placement="top"
offset={0}
open={isShow}
onOpenChange={onShowChange}
>
<PortalToFollowElemTrigger
className='block w-full'
className="block w-full"
onClick={toggleShowPopup}
>
{trigger}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<PortalToFollowElemContent className="z-[1000]">
<div className={cn('relative min-h-20 w-full rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur pb-2 shadow-lg backdrop-blur-sm')}>
<div className='p-2 pb-1'>
<div className="p-2 pb-1">
<SearchBox
search={query}
onSearchChange={setQuery}
tags={tags}
onTagsChange={setTags}
placeholder={t('plugin.searchTools')!}
inputClassName='w-full'
placeholder={t('searchTools', { ns: 'plugin' })!}
inputClassName="w-full"
/>
</div>
<div className='flex items-center justify-between border-b-[0.5px] border-divider-subtle bg-background-default-hover px-3 shadow-xs'>
<div className='flex h-8 items-center space-x-1'>
<div className="flex items-center justify-between border-b-[0.5px] border-divider-subtle bg-background-default-hover px-3 shadow-xs">
<div className="flex h-8 items-center space-x-1">
{
tabs.map(tab => (
<div

View File

@ -1,7 +1,7 @@
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
dayjs.extend(timezone)
@ -23,7 +23,8 @@ export const convertLocalSecondsToUTCDaySeconds = (secondsInDay: number, localTi
}
export const dayjsToTimeOfDay = (date?: Dayjs): number => {
if (!date) return 0
if (!date)
return 0
return date.hour() * 3600 + date.minute() * 60
}