diff --git a/lint.config.ts b/lint.config.ts index 0976f698f44..a39467f0f50 100644 --- a/lint.config.ts +++ b/lint.config.ts @@ -876,11 +876,6 @@ export const lintConfig = { height: 'h', }, libraries: [ - { - prefix: 'i-custom-', - source: '^@/app/components/base/icons/src/(?(?:public|vender)(?:/.*)?)$', - name: '^(?.*)$', - }, { source: '^@remixicon/react$', name: '^(?Ri)(?.+)$', diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index 7b9d1907d81..013ce466cf0 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -63,9 +63,6 @@ } }, "web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx": { - "eslint-react/static-components": { - "count": 2 - }, "jsx-a11y/click-events-have-key-events": { "count": 3 }, @@ -284,11 +281,6 @@ "count": 1 } }, - "web/app/components/app/configuration/config-var/select-var-type.tsx": { - "typescript/no-explicit-any": { - "count": 1 - } - }, "web/app/components/app/configuration/config-var/var-item.tsx": { "jsx-a11y/mouse-events-have-key-events": { "count": 1 @@ -1071,216 +1063,6 @@ "count": 2 } }, - "web/app/components/base/icons/src/public/avatar/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/public/common/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 5 - } - }, - "web/app/components/base/icons/src/public/files/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 10 - } - }, - "web/app/components/base/icons/src/public/knowledge/dataset-card/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 4 - } - }, - "web/app/components/base/icons/src/public/knowledge/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 6 - } - }, - "web/app/components/base/icons/src/public/knowledge/online-drive/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/public/llm/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 9 - } - }, - "web/app/components/base/icons/src/public/other/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 4 - } - }, - "web/app/components/base/icons/src/public/tracing/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 21 - } - }, - "web/app/components/base/icons/src/vender/features/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 10 - } - }, - "web/app/components/base/icons/src/vender/knowledge/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 15 - } - }, - "web/app/components/base/icons/src/vender/line/alertsAndFeedback/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/line/arrows/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 4 - } - }, - "web/app/components/base/icons/src/vender/line/communication/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 3 - } - }, - "web/app/components/base/icons/src/vender/line/development/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/line/editor/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/line/education/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/line/files/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 4 - } - }, - "web/app/components/base/icons/src/vender/line/financeAndECommerce/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 3 - } - }, - "web/app/components/base/icons/src/vender/line/general/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 9 - } - }, - "web/app/components/base/icons/src/vender/line/images/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/line/mediaAndDevices/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/vender/line/others/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 4 - } - }, - "web/app/components/base/icons/src/vender/line/time/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/vender/other/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 8 - } - }, - "web/app/components/base/icons/src/vender/pipeline/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 3 - } - }, - "web/app/components/base/icons/src/vender/plugin/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/alertsAndFeedback/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/communication/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 6 - } - }, - "web/app/components/base/icons/src/vender/solid/development/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 3 - } - }, - "web/app/components/base/icons/src/vender/solid/editor/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/education/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/files/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 3 - } - }, - "web/app/components/base/icons/src/vender/solid/general/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 11 - } - }, - "web/app/components/base/icons/src/vender/solid/mediaAndDevices/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 2 - } - }, - "web/app/components/base/icons/src/vender/solid/security/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/shapes/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/solid/users/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/system/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 1 - } - }, - "web/app/components/base/icons/src/vender/workflow/index.ts": { - "no-barrel-files/no-barrel-files": { - "count": 30 - } - }, - "web/app/components/base/icons/utils.ts": { - "typescript/no-explicit-any": { - "count": 3 - } - }, "web/app/components/base/image-uploader/__tests__/utils.spec.ts": { "no-restricted-imports": { "count": 1 @@ -3275,7 +3057,7 @@ "count": 3 }, "typescript/no-explicit-any": { - "count": 2 + "count": 1 } }, "web/app/components/workflow/nodes/_base/components/setting-item.tsx": { @@ -3335,11 +3117,6 @@ "count": 1 } }, - "web/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-icon.tsx": { - "eslint-react/static-components": { - "count": 2 - } - }, "web/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-label.tsx": { "jsx-a11y/click-events-have-key-events": { "count": 1 @@ -3350,7 +3127,7 @@ }, "web/app/components/workflow/nodes/_base/components/variable/variable-label/hooks.ts": { "eslint-react/no-unnecessary-use-prefix": { - "count": 2 + "count": 1 } }, "web/app/components/workflow/nodes/_base/components/variable/variable-label/index.tsx": { @@ -3635,14 +3412,9 @@ "count": 6 } }, - "web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx": { - "typescript/no-explicit-any": { - "count": 4 - } - }, "web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/type.ts": { "typescript/no-explicit-any": { - "count": 2 + "count": 1 } }, "web/app/components/workflow/nodes/knowledge-base/types.ts": { @@ -4297,11 +4069,6 @@ "count": 2 } }, - "web/app/components/workflow/run/iteration-log/iteration-log-trigger.tsx": { - "dify/require-disable-directive-description": { - "count": 2 - } - }, "web/app/components/workflow/run/iteration-log/iteration-result-panel.tsx": { "jsx-a11y/click-events-have-key-events": { "count": 2 diff --git a/packages/iconify-collections/README.md b/packages/iconify-collections/README.md index f36b63d03b8..6271901e574 100644 --- a/packages/iconify-collections/README.md +++ b/packages/iconify-collections/README.md @@ -1,6 +1,6 @@ # @dify/iconify-collections -Pre-generated Iconify collections for Dify custom SVG icons. The web app imports these collections from this package so Tailwind does not need to scan and build custom SVG icon data from the old `web/app/components/base/icons/src` tree during dev startup. +Pre-generated Iconify collections for Dify custom SVG icons. The web app imports these collections from this package and renders icons with Tailwind CSS classes. ## Adding Custom SVG Icons @@ -38,6 +38,6 @@ becomes: ``` -Do not add new generated React icon components or JSON files under `web/app/components/base/icons/src/...` for new custom SVG icons. That path is legacy; new custom icons should flow through this package and be consumed as `i-custom-*` classes. +Custom vector icons flow through this package and are consumed as `i-custom-*` classes. Keep bitmap images (including SVGs embedding raster images) in their owning feature asset directory and render them as images. When reviewing generated `icons.json` diffs, check that unrelated existing icon groups did not lose or change their intrinsic `width` and `height`. If a group is layout-sensitive, add it to `scripts/check-icon-dimensions.ts`. diff --git a/packages/iconify-collections/assets/vender/line/arrows/sidebar-left-arrow.svg b/packages/iconify-collections/assets/vender/line/arrows/sidebar-left-arrow.svg new file mode 100644 index 00000000000..1fb59c899b2 --- /dev/null +++ b/packages/iconify-collections/assets/vender/line/arrows/sidebar-left-arrow.svg @@ -0,0 +1 @@ + diff --git a/packages/iconify-collections/assets/vender/line/general/annotations.svg b/packages/iconify-collections/assets/vender/line/general/annotations.svg new file mode 100644 index 00000000000..d71f4eabaed --- /dev/null +++ b/packages/iconify-collections/assets/vender/line/general/annotations.svg @@ -0,0 +1 @@ + diff --git a/packages/iconify-collections/assets/vender/plugin/plugin.svg b/packages/iconify-collections/assets/vender/plugin/plugin.svg new file mode 100644 index 00000000000..1d66a67c732 --- /dev/null +++ b/packages/iconify-collections/assets/vender/plugin/plugin.svg @@ -0,0 +1 @@ + diff --git a/packages/iconify-collections/assets/vender/solid/general/star.svg b/packages/iconify-collections/assets/vender/solid/general/star.svg new file mode 100644 index 00000000000..3c930053d4b --- /dev/null +++ b/packages/iconify-collections/assets/vender/solid/general/star.svg @@ -0,0 +1 @@ + diff --git a/packages/iconify-collections/custom-public/icons.json b/packages/iconify-collections/custom-public/icons.json index 2e6fbd864c8..39bde67c700 100644 --- a/packages/iconify-collections/custom-public/icons.json +++ b/packages/iconify-collections/custom-public/icons.json @@ -1,6 +1,6 @@ { "prefix": "custom-public", - "lastModified": 1786856617, + "lastModified": 1790053805, "icons": { "agent-building-blocks": { "body": "" diff --git a/packages/iconify-collections/custom-vender/icons.json b/packages/iconify-collections/custom-vender/icons.json index d92c4e2fd1e..57523bb3e96 100644 --- a/packages/iconify-collections/custom-vender/icons.json +++ b/packages/iconify-collections/custom-vender/icons.json @@ -1,6 +1,6 @@ { "prefix": "custom-vender", - "lastModified": 1785319384, + "lastModified": 1790053805, "icons": { "agent-v2-access-point": { "body": "", @@ -43,6 +43,24 @@ "body": "", "width": 17 }, + "app-publisher-deploying-chevron": { + "body": "", + "width": 8.27613, + "height": 5.08087 + }, + "deploy-code-block": { + "body": "" + }, + "deploy-line-5": { + "body": "", + "width": 12, + "height": 39 + }, + "deploy-rocket": { + "body": "", + "width": 14, + "height": 14 + }, "features-citations": { "body": "", "width": 24, @@ -283,13 +301,12 @@ }, "line-arrows-arrow-narrow-left": { "body": "", - "width": 17, - "height": 16 + "width": 17 }, "line-arrows-arrow-up-right": { "body": "", - "width": 14, - "height": 14 + "height": 14, + "width": 14 }, "line-arrows-chevron-down-double": { "body": "", @@ -298,8 +315,8 @@ }, "line-arrows-chevron-right": { "body": "", - "width": 14, - "height": 14 + "height": 14, + "width": 14 }, "line-arrows-chevron-selector-vertical": { "body": "", @@ -308,8 +325,8 @@ }, "line-arrows-iconr": { "body": "", - "width": 14, - "height": 14 + "height": 14, + "width": 14 }, "line-arrows-refresh-ccw-01": { "body": "", @@ -318,13 +335,15 @@ }, "line-arrows-refresh-cw-05": { "body": "", - "width": 16, - "height": 16 + "width": 16 }, "line-arrows-reverse-left": { "body": "", - "width": 16, - "height": 16 + "width": 16 + }, + "line-arrows-sidebar-left-arrow": { + "body": "", + "width": 16 }, "line-communication-ai-text": { "body": "", @@ -531,6 +550,9 @@ "width": 16, "height": 16 }, + "line-general-annotations": { + "body": "" + }, "line-general-at-sign": { "body": "" }, @@ -1020,6 +1042,9 @@ "width": 13, "height": 20 }, + "plugin-plugin": { + "body": "" + }, "plugin-trigger": { "body": "" }, @@ -1291,6 +1316,11 @@ "width": 24, "height": 24 }, + "solid-general-star": { + "body": "", + "width": 18, + "height": 18 + }, "solid-general-target-04": { "body": "", "width": 24, @@ -1592,24 +1622,6 @@ "body": "", "width": 16, "height": 16 - }, - "app-publisher-deploying-chevron": { - "body": "", - "width": 8.27613, - "height": 5.08087 - }, - "deploy-code-block": { - "body": "" - }, - "deploy-line-5": { - "body": "", - "width": 12, - "height": 39 - }, - "deploy-rocket": { - "body": "", - "width": 14, - "height": 14 } } } diff --git a/packages/iconify-collections/custom-vender/info.json b/packages/iconify-collections/custom-vender/info.json index 6c61adcc7c4..368602cddfc 100644 --- a/packages/iconify-collections/custom-vender/info.json +++ b/packages/iconify-collections/custom-vender/info.json @@ -1,7 +1,7 @@ { "prefix": "custom-vender", "name": "Dify Custom Vender", - "total": 350, + "total": 354, "version": "0.0.0-private", "author": { "name": "LangGenius, Inc.", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7abd3799a6..e0974435ba6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -260,9 +260,6 @@ catalogs: '@remixicon/react': specifier: 4.9.0 version: 4.9.0 - '@rgrove/parse-xml': - specifier: 5.0.0 - version: 5.0.0 '@sentry/react': specifier: 10.75.0 version: 10.75.0 @@ -1746,9 +1743,6 @@ importers: '@langgenius/dify-ui': specifier: workspace:* version: link:../packages/dify-ui - '@rgrove/parse-xml': - specifier: 'catalog:' - version: 5.0.0 '@storybook/addon-docs': specifier: 'catalog:' version: 10.6.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(storybook@10.6.0(@types/react@19.3.0)(react@19.3.0)(vite-plus@0.3.3(@types/node@25.9.7)(@typescript/typescript6@6.0.2)(@vitest/browser-playwright@4.1.11)(@vitest/coverage-v8@4.1.11)(esbuild@0.28.2)(happy-dom@20.14.5)(jiti@2.7.0)(tsx@4.23.13)(yaml@2.9.1))) @@ -4184,10 +4178,6 @@ packages: resolution: {integrity: sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg==} engines: {node: '>= 10'} - '@rgrove/parse-xml@5.0.0': - resolution: {integrity: sha512-SgHFyisNAkS2ZbM8SCriUm1N0bxLiz0POKvpDeAtrnLrXaYG1PawNwu1rSjmE/vcVHbZzYWNgVP6xkep6R4uXg==} - engines: {node: '>=22.12.0'} - '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} @@ -11762,8 +11752,6 @@ snapshots: '@resvg/resvg-wasm@2.4.0': {} - '@rgrove/parse-xml@5.0.0': {} - '@rolldown/pluginutils@1.0.1': {} '@rollup/pluginutils@5.4.0': @@ -18075,7 +18063,7 @@ snapshots: optionalDependencies: '@types/node': 25.9.7 '@vitest/browser-playwright': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.9.7)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)(typescript@7.0.2)(yaml@2.9.1))(playwright@1.63.0)(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.9.7)(@typescript/typescript6@6.0.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)(yaml@2.9.1))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.9.7)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)(typescript@7.0.2)(yaml@2.9.1))(vitest@4.1.11) '@vitest/coverage-v8': 4.1.11(@vitest/browser@4.1.11)(vitest@4.1.11) happy-dom: 20.14.5 transitivePeerDependencies: @@ -18291,7 +18279,6 @@ time: '@orpc/tanstack-query@1.15.1': '2026-09-15T07:09:56.725Z' '@playwright/test@1.63.0': '2026-09-04T22:44:00.304Z' '@remixicon/react@4.9.0': '2026-01-29T10:53:18.993Z' - '@rgrove/parse-xml@5.0.0': '2026-08-30T03:19:42.049Z' '@sentry/react@10.75.0': '2026-09-16T14:58:08.681Z' '@shadcn/lint@0.1.3': '2026-09-20T18:26:44.252Z' '@storybook/addon-a11y@10.6.0': '2026-09-02T13:57:15.272Z' diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bc8cfc5e39d..43867df97ef 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -94,7 +94,6 @@ catalog: '@orpc/tanstack-query': 1.15.1 '@playwright/test': 1.63.0 '@remixicon/react': 4.9.0 - '@rgrove/parse-xml': 5.0.0 '@sentry/react': 10.75.0 '@shadcn/lint': 0.1.3 '@storybook/addon-a11y': 10.6.0 diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/index.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/index.tsx index 401424965b6..53803270228 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/index.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/index.tsx @@ -10,7 +10,6 @@ import dayjs from 'dayjs' import * as React from 'react' import { useCallback, useState } from 'react' import { useLocale } from '#i18n' -import { HourglassShape } from '@/app/components/base/icons/src/vender/other' import { formatToLocalTime } from '@/utils/format' import DatePicker from './date-picker' import RangeSelector from './range-selector' @@ -76,7 +75,10 @@ const TimeRangePicker: FC = ({ ranges, onSelect, queryDateFormat }) => { return (
- + ({ StatusDot: ({ status }: { status: string }) => {status}, })) -vi.mock('@/app/components/base/icons/src/public/tracing', () => ({ - AliyunIcon: () => , - ArizeIcon: () => , - DatabricksIcon: () => , - LangfuseIcon: () => , - LangsmithIcon: () => , - MlflowIcon: () => , - OpikIcon: () => , - PhoenixIcon: () => , - TencentIcon: () => , - TracingIcon: () => , - WeaveIcon: () => , -})) - vi.mock('../config-button', () => ({ default: ({ children, diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx index 1b3db3e4133..fa7366fe36e 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx @@ -24,18 +24,6 @@ import * as React from 'react' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useStore as useAppStore } from '@/app/components/app/store' -import { - AliyunIcon, - ArizeIcon, - DatabricksIcon, - LangfuseIcon, - LangsmithIcon, - MlflowIcon, - OpikIcon, - PhoenixIcon, - TencentIcon, - WeaveIcon, -} from '@/app/components/base/icons/src/public/tracing' import { LoadingPlaceholder } from '@/app/components/base/loading-placeholder' import { toast } from '@/app/notifications' import { workspacePermissionKeysAtom } from '@/context/permission-state' @@ -105,19 +93,21 @@ const Panel: FC = () => { } const inUseTracingProvider: TracingProvider | null = tracingStatus?.tracing_provider || null - const providerIconMap: Record> = { - [TracingProvider.arize]: ArizeIcon, - [TracingProvider.phoenix]: PhoenixIcon, - [TracingProvider.langSmith]: LangsmithIcon, - [TracingProvider.langfuse]: LangfuseIcon, - [TracingProvider.opik]: OpikIcon, - [TracingProvider.weave]: WeaveIcon, - [TracingProvider.aliyun]: AliyunIcon, - [TracingProvider.mlflow]: MlflowIcon, - [TracingProvider.databricks]: DatabricksIcon, - [TracingProvider.tencent]: TencentIcon, + const providerIconClassMap: Record = { + [TracingProvider.arize]: 'i-custom-public-tracing-arize-icon w-18.5', + [TracingProvider.phoenix]: 'i-custom-public-tracing-phoenix-icon w-18.5', + [TracingProvider.langSmith]: 'i-custom-public-tracing-langsmith-icon w-21', + [TracingProvider.langfuse]: 'i-custom-public-tracing-langfuse-icon w-18.5', + [TracingProvider.opik]: 'i-custom-public-tracing-opik-icon w-[47.133904px]', + [TracingProvider.weave]: 'i-custom-public-tracing-weave-icon w-30', + [TracingProvider.aliyun]: 'i-custom-public-tracing-aliyun-icon w-16.25', + [TracingProvider.mlflow]: 'i-custom-public-tracing-mlflow-icon w-11', + [TracingProvider.databricks]: 'i-custom-public-tracing-databricks-icon w-25', + [TracingProvider.tencent]: 'i-custom-public-tracing-tencent-icon w-20', } - const InUseProviderIcon = inUseTracingProvider ? providerIconMap[inUseTracingProvider] : undefined + const inUseProviderIconClassName = inUseTracingProvider + ? providerIconClassMap[inUseTracingProvider] + : undefined const [arizeConfig, setArizeConfig] = useState(null) const [phoenixConfig, setPhoenixConfig] = useState(null) @@ -339,7 +329,9 @@ const Panel: FC = () => { {t(($) => $[`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`], { ns: 'app' })}
- {InUseProviderIcon && } + {inUseProviderIconClassName && ( + + )}
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx index 4a2921eadc2..2d3dff24e84 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx @@ -28,8 +28,6 @@ import { useBoolean } from 'ahooks' import * as React from 'react' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' -import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security' import { toast } from '@/app/notifications' import { addTracingConfig, removeTracingConfig, updateTracingConfig } from '@/service/apps' import { docURL } from './config' @@ -783,7 +781,10 @@ const ProviderConfigModal: FC = ({ key: t(($) => $[`tracing.${type}.title`], { ns: 'app' }), })}
- +
{isEdit && ( @@ -820,7 +821,10 @@ const ProviderConfigModal: FC = ({
- + {t(($) => $['modelProvider.encrypted.front'], { ns: 'common' })} void }> -const getIcon = (type: TracingProvider) => { +const getIconClassName = (type: TracingProvider) => { return { - [TracingProvider.arize]: ArizeIconBig, - [TracingProvider.phoenix]: PhoenixIconBig, - [TracingProvider.langSmith]: LangsmithIconBig, - [TracingProvider.langfuse]: LangfuseIconBig, - [TracingProvider.opik]: OpikIconBig, - [TracingProvider.weave]: WeaveIconBig, - [TracingProvider.aliyun]: AliyunIconBig, - [TracingProvider.mlflow]: MlflowIconBig, - [TracingProvider.databricks]: DatabricksIconBig, - [TracingProvider.tencent]: TencentIconBig, + [TracingProvider.arize]: 'i-custom-public-tracing-arize-icon-big w-27.75', + [TracingProvider.phoenix]: 'i-custom-public-tracing-phoenix-icon-big w-27.75', + [TracingProvider.langSmith]: 'i-custom-public-tracing-langsmith-icon-big w-31', + [TracingProvider.langfuse]: 'i-custom-public-tracing-langfuse-icon-big w-27.75', + [TracingProvider.opik]: 'i-custom-public-tracing-opik-icon-big w-[70.700851px]', + [TracingProvider.weave]: 'i-custom-public-tracing-weave-icon-big w-31', + [TracingProvider.aliyun]: 'i-custom-public-tracing-aliyun-icon-big w-24', + [TracingProvider.mlflow]: 'i-custom-public-tracing-mlflow-icon-big w-16.25', + [TracingProvider.databricks]: 'i-custom-public-tracing-databricks-icon-big w-37.5', + [TracingProvider.tencent]: 'i-custom-public-tracing-tencent-icon-big w-30', }[type] } @@ -57,7 +44,7 @@ const ProviderPanel: FC = ({ onConfig, }) => { const { t } = useTranslation() - const Icon = getIcon(type) + const iconClassName = getIconClassName(type) const handleConfigBtnClick = useCallback( (e: React.MouseEvent) => { @@ -99,7 +86,7 @@ const ProviderPanel: FC = ({ >
- + {isChosen && (
{t(($) => $[`${I18N_PREFIX}.inUse`], { ns: 'app' })} @@ -113,7 +100,7 @@ const ProviderPanel: FC = ({ className="flex h-6 cursor-pointer items-center space-x-1 rounded-md border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-2 text-text-secondary shadow-xs" onClick={viewBtnClick} > - +
{t(($) => $[`${I18N_PREFIX}.view`], { ns: 'app' })}
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/tracing-icon.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/tracing-icon.tsx index 6bbf84148cf..129e1e67fd7 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/tracing-icon.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/tracing-icon.tsx @@ -2,7 +2,6 @@ import type { FC } from 'react' import { cn } from '@langgenius/dify-ui/cn' import * as React from 'react' -import { TracingIcon as Icon } from '@/app/components/base/icons/src/public/tracing' type Props = Readonly<{ className?: string @@ -18,7 +17,7 @@ const TracingIcon: FC = ({ className, size }) => { const sizeClass = sizeClassMap[size] return (
- +
) } diff --git a/web/app/(shareLayout)/webapp-signin/components/sso-auth.tsx b/web/app/(shareLayout)/webapp-signin/components/sso-auth.tsx index 210a7077e31..b4e7d27ce10 100644 --- a/web/app/(shareLayout)/webapp-signin/components/sso-auth.tsx +++ b/web/app/(shareLayout)/webapp-signin/components/sso-auth.tsx @@ -5,7 +5,6 @@ import { Button } from '@langgenius/dify-ui/button' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { resolveWebAppLoginRedirect } from '@/app/(shareLayout)/webapp-signin/login-redirect' -import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security' import { toast } from '@/app/notifications' import { useRouter, useSearchParams } from '@/next/navigation' import { @@ -81,7 +80,10 @@ function SSOAuth({ protocol }: SSOAuthProps) { disabled={isLoading} className="w-full" > - + {t(($) => $.withSSO, { ns: 'login' })} ) diff --git a/web/app/components/app-sidebar/app-detail-section.tsx b/web/app/components/app-sidebar/app-detail-section.tsx index 7075369343c..65adcf7043b 100644 --- a/web/app/components/app-sidebar/app-detail-section.tsx +++ b/web/app/components/app-sidebar/app-detail-section.tsx @@ -1,7 +1,5 @@ 'use client' -import type { ComponentProps } from 'react' -import type { NavIcon } from './nav-link' import { cn } from '@langgenius/dify-ui/cn' import { Separator } from '@langgenius/dify-ui/separator' import { useSuspenseQuery } from '@tanstack/react-query' @@ -9,7 +7,6 @@ import { useAtomValue } from 'jotai' import { Fragment, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { useStore } from '@/app/components/app/store' -import Annotations from '@/app/components/base/icons/src/vender/Annotations' import { workspacePermissionKeysAtom } from '@/context/permission-state' import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' @@ -23,38 +20,10 @@ import NavLink from './nav-link' type AppDetailNavItem = { name: string href: string - icon: NavIcon - selectedIcon: NavIcon + icon: string + selectedIcon: string } -const AnnotationNavIcon = ({ className, ...props }: ComponentProps) => ( - -) - -AnnotationNavIcon.displayName = 'Annotations' - -const createClassNameNavIcon = (iconClassName: string) => { - const ClassNameNavIcon = ({ className }: ComponentProps<'svg'>) => ( - - ) - - ClassNameNavIcon.displayName = 'ClassNameNavIcon' - - return ClassNameNavIcon -} - -const accessPointNavIcon = createClassNameNavIcon('i-custom-vender-agent-v2-access-point') -const terminalWindowLineNavIcon = createClassNameNavIcon('i-ri-terminal-window-line') -const terminalWindowFillNavIcon = createClassNameNavIcon('i-ri-terminal-window-fill') -const instanceLineNavIcon = createClassNameNavIcon('i-ri-instance-line') -const instanceFillNavIcon = createClassNameNavIcon('i-ri-instance-fill') -const fileListLineNavIcon = createClassNameNavIcon('i-ri-file-list-3-line') -const fileListFillNavIcon = createClassNameNavIcon('i-ri-file-list-3-fill') -const dashboardLineNavIcon = createClassNameNavIcon('i-ri-dashboard-2-line') -const dashboardFillNavIcon = createClassNameNavIcon('i-ri-dashboard-2-fill') -const lockLineNavIcon = createClassNameNavIcon('i-ri-lock-2-line') -const lockFillNavIcon = createClassNameNavIcon('i-ri-lock-2-fill') - const isLogsNavItem = (item: AppDetailNavItem) => item.href.endsWith('/logs') const isAnnotationsNavItem = (item: AppDetailNavItem) => item.href.endsWith('/annotations') @@ -109,8 +78,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.promptEng'], { ns: 'common' }), href: `/app/${appId}/${isWorkflowApp ? 'workflow' : 'configuration'}`, - icon: terminalWindowLineNavIcon, - selectedIcon: terminalWindowFillNavIcon, + icon: 'i-ri-terminal-window-line', + selectedIcon: 'i-ri-terminal-window-fill', }, ] : []), @@ -119,8 +88,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.accessPoint'], { ns: 'common' }), href: `/app/${appId}/access-point`, - icon: accessPointNavIcon, - selectedIcon: accessPointNavIcon, + icon: 'i-custom-vender-agent-v2-access-point', + selectedIcon: 'i-custom-vender-agent-v2-access-point', }, ] : []), @@ -129,8 +98,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.deploy'], { ns: 'common' }), href: `/app/${appId}/deploy`, - icon: instanceLineNavIcon, - selectedIcon: instanceFillNavIcon, + icon: 'i-ri-instance-line', + selectedIcon: 'i-ri-instance-fill', }, ] : []), @@ -139,8 +108,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.logs'], { ns: 'common' }), href: `/app/${appId}/logs`, - icon: fileListLineNavIcon, - selectedIcon: fileListFillNavIcon, + icon: 'i-ri-file-list-3-line', + selectedIcon: 'i-ri-file-list-3-fill', }, ] : []), @@ -149,8 +118,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.annotations'], { ns: 'common' }), href: `/app/${appId}/annotations`, - icon: AnnotationNavIcon, - selectedIcon: AnnotationNavIcon, + icon: 'i-custom-vender-line-general-annotations size-4', + selectedIcon: 'i-custom-vender-line-general-annotations size-4', }, ] : []), @@ -159,8 +128,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['appMenus.overview'], { ns: 'common' }), href: `/app/${appId}/overview`, - icon: dashboardLineNavIcon, - selectedIcon: dashboardFillNavIcon, + icon: 'i-ri-dashboard-2-line', + selectedIcon: 'i-ri-dashboard-2-fill', }, ] : []), @@ -169,8 +138,8 @@ const AppDetailSection = ({ expand = true }: AppDetailSectionProps) => { { name: t(($) => $['settings.resourceAccess'], { ns: 'common' }), href: `/app/${appId}/access-config`, - icon: lockLineNavIcon, - selectedIcon: lockFillNavIcon, + icon: 'i-ri-lock-2-line', + selectedIcon: 'i-ri-lock-2-fill', }, ] : []), diff --git a/web/app/components/app-sidebar/app-detail-top.tsx b/web/app/components/app-sidebar/app-detail-top.tsx index 0728543faca..6983e8b744b 100644 --- a/web/app/components/app-sidebar/app-detail-top.tsx +++ b/web/app/components/app-sidebar/app-detail-top.tsx @@ -12,7 +12,6 @@ import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { formatForDisplay } from '@tanstack/react-hotkeys' import { useTranslation } from 'react-i18next' -import SidebarLeftArrowIcon from '@/app/components/base/icons/src/vender/SidebarLeftArrowIcon' import { DetailSidebarToggleButton } from '@/app/components/detail-sidebar/toggle-button' import { gotoAnythingDialogHandle } from '@/app/components/goto-anything/dialog-handle' import { GOTO_ANYTHING_HOTKEY } from '@/app/components/goto-anything/hotkeys' @@ -33,7 +32,9 @@ export function AppDetailTop({ expand = true, onToggle }: AppDetailTopProps) { } + icon={ + + } /> )}
@@ -101,7 +102,9 @@ export function AppDetailTop({ expand = true, onToggle }: AppDetailTopProps) { } + icon={ + + } /> )}
diff --git a/web/app/components/app-sidebar/dataset-detail-section.tsx b/web/app/components/app-sidebar/dataset-detail-section.tsx index 3f9df66854a..68e6b6e3024 100644 --- a/web/app/components/app-sidebar/dataset-detail-section.tsx +++ b/web/app/components/app-sidebar/dataset-detail-section.tsx @@ -1,23 +1,11 @@ 'use client' -import type { RemixiconComponentType } from '@remixicon/react' import { cn } from '@langgenius/dify-ui/cn' import { Separator } from '@langgenius/dify-ui/separator' -import { - RiEqualizer2Fill, - RiEqualizer2Line, - RiFileTextFill, - RiFileTextLine, - RiFocus2Fill, - RiFocus2Line, - RiLock2Fill, - RiLock2Line, -} from '@remixicon/react' import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { PipelineFill, PipelineLine } from '@/app/components/base/icons/src/vender/pipeline' import ExtraInfo from '@/app/components/datasets/extra-info' import DatasetDetailContext from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' @@ -84,15 +72,15 @@ const DatasetDetailSection = ({ expand = true }: DatasetDetailSectionProps) => { { name: t(($) => $['datasetMenus.hitTesting'], { ns: 'common' }), href: `/datasets/${datasetId}/hitTesting`, - icon: RiFocus2Line, - selectedIcon: RiFocus2Fill, + icon: 'i-ri-focus-2-line', + selectedIcon: 'i-ri-focus-2-fill', disabled: isButtonDisabledWithPipeline || !datasetACLCapabilities.canRetrievalRecall, }, { name: t(($) => $['datasetMenus.settings'], { ns: 'common' }), href: `/datasets/${datasetId}/settings`, - icon: RiEqualizer2Line, - selectedIcon: RiEqualizer2Fill, + icon: 'i-ri-equalizer-2-line', + selectedIcon: 'i-ri-equalizer-2-fill', disabled: false, }, ...(datasetACLCapabilities.canAccessConfig @@ -100,8 +88,8 @@ const DatasetDetailSection = ({ expand = true }: DatasetDetailSectionProps) => { { name: t(($) => $['settings.resourceAccess'], { ns: 'common' }), href: `/datasets/${datasetId}/access-config`, - icon: RiLock2Line, - selectedIcon: RiLock2Fill, + icon: 'i-ri-lock-2-line', + selectedIcon: 'i-ri-lock-2-fill', disabled: false, }, ] @@ -112,15 +100,15 @@ const DatasetDetailSection = ({ expand = true }: DatasetDetailSectionProps) => { baseNavigation.unshift({ name: t(($) => $['datasetMenus.pipeline'], { ns: 'common' }), href: `/datasets/${datasetId}/pipeline`, - icon: PipelineLine as RemixiconComponentType, - selectedIcon: PipelineFill as RemixiconComponentType, + icon: 'i-custom-vender-pipeline-pipeline-line', + selectedIcon: 'i-custom-vender-pipeline-pipeline-fill', disabled: false, }) baseNavigation.unshift({ name: t(($) => $['datasetMenus.documents'], { ns: 'common' }), href: `/datasets/${datasetId}/documents`, - icon: RiFileTextLine, - selectedIcon: RiFileTextFill, + icon: 'i-ri-file-text-line', + selectedIcon: 'i-ri-file-text-fill', disabled: isButtonDisabledWithPipeline, }) } diff --git a/web/app/components/app-sidebar/dataset-detail-top.tsx b/web/app/components/app-sidebar/dataset-detail-top.tsx index 27b3008b3b1..1642f285a2d 100644 --- a/web/app/components/app-sidebar/dataset-detail-top.tsx +++ b/web/app/components/app-sidebar/dataset-detail-top.tsx @@ -12,7 +12,6 @@ import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { formatForDisplay } from '@tanstack/react-hotkeys' import { useTranslation } from 'react-i18next' -import SidebarLeftArrowIcon from '@/app/components/base/icons/src/vender/SidebarLeftArrowIcon' import { DetailSidebarToggleButton } from '@/app/components/detail-sidebar/toggle-button' import { gotoAnythingDialogHandle } from '@/app/components/goto-anything/dialog-handle' import { GOTO_ANYTHING_HOTKEY } from '@/app/components/goto-anything/hotkeys' @@ -33,7 +32,9 @@ export function DatasetDetailTop({ expand = true, onToggle }: DatasetDetailTopPr } + icon={ + + } /> )}
@@ -101,7 +102,9 @@ export function DatasetDetailTop({ expand = true, onToggle }: DatasetDetailTopPr } + icon={ + + } /> )}
diff --git a/web/app/components/app-sidebar/nav-link/__tests__/index.spec.tsx b/web/app/components/app-sidebar/nav-link/__tests__/index.spec.tsx index e140934cfe0..eb4d8e6d70e 100644 --- a/web/app/components/app-sidebar/nav-link/__tests__/index.spec.tsx +++ b/web/app/components/app-sidebar/nav-link/__tests__/index.spec.tsx @@ -30,48 +30,24 @@ vi.mock('@/next/link', () => ({ }, })) -const SelectedIcon = ({ className }: { className?: string }) => ( - -) - -const NormalIcon = ({ className }: { className?: string }) => ( - -) - describe('NavLink', () => { const mockProps: NavLinkProps = { name: 'Orchestrate', href: '/app/123/workflow', iconMap: { - selected: SelectedIcon, - normal: NormalIcon, + selected: 'i-ri-terminal-window-fill', + normal: 'i-ri-terminal-window-line', }, } describe('Active State Handling', () => { - it('should use the selected icon when the link matches the current route', () => { + it('links to the selected destination with its accessible name', () => { render() expect(screen.getByRole('link', { name: 'Orchestrate' })).toHaveAttribute( 'href', '/app/123/overview', ) - expect(screen.getByTestId('selected-nav-icon')).toBeInTheDocument() - expect(screen.queryByTestId('normal-nav-icon')).not.toBeInTheDocument() - }) - - it('should not mark logs active on the annotations pathname', () => { - render() - - expect(screen.getByTestId('normal-nav-icon')).toBeInTheDocument() - expect(screen.queryByTestId('selected-nav-icon')).not.toBeInTheDocument() - }) - - it('should use pathname to mark annotations active when rendered outside the app detail route segment', () => { - render() - - expect(screen.getByTestId('selected-nav-icon')).toBeInTheDocument() - expect(screen.queryByTestId('normal-nav-icon')).not.toBeInTheDocument() }) }) diff --git a/web/app/components/app-sidebar/nav-link/index.tsx b/web/app/components/app-sidebar/nav-link/index.tsx index 8c6d9a2b486..c7779020344 100644 --- a/web/app/components/app-sidebar/nav-link/index.tsx +++ b/web/app/components/app-sidebar/nav-link/index.tsx @@ -1,25 +1,15 @@ 'use client' -import type { RemixiconComponentType } from '@remixicon/react' import { cn } from '@langgenius/dify-ui/cn' import * as React from 'react' import Link from '@/next/link' import { useSelectedLayoutSegment } from '@/next/navigation' -export type NavIcon = - | React.ComponentType< - React.PropsWithoutRef> & { - title?: string | undefined - titleId?: string | undefined - } - > - | RemixiconComponentType - export type NavLinkProps = { name: string href?: string iconMap: { - selected: NavIcon - normal: NavIcon + selected: string + normal: string } mode?: string disabled?: boolean @@ -49,7 +39,7 @@ const NavLink = ({ ) const isActive = active ?? (href ? href.toLowerCase().split('/')?.pop() === formattedSegment : false) - const NavIcon = isActive ? iconMap.selected : iconMap.normal + const iconClassName = isActive ? iconMap.selected : iconMap.normal const isCollapsed = mode !== 'expand' const borderClassName = 'border-t-[0.75px] border-r-[0.25px] border-b-[0.25px] border-l-[0.75px]' @@ -66,7 +56,7 @@ const NavLink = ({ const renderIcon = () => (
-
) diff --git a/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx b/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx index 7936fbd0ca5..4dc979e3208 100644 --- a/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx +++ b/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react' import { Textarea } from '@langgenius/dify-ui/textarea' import * as React from 'react' import { useTranslation } from 'react-i18next' -import { Robot, User } from '@/app/components/base/icons/src/public/avatar' +import robotAvatar from '../../assets/robot-avatar.svg' export const EditItemType = { Query: 'query', @@ -20,7 +20,11 @@ type Props = Readonly<{ const EditItem: FC = ({ type, content, onChange }) => { const { t } = useTranslation() const avatar = - type === EditItemType.Query ? : + type === EditItemType.Query ? ( + + ) : ( + + ) const name = type === EditItemType.Query ? t(($) => $['addModal.queryName'], { ns: 'appAnnotation' }) diff --git a/packages/iconify-collections/assets/public/avatar/robot.svg b/web/app/components/app/annotation/assets/robot-avatar.svg similarity index 100% rename from packages/iconify-collections/assets/public/avatar/robot.svg rename to web/app/components/app/annotation/assets/robot-avatar.svg diff --git a/web/app/components/app/annotation/batch-add-annotation-modal/csv-downloader.tsx b/web/app/components/app/annotation/batch-add-annotation-modal/csv-downloader.tsx index 6648a6472f7..4aadfdddb89 100644 --- a/web/app/components/app/annotation/batch-add-annotation-modal/csv-downloader.tsx +++ b/web/app/components/app/annotation/batch-add-annotation-modal/csv-downloader.tsx @@ -4,7 +4,6 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' import { useCSVDownloader } from 'react-papaparse' import { useLocale } from '#i18n' -import { Download02 as DownloadIcon } from '@/app/components/base/icons/src/vender/solid/general' import { LanguagesSupported } from '@/i18n/language' const CSV_TEMPLATE_QA_EN = [ @@ -73,7 +72,7 @@ const CSVDownload: FC = () => { data={getTemplate()} >
- + {t(($) => $['batchModal.template'], { ns: 'appAnnotation' })}
diff --git a/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx b/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx index 7388d5cea69..12f5147efad 100644 --- a/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx +++ b/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx @@ -6,7 +6,6 @@ import { RiDeleteBinLine } from '@remixicon/react' import * as React from 'react' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Csv as CSVIcon } from '@/app/components/base/icons/src/public/files' import { toast } from '@/app/notifications' export type Props = Readonly<{ @@ -92,7 +91,7 @@ const CSVUploader: FC = ({ file, updateFile }) => { )} >
- +
{t(($) => $['batchModal.csvUploadTitle'], { ns: 'appAnnotation' })} , - CopyCheck: () => copy-checked, -})) - vi.mock('@/context/event-emitter', () => ({ useEventEmitterContextContext: () => ({ eventEmitter: { @@ -115,7 +111,8 @@ describe('AdvancedPromptInput', () => { vi.clearAllMocks() }) - it('should delegate prompt text and role changes to the parent callbacks', () => { + it('should delegate prompt text and role changes to the parent callbacks', async () => { + const user = userEvent.setup() render( { , ) - fireEvent.click(screen.getByText('change-advanced')) - fireEvent.click(screen.getByText('selector:user')) - fireEvent.click(screen.getByText('copy-prompt')) - fireEvent.click(screen.getByText('delete-prompt')) + await user.click(screen.getByText('change-advanced')) + await user.click(screen.getByText('selector:user')) + const copyButton = screen.getByRole('button', { name: 'common.operation.copy' }) + await user.click(copyButton) + expect(copyButton).toHaveFocus() + expect(copyButton).toHaveAttribute('aria-disabled', 'true') + await user.keyboard('{Enter} ') + expect(mockCopy).toHaveBeenCalledTimes(1) + await user.click(screen.getByText('delete-prompt')) expect(mockOnChange).toHaveBeenCalledWith('Updated {{new_var}}') expect(mockOnTypeChange).toHaveBeenCalledWith('assistant') diff --git a/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx b/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx index efaeeb08409..3bf82ec748d 100644 --- a/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx +++ b/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx @@ -4,6 +4,7 @@ import type { ExternalDataTool } from '@/models/common' import type { PromptRole, PromptVariable } from '@/models/debug' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' +import { IconButton } from '@langgenius/dify-ui/icon-button' import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip' import { RiDeleteBinLine, RiErrorWarningFill } from '@remixicon/react' import { useBoolean } from 'ahooks' @@ -14,7 +15,6 @@ import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import { ADD_EXTERNAL_DATA_TOOL } from '@/app/components/app/configuration/config-var' import { toast } from '@/app/components/app/configuration/toast' -import { Copy, CopyCheck } from '@/app/components/base/icons/src/vender/line/files' import PromptEditor from '@/app/components/base/prompt-editor' import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block' import ConfigContext from '@/context/debug-configuration' @@ -210,17 +210,26 @@ const AdvancedPromptInput: FC = ({ className="size-6 cursor-pointer p-1 text-text-tertiary" /> )} - {!isCopied ? ( - { - copy(value) - setIsCopied(true) - }} + $['operation.copy'], { ns: 'common' })} + aria-disabled={isCopied} + size="md" + onClick={() => { + if (isCopied) return + copy(value) + setIsCopied(true) + }} + > + - ) : ( - - )} +
)} diff --git a/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx b/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx index 3ac01847344..82f19a6c223 100644 --- a/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx +++ b/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx @@ -4,7 +4,6 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' import Panel from '@/app/components/app/configuration/base/feature-panel' import { OperationButton } from '@/app/components/app/configuration/base/operation-button' -import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid/general' type Props = Readonly<{ showWarning: boolean @@ -23,7 +22,10 @@ const HistoryPanel: FC = ({ showWarning, onShowEditModal }) => { } headerIcon={
- +
} headerRight={ diff --git a/web/app/components/app/configuration/config-prompt/message-type-selector.tsx b/web/app/components/app/configuration/config-prompt/message-type-selector.tsx index 94520e6d5c0..c1f63dbff5f 100644 --- a/web/app/components/app/configuration/config-prompt/message-type-selector.tsx +++ b/web/app/components/app/configuration/config-prompt/message-type-selector.tsx @@ -3,7 +3,6 @@ import type { FC } from 'react' import { cn } from '@langgenius/dify-ui/cn' import { useBoolean, useClickAway } from 'ahooks' import * as React from 'react' -import { ChevronSelectorVertical } from '@/app/components/base/icons/src/vender/line/arrows' import { PromptRole } from '@/models/debug' type Props = Readonly<{ @@ -28,7 +27,10 @@ const MessageTypeSelector: FC = ({ value, onChange }) => { )} >
{value}
- +
{showOption && (
diff --git a/web/app/components/app/configuration/config-prompt/style.module.css b/web/app/components/app/configuration/config-prompt/style.module.css index fee2e28259e..bb615503da3 100644 --- a/web/app/components/app/configuration/config-prompt/style.module.css +++ b/web/app/components/app/configuration/config-prompt/style.module.css @@ -25,9 +25,13 @@ } .optionWrap { - display: none; + display: flex; + opacity: 0; + pointer-events: none; } -.boxHeader:hover .optionWrap { - display: flex; +.boxHeader:hover .optionWrap, +.optionWrap:focus-within { + opacity: 1; + pointer-events: auto; } diff --git a/web/app/components/app/configuration/config-var/input-type-icon.tsx b/web/app/components/app/configuration/config-var/input-type-icon.tsx index fb4c2ac4785..9ed6384c6d4 100644 --- a/web/app/components/app/configuration/config-var/input-type-icon.tsx +++ b/web/app/components/app/configuration/config-var/input-type-icon.tsx @@ -1,7 +1,7 @@ 'use client' import type { FC } from 'react' +import { cn } from '@langgenius/dify-ui/cn' import * as React from 'react' -import { ApiConnection } from '@/app/components/base/icons/src/vender/solid/development' import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon' import { InputVarType } from '@/app/components/workflow/types' @@ -17,7 +17,12 @@ const IconMap = (type: IInputTypeIconProps['type'], className: string) => { paragraph: , select: , number: , - api: , + api: ( + + ), } return icons[type] diff --git a/web/app/components/app/configuration/config-var/select-var-type.tsx b/web/app/components/app/configuration/config-var/select-var-type.tsx index 96b2c8ba4d3..dbf11f188ee 100644 --- a/web/app/components/app/configuration/config-var/select-var-type.tsx +++ b/web/app/components/app/configuration/config-var/select-var-type.tsx @@ -1,5 +1,6 @@ 'use client' import type { FC } from 'react' +import { cn } from '@langgenius/dify-ui/cn' import { DropdownMenu, DropdownMenuContent, @@ -10,7 +11,6 @@ import { import * as React from 'react' import { useTranslation } from 'react-i18next' import { OperationButton } from '@/app/components/app/configuration/base/operation-button' -import { ApiConnection } from '@/app/components/base/icons/src/vender/solid/development' import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon' import { InputVarType } from '@/app/components/workflow/types' @@ -21,20 +21,20 @@ type Props = Readonly<{ type ItemProps = { text: string value: string - Icon?: any + iconClassName?: string type?: InputVarType onClick: (value: string) => void } -const SelectItem: FC = ({ text, type, value, Icon, onClick }) => { +const SelectItem: FC = ({ text, type, value, iconClassName, onClick }) => { return ( onClick(value)} > - {Icon ? ( - + {iconClassName ? ( + ) : ( )} @@ -92,7 +92,7 @@ const SelectVarType: FC = ({ onChange }) => {
$['variableConfig.apiBasedVar'], { ns: 'appDebug' })} onClick={handleChange} diff --git a/web/app/components/app/configuration/config-var/var-item.tsx b/web/app/components/app/configuration/config-var/var-item.tsx index 5387a7fdbf7..9f306fc837a 100644 --- a/web/app/components/app/configuration/config-var/var-item.tsx +++ b/web/app/components/app/configuration/config-var/var-item.tsx @@ -9,7 +9,6 @@ import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' import Badge from '@/app/components/base/badge' -import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development' import IconTypeIcon from './input-type-icon' type ItemProps = { @@ -49,10 +48,14 @@ const VarItem: FC = ({ className, )} > - {canDrag && ( diff --git a/web/app/components/app/configuration/config-vision/index.tsx b/web/app/components/app/configuration/config-vision/index.tsx index 06462db608a..d683de10ab9 100644 --- a/web/app/components/app/configuration/config-vision/index.tsx +++ b/web/app/components/app/configuration/config-vision/index.tsx @@ -11,7 +11,6 @@ import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' // import { Resolution } from '@/types/app' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' -import { Vision } from '@/app/components/base/icons/src/vender/features' import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card' import { SupportUploadFileTypes } from '@/app/components/workflow/types' // import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card' @@ -68,7 +67,10 @@ const ConfigVision: FC = () => {
- +
diff --git a/web/app/components/app/configuration/config/agent/agent-setting/index.tsx b/web/app/components/app/configuration/config/agent/agent-setting/index.tsx index e5b8b8d23f5..5622df14a91 100644 --- a/web/app/components/app/configuration/config/agent/agent-setting/index.tsx +++ b/web/app/components/app/configuration/config/agent/agent-setting/index.tsx @@ -14,8 +14,6 @@ import { } from '@langgenius/dify-ui/slider' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { CuteRobot } from '@/app/components/base/icons/src/vender/solid/communication' -import { Unblur } from '@/app/components/base/icons/src/vender/solid/education' import { DEFAULT_AGENT_PROMPT, MAX_ITERATIONS_NUM } from '@/config' import ItemPanel from './item-panel' @@ -80,7 +78,12 @@ export function AgentSetting({ isChatModel, payload, isFunctionCall, onCancel, o {/* Agent Mode */} } + icon={ + + } name={t(($) => $['agent.agentMode'], { ns: 'appDebug' })} description={t(($) => $['agent.agentModeDes'], { ns: 'appDebug' })} > @@ -93,7 +96,12 @@ export function AgentSetting({ isChatModel, payload, isFunctionCall, onCancel, o } + icon={ + + } name={maximumIterationsLabel} description={t(($) => $['agent.setting.maximumIterations.description'], { ns: 'appDebug', diff --git a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx index ee657ca2a73..83c44b216f3 100644 --- a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx +++ b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx @@ -20,8 +20,6 @@ import { useContext } from 'use-context-selector' import Panel from '@/app/components/app/configuration/base/feature-panel' import { OperationButton } from '@/app/components/app/configuration/base/operation-button' import AppIcon from '@/app/components/base/app-icon' -import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other' -import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' import { parseToolProviderType } from '@/app/components/tools/provider-type' import { CollectionType } from '@/app/components/tools/types' import { @@ -216,7 +214,9 @@ const AgentTools: FC = () => { )} >
- {item.isDeleted && } + {item.isDeleted && ( + + )} {!item.isDeleted && (
{typeof item.icon === 'string' && ( @@ -280,7 +280,10 @@ const AgentTools: FC = () => { type="button" className="mr-1 cursor-pointer rounded-md p-1 outline-hidden hover:bg-black/5 focus-visible:ring-1 focus-visible:ring-components-input-border-hover" > - + } /> diff --git a/web/app/components/app/configuration/config/automatic/idea-output.tsx b/web/app/components/app/configuration/config/automatic/idea-output.tsx index 5a6678a6ab4..db3759a91dc 100644 --- a/web/app/components/app/configuration/config/automatic/idea-output.tsx +++ b/web/app/components/app/configuration/config/automatic/idea-output.tsx @@ -4,7 +4,6 @@ import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from '@langgenius/d import { Textarea } from '@langgenius/dify-ui/textarea' import * as React from 'react' import { useTranslation } from 'react-i18next' -import { ArrowDownRoundFill } from '@/app/components/base/icons/src/vender/solid/general' const i18nPrefix = 'generate' @@ -25,9 +24,9 @@ const IdeaOutput: FC = ({ value, onChange }) => { ({t(($) => $[`${i18nPrefix}.optional`], { ns: 'appDebug' })}) - diff --git a/web/app/components/app/configuration/config/automatic/res-placeholder.tsx b/web/app/components/app/configuration/config/automatic/res-placeholder.tsx index 5ef90291cfd..2212a5866fe 100644 --- a/web/app/components/app/configuration/config/automatic/res-placeholder.tsx +++ b/web/app/components/app/configuration/config/automatic/res-placeholder.tsx @@ -2,13 +2,12 @@ import type { FC } from 'react' import * as React from 'react' import { useTranslation } from 'react-i18next' -import { Generator } from '@/app/components/base/icons/src/vender/other' const ResPlaceholder: FC = () => { const { t } = useTranslation() return (
- +
{t(($) => $['generate.newNoDataLine1'], { ns: 'appDebug' })}
diff --git a/web/app/components/app/configuration/config/config-audio.tsx b/web/app/components/app/configuration/config/config-audio.tsx index 3e0ee2fdb55..0be0bb440c3 100644 --- a/web/app/components/app/configuration/config/config-audio.tsx +++ b/web/app/components/app/configuration/config/config-audio.tsx @@ -8,7 +8,6 @@ import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' -import { Microphone01 } from '@/app/components/base/icons/src/vender/features' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import ConfigContext from '@/context/debug-configuration' @@ -47,7 +46,10 @@ const ConfigAudio: FC = () => {
- +
diff --git a/web/app/components/app/configuration/config/config-document.tsx b/web/app/components/app/configuration/config/config-document.tsx index 5e1f72436a1..a35cb8687fe 100644 --- a/web/app/components/app/configuration/config/config-document.tsx +++ b/web/app/components/app/configuration/config/config-document.tsx @@ -8,7 +8,6 @@ import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' -import { Document } from '@/app/components/base/icons/src/vender/features' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import ConfigContext from '@/context/debug-configuration' @@ -48,7 +47,10 @@ const ConfigDocument: FC = () => {
- +
diff --git a/web/app/components/app/configuration/dataset-config/context-var/index.tsx b/web/app/components/app/configuration/dataset-config/context-var/index.tsx index cf9d6f4bbda..8d40908ad32 100644 --- a/web/app/components/app/configuration/dataset-config/context-var/index.tsx +++ b/web/app/components/app/configuration/dataset-config/context-var/index.tsx @@ -5,7 +5,6 @@ import { cn } from '@langgenius/dify-ui/cn' import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip' import * as React from 'react' import { useTranslation } from 'react-i18next' -import { BracketsX } from '@/app/components/base/icons/src/vender/line/development' import VarPicker from './var-picker' const ContextVar: FC = (props) => { @@ -24,7 +23,10 @@ const ContextVar: FC = (props) => { >
- +
{t(($) => $['feature.dataSet.queryVariable.title'], { ns: 'appDebug' })} diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/retrieval-section.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/retrieval-section.tsx index aa43d3a3aa7..517d3238447 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/retrieval-section.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/retrieval-section.tsx @@ -6,8 +6,6 @@ import type { DocPathWithoutLang } from '@/types/doc-paths' import { cn } from '@langgenius/dify-ui/cn' import { Separator } from '@langgenius/dify-ui/separator' import { RiCloseLine } from '@remixicon/react' -import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' -import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config' import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config' import { IndexingType } from '@/app/components/datasets/create/step-two' @@ -75,7 +73,10 @@ const ExternalRetrievalSection: FC = ({
- +
{currentDataset?.external_knowledge_info.external_knowledge_api_name}
@@ -232,7 +233,10 @@ export const RetrievalChangeTip: FC = ({ return (
- +
{message}
diff --git a/web/app/components/app/log/var-panel.tsx b/web/app/components/app/log/var-panel.tsx index ceb18463734..0322e28dc04 100644 --- a/web/app/components/app/log/var-panel.tsx +++ b/web/app/components/app/log/var-panel.tsx @@ -6,7 +6,6 @@ import { useBoolean } from 'ahooks' import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' import ImagePreview from '@/app/components/base/image-uploader/image-preview' type Props = Readonly<{ @@ -28,7 +27,7 @@ const VarPanel: FC = ({ varList, message_files }) => { )} onClick={toggleCollapse} > - +
{t(($) => $['detail.variables'], { ns: 'appLog' })}
diff --git a/web/app/components/app/overview/apikey-info-panel/index.tsx b/web/app/components/app/overview/apikey-info-panel/index.tsx index 143f215ec2d..5a25ff244cd 100644 --- a/web/app/components/app/overview/apikey-info-panel/index.tsx +++ b/web/app/components/app/overview/apikey-info-panel/index.tsx @@ -8,7 +8,6 @@ import { useQueryState } from 'nuqs' import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' import { settingsQueryParamName, settingsQueryParser, @@ -76,7 +75,7 @@ const APIKeyInfoPanel: FC = () => {
{t(($) => $['apiKeyInfo.setAPIBtn'], { ns: 'appOverview' })}
- + {!isCloud && (
{ rel="noopener noreferrer" >
{t(($) => $['apiKeyInfo.tryCloud'], { ns: 'appOverview' })}
- +
)}
= ({
} /> @@ -192,7 +203,10 @@ const FeatureBar = ({ - +
} /> diff --git a/web/app/components/base/features/new-feature-panel/file-upload/index.tsx b/web/app/components/base/features/new-feature-panel/file-upload/index.tsx index a78ee950645..96e8bc43594 100644 --- a/web/app/components/base/features/new-feature-panel/file-upload/index.tsx +++ b/web/app/components/base/features/new-feature-panel/file-upload/index.tsx @@ -9,7 +9,6 @@ import { useFeatures, useFeaturesStore } from '@/app/components/base/features/ho import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' import SettingModal from '@/app/components/base/features/new-feature-panel/file-upload/setting-modal' import { FeatureEnum } from '@/app/components/base/features/types' -import { FolderUpload } from '@/app/components/base/icons/src/vender/features' type Props = Readonly<{ disabled: boolean @@ -48,7 +47,10 @@ const FileUpload = ({ disabled, onChange }: Props) => { - +
} title={t(($) => $['feature.fileUpload.title'], { ns: 'appDebug' })} diff --git a/web/app/components/base/features/new-feature-panel/follow-up.tsx b/web/app/components/base/features/new-feature-panel/follow-up.tsx index d1092dc00de..91549af4236 100644 --- a/web/app/components/base/features/new-feature-panel/follow-up.tsx +++ b/web/app/components/base/features/new-feature-panel/follow-up.tsx @@ -12,7 +12,6 @@ import { useFeatures, useFeaturesStore } from '@/app/components/base/features/ho import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' import FollowUpSettingModal from '@/app/components/base/features/new-feature-panel/follow-up-setting-modal' import { FeatureEnum } from '@/app/components/base/features/types' -import { VirtualAssistant } from '@/app/components/base/icons/src/vender/features' type Props = Readonly<{ disabled?: boolean @@ -69,7 +68,10 @@ const FollowUp = ({ disabled, onChange }: Props) => { - +
} title={t(($) => $['feature.suggestedQuestionsAfterAnswer.title'], { ns: 'appDebug' })} diff --git a/web/app/components/base/features/new-feature-panel/moderation/index.tsx b/web/app/components/base/features/new-feature-panel/moderation/index.tsx index 49170c50d6a..80b0842df56 100644 --- a/web/app/components/base/features/new-feature-panel/moderation/index.tsx +++ b/web/app/components/base/features/new-feature-panel/moderation/index.tsx @@ -8,7 +8,6 @@ import { useLocale } from '#i18n' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' import { FeatureEnum } from '@/app/components/base/features/types' -import { ContentModeration } from '@/app/components/base/icons/src/vender/features' import { useModalContext } from '@/context/modal-context' import { useCodeBasedExtensions } from '@/service/use-common' @@ -119,7 +118,10 @@ const Moderation = ({ disabled, onChange }: Props) => { - +
} title={t(($) => $['feature.moderation.title'], { ns: 'appDebug' })} diff --git a/web/app/components/base/features/new-feature-panel/speech-to-text.tsx b/web/app/components/base/features/new-feature-panel/speech-to-text.tsx index 258d00000ed..dae5cb1e284 100644 --- a/web/app/components/base/features/new-feature-panel/speech-to-text.tsx +++ b/web/app/components/base/features/new-feature-panel/speech-to-text.tsx @@ -6,7 +6,6 @@ import { useTranslation } from 'react-i18next' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' import { FeatureEnum } from '@/app/components/base/features/types' -import { Microphone01 } from '@/app/components/base/icons/src/vender/features' type Props = Readonly<{ disabled: boolean @@ -38,7 +37,10 @@ const SpeechToText = ({ disabled, onChange }: Props) => { - +
} title={t(($) => $['feature.speechToText.title'], { ns: 'appDebug' })} diff --git a/web/app/components/base/features/new-feature-panel/text-to-speech/index.tsx b/web/app/components/base/features/new-feature-panel/text-to-speech/index.tsx index 5a923b15ab9..d6867bd5609 100644 --- a/web/app/components/base/features/new-feature-panel/text-to-speech/index.tsx +++ b/web/app/components/base/features/new-feature-panel/text-to-speech/index.tsx @@ -9,7 +9,6 @@ import { useFeatures, useFeaturesStore } from '@/app/components/base/features/ho import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' import VoiceSettings from '@/app/components/base/features/new-feature-panel/text-to-speech/voice-settings' import { FeatureEnum } from '@/app/components/base/features/types' -import { TextToAudio } from '@/app/components/base/icons/src/vender/features' import { languages } from '@/i18n/language' import { TtsAutoPlay } from '@/types/app' @@ -47,7 +46,10 @@ const TextToSpeech = ({ disabled, onChange }: Props) => { - +
} title={t(($) => $['feature.textToSpeech.title'], { ns: 'appDebug' })} diff --git a/web/app/components/base/file-icon/index.tsx b/web/app/components/base/file-icon/index.tsx index 7720d277b8e..deec65f9ab4 100644 --- a/web/app/components/base/file-icon/index.tsx +++ b/web/app/components/base/file-icon/index.tsx @@ -1,17 +1,5 @@ import type { FC } from 'react' -import { Notion } from '@/app/components/base/icons/src/public/common' -import { - Csv, - Doc, - Docx, - Html, - Json, - Md, - Pdf, - Txt, - Unknown, - Xlsx, -} from '@/app/components/base/icons/src/public/files' +import { cn } from '@langgenius/dify-ui/cn' type FileIconProps = { type: string @@ -21,31 +9,33 @@ type FileIconProps = { const FileIcon: FC = ({ type, className }) => { switch (type) { case 'csv': - return + return case 'doc': - return + return case 'docx': - return + return case 'htm': case 'html': - return + return case 'json': - return + return case 'md': case 'markdown': case 'mdx': - return + return case 'pdf': - return + return case 'txt': - return + return case 'xls': case 'xlsx': - return + return case 'notion': - return + return default: - return + return ( + + ) } } diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/file-item.spec.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/file-item.spec.tsx index 1f6be2ffe73..76286c36adb 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/file-item.spec.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/file-item.spec.tsx @@ -117,33 +117,28 @@ describe('FileInAttachmentItem', () => { expect(circle)!.toBeInTheDocument() }) - it('should render replay icon when upload failed', () => { - const { container } = render() + it('should render retry button when upload failed', () => { + render() - // ReplayLine renders an SVG with data-icon="ReplayLine" - const replayIcon = container.querySelector('[data-icon="ReplayLine"]') - expect(replayIcon)!.toBeInTheDocument() + const retryButton = screen.getByRole('button', { name: 'common.operation.retry document.pdf' }) + expect(retryButton)!.toBeInTheDocument() }) - it('should call onReUpload when replay icon is clicked', () => { + it('should call onReUpload when retry button is clicked', () => { const onReUpload = vi.fn() - const { container } = render( - , - ) + render() - const replayIcon = container.querySelector('[data-icon="ReplayLine"]') - const replayBtn = replayIcon!.closest('button') - fireEvent.click(replayBtn!) + const retryButton = screen.getByRole('button', { name: 'common.operation.retry document.pdf' }) + fireEvent.click(retryButton) expect(onReUpload).toHaveBeenCalledWith('file-1') }) it('should indicate error state when progress is -1', () => { - const { container } = render() + render() - // Error state is confirmed by the presence of the replay icon - const replayIcon = container.querySelector('[data-icon="ReplayLine"]') - expect(replayIcon)!.toBeInTheDocument() + const retryButton = screen.getByRole('button', { name: 'common.operation.retry document.pdf' }) + expect(retryButton)!.toBeInTheDocument() }) it('should render eye icon for previewable image files', () => { diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/index.spec.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/index.spec.tsx index e29d74617e9..fdd0038c782 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/index.spec.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/__tests__/index.spec.tsx @@ -188,7 +188,7 @@ describe('FileUploaderInAttachmentWrapper', () => { it('should call handleReUploadFile when reupload button is clicked', () => { const files = [createFile({ id: 'f1', name: 'a.txt', progress: -1 })] - const { container } = render( + render( { />, ) - // ReplayLine is inside an icon button with a data-icon attribute. - const replayIcon = container.querySelector('svg[data-icon="ReplayLine"]') - const replayBtn = replayIcon!.closest('button') - fireEvent.click(replayBtn!) + fireEvent.click(screen.getByRole('button', { name: 'common.operation.retry a.txt' })) expect(mockHandleReUploadFile).toHaveBeenCalledWith('f1') }) diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx index f3731114f19..399baaa04dc 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx @@ -6,7 +6,6 @@ import { RiDeleteBinLine, RiDownloadLine, RiEyeLine } from '@remixicon/react' import { memo, useState } from 'react' import { useTranslation } from 'react-i18next' import { PreviewMode } from '@/app/components/base/features/types' -import { ReplayLine } from '@/app/components/base/icons/src/vender/other' import ImagePreview from '@/app/components/base/image-uploader/image-preview' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import { downloadUrl } from '@/utils/download' @@ -82,7 +81,10 @@ const FileInAttachmentItem = ({ className="mr-1" onClick={() => onReUpload?.(id)} > -