| useState, | useState, | ||||
| } from 'react' | } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import dayjs from 'dayjs' | |||||
| import relativeTime from 'dayjs/plugin/relativeTime' | |||||
| import { | import { | ||||
| RiArrowDownSLine, | RiArrowDownSLine, | ||||
| RiArrowRightSLine, | RiArrowRightSLine, | ||||
| import { fetchInstalledAppList } from '@/service/explore' | import { fetchInstalledAppList } from '@/service/explore' | ||||
| import EmbeddedModal from '@/app/components/app/overview/embedded' | import EmbeddedModal from '@/app/components/app/overview/embedded' | ||||
| import { useStore as useAppStore } from '@/app/components/app/store' | import { useStore as useAppStore } from '@/app/components/app/store' | ||||
| import { useGetLanguage } from '@/context/i18n' | |||||
| import { CodeBrowser } from '@/app/components/base/icons/src/vender/line/development' | import { CodeBrowser } from '@/app/components/base/icons/src/vender/line/development' | ||||
| import WorkflowToolConfigureButton from '@/app/components/tools/workflow-tool/configure-button' | import WorkflowToolConfigureButton from '@/app/components/tools/workflow-tool/configure-button' | ||||
| import type { InputVar } from '@/app/components/workflow/types' | import type { InputVar } from '@/app/components/workflow/types' | ||||
| import { AccessMode } from '@/models/access-control' | import { AccessMode } from '@/models/access-control' | ||||
| import { fetchAppDetail } from '@/service/apps' | import { fetchAppDetail } from '@/service/apps' | ||||
| import { useGlobalPublicStore } from '@/context/global-public-context' | import { useGlobalPublicStore } from '@/context/global-public-context' | ||||
| dayjs.extend(relativeTime) | |||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| export type AppPublisherProps = { | export type AppPublisherProps = { | ||||
| disabled?: boolean | disabled?: boolean | ||||
| const appDetail = useAppStore(state => state.appDetail) | const appDetail = useAppStore(state => state.appDetail) | ||||
| const setAppDetail = useAppStore(s => s.setAppDetail) | const setAppDetail = useAppStore(s => s.setAppDetail) | ||||
| const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) | const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) | ||||
| const { formatTimeFromNow } = useFormatTimeFromNow() | |||||
| const { app_base_url: appBaseURL = '', access_token: accessToken = '' } = appDetail?.site ?? {} | const { app_base_url: appBaseURL = '', access_token: accessToken = '' } = appDetail?.site ?? {} | ||||
| const appMode = (appDetail?.mode !== 'completion' && appDetail?.mode !== 'workflow') ? 'chat' : appDetail.mode | const appMode = (appDetail?.mode !== 'completion' && appDetail?.mode !== 'workflow') ? 'chat' : appDetail.mode | ||||
| const appURL = `${appBaseURL}${basePath}/${appMode}/${accessToken}` | const appURL = `${appBaseURL}${basePath}/${appMode}/${accessToken}` | ||||
| setIsAppAccessSet(true) | setIsAppAccessSet(true) | ||||
| } | } | ||||
| }, [appAccessSubjects, appDetail]) | }, [appAccessSubjects, appDetail]) | ||||
| const language = useGetLanguage() | |||||
| const formatTimeFromNow = useCallback((time: number) => { | |||||
| return dayjs(time).locale(language === 'zh_Hans' ? 'zh-cn' : language.replace('_', '-')).fromNow() | |||||
| }, [language]) | |||||
| const handlePublish = useCallback(async (params?: ModelAndParameter | PublishWorkflowParams) => { | const handlePublish = useCallback(async (params?: ModelAndParameter | PublishWorkflowParams) => { | ||||
| try { | try { |
| 'use client' | 'use client' | ||||
| import { useState } from 'react' | import { useState } from 'react' | ||||
| import useSWR from 'swr' | import useSWR from 'swr' | ||||
| import dayjs from 'dayjs' | |||||
| import 'dayjs/locale/zh-cn' | |||||
| import relativeTime from 'dayjs/plugin/relativeTime' | |||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { RiUserAddLine } from '@remixicon/react' | import { RiUserAddLine } from '@remixicon/react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| import { RiPencilLine } from '@remixicon/react' | import { RiPencilLine } from '@remixicon/react' | ||||
| import { useGlobalPublicStore } from '@/context/global-public-context' | import { useGlobalPublicStore } from '@/context/global-public-context' | ||||
| dayjs.extend(relativeTime) | |||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| const MembersPage = () => { | const MembersPage = () => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| fetchMembers, | fetchMembers, | ||||
| ) | ) | ||||
| const { systemFeatures } = useGlobalPublicStore() | const { systemFeatures } = useGlobalPublicStore() | ||||
| const { formatTimeFromNow } = useFormatTimeFromNow() | |||||
| const [inviteModalVisible, setInviteModalVisible] = useState(false) | const [inviteModalVisible, setInviteModalVisible] = useState(false) | ||||
| const [invitationResults, setInvitationResults] = useState<InvitationResult[]>([]) | const [invitationResults, setInvitationResults] = useState<InvitationResult[]>([]) | ||||
| const [invitedModalVisible, setInvitedModalVisible] = useState(false) | const [invitedModalVisible, setInvitedModalVisible] = useState(false) | ||||
| <div className='system-xs-regular text-text-tertiary'>{account.email}</div> | <div className='system-xs-regular text-text-tertiary'>{account.email}</div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div className='system-sm-regular flex w-[104px] shrink-0 items-center py-2 text-text-secondary'>{dayjs(Number((account.last_active_at || account.created_at)) * 1000).locale(locale === 'zh-Hans' ? 'zh-cn' : 'en').fromNow()}</div> | |||||
| <div className='system-sm-regular flex w-[104px] shrink-0 items-center py-2 text-text-secondary'>{formatTimeFromNow(Number((account.last_active_at || account.created_at)) * 1000)}</div> | |||||
| <div className='flex w-[96px] shrink-0 items-center'> | <div className='flex w-[96px] shrink-0 items-center'> | ||||
| {isCurrentWorkspaceOwner && account.role === 'owner' && isAllowTransferWorkspace && ( | {isCurrentWorkspaceOwner && account.role === 'owner' && isAllowTransferWorkspace && ( | ||||
| <TransferOwnership onOperate={() => setShowTransferOwnershipModal(true)}></TransferOwnership> | <TransferOwnership onOperate={() => setShowTransferOwnershipModal(true)}></TransferOwnership> |
| import { RiHammerFill } from '@remixicon/react' | import { RiHammerFill } from '@remixicon/react' | ||||
| import Indicator from '@/app/components/header/indicator' | import Indicator from '@/app/components/header/indicator' | ||||
| import Icon from '@/app/components/plugins/card/base/card-icon' | import Icon from '@/app/components/plugins/card/base/card-icon' | ||||
| import { useFormatTimeFromNow } from './hooks' | |||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| import type { ToolWithProvider } from '../../workflow/types' | import type { ToolWithProvider } from '../../workflow/types' | ||||
| import Confirm from '@/app/components/base/confirm' | import Confirm from '@/app/components/base/confirm' | ||||
| import MCPModal from './modal' | import MCPModal from './modal' |
| import { memo } from 'react' | import { memo } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useFormatTimeFromNow } from '../hooks' | |||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| import { useStore } from '@/app/components/workflow/store' | import { useStore } from '@/app/components/workflow/store' | ||||
| import useTimestamp from '@/hooks/use-timestamp' | import useTimestamp from '@/hooks/use-timestamp' | ||||
| import { memo, useMemo } from 'react' | import { memo, useMemo } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useFormatTimeFromNow } from '../hooks' | |||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| import { useStore } from '../store' | import { useStore } from '../store' | ||||
| import { WorkflowVersion } from '../types' | import { WorkflowVersion } from '../types' | ||||
| import useTimestamp from '@/hooks/use-timestamp' | import useTimestamp from '@/hooks/use-timestamp' |
| RiErrorWarningLine, | RiErrorWarningLine, | ||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import { | import { | ||||
| useFormatTimeFromNow, | |||||
| useIsChatMode, | useIsChatMode, | ||||
| useNodesInteractions, | useNodesInteractions, | ||||
| useWorkflowInteractions, | useWorkflowInteractions, | ||||
| useWorkflowRun, | useWorkflowRun, | ||||
| } from '../hooks' | } from '../hooks' | ||||
| import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' | |||||
| import { ControlMode, WorkflowRunningStatus } from '../types' | import { ControlMode, WorkflowRunningStatus } from '../types' | ||||
| import { formatWorkflowRunIdentifier } from '../utils' | import { formatWorkflowRunIdentifier } from '../utils' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' |
| export * from './use-shortcuts' | export * from './use-shortcuts' | ||||
| export * from './use-workflow-interactions' | export * from './use-workflow-interactions' | ||||
| export * from './use-workflow-mode' | export * from './use-workflow-mode' | ||||
| export * from './use-format-time-from-now' | |||||
| export * from './use-workflow-refresh-draft' | export * from './use-workflow-refresh-draft' | ||||
| export * from './use-inspect-vars-crud' | export * from './use-inspect-vars-crud' | ||||
| export * from './use-set-workflow-vars-with-value' | export * from './use-set-workflow-vars-with-value' |
| import dayjs from 'dayjs' | |||||
| import { useCallback } from 'react' | |||||
| import { useI18N } from '@/context/i18n' | |||||
| export const useFormatTimeFromNow = () => { | |||||
| const { locale } = useI18N() | |||||
| const formatTimeFromNow = useCallback((time: number) => { | |||||
| return dayjs(time).locale(locale === 'zh-Hans' ? 'zh-cn' : locale).fromNow() | |||||
| }, [locale]) | |||||
| return { formatTimeFromNow } | |||||
| } |
| import relativeTime from 'dayjs/plugin/relativeTime' | import relativeTime from 'dayjs/plugin/relativeTime' | ||||
| import { useCallback } from 'react' | import { useCallback } from 'react' | ||||
| import { useI18N } from '@/context/i18n' | import { useI18N } from '@/context/i18n' | ||||
| import 'dayjs/locale/zh-cn' | |||||
| dayjs.extend(relativeTime) | dayjs.extend(relativeTime) | ||||