diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx index d70179266..f8189b0c8 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx @@ -4,7 +4,6 @@ import React, { useEffect, useMemo } from 'react' import { usePathname } from 'next/navigation' import useSWR from 'swr' import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' import { RiEqualizer2Fill, RiEqualizer2Line, @@ -44,17 +43,12 @@ type IExtraInfoProps = { } const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => { - const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile) const { t } = useTranslation() const docLink = useDocLink() const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0 const relatedAppsTotal = relatedApps?.data?.length || 0 - useEffect(() => { - setShowTips(!isMobile) - }, [isMobile, setShowTips]) - return
{/* Related apps for desktop */}
= ({ const { data: embeddingsModelList } = useModelList(ModelTypeEnum.textEmbedding) const { modelList: rerankModelList, - defaultModel: rerankDefaultModel, - currentModel: isRerankDefaultModelValid, } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank) const { t } = useTranslation() const docLink = useDocLink() diff --git a/web/app/components/base/markdown-blocks/code-block.tsx b/web/app/components/base/markdown-blocks/code-block.tsx index c88cfde9e..48de8bf4a 100644 --- a/web/app/components/base/markdown-blocks/code-block.tsx +++ b/web/app/components/base/markdown-blocks/code-block.tsx @@ -81,7 +81,6 @@ const CodeBlock: any = memo(({ inline, className, children = '', ...props }: any const echartsRef = useRef(null) const contentRef = useRef('') const processedRef = useRef(false) // Track if content was successfully processed - const instanceIdRef = useRef(`chart-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`) // Unique ID for logging const isInitialRenderRef = useRef(true) // Track if this is initial render const chartInstanceRef = useRef(null) // Direct reference to ECharts instance const resizeTimerRef = useRef(null) // For debounce handling diff --git a/web/app/components/base/mermaid/index.tsx b/web/app/components/base/mermaid/index.tsx index a953ef15a..80271bb29 100644 --- a/web/app/components/base/mermaid/index.tsx +++ b/web/app/components/base/mermaid/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import mermaid, { type MermaidConfig } from 'mermaid' import { useTranslation } from 'react-i18next' import { ExclamationTriangleIcon } from '@heroicons/react/24/outline' @@ -122,14 +122,6 @@ const Flowchart = React.forwardRef((props: { const renderTimeoutRef = useRef() const [errMsg, setErrMsg] = useState('') const [imagePreviewUrl, setImagePreviewUrl] = useState('') - const [isCodeComplete, setIsCodeComplete] = useState(false) - const codeCompletionCheckRef = useRef() - const prevCodeRef = useRef() - - // Create cache key from code, style and theme - const cacheKey = useMemo(() => { - return `${props.PrimitiveCode}-${look}-${currentTheme}` - }, [props.PrimitiveCode, look, currentTheme]) /** * Renders Mermaid chart @@ -537,11 +529,9 @@ const Flowchart = React.forwardRef((props: { {isLoading && !svgString && (
- {!isCodeComplete && (
{t('common.wait_for_completion', 'Waiting for diagram code to complete...')}
- )}
)} diff --git a/web/app/components/datasets/external-api/external-api-modal/Form.tsx b/web/app/components/datasets/external-api/external-api-modal/Form.tsx index 8884cb787..5479f8147 100644 --- a/web/app/components/datasets/external-api/external-api-modal/Form.tsx +++ b/web/app/components/datasets/external-api/external-api-modal/Form.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React from 'react' import type { FC } from 'react' import { useTranslation } from 'react-i18next' import { RiBookOpenLine } from '@remixicon/react' @@ -28,10 +28,8 @@ const Form: FC = React.memo(({ }) => { const { t, i18n } = useTranslation() const docLink = useDocLink() - const [changeKey, setChangeKey] = useState('') const handleFormChange = (key: string, val: string) => { - setChangeKey(key) if (key === 'name') { onChange({ ...value, [key]: val }) } diff --git a/web/app/components/datasets/rename-modal/index.tsx b/web/app/components/datasets/rename-modal/index.tsx index dd53bafdd..c497dbb95 100644 --- a/web/app/components/datasets/rename-modal/index.tsx +++ b/web/app/components/datasets/rename-modal/index.tsx @@ -28,8 +28,8 @@ const RenameDatasetModal = ({ show, dataset, onSuccess, onClose }: RenameDataset const [loading, setLoading] = useState(false) const [name, setName] = useState(dataset.name) const [description, setDescription] = useState(dataset.description) - const [externalKnowledgeId, setExternalKnowledgeId] = useState(dataset.external_knowledge_info.external_knowledge_id) - const [externalKnowledgeApiId, setExternalKnowledgeApiId] = useState(dataset.external_knowledge_info.external_knowledge_api_id) + const externalKnowledgeId = dataset.external_knowledge_info.external_knowledge_id + const externalKnowledgeApiId = dataset.external_knowledge_info.external_knowledge_api_id const onConfirm: MouseEventHandler = async () => { if (!name.trim()) { diff --git a/web/app/components/explore/app-list/index.tsx b/web/app/components/explore/app-list/index.tsx index 7e2d990bc..79cbff81c 100644 --- a/web/app/components/explore/app-list/index.tsx +++ b/web/app/components/explore/app-list/index.tsx @@ -51,7 +51,6 @@ const Apps = ({ handleSearch() } - const [currentType, setCurrentType] = useState('') const [currCategory, setCurrCategory] = useTabSearchParams({ defaultTab: allCategoriesEn, disableSearchParams: false, @@ -74,28 +73,7 @@ const Apps = ({ }, ) - const filteredList = useMemo(() => { - if (currCategory === allCategoriesEn) { - if (!currentType) - return allList - else if (currentType === 'chatbot') - return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat')) - else if (currentType === 'agent') - return allList.filter(item => (item.app.mode === 'agent-chat')) - else - return allList.filter(item => (item.app.mode === 'workflow')) - } - else { - if (!currentType) - return allList.filter(item => item.category === currCategory) - else if (currentType === 'chatbot') - return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat') && item.category === currCategory) - else if (currentType === 'agent') - return allList.filter(item => (item.app.mode === 'agent-chat') && item.category === currCategory) - else - return allList.filter(item => (item.app.mode === 'workflow') && item.category === currCategory) - } - }, [currentType, currCategory, allCategoriesEn, allList]) + const filteredList = allList.filter(item => currCategory === allCategoriesEn || item.category === currCategory) const searchFilteredList = useMemo(() => { if (!searchKeywords || !filteredList || filteredList.length === 0) diff --git a/web/app/components/explore/sidebar/index.tsx b/web/app/components/explore/sidebar/index.tsx index 74c397f4f..c5866c31d 100644 --- a/web/app/components/explore/sidebar/index.tsx +++ b/web/app/components/explore/sidebar/index.tsx @@ -49,7 +49,6 @@ const SideBar: FC = ({ const segments = useSelectedLayoutSegments() const lastSegment = segments.slice(-1)[0] const isDiscoverySelected = lastSegment === 'apps' - const isChatSelected = lastSegment === 'chat' const { installedApps, setInstalledApps, setIsFetchingInstalledApps } = useContext(ExploreContext) const { isFetching: isFetchingInstalledApps, data: ret, refetch: fetchInstalledAppList } = useGetInstalledApps() const { mutateAsync: uninstallApp } = useUninstallApp() diff --git a/web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx b/web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx index 68a575f50..a94ef4584 100644 --- a/web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx +++ b/web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx @@ -1,11 +1,10 @@ 'use client' -import React, { useCallback, useEffect, useRef, useState } from 'react' +import React, { useCallback, useEffect, useState } from 'react' import { t } from 'i18next' import copy from 'copy-to-clipboard' import s from './index.module.css' import type { SuccessInvitationResult } from '.' import Tooltip from '@/app/components/base/tooltip' -import { randomString } from '@/utils' type IInvitationLinkProps = { value: SuccessInvitationResult @@ -15,7 +14,6 @@ const InvitationLink = ({ value, }: IInvitationLinkProps) => { const [isCopied, setIsCopied] = useState(false) - const selector = useRef(`invite-link-${randomString(4)}`) const copyHandle = useCallback(() => { // No prefix is needed here because the backend has already processed it diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx index 3e969d708..7cfb90620 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx @@ -1,7 +1,6 @@ import type { FC } from 'react' import { useEffect, useRef, useState } from 'react' import type { ModelParameterRule } from '../declarations' -import { useLanguage } from '../hooks' import { isNullOrUndefined } from '../utils' import cn from '@/utils/classnames' import Switch from '@/app/components/base/switch' @@ -10,7 +9,6 @@ import Slider from '@/app/components/base/slider' import Radio from '@/app/components/base/radio' import { SimpleSelect } from '@/app/components/base/select' import TagInput from '@/app/components/base/tag-input' -import { useTranslation } from 'react-i18next' export type ParameterValue = number | string | string[] | boolean | undefined @@ -28,8 +26,6 @@ const ParameterItem: FC = ({ onSwitch, isInWorkflow, }) => { - const { t } = useTranslation() - const language = useLanguage() const [localValue, setLocalValue] = useState(value) const numberInputRef = useRef(null) diff --git a/web/app/components/plugins/marketplace/search-box/tags-filter.tsx b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx index bae649172..12b84490a 100644 --- a/web/app/components/plugins/marketplace/search-box/tags-filter.tsx +++ b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx @@ -30,7 +30,7 @@ const TagsFilter = ({ const { t } = useMixedTranslation(locale) const [open, setOpen] = useState(false) const [searchText, setSearchText] = useState('') - const { tags: options, tagsMap } = useTags(t) + const { tags: options } = useTags(t) const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchText.toLowerCase())) const handleCheck = (id: string) => { if (tags.includes(id)) @@ -38,7 +38,6 @@ const TagsFilter = ({ else onTagsChange([...tags, id]) } - const selectedTagsLength = tags.length return ( { } export const getMarketplacePluginsByCollectionId = async (collectionId: string, query?: CollectionsAndPluginsSearchParams) => { - let plugins = [] as Plugin[] + let plugins: Plugin[] try { const url = `${MARKETPLACE_API_PREFIX}/collections/${collectionId}/plugins` diff --git a/web/app/components/share/text-generation/index.tsx b/web/app/components/share/text-generation/index.tsx index 4a6d1c996..da5b09b06 100644 --- a/web/app/components/share/text-generation/index.tsx +++ b/web/app/components/share/text-generation/index.tsx @@ -151,10 +151,9 @@ const TextGeneration: FC = ({ const pendingTaskList = allTaskList.filter(task => task.status === TaskStatus.pending) const noPendingTask = pendingTaskList.length === 0 const showTaskList = allTaskList.filter(task => task.status !== TaskStatus.pending) - const [currGroupNum, doSetCurrGroupNum] = useState(0) const currGroupNumRef = useRef(0) + const setCurrGroupNum = (num: number) => { - doSetCurrGroupNum(num) currGroupNumRef.current = num } const getCurrGroupNum = () => { @@ -164,10 +163,8 @@ const TextGeneration: FC = ({ const allFailedTaskList = allTaskList.filter(task => task.status === TaskStatus.failed) const allTasksFinished = allTaskList.every(task => task.status === TaskStatus.completed) const allTasksRun = allTaskList.every(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status)) - const [batchCompletionRes, doSetBatchCompletionRes] = useState>({}) const batchCompletionResRef = useRef>({}) const setBatchCompletionRes = (res: Record) => { - doSetBatchCompletionRes(res) batchCompletionResRef.current = res } const getBatchCompletionRes = () => batchCompletionResRef.current diff --git a/web/app/components/workflow/block-selector/use-sticky-scroll.ts b/web/app/components/workflow/block-selector/use-sticky-scroll.ts index 405ecdba7..c828e9ce9 100644 --- a/web/app/components/workflow/block-selector/use-sticky-scroll.ts +++ b/web/app/components/workflow/block-selector/use-sticky-scroll.ts @@ -23,7 +23,7 @@ const useStickyScroll = ({ return const { height: wrapHeight, top: wrapTop } = wrapDom.getBoundingClientRect() const { top: nextToStickyTop } = stickyDOM.getBoundingClientRect() - let scrollPositionNew = ScrollPosition.belowTheWrap + let scrollPositionNew: ScrollPosition if (nextToStickyTop - wrapTop >= wrapHeight) scrollPositionNew = ScrollPosition.belowTheWrap diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts index f9120f45b..a6435ec63 100644 --- a/web/app/components/workflow/hooks/use-workflow.ts +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -444,7 +444,7 @@ export const useFetchToolsData = () => { workflowTools: workflowTools || [], }) } - if(type === 'mcp') { + if (type === 'mcp') { const mcpTools = await fetchAllMCPTools() workflowStore.setState({ @@ -500,18 +500,17 @@ export const useToolIcon = (data: Node['data']) => { const mcpTools = useStore(s => s.mcpTools) const toolIcon = useMemo(() => { - if(!data) + if (!data) return '' if (data.type === BlockEnum.Tool) { - let targetTools = buildInTools + let targetTools = workflowTools if (data.provider_type === CollectionType.builtIn) targetTools = buildInTools else if (data.provider_type === CollectionType.custom) targetTools = customTools else if (data.provider_type === CollectionType.mcp) targetTools = mcpTools - else - targetTools = workflowTools + return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon } }, [data, buildInTools, customTools, mcpTools, workflowTools]) diff --git a/web/app/components/workflow/nodes/_base/components/node-control.tsx b/web/app/components/workflow/nodes/_base/components/node-control.tsx index 5b92b7b6b..0e3f54f10 100644 --- a/web/app/components/workflow/nodes/_base/components/node-control.tsx +++ b/web/app/components/workflow/nodes/_base/components/node-control.tsx @@ -11,7 +11,6 @@ import { import { useNodeDataUpdate, useNodesInteractions, - useNodesSyncDraft, } from '../../../hooks' import { type Node, NodeRunningStatus } from '../../../types' import { canRunBySingle } from '../../../utils' @@ -30,7 +29,6 @@ const NodeControl: FC = ({ const [open, setOpen] = useState(false) const { handleNodeDataUpdate } = useNodeDataUpdate() const { handleNodeSelect } = useNodesInteractions() - const { handleSyncWorkflowDraft } = useNodesSyncDraft() const isSingleRunning = data._singleRunningStatus === NodeRunningStatus.Running const handleOpenChange = useCallback((newOpen: boolean) => { setOpen(newOpen) diff --git a/web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx b/web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx index 93fab8317..4723b2dce 100644 --- a/web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx @@ -198,7 +198,6 @@ const BasePanel: FC = ({ isShowSingleRun, hideSingleRun, runningStatus, - handleStop, runInputData, runInputDataRef, runResult, diff --git a/web/app/components/workflow/nodes/list-operator/use-config.ts b/web/app/components/workflow/nodes/list-operator/use-config.ts index efbf32b8c..21e976172 100644 --- a/web/app/components/workflow/nodes/list-operator/use-config.ts +++ b/web/app/components/workflow/nodes/list-operator/use-config.ts @@ -36,6 +36,7 @@ const useConfig = (id: string, payload: ListFilterNodeType) => { const { inputs, setInputs } = useNodeCrud(id, payload) const { getCurrentVariableType } = useWorkflowVariables() + const getType = useCallback((variable?: ValueSelector) => { const varType = getCurrentVariableType({ parentNode: isInIteration ? iterationNode : loopNode, @@ -44,7 +45,7 @@ const useConfig = (id: string, payload: ListFilterNodeType) => { isChatMode, isConstant: false, }) - let itemVarType = VarType.string + let itemVarType = varType switch (varType) { case VarType.arrayNumber: itemVarType = VarType.number @@ -58,8 +59,6 @@ const useConfig = (id: string, payload: ListFilterNodeType) => { case VarType.arrayObject: itemVarType = VarType.object break - default: - itemVarType = varType } return { varType, itemVarType } }, [availableNodes, getCurrentVariableType, inputs.variable, isChatMode, isInIteration, iterationNode, loopNode]) diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs index dda2beff0..747c14ad6 100644 --- a/web/eslint.config.mjs +++ b/web/eslint.config.mjs @@ -163,7 +163,7 @@ export default combine( 'sonarjs/single-char-in-character-classes': 'off', 'sonarjs/anchor-precedence': 'warn', 'sonarjs/updated-loop-counter': 'off', - 'sonarjs/no-dead-store': 'warn', + 'sonarjs/no-dead-store': 'error', 'sonarjs/no-duplicated-branches': 'warn', 'sonarjs/max-lines': 'warn', // max 1000 lines 'sonarjs/no-variable-usage-before-declaration': 'error',