浏览代码

lint: fix sonarjs/no-dead-store issues (#23653)

tags/1.7.2
Matri Qi 2 个月前
父节点
当前提交
ea502d36a9
没有帐户链接到提交者的电子邮件

+ 0
- 6
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx 查看文件

import { usePathname } from 'next/navigation' import { usePathname } from 'next/navigation'
import useSWR from 'swr' import useSWR from 'swr'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import { import {
RiEqualizer2Fill, RiEqualizer2Fill,
RiEqualizer2Line, RiEqualizer2Line,
} }


const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => { const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink() const docLink = useDocLink()


const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0 const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
const relatedAppsTotal = relatedApps?.data?.length || 0 const relatedAppsTotal = relatedApps?.data?.length || 0


useEffect(() => {
setShowTips(!isMobile)
}, [isMobile, setShowTips])

return <div> return <div>
{/* Related apps for desktop */} {/* Related apps for desktop */}
<div className={classNames( <div className={classNames(

+ 0
- 2
web/app/components/app/configuration/dataset-config/settings-modal/index.tsx 查看文件

const { data: embeddingsModelList } = useModelList(ModelTypeEnum.textEmbedding) const { data: embeddingsModelList } = useModelList(ModelTypeEnum.textEmbedding)
const { const {
modelList: rerankModelList, modelList: rerankModelList,
defaultModel: rerankDefaultModel,
currentModel: isRerankDefaultModelValid,
} = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank) } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank)
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink() const docLink = useDocLink()

+ 0
- 1
web/app/components/base/markdown-blocks/code-block.tsx 查看文件

const echartsRef = useRef<any>(null) const echartsRef = useRef<any>(null)
const contentRef = useRef<string>('') const contentRef = useRef<string>('')
const processedRef = useRef<boolean>(false) // Track if content was successfully processed const processedRef = useRef<boolean>(false) // Track if content was successfully processed
const instanceIdRef = useRef<string>(`chart-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`) // Unique ID for logging
const isInitialRenderRef = useRef<boolean>(true) // Track if this is initial render const isInitialRenderRef = useRef<boolean>(true) // Track if this is initial render
const chartInstanceRef = useRef<any>(null) // Direct reference to ECharts instance const chartInstanceRef = useRef<any>(null) // Direct reference to ECharts instance
const resizeTimerRef = useRef<NodeJS.Timeout | null>(null) // For debounce handling const resizeTimerRef = useRef<NodeJS.Timeout | null>(null) // For debounce handling

+ 1
- 11
web/app/components/base/mermaid/index.tsx 查看文件

import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import mermaid, { type MermaidConfig } from 'mermaid' import mermaid, { type MermaidConfig } from 'mermaid'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline' import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'
const renderTimeoutRef = useRef<NodeJS.Timeout>() const renderTimeoutRef = useRef<NodeJS.Timeout>()
const [errMsg, setErrMsg] = useState('') const [errMsg, setErrMsg] = useState('')
const [imagePreviewUrl, setImagePreviewUrl] = useState('') const [imagePreviewUrl, setImagePreviewUrl] = useState('')
const [isCodeComplete, setIsCodeComplete] = useState(false)
const codeCompletionCheckRef = useRef<NodeJS.Timeout>()
const prevCodeRef = useRef<string>()

// Create cache key from code, style and theme
const cacheKey = useMemo(() => {
return `${props.PrimitiveCode}-${look}-${currentTheme}`
}, [props.PrimitiveCode, look, currentTheme])


/** /**
* Renders Mermaid chart * Renders Mermaid chart
{isLoading && !svgString && ( {isLoading && !svgString && (
<div className='px-[26px] py-4'> <div className='px-[26px] py-4'>
<LoadingAnim type='text'/> <LoadingAnim type='text'/>
{!isCodeComplete && (
<div className="mt-2 text-sm text-gray-500"> <div className="mt-2 text-sm text-gray-500">
{t('common.wait_for_completion', 'Waiting for diagram code to complete...')} {t('common.wait_for_completion', 'Waiting for diagram code to complete...')}
</div> </div>
)}
</div> </div>
)} )}



+ 1
- 3
web/app/components/datasets/external-api/external-api-modal/Form.tsx 查看文件

import React, { useState } from 'react'
import React from 'react'
import type { FC } from 'react' import type { FC } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { RiBookOpenLine } from '@remixicon/react' import { RiBookOpenLine } from '@remixicon/react'
}) => { }) => {
const { t, i18n } = useTranslation() const { t, i18n } = useTranslation()
const docLink = useDocLink() const docLink = useDocLink()
const [changeKey, setChangeKey] = useState('')


const handleFormChange = (key: string, val: string) => { const handleFormChange = (key: string, val: string) => {
setChangeKey(key)
if (key === 'name') { if (key === 'name') {
onChange({ ...value, [key]: val }) onChange({ ...value, [key]: val })
} }

+ 2
- 2
web/app/components/datasets/rename-modal/index.tsx 查看文件

const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [name, setName] = useState<string>(dataset.name) const [name, setName] = useState<string>(dataset.name)
const [description, setDescription] = useState<string>(dataset.description) const [description, setDescription] = useState<string>(dataset.description)
const [externalKnowledgeId, setExternalKnowledgeId] = useState<string>(dataset.external_knowledge_info.external_knowledge_id)
const [externalKnowledgeApiId, setExternalKnowledgeApiId] = useState<string>(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 () => { const onConfirm: MouseEventHandler = async () => {
if (!name.trim()) { if (!name.trim()) {

+ 1
- 23
web/app/components/explore/app-list/index.tsx 查看文件

handleSearch() handleSearch()
} }


const [currentType, setCurrentType] = useState<string>('')
const [currCategory, setCurrCategory] = useTabSearchParams({ const [currCategory, setCurrCategory] = useTabSearchParams({
defaultTab: allCategoriesEn, defaultTab: allCategoriesEn,
disableSearchParams: false, disableSearchParams: false,
}, },
) )


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(() => { const searchFilteredList = useMemo(() => {
if (!searchKeywords || !filteredList || filteredList.length === 0) if (!searchKeywords || !filteredList || filteredList.length === 0)

+ 0
- 1
web/app/components/explore/sidebar/index.tsx 查看文件

const segments = useSelectedLayoutSegments() const segments = useSelectedLayoutSegments()
const lastSegment = segments.slice(-1)[0] const lastSegment = segments.slice(-1)[0]
const isDiscoverySelected = lastSegment === 'apps' const isDiscoverySelected = lastSegment === 'apps'
const isChatSelected = lastSegment === 'chat'
const { installedApps, setInstalledApps, setIsFetchingInstalledApps } = useContext(ExploreContext) const { installedApps, setInstalledApps, setIsFetchingInstalledApps } = useContext(ExploreContext)
const { isFetching: isFetchingInstalledApps, data: ret, refetch: fetchInstalledAppList } = useGetInstalledApps() const { isFetching: isFetchingInstalledApps, data: ret, refetch: fetchInstalledAppList } = useGetInstalledApps()
const { mutateAsync: uninstallApp } = useUninstallApp() const { mutateAsync: uninstallApp } = useUninstallApp()

+ 1
- 3
web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx 查看文件

'use client' 'use client'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { t } from 'i18next' import { t } from 'i18next'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import s from './index.module.css' import s from './index.module.css'
import type { SuccessInvitationResult } from '.' import type { SuccessInvitationResult } from '.'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import { randomString } from '@/utils'


type IInvitationLinkProps = { type IInvitationLinkProps = {
value: SuccessInvitationResult value: SuccessInvitationResult
value, value,
}: IInvitationLinkProps) => { }: IInvitationLinkProps) => {
const [isCopied, setIsCopied] = useState(false) const [isCopied, setIsCopied] = useState(false)
const selector = useRef(`invite-link-${randomString(4)}`)


const copyHandle = useCallback(() => { const copyHandle = useCallback(() => {
// No prefix is needed here because the backend has already processed it // No prefix is needed here because the backend has already processed it

+ 0
- 4
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx 查看文件

import type { FC } from 'react' import type { FC } from 'react'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import type { ModelParameterRule } from '../declarations' import type { ModelParameterRule } from '../declarations'
import { useLanguage } from '../hooks'
import { isNullOrUndefined } from '../utils' import { isNullOrUndefined } from '../utils'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import Switch from '@/app/components/base/switch' import Switch from '@/app/components/base/switch'
import Radio from '@/app/components/base/radio' import Radio from '@/app/components/base/radio'
import { SimpleSelect } from '@/app/components/base/select' import { SimpleSelect } from '@/app/components/base/select'
import TagInput from '@/app/components/base/tag-input' import TagInput from '@/app/components/base/tag-input'
import { useTranslation } from 'react-i18next'


export type ParameterValue = number | string | string[] | boolean | undefined export type ParameterValue = number | string | string[] | boolean | undefined


onSwitch, onSwitch,
isInWorkflow, isInWorkflow,
}) => { }) => {
const { t } = useTranslation()
const language = useLanguage()
const [localValue, setLocalValue] = useState(value) const [localValue, setLocalValue] = useState(value)
const numberInputRef = useRef<HTMLInputElement>(null) const numberInputRef = useRef<HTMLInputElement>(null)



+ 1
- 2
web/app/components/plugins/marketplace/search-box/tags-filter.tsx 查看文件

const { t } = useMixedTranslation(locale) const { t } = useMixedTranslation(locale)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [searchText, setSearchText] = useState('') 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 filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchText.toLowerCase()))
const handleCheck = (id: string) => { const handleCheck = (id: string) => {
if (tags.includes(id)) if (tags.includes(id))
else else
onTagsChange([...tags, id]) onTagsChange([...tags, id])
} }
const selectedTagsLength = tags.length


return ( return (
<PortalToFollowElem <PortalToFollowElem

+ 1
- 1
web/app/components/plugins/marketplace/utils.ts 查看文件

} }


export const getMarketplacePluginsByCollectionId = async (collectionId: string, query?: CollectionsAndPluginsSearchParams) => { export const getMarketplacePluginsByCollectionId = async (collectionId: string, query?: CollectionsAndPluginsSearchParams) => {
let plugins = [] as Plugin[]
let plugins: Plugin[]


try { try {
const url = `${MARKETPLACE_API_PREFIX}/collections/${collectionId}/plugins` const url = `${MARKETPLACE_API_PREFIX}/collections/${collectionId}/plugins`

+ 1
- 4
web/app/components/share/text-generation/index.tsx 查看文件

const pendingTaskList = allTaskList.filter(task => task.status === TaskStatus.pending) const pendingTaskList = allTaskList.filter(task => task.status === TaskStatus.pending)
const noPendingTask = pendingTaskList.length === 0 const noPendingTask = pendingTaskList.length === 0
const showTaskList = allTaskList.filter(task => task.status !== TaskStatus.pending) const showTaskList = allTaskList.filter(task => task.status !== TaskStatus.pending)
const [currGroupNum, doSetCurrGroupNum] = useState(0)
const currGroupNumRef = useRef(0) const currGroupNumRef = useRef(0)

const setCurrGroupNum = (num: number) => { const setCurrGroupNum = (num: number) => {
doSetCurrGroupNum(num)
currGroupNumRef.current = num currGroupNumRef.current = num
} }
const getCurrGroupNum = () => { const getCurrGroupNum = () => {
const allFailedTaskList = allTaskList.filter(task => task.status === TaskStatus.failed) const allFailedTaskList = allTaskList.filter(task => task.status === TaskStatus.failed)
const allTasksFinished = allTaskList.every(task => task.status === TaskStatus.completed) const allTasksFinished = allTaskList.every(task => task.status === TaskStatus.completed)
const allTasksRun = allTaskList.every(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status)) const allTasksRun = allTaskList.every(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status))
const [batchCompletionRes, doSetBatchCompletionRes] = useState<Record<string, string>>({})
const batchCompletionResRef = useRef<Record<string, string>>({}) const batchCompletionResRef = useRef<Record<string, string>>({})
const setBatchCompletionRes = (res: Record<string, string>) => { const setBatchCompletionRes = (res: Record<string, string>) => {
doSetBatchCompletionRes(res)
batchCompletionResRef.current = res batchCompletionResRef.current = res
} }
const getBatchCompletionRes = () => batchCompletionResRef.current const getBatchCompletionRes = () => batchCompletionResRef.current

+ 1
- 1
web/app/components/workflow/block-selector/use-sticky-scroll.ts 查看文件

return return
const { height: wrapHeight, top: wrapTop } = wrapDom.getBoundingClientRect() const { height: wrapHeight, top: wrapTop } = wrapDom.getBoundingClientRect()
const { top: nextToStickyTop } = stickyDOM.getBoundingClientRect() const { top: nextToStickyTop } = stickyDOM.getBoundingClientRect()
let scrollPositionNew = ScrollPosition.belowTheWrap
let scrollPositionNew: ScrollPosition


if (nextToStickyTop - wrapTop >= wrapHeight) if (nextToStickyTop - wrapTop >= wrapHeight)
scrollPositionNew = ScrollPosition.belowTheWrap scrollPositionNew = ScrollPosition.belowTheWrap

+ 4
- 5
web/app/components/workflow/hooks/use-workflow.ts 查看文件

workflowTools: workflowTools || [], workflowTools: workflowTools || [],
}) })
} }
if(type === 'mcp') {
if (type === 'mcp') {
const mcpTools = await fetchAllMCPTools() const mcpTools = await fetchAllMCPTools()


workflowStore.setState({ workflowStore.setState({
const mcpTools = useStore(s => s.mcpTools) const mcpTools = useStore(s => s.mcpTools)


const toolIcon = useMemo(() => { const toolIcon = useMemo(() => {
if(!data)
if (!data)
return '' return ''
if (data.type === BlockEnum.Tool) { if (data.type === BlockEnum.Tool) {
let targetTools = buildInTools
let targetTools = workflowTools
if (data.provider_type === CollectionType.builtIn) if (data.provider_type === CollectionType.builtIn)
targetTools = buildInTools targetTools = buildInTools
else if (data.provider_type === CollectionType.custom) else if (data.provider_type === CollectionType.custom)
targetTools = customTools targetTools = customTools
else if (data.provider_type === CollectionType.mcp) else if (data.provider_type === CollectionType.mcp)
targetTools = mcpTools targetTools = mcpTools
else
targetTools = workflowTools

return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon
} }
}, [data, buildInTools, customTools, mcpTools, workflowTools]) }, [data, buildInTools, customTools, mcpTools, workflowTools])

+ 0
- 2
web/app/components/workflow/nodes/_base/components/node-control.tsx 查看文件

import { import {
useNodeDataUpdate, useNodeDataUpdate,
useNodesInteractions, useNodesInteractions,
useNodesSyncDraft,
} from '../../../hooks' } from '../../../hooks'
import { type Node, NodeRunningStatus } from '../../../types' import { type Node, NodeRunningStatus } from '../../../types'
import { canRunBySingle } from '../../../utils' import { canRunBySingle } from '../../../utils'
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const { handleNodeDataUpdate } = useNodeDataUpdate() const { handleNodeDataUpdate } = useNodeDataUpdate()
const { handleNodeSelect } = useNodesInteractions() const { handleNodeSelect } = useNodesInteractions()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const isSingleRunning = data._singleRunningStatus === NodeRunningStatus.Running const isSingleRunning = data._singleRunningStatus === NodeRunningStatus.Running
const handleOpenChange = useCallback((newOpen: boolean) => { const handleOpenChange = useCallback((newOpen: boolean) => {
setOpen(newOpen) setOpen(newOpen)

+ 0
- 1
web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx 查看文件

isShowSingleRun, isShowSingleRun,
hideSingleRun, hideSingleRun,
runningStatus, runningStatus,
handleStop,
runInputData, runInputData,
runInputDataRef, runInputDataRef,
runResult, runResult,

+ 2
- 3
web/app/components/workflow/nodes/list-operator/use-config.ts 查看文件

const { inputs, setInputs } = useNodeCrud<ListFilterNodeType>(id, payload) const { inputs, setInputs } = useNodeCrud<ListFilterNodeType>(id, payload)


const { getCurrentVariableType } = useWorkflowVariables() const { getCurrentVariableType } = useWorkflowVariables()

const getType = useCallback((variable?: ValueSelector) => { const getType = useCallback((variable?: ValueSelector) => {
const varType = getCurrentVariableType({ const varType = getCurrentVariableType({
parentNode: isInIteration ? iterationNode : loopNode, parentNode: isInIteration ? iterationNode : loopNode,
isChatMode, isChatMode,
isConstant: false, isConstant: false,
}) })
let itemVarType = VarType.string
let itemVarType = varType
switch (varType) { switch (varType) {
case VarType.arrayNumber: case VarType.arrayNumber:
itemVarType = VarType.number itemVarType = VarType.number
case VarType.arrayObject: case VarType.arrayObject:
itemVarType = VarType.object itemVarType = VarType.object
break break
default:
itemVarType = varType
} }
return { varType, itemVarType } return { varType, itemVarType }
}, [availableNodes, getCurrentVariableType, inputs.variable, isChatMode, isInIteration, iterationNode, loopNode]) }, [availableNodes, getCurrentVariableType, inputs.variable, isChatMode, isInIteration, iterationNode, loopNode])

+ 1
- 1
web/eslint.config.mjs 查看文件

'sonarjs/single-char-in-character-classes': 'off', 'sonarjs/single-char-in-character-classes': 'off',
'sonarjs/anchor-precedence': 'warn', 'sonarjs/anchor-precedence': 'warn',
'sonarjs/updated-loop-counter': 'off', 'sonarjs/updated-loop-counter': 'off',
'sonarjs/no-dead-store': 'warn',
'sonarjs/no-dead-store': 'error',
'sonarjs/no-duplicated-branches': 'warn', 'sonarjs/no-duplicated-branches': 'warn',
'sonarjs/max-lines': 'warn', // max 1000 lines 'sonarjs/max-lines': 'warn', // max 1000 lines
'sonarjs/no-variable-usage-before-declaration': 'error', 'sonarjs/no-variable-usage-before-declaration': 'error',

正在加载...
取消
保存