From 6899c7720f26ffa7b27407ff727063d21d487704 Mon Sep 17 00:00:00 2001
From: Wu Tianwei <30284043+WTW0313@users.noreply.github.com>
Date: Wed, 12 Aug 2026 16:49:51 +0800
Subject: [PATCH] refactor(web): remove deprecated deployments pages (#40593)
---
knip.config.ts | 2 -
pnpm-lock.yaml | 6 -
.../[appInstanceId]/access/page.tsx | 5 -
.../[appInstanceId]/api-tokens/page.tsx | 5 -
.../[appInstanceId]/instances/page.tsx | 5 -
.../[appInstanceId]/overview/page.tsx | 5 -
.../deployments/[appInstanceId]/page.tsx | 5 -
.../[appInstanceId]/releases/page.tsx | 5 -
.../[appInstanceId]/sidebar-page.tsx | 5 -
.../deployments/create/page.tsx | 3 -
.../[appInstanceId]/access/page.tsx | 5 -
.../[appInstanceId]/api-tokens/page.tsx | 5 -
.../[appInstanceId]/instances/page.tsx | 5 -
.../deployments/[appInstanceId]/layout.tsx | 6 -
.../[appInstanceId]/overview/page.tsx | 5 -
.../deployments/[appInstanceId]/page.tsx | 10 -
.../[appInstanceId]/releases/page.tsx | 5 -
.../deployments/__tests__/layout.spec.tsx | 23 -
.../deployments/create/page.tsx | 12 -
web/app/(commonLayout)/deployments/layout.tsx | 5 -
web/app/(commonLayout)/deployments/page.tsx | 10 -
web/app/(commonLayout)/layout.tsx | 17 +-
.../main-nav/__tests__/index.spec.tsx | 28 +-
.../main-nav/__tests__/layout.spec.tsx | 91 +--
web/app/components/main-nav/index.tsx | 9 +-
web/app/components/main-nav/layout.tsx | 10 +-
web/app/components/main-nav/routes.ts | 16 +-
web/app/components/next-route-state/atoms.ts | 50 --
web/app/components/next-route-state/index.tsx | 27 -
web/context/workspace-state.ts | 5 +
web/features/deployments/README.md | 101 ---
.../deployments/create-guide/README.md | 18 -
.../deployments/create-guide/index.tsx | 38 --
.../deployments/create-guide/link.tsx | 12 -
.../state/__tests__/index.spec.ts | 202 ------
.../create-guide/state/environment.ts | 8 -
.../create-guide/state/primitives.ts | 37 --
.../create-guide/state/provider.tsx | 9 -
.../deployments/create-guide/state/queries.ts | 225 -------
.../deployments/create-guide/state/release.ts | 91 ---
.../deployments/create-guide/state/scoped.ts | 41 --
.../deployments/create-guide/state/source.ts | 145 -----
.../create-guide/state/submission.ts | 221 -------
.../deployments/create-guide/state/target.ts | 172 ------
.../deployments/create-guide/state/types.ts | 7 -
.../deployments/create-guide/state/utils.ts | 107 ----
.../create-guide/state/workflow.ts | 130 ----
.../ui/__tests__/source-step.spec.tsx | 178 ------
.../deployments/create-guide/ui/layout.tsx | 220 -------
.../create-guide/ui/release-step.tsx | 222 -------
.../deployments/create-guide/ui/shell.tsx | 69 ---
.../create-guide/ui/source-step.tsx | 418 -------------
.../create-guide/ui/target-step.tsx | 389 ------------
.../deployments/create-release/README.md | 18 -
.../deployments/create-release/index.tsx | 82 ---
.../state/__tests__/dsl-enabled.spec.ts | 205 -------
.../state/__tests__/index.spec.ts | 513 ----------------
.../deployments/create-release/state/index.ts | 575 ------------------
.../ui/__tests__/source-app-picker.spec.tsx | 178 ------
.../deployments/create-release/ui/actions.tsx | 61 --
.../create-release/ui/content-feedback.tsx | 41 --
.../deployments/create-release/ui/dialog.tsx | 115 ----
.../create-release/ui/metadata-fields.tsx | 129 ----
.../create-release/ui/source-app-picker.tsx | 247 --------
.../create-release/ui/source-section.tsx | 125 ----
.../deployments/deploy-drawer/README.md | 15 -
.../deployments/deploy-drawer/index.tsx | 64 --
.../state/__tests__/index.spec.ts | 438 -------------
.../deployments/deploy-drawer/state/index.ts | 521 ----------------
.../deploy-drawer/state/release-options.ts | 26 -
.../deploy-drawer/ui/form-sections.tsx | 195 ------
.../deploy-drawer/ui/form-skeleton.tsx | 42 --
.../deployments/deploy-drawer/ui/form.tsx | 285 ---------
.../deployments/deploy-drawer/ui/select.tsx | 145 -----
.../deploy-drawer/ui/status-badge.tsx | 17 -
.../deployments/deployment-actions/README.md | 11 -
.../__tests__/delete-dialog.spec.tsx | 117 ----
.../__tests__/edit-dialog.spec.tsx | 138 -----
.../deployment-actions/delete-dialog.tsx | 84 ---
.../deployment-actions/edit-dialog.tsx | 160 -----
.../deployments/deployment-actions/index.tsx | 100 ---
.../deployments/deployment-actions/state.ts | 27 -
.../deployments/deployment-actions/types.ts | 3 -
web/features/deployments/detail/README.md | 20 -
.../detail/__tests__/index.spec.tsx | 84 ---
.../detail/__tests__/state.spec.ts | 162 -----
.../deployments/detail/access/README.md | 15 -
.../detail/access/__tests__/state.spec.ts | 70 ---
.../detail/access/channels/README.md | 17 -
.../detail/access/channels/section.tsx | 250 --------
.../deployments/detail/access/channels/url.ts | 8 -
.../deployments/detail/access/index.tsx | 13 -
.../detail/access/permissions/README.md | 18 -
.../__tests__/access-control-dialog.spec.tsx | 128 ----
.../__tests__/access-policy.spec.ts | 208 -------
.../__tests__/permissions.spec.tsx | 300 ---------
.../permissions/access-control-dialog.tsx | 260 --------
.../access/permissions/access-policy.ts | 170 ------
.../access-subject-selector/README.md | 17 -
.../__tests__/add-button.spec.tsx | 127 ----
.../access-subject-selector/add-button.tsx | 218 -------
.../selection-list.tsx | 226 -------
.../subject-options.tsx | 225 -------
.../access-subject-selector/types.ts | 12 -
.../access-subject-selector/utils.ts | 55 --
.../environment-permission-row.tsx | 143 -----
.../permissions/permission-summary-button.tsx | 74 ---
.../detail/access/permissions/section.tsx | 80 ---
.../deployments/detail/access/state.ts | 30 -
.../deployments/detail/api-tokens/README.md | 14 -
.../detail/api-tokens/__tests__/state.spec.ts | 70 ---
.../detail/api-tokens/api-keys/README.md | 15 -
.../__tests__/api-key-generate-menu.spec.tsx | 96 ---
.../api-keys/api-key-generate-menu.tsx | 239 --------
.../api-tokens/api-keys/api-key-list.tsx | 250 --------
.../api-tokens/api-keys/api-token-name.ts | 39 --
.../api-keys/created-token-dialog.tsx | 100 ---
.../api-tokens/api-token-management/README.md | 17 -
.../api-token-management/section.tsx | 164 -----
.../api-token-management/skeleton.tsx | 120 ----
.../developer-api-header-switch.tsx | 71 ---
.../detail/api-tokens/docs/README.md | 19 -
.../detail/api-tokens/docs/docs-drawer.tsx | 116 ----
.../deployments/detail/api-tokens/index.tsx | 11 -
.../deployments/detail/api-tokens/state.ts | 33 -
.../detail/api-tokens/table-styles.ts | 6 -
.../deployments/detail/deployment-sidebar.tsx | 307 ----------
.../deployments/detail/detail-sidebar.tsx | 15 -
web/features/deployments/detail/index.tsx | 95 ---
.../deployments/detail/instances/README.md | 18 -
.../instances/environment-list/README.md | 15 -
.../deployment-environment-list.tsx | 152 -----
.../deployment-status-summary.tsx | 116 ----
.../detail/instances/header-actions/README.md | 15 -
.../header-actions/new-deployment-button.tsx | 44 --
.../deployments/detail/instances/index.tsx | 129 ----
.../detail/instances/row-actions/README.md | 15 -
.../deployment-row-actions-menu.spec.tsx | 46 --
.../row-actions/deployment-error-dialog.tsx | 78 ---
.../deployment-row-actions-menu.tsx | 136 -----
.../row-actions/deployment-row-actions.tsx | 112 ----
.../undeploy-deployment-dialog.tsx | 60 --
.../detail/instances/table-styles.ts | 6 -
.../deployments/detail/overview/README.md | 17 -
.../detail/overview/__tests__/state.spec.ts | 76 ---
.../detail/overview/access-summary/README.md | 15 -
.../access-summary/access-status-section.tsx | 244 --------
.../overview/environment-status/README.md | 16 -
.../__tests__/environment-tile-utils.spec.ts | 158 -----
.../environment-status/environment-strip.tsx | 154 -----
.../environment-tile-utils.ts | 162 -----
.../environment-status/environment-tile.tsx | 181 ------
.../environment-status/overview-drift.ts | 25 -
.../deployments/detail/overview/index.tsx | 116 ----
.../detail/overview/release-summary/README.md | 16 -
.../overview/release-summary/release-hero.tsx | 188 ------
.../deployments/detail/overview/state.ts | 30 -
.../deployments/detail/releases/README.md | 14 -
.../detail/releases/__tests__/state.spec.ts | 100 ---
.../deployments/detail/releases/index.tsx | 19 -
.../detail/releases/release-actions/README.md | 17 -
.../deploy-release-menu-utils.spec.ts | 65 --
.../__tests__/deploy-release-menu.spec.tsx | 154 -----
.../release-actions/__tests__/state.spec.ts | 121 ----
.../release-actions/delete-release-dialog.tsx | 57 --
.../deploy-release-menu-utils.ts | 157 -----
.../release-actions/deploy-release-menu.tsx | 260 --------
.../release-actions/edit-release-dialog.tsx | 180 ------
.../release-actions/release-dsl-export.ts | 50 --
.../releases/release-actions/release-dsl.ts | 11 -
.../detail/releases/release-actions/state.ts | 86 ---
.../detail/releases/release-history/README.md | 17 -
.../release-history/deployed-to-badge.tsx | 39 --
.../release-history/release-deployments.ts | 58 --
.../release-history-deployments.tsx | 12 -
.../release-history/release-history-rows.tsx | 245 --------
.../release-history-table-skeleton.tsx | 110 ----
.../release-history/release-history-table.tsx | 81 ---
.../release-history/release-history-types.ts | 10 -
.../releases/release-history/table-styles.ts | 8 -
.../deployments/detail/releases/state.ts | 56 --
web/features/deployments/detail/state.ts | 85 ---
web/features/deployments/detail/tabs.ts | 15 -
web/features/deployments/list/README.md | 21 -
web/features/deployments/list/index.tsx | 12 -
web/features/deployments/list/state/index.ts | 174 ------
.../ui/__tests__/environment-filter.spec.tsx | 39 --
.../list/ui/create-deployment-button.tsx | 21 -
.../list/ui/environment-filter.tsx | 109 ----
.../list/ui/instance-card-sections.tsx | 274 ---------
.../list/ui/instance-card-utils.ts | 17 -
.../deployments/list/ui/instance-card.tsx | 122 ----
web/features/deployments/list/ui/shell.tsx | 219 -------
web/features/deployments/route-state.ts | 10 -
web/features/deployments/shared/README.md | 19 -
.../__tests__/env-var-bindings-utils.spec.ts | 58 --
.../runtime-credential-bindings-utils.spec.ts | 124 ----
.../__tests__/title-tooltip.spec.tsx | 64 --
.../shared/components/detail-table-styles.ts | 8 -
.../shared/components/detail-table.tsx | 106 ----
.../shared/components/empty-state.tsx | 146 -----
.../shared/components/endpoint.tsx | 76 ---
.../components/env-var-bindings-utils.ts | 30 -
.../shared/components/env-var-bindings.tsx | 268 --------
.../runtime-credential-bindings-utils.ts | 115 ----
.../runtime-credential-bindings.tsx | 200 ------
.../deployments/shared/components/section.tsx | 84 ---
.../shared/components/title-tooltip.tsx | 68 ---
.../unsupported-dsl-nodes-alert.tsx | 120 ----
.../shared/domain/__tests__/dsl.spec.ts | 115 ----
web/features/deployments/shared/domain/dsl.ts | 140 -----
.../deployments/shared/domain/error.ts | 125 ----
.../shared/domain/feature-flags.ts | 2 -
.../deployments/shared/domain/idempotency.ts | 5 -
.../shared/domain/release-action.ts | 68 ---
.../deployments/shared/domain/release.ts | 20 -
.../shared/domain/runtime-status.ts | 39 --
.../shared/ui/deployment-status-badge.tsx | 112 ----
.../shared/ui/deployment-status-style.ts | 84 ---
web/i18n/ar-TN/common.json | 1 -
web/i18n/ar-TN/deployments.json | 364 +----------
web/i18n/de-DE/common.json | 1 -
web/i18n/de-DE/deployments.json | 364 +----------
web/i18n/en-US/common.json | 1 -
web/i18n/en-US/deployments.json | 364 +----------
web/i18n/es-ES/common.json | 1 -
web/i18n/es-ES/deployments.json | 364 +----------
web/i18n/fa-IR/common.json | 1 -
web/i18n/fa-IR/deployments.json | 364 +----------
web/i18n/fr-FR/common.json | 1 -
web/i18n/fr-FR/deployments.json | 364 +----------
web/i18n/hi-IN/common.json | 1 -
web/i18n/hi-IN/deployments.json | 364 +----------
web/i18n/id-ID/common.json | 1 -
web/i18n/id-ID/deployments.json | 364 +----------
web/i18n/it-IT/common.json | 1 -
web/i18n/it-IT/deployments.json | 364 +----------
web/i18n/ja-JP/common.json | 1 -
web/i18n/ja-JP/deployments.json | 364 +----------
web/i18n/ko-KR/common.json | 1 -
web/i18n/ko-KR/deployments.json | 364 +----------
web/i18n/lo-LA/common.json | 1 -
web/i18n/lo-LA/deployments.json | 364 +----------
web/i18n/nl-NL/common.json | 1 -
web/i18n/nl-NL/deployments.json | 364 +----------
web/i18n/pl-PL/common.json | 1 -
web/i18n/pl-PL/deployments.json | 364 +----------
web/i18n/pt-BR/common.json | 1 -
web/i18n/pt-BR/deployments.json | 364 +----------
web/i18n/ro-RO/common.json | 1 -
web/i18n/ro-RO/deployments.json | 364 +----------
web/i18n/ru-RU/common.json | 1 -
web/i18n/ru-RU/deployments.json | 364 +----------
web/i18n/sl-SI/common.json | 1 -
web/i18n/sl-SI/deployments.json | 364 +----------
web/i18n/th-TH/common.json | 1 -
web/i18n/th-TH/deployments.json | 364 +----------
web/i18n/tr-TR/common.json | 1 -
web/i18n/tr-TR/deployments.json | 364 +----------
web/i18n/uk-UA/common.json | 1 -
web/i18n/uk-UA/deployments.json | 364 +----------
web/i18n/vi-VN/common.json | 1 -
web/i18n/vi-VN/deployments.json | 364 +----------
web/i18n/zh-Hans/common.json | 1 -
web/i18n/zh-Hans/deployments.json | 364 +----------
web/i18n/zh-Hant/common.json | 1 -
web/i18n/zh-Hant/deployments.json | 364 +----------
web/package.json | 2 -
.../access-control/use-access-subjects.ts | 51 --
269 files changed, 61 insertions(+), 29187 deletions(-)
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/access/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/api-tokens/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/instances/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/overview/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/releases/page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/sidebar-page.tsx
delete mode 100644 web/app/(commonLayout)/@detailSidebar/deployments/create/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/access/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/api-tokens/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/instances/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/layout.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/overview/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/[appInstanceId]/releases/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/__tests__/layout.spec.tsx
delete mode 100644 web/app/(commonLayout)/deployments/create/page.tsx
delete mode 100644 web/app/(commonLayout)/deployments/layout.tsx
delete mode 100644 web/app/(commonLayout)/deployments/page.tsx
delete mode 100644 web/app/components/next-route-state/atoms.ts
delete mode 100644 web/app/components/next-route-state/index.tsx
delete mode 100644 web/features/deployments/README.md
delete mode 100644 web/features/deployments/create-guide/README.md
delete mode 100644 web/features/deployments/create-guide/index.tsx
delete mode 100644 web/features/deployments/create-guide/link.tsx
delete mode 100644 web/features/deployments/create-guide/state/__tests__/index.spec.ts
delete mode 100644 web/features/deployments/create-guide/state/environment.ts
delete mode 100644 web/features/deployments/create-guide/state/primitives.ts
delete mode 100644 web/features/deployments/create-guide/state/provider.tsx
delete mode 100644 web/features/deployments/create-guide/state/queries.ts
delete mode 100644 web/features/deployments/create-guide/state/release.ts
delete mode 100644 web/features/deployments/create-guide/state/scoped.ts
delete mode 100644 web/features/deployments/create-guide/state/source.ts
delete mode 100644 web/features/deployments/create-guide/state/submission.ts
delete mode 100644 web/features/deployments/create-guide/state/target.ts
delete mode 100644 web/features/deployments/create-guide/state/types.ts
delete mode 100644 web/features/deployments/create-guide/state/utils.ts
delete mode 100644 web/features/deployments/create-guide/state/workflow.ts
delete mode 100644 web/features/deployments/create-guide/ui/__tests__/source-step.spec.tsx
delete mode 100644 web/features/deployments/create-guide/ui/layout.tsx
delete mode 100644 web/features/deployments/create-guide/ui/release-step.tsx
delete mode 100644 web/features/deployments/create-guide/ui/shell.tsx
delete mode 100644 web/features/deployments/create-guide/ui/source-step.tsx
delete mode 100644 web/features/deployments/create-guide/ui/target-step.tsx
delete mode 100644 web/features/deployments/create-release/README.md
delete mode 100644 web/features/deployments/create-release/index.tsx
delete mode 100644 web/features/deployments/create-release/state/__tests__/dsl-enabled.spec.ts
delete mode 100644 web/features/deployments/create-release/state/__tests__/index.spec.ts
delete mode 100644 web/features/deployments/create-release/state/index.ts
delete mode 100644 web/features/deployments/create-release/ui/__tests__/source-app-picker.spec.tsx
delete mode 100644 web/features/deployments/create-release/ui/actions.tsx
delete mode 100644 web/features/deployments/create-release/ui/content-feedback.tsx
delete mode 100644 web/features/deployments/create-release/ui/dialog.tsx
delete mode 100644 web/features/deployments/create-release/ui/metadata-fields.tsx
delete mode 100644 web/features/deployments/create-release/ui/source-app-picker.tsx
delete mode 100644 web/features/deployments/create-release/ui/source-section.tsx
delete mode 100644 web/features/deployments/deploy-drawer/README.md
delete mode 100644 web/features/deployments/deploy-drawer/index.tsx
delete mode 100644 web/features/deployments/deploy-drawer/state/__tests__/index.spec.ts
delete mode 100644 web/features/deployments/deploy-drawer/state/index.ts
delete mode 100644 web/features/deployments/deploy-drawer/state/release-options.ts
delete mode 100644 web/features/deployments/deploy-drawer/ui/form-sections.tsx
delete mode 100644 web/features/deployments/deploy-drawer/ui/form-skeleton.tsx
delete mode 100644 web/features/deployments/deploy-drawer/ui/form.tsx
delete mode 100644 web/features/deployments/deploy-drawer/ui/select.tsx
delete mode 100644 web/features/deployments/deploy-drawer/ui/status-badge.tsx
delete mode 100644 web/features/deployments/deployment-actions/README.md
delete mode 100644 web/features/deployments/deployment-actions/__tests__/delete-dialog.spec.tsx
delete mode 100644 web/features/deployments/deployment-actions/__tests__/edit-dialog.spec.tsx
delete mode 100644 web/features/deployments/deployment-actions/delete-dialog.tsx
delete mode 100644 web/features/deployments/deployment-actions/edit-dialog.tsx
delete mode 100644 web/features/deployments/deployment-actions/index.tsx
delete mode 100644 web/features/deployments/deployment-actions/state.ts
delete mode 100644 web/features/deployments/deployment-actions/types.ts
delete mode 100644 web/features/deployments/detail/README.md
delete mode 100644 web/features/deployments/detail/__tests__/index.spec.tsx
delete mode 100644 web/features/deployments/detail/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/access/README.md
delete mode 100644 web/features/deployments/detail/access/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/access/channels/README.md
delete mode 100644 web/features/deployments/detail/access/channels/section.tsx
delete mode 100644 web/features/deployments/detail/access/channels/url.ts
delete mode 100644 web/features/deployments/detail/access/index.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/README.md
delete mode 100644 web/features/deployments/detail/access/permissions/__tests__/access-control-dialog.spec.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/__tests__/access-policy.spec.ts
delete mode 100644 web/features/deployments/detail/access/permissions/__tests__/permissions.spec.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-control-dialog.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-policy.ts
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/README.md
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/__tests__/add-button.spec.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/add-button.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/selection-list.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/subject-options.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/types.ts
delete mode 100644 web/features/deployments/detail/access/permissions/access-subject-selector/utils.ts
delete mode 100644 web/features/deployments/detail/access/permissions/environment-permission-row.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/permission-summary-button.tsx
delete mode 100644 web/features/deployments/detail/access/permissions/section.tsx
delete mode 100644 web/features/deployments/detail/access/state.ts
delete mode 100644 web/features/deployments/detail/api-tokens/README.md
delete mode 100644 web/features/deployments/detail/api-tokens/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/README.md
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/__tests__/api-key-generate-menu.spec.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/api-key-generate-menu.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/api-key-list.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/api-token-name.ts
delete mode 100644 web/features/deployments/detail/api-tokens/api-keys/created-token-dialog.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/api-token-management/README.md
delete mode 100644 web/features/deployments/detail/api-tokens/api-token-management/section.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/api-token-management/skeleton.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/developer-api-header-switch.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/docs/README.md
delete mode 100644 web/features/deployments/detail/api-tokens/docs/docs-drawer.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/index.tsx
delete mode 100644 web/features/deployments/detail/api-tokens/state.ts
delete mode 100644 web/features/deployments/detail/api-tokens/table-styles.ts
delete mode 100644 web/features/deployments/detail/deployment-sidebar.tsx
delete mode 100644 web/features/deployments/detail/detail-sidebar.tsx
delete mode 100644 web/features/deployments/detail/index.tsx
delete mode 100644 web/features/deployments/detail/instances/README.md
delete mode 100644 web/features/deployments/detail/instances/environment-list/README.md
delete mode 100644 web/features/deployments/detail/instances/environment-list/deployment-environment-list.tsx
delete mode 100644 web/features/deployments/detail/instances/environment-list/deployment-status-summary.tsx
delete mode 100644 web/features/deployments/detail/instances/header-actions/README.md
delete mode 100644 web/features/deployments/detail/instances/header-actions/new-deployment-button.tsx
delete mode 100644 web/features/deployments/detail/instances/index.tsx
delete mode 100644 web/features/deployments/detail/instances/row-actions/README.md
delete mode 100644 web/features/deployments/detail/instances/row-actions/__tests__/deployment-row-actions-menu.spec.tsx
delete mode 100644 web/features/deployments/detail/instances/row-actions/deployment-error-dialog.tsx
delete mode 100644 web/features/deployments/detail/instances/row-actions/deployment-row-actions-menu.tsx
delete mode 100644 web/features/deployments/detail/instances/row-actions/deployment-row-actions.tsx
delete mode 100644 web/features/deployments/detail/instances/row-actions/undeploy-deployment-dialog.tsx
delete mode 100644 web/features/deployments/detail/instances/table-styles.ts
delete mode 100644 web/features/deployments/detail/overview/README.md
delete mode 100644 web/features/deployments/detail/overview/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/overview/access-summary/README.md
delete mode 100644 web/features/deployments/detail/overview/access-summary/access-status-section.tsx
delete mode 100644 web/features/deployments/detail/overview/environment-status/README.md
delete mode 100644 web/features/deployments/detail/overview/environment-status/__tests__/environment-tile-utils.spec.ts
delete mode 100644 web/features/deployments/detail/overview/environment-status/environment-strip.tsx
delete mode 100644 web/features/deployments/detail/overview/environment-status/environment-tile-utils.ts
delete mode 100644 web/features/deployments/detail/overview/environment-status/environment-tile.tsx
delete mode 100644 web/features/deployments/detail/overview/environment-status/overview-drift.ts
delete mode 100644 web/features/deployments/detail/overview/index.tsx
delete mode 100644 web/features/deployments/detail/overview/release-summary/README.md
delete mode 100644 web/features/deployments/detail/overview/release-summary/release-hero.tsx
delete mode 100644 web/features/deployments/detail/overview/state.ts
delete mode 100644 web/features/deployments/detail/releases/README.md
delete mode 100644 web/features/deployments/detail/releases/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/releases/index.tsx
delete mode 100644 web/features/deployments/detail/releases/release-actions/README.md
delete mode 100644 web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu-utils.spec.ts
delete mode 100644 web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu.spec.tsx
delete mode 100644 web/features/deployments/detail/releases/release-actions/__tests__/state.spec.ts
delete mode 100644 web/features/deployments/detail/releases/release-actions/delete-release-dialog.tsx
delete mode 100644 web/features/deployments/detail/releases/release-actions/deploy-release-menu-utils.ts
delete mode 100644 web/features/deployments/detail/releases/release-actions/deploy-release-menu.tsx
delete mode 100644 web/features/deployments/detail/releases/release-actions/edit-release-dialog.tsx
delete mode 100644 web/features/deployments/detail/releases/release-actions/release-dsl-export.ts
delete mode 100644 web/features/deployments/detail/releases/release-actions/release-dsl.ts
delete mode 100644 web/features/deployments/detail/releases/release-actions/state.ts
delete mode 100644 web/features/deployments/detail/releases/release-history/README.md
delete mode 100644 web/features/deployments/detail/releases/release-history/deployed-to-badge.tsx
delete mode 100644 web/features/deployments/detail/releases/release-history/release-deployments.ts
delete mode 100644 web/features/deployments/detail/releases/release-history/release-history-deployments.tsx
delete mode 100644 web/features/deployments/detail/releases/release-history/release-history-rows.tsx
delete mode 100644 web/features/deployments/detail/releases/release-history/release-history-table-skeleton.tsx
delete mode 100644 web/features/deployments/detail/releases/release-history/release-history-table.tsx
delete mode 100644 web/features/deployments/detail/releases/release-history/release-history-types.ts
delete mode 100644 web/features/deployments/detail/releases/release-history/table-styles.ts
delete mode 100644 web/features/deployments/detail/releases/state.ts
delete mode 100644 web/features/deployments/detail/state.ts
delete mode 100644 web/features/deployments/detail/tabs.ts
delete mode 100644 web/features/deployments/list/README.md
delete mode 100644 web/features/deployments/list/index.tsx
delete mode 100644 web/features/deployments/list/state/index.ts
delete mode 100644 web/features/deployments/list/ui/__tests__/environment-filter.spec.tsx
delete mode 100644 web/features/deployments/list/ui/create-deployment-button.tsx
delete mode 100644 web/features/deployments/list/ui/environment-filter.tsx
delete mode 100644 web/features/deployments/list/ui/instance-card-sections.tsx
delete mode 100644 web/features/deployments/list/ui/instance-card-utils.ts
delete mode 100644 web/features/deployments/list/ui/instance-card.tsx
delete mode 100644 web/features/deployments/list/ui/shell.tsx
delete mode 100644 web/features/deployments/route-state.ts
delete mode 100644 web/features/deployments/shared/README.md
delete mode 100644 web/features/deployments/shared/components/__tests__/env-var-bindings-utils.spec.ts
delete mode 100644 web/features/deployments/shared/components/__tests__/runtime-credential-bindings-utils.spec.ts
delete mode 100644 web/features/deployments/shared/components/__tests__/title-tooltip.spec.tsx
delete mode 100644 web/features/deployments/shared/components/detail-table-styles.ts
delete mode 100644 web/features/deployments/shared/components/detail-table.tsx
delete mode 100644 web/features/deployments/shared/components/empty-state.tsx
delete mode 100644 web/features/deployments/shared/components/endpoint.tsx
delete mode 100644 web/features/deployments/shared/components/env-var-bindings-utils.ts
delete mode 100644 web/features/deployments/shared/components/env-var-bindings.tsx
delete mode 100644 web/features/deployments/shared/components/runtime-credential-bindings-utils.ts
delete mode 100644 web/features/deployments/shared/components/runtime-credential-bindings.tsx
delete mode 100644 web/features/deployments/shared/components/section.tsx
delete mode 100644 web/features/deployments/shared/components/title-tooltip.tsx
delete mode 100644 web/features/deployments/shared/components/unsupported-dsl-nodes-alert.tsx
delete mode 100644 web/features/deployments/shared/domain/__tests__/dsl.spec.ts
delete mode 100644 web/features/deployments/shared/domain/dsl.ts
delete mode 100644 web/features/deployments/shared/domain/error.ts
delete mode 100644 web/features/deployments/shared/domain/feature-flags.ts
delete mode 100644 web/features/deployments/shared/domain/idempotency.ts
delete mode 100644 web/features/deployments/shared/domain/release-action.ts
delete mode 100644 web/features/deployments/shared/domain/release.ts
delete mode 100644 web/features/deployments/shared/domain/runtime-status.ts
delete mode 100644 web/features/deployments/shared/ui/deployment-status-badge.tsx
delete mode 100644 web/features/deployments/shared/ui/deployment-status-style.ts
delete mode 100644 web/service/access-control/use-access-subjects.ts
diff --git a/knip.config.ts b/knip.config.ts
index 887534fa1ab..63e60aeab63 100644
--- a/knip.config.ts
+++ b/knip.config.ts
@@ -10,8 +10,6 @@ const config: KnipConfig = {
workspaces: {
web: {
entry: [
- // todo: Keep the deploy drawer analyzed while the deployments routes are disabled. Delete this entry when relative files are deleted.
- 'features/deployments/deploy-drawer/index.tsx!',
'scripts/**/*.{js,ts,mjs}',
'bin/**/*.{js,ts,mjs}',
'tsslint.config.ts',
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d2104938791..2334544b137 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1242,9 +1242,6 @@ importers:
'@tailwindcss/typography':
specifier: 'catalog:'
version: 0.5.20(tailwindcss@4.3.3)
- '@tanstack/form-core':
- specifier: 'catalog:'
- version: 1.33.3
'@tanstack/query-core':
specifier: 'catalog:'
version: 5.101.4
@@ -1341,9 +1338,6 @@ importers:
jotai-scope:
specifier: 'catalog:'
version: 0.11.0(jotai@2.20.2(@babel/core@7.29.7(supports-color@11.0.0))(@babel/template@7.29.7)(@types/react@19.2.18)(react@19.2.8))(react@19.2.8)
- jotai-tanstack-form:
- specifier: workspace:*
- version: link:../packages/jotai-tanstack-form
jotai-tanstack-query:
specifier: 'catalog:'
version: 0.11.0(@tanstack/query-core@5.101.4)(@tanstack/react-query@5.101.4(react@19.2.8))(jotai@2.20.2(@babel/core@7.29.7(supports-color@11.0.0))(@babel/template@7.29.7)(@types/react@19.2.18)(react@19.2.8))(react@19.2.8)
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/access/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/access/page.tsx
deleted file mode 100644
index 20a44044ef7..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/access/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from '../sidebar-page'
-
-export default function DeploymentAccessDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/api-tokens/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/api-tokens/page.tsx
deleted file mode 100644
index 806e69b471a..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/api-tokens/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from '../sidebar-page'
-
-export default function DeploymentApiTokensDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/instances/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/instances/page.tsx
deleted file mode 100644
index 0d17b43799c..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/instances/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from '../sidebar-page'
-
-export default function DeploymentInstancesDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/overview/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/overview/page.tsx
deleted file mode 100644
index dbbcc7a93fa..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/overview/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from '../sidebar-page'
-
-export default function DeploymentOverviewDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/page.tsx
deleted file mode 100644
index 9672050cee0..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from './sidebar-page'
-
-export default function DeploymentDetailPageSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/releases/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/releases/page.tsx
deleted file mode 100644
index 1e9c907a376..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/releases/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebarSlot } from '../sidebar-page'
-
-export default function DeploymentReleasesDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/sidebar-page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/sidebar-page.tsx
deleted file mode 100644
index 720cef52a6b..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/[appInstanceId]/sidebar-page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentDetailSidebar } from '@/features/deployments/detail/detail-sidebar'
-
-export function DeploymentDetailSidebarSlot() {
- return
-}
diff --git a/web/app/(commonLayout)/@detailSidebar/deployments/create/page.tsx b/web/app/(commonLayout)/@detailSidebar/deployments/create/page.tsx
deleted file mode 100644
index f552d57c415..00000000000
--- a/web/app/(commonLayout)/@detailSidebar/deployments/create/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function DeploymentCreateDetailSidebarSlot() {
- return null
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/access/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/access/page.tsx
deleted file mode 100644
index eff309f8e85..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/access/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentAccess } from '@/features/deployments/detail/access'
-
-export default function InstanceDetailAccessPage() {
- return
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/api-tokens/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/api-tokens/page.tsx
deleted file mode 100644
index 1adba300386..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/api-tokens/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentApiTokens } from '@/features/deployments/detail/api-tokens'
-
-export default function InstanceDetailApiTokensPage() {
- return
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/instances/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/instances/page.tsx
deleted file mode 100644
index 0c4cbafc18e..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/instances/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentInstances } from '@/features/deployments/detail/instances'
-
-export default function InstanceDetailInstancesPage() {
- return
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/layout.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/layout.tsx
deleted file mode 100644
index a6d2dfacd61..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/layout.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { ReactNode } from 'react'
-import { InstanceDetail } from '@/features/deployments/detail'
-
-export default function InstanceDetailLayout({ children }: { children: ReactNode }) {
- return {children}
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/overview/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/overview/page.tsx
deleted file mode 100644
index 2ba3deb2202..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/overview/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentOverview } from '@/features/deployments/detail/overview'
-
-export default function InstanceDetailOverviewPage() {
- return
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/page.tsx
deleted file mode 100644
index 95530c5e4ff..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { redirect } from '@/next/navigation'
-
-export default async function InstanceDetailPage({
- params,
-}: {
- params: Promise<{ appInstanceId: string }>
-}) {
- const { appInstanceId } = await params
- redirect(`/deployments/${appInstanceId}/overview`)
-}
diff --git a/web/app/(commonLayout)/deployments/[appInstanceId]/releases/page.tsx b/web/app/(commonLayout)/deployments/[appInstanceId]/releases/page.tsx
deleted file mode 100644
index 29c928a8a8b..00000000000
--- a/web/app/(commonLayout)/deployments/[appInstanceId]/releases/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { DeploymentReleases } from '@/features/deployments/detail/releases'
-
-export default function InstanceDetailReleasesPage() {
- return
-}
diff --git a/web/app/(commonLayout)/deployments/__tests__/layout.spec.tsx b/web/app/(commonLayout)/deployments/__tests__/layout.spec.tsx
deleted file mode 100644
index f84508352e8..00000000000
--- a/web/app/(commonLayout)/deployments/__tests__/layout.spec.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-const mocks = vi.hoisted(() => ({
- notFound: vi.fn(() => {
- throw new Error('NEXT_NOT_FOUND')
- }),
-}))
-
-vi.mock('@/next/navigation', () => ({
- notFound: () => mocks.notFound(),
-}))
-
-describe('DeploymentsLayout', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should always trigger notFound', async () => {
- const { default: DeploymentsLayout } = await import('../layout')
-
- expect(() => DeploymentsLayout()).toThrow('NEXT_NOT_FOUND')
-
- expect(mocks.notFound).toHaveBeenCalledTimes(1)
- })
-})
diff --git a/web/app/(commonLayout)/deployments/create/page.tsx b/web/app/(commonLayout)/deployments/create/page.tsx
deleted file mode 100644
index 0be7206cc62..00000000000
--- a/web/app/(commonLayout)/deployments/create/page.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-'use client'
-
-import { useTranslation } from 'react-i18next'
-import { CreateDeploymentGuide } from '@/features/deployments/create-guide'
-import useDocumentTitle from '@/hooks/use-document-title'
-
-export default function CreateDeploymentPage() {
- const { t } = useTranslation('deployments')
- useDocumentTitle(t(($) => $['documentTitle.create']))
-
- return
-}
diff --git a/web/app/(commonLayout)/deployments/layout.tsx b/web/app/(commonLayout)/deployments/layout.tsx
deleted file mode 100644
index 2070a44ff99..00000000000
--- a/web/app/(commonLayout)/deployments/layout.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { notFound } from '@/next/navigation'
-
-export default function DeploymentsLayout() {
- notFound()
-}
diff --git a/web/app/(commonLayout)/deployments/page.tsx b/web/app/(commonLayout)/deployments/page.tsx
deleted file mode 100644
index 0dfa2117048..00000000000
--- a/web/app/(commonLayout)/deployments/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-'use client'
-import { useTranslation } from 'react-i18next'
-import { DeploymentsList } from '@/features/deployments/list'
-import useDocumentTitle from '@/hooks/use-document-title'
-
-export default function DeploymentsPage() {
- const { t } = useTranslation('deployments')
- useDocumentTitle(t(($) => $['documentTitle.list']))
- return
-}
diff --git a/web/app/(commonLayout)/layout.tsx b/web/app/(commonLayout)/layout.tsx
index 60e56f80f43..c8388ad6282 100644
--- a/web/app/(commonLayout)/layout.tsx
+++ b/web/app/(commonLayout)/layout.tsx
@@ -2,7 +2,6 @@ import * as React from 'react'
import Zendesk from '@/app/components/base/zendesk'
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
import MainNavLayout from '@/app/components/main-nav/layout'
-import { NextRouteStateBridge } from '@/app/components/next-route-state'
import { CommonLayoutGlobalMounts } from './global-mounts'
import { ConsoleContextProviders, ConsoleRuntimeProviders } from './providers'
@@ -16,15 +15,13 @@ export default async function Layout({
return (
-
-
-
-
- {children}
-
-
-
-
+
+
+
+ {children}
+
+
+
diff --git a/web/app/components/main-nav/__tests__/index.spec.tsx b/web/app/components/main-nav/__tests__/index.spec.tsx
index 57d5f2e5fe1..9bbc932eb25 100644
--- a/web/app/components/main-nav/__tests__/index.spec.tsx
+++ b/web/app/components/main-nav/__tests__/index.spec.tsx
@@ -720,12 +720,6 @@ describe('MainNav', () => {
).not.toBeInTheDocument()
})
- it('hides deployments in primary navigation when app deploy is enabled', () => {
- renderMainNav({ branding: { enabled: false }, enable_app_deploy: true })
-
- expect(screen.queryByRole('link', { name: /common.menus.deployments/ })).not.toBeInTheDocument()
- })
-
it('orders the Step-by-step Tour before the account and help actions', async () => {
localStorage.setItem(STEP_BY_STEP_TOUR_SHELL_MODE_STORAGE_KEY, 'collapsed')
@@ -811,7 +805,6 @@ describe('MainNav', () => {
'href',
'/marketplace',
)
- expect(screen.queryByRole('link', { name: /common.menus.deployments/ })).not.toBeInTheDocument()
expect(
screen.queryByRole('button', { name: 'explore.sidebar.webApps' }),
).not.toBeInTheDocument()
@@ -831,14 +824,13 @@ describe('MainNav', () => {
workspacePermissionKeys: ['app_library.access', 'tool.manage', 'agent.manage'],
}
- renderMainNav({ branding: { enabled: false }, enable_app_deploy: true })
+ renderMainNav({ branding: { enabled: false } })
expect(screen.getByRole('link', { name: /common.mainNav.home/ })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /common.menus.apps/ })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /Agents/ })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /common.menus.datasets/ })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /common.mainNav.integrations/ })).toBeInTheDocument()
- expect(screen.queryByRole('link', { name: /common.menus.deployments/ })).not.toBeInTheDocument()
expect(screen.getByRole('link', { name: /common.mainNav.marketplace/ })).toBeInTheDocument()
})
@@ -892,24 +884,6 @@ describe('MainNav', () => {
expect(screen.getByRole('link', { name: /common.menus.apps/ })).toHaveAttribute('href', '/apps')
})
- it.each(['/deployments', '/deployments/create'])(
- 'keeps global navigation on deployment collection route %s',
- (pathname) => {
- mockPathname = pathname
-
- renderMainNav({ branding: { enabled: false }, enable_app_deploy: true })
-
- expect(screen.queryByTestId('deployment-detail-top')).not.toBeInTheDocument()
- expect(screen.queryByTestId('deployment-detail-section')).not.toBeInTheDocument()
- expect(
- screen.getByRole('button', { name: 'common.mainNav.workspace.openMenu' }),
- ).toBeInTheDocument()
- expect(
- screen.queryByRole('link', { name: /common.menus.deployments/ }),
- ).not.toBeInTheDocument()
- },
- )
-
it.each([
'/datasets/create',
'/datasets/create-from-pipeline',
diff --git a/web/app/components/main-nav/__tests__/layout.spec.tsx b/web/app/components/main-nav/__tests__/layout.spec.tsx
index 4937f4e9270..cf93c353bd4 100644
--- a/web/app/components/main-nav/__tests__/layout.spec.tsx
+++ b/web/app/components/main-nav/__tests__/layout.spec.tsx
@@ -1,6 +1,5 @@
import type { ReactNode } from 'react'
import type { Mock } from 'vitest'
-import { useSuspenseQuery } from '@tanstack/react-query'
import { fireEvent, screen } from '@testing-library/react'
import { useStore as useAppStore } from '@/app/components/app/store'
import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag'
@@ -11,7 +10,6 @@ import MainNavLayout from '../layout'
const mockConsoleState = vi.hoisted(() => ({
current: {
isCurrentWorkspaceDatasetOperator: false,
- isCurrentWorkspaceEditor: true,
},
}))
@@ -24,14 +22,6 @@ vi.mock('@/app/components/header/header-wrapper', () => ({
{children}
),
}))
-vi.mock('@tanstack/react-query', async (importOriginal) => {
- const actual = await importOriginal()
- return {
- ...actual,
- useSuspenseQuery: vi.fn(),
- }
-})
-
vi.mock('@/context/workspace-state', async () => {
const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture')
return createWorkspaceStateModuleMock(() => mockConsoleState.current)
@@ -65,13 +55,7 @@ describe('MainNavLayout', () => {
;(usePathname as Mock).mockReturnValue('/apps')
mockConsoleState.current = {
isCurrentWorkspaceDatasetOperator: false,
- isCurrentWorkspaceEditor: true,
}
- ;(useSuspenseQuery as Mock).mockReturnValue({
- data: {
- enable_app_deploy: true,
- },
- })
;(isAgentV2Enabled as Mock).mockReturnValue(true)
})
@@ -196,64 +180,29 @@ describe('MainNavLayout', () => {
expect(screen.getByRole('main')).toHaveTextContent('new knowledge detail')
})
- it.each([
- '/datasets/create',
- '/datasets/new/create',
- '/datasets/dataset-1/documents/create',
- '/deployments/create',
- ])('keeps the global main nav on collection and creation route %s', (pathname) => {
- ;(usePathname as Mock).mockReturnValue(pathname)
+ it.each(['/datasets/create', '/datasets/new/create', '/datasets/dataset-1/documents/create'])(
+ 'keeps the global main nav on collection and creation route %s',
+ (pathname) => {
+ ;(usePathname as Mock).mockReturnValue(pathname)
- render(
- Detail sidebar}>
- content
- ,
- )
+ render(
+ Detail sidebar}>
+ content
+ ,
+ )
- expect(screen.getByTestId('main-nav')).toBeInTheDocument()
- expect(screen.queryByRole('complementary', { name: 'Detail sidebar' })).not.toBeInTheDocument()
- })
+ expect(screen.getByTestId('main-nav')).toBeInTheDocument()
+ expect(
+ screen.queryByRole('complementary', { name: 'Detail sidebar' }),
+ ).not.toBeInTheDocument()
+ },
+ )
- it.each([
- {
- label: 'agent detail route for dataset operators',
- pathname: '/agents/agent-1/configure',
- consoleState: {
- isCurrentWorkspaceDatasetOperator: true,
- isCurrentWorkspaceEditor: true,
- },
- systemFeatures: {
- enable_app_deploy: true,
- },
- },
- {
- label: 'deployment detail route for non-editor workspaces',
- pathname: '/deployments/app-instance-1/overview',
- consoleState: {
- isCurrentWorkspaceDatasetOperator: false,
- isCurrentWorkspaceEditor: false,
- },
- systemFeatures: {
- enable_app_deploy: true,
- },
- },
- {
- label: 'deployment detail route when deployment is disabled',
- pathname: '/deployments/app-instance-1/overview',
- consoleState: {
- isCurrentWorkspaceDatasetOperator: false,
- isCurrentWorkspaceEditor: true,
- },
- systemFeatures: {
- enable_app_deploy: false,
- },
- },
- ])('keeps the global main nav on $label', ({ pathname, consoleState, systemFeatures }) => {
- ;(usePathname as Mock).mockReturnValue(pathname)
- mockConsoleState.current = consoleState
- ;(useSuspenseQuery as Mock).mockReturnValue({
- data: systemFeatures,
- })
+ it('keeps the global main nav on agent detail routes for dataset operators', () => {
+ ;(usePathname as Mock).mockReturnValue('/agents/agent-1/configure')
+ mockConsoleState.current = {
+ isCurrentWorkspaceDatasetOperator: true,
+ }
render(
Detail sidebar}>
diff --git a/web/app/components/main-nav/index.tsx b/web/app/components/main-nav/index.tsx
index 4d82690e400..94e49570e54 100644
--- a/web/app/components/main-nav/index.tsx
+++ b/web/app/components/main-nav/index.tsx
@@ -10,10 +10,7 @@ import Badge from '@/app/components/base/badge'
import { DifyLogo } from '@/app/components/base/logo/dify-logo'
import EnvNav from '@/app/components/header/env-nav'
import StepByStepTourMount from '@/app/components/step-by-step-tour/mount'
-import {
- isCurrentWorkspaceDatasetOperatorAtom,
- isCurrentWorkspaceEditorAtom,
-} from '@/context/workspace-state'
+import { isCurrentWorkspaceDatasetOperatorAtom } from '@/context/workspace-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag'
import { useCanManageAgents } from '@/features/agent-v2/permissions'
@@ -34,7 +31,6 @@ export function MainNav({ className }: MainNavProps) {
const { t } = useTranslation()
const pathname = usePathname()
const isCurrentWorkspaceDatasetOperator = useAtomValue(isCurrentWorkspaceDatasetOperatorAtom)
- const isCurrentWorkspaceEditor = useAtomValue(isCurrentWorkspaceEditorAtom)
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
const { data: currentEnv } = useSuspenseQuery({
...userProfileQueryOptions(),
@@ -43,7 +39,6 @@ export function MainNav({ className }: MainNavProps) {
const agentV2Enabled = isAgentV2Enabled()
const canManageAgents = useCanManageAgents()
const showEnvTag = currentEnv === 'TESTING' || currentEnv === 'DEVELOPMENT'
- const canUseAppDeploy = isCurrentWorkspaceEditor && systemFeatures.enable_app_deploy
const navItems = useMemo(
() =>
@@ -51,7 +46,6 @@ export function MainNav({ className }: MainNavProps) {
isMainNavRouteVisible(route, {
agentV2Enabled,
canManageAgents,
- canUseAppDeploy,
isCurrentWorkspaceDatasetOperator,
marketplaceEnabled: systemFeatures.enable_marketplace,
}),
@@ -65,7 +59,6 @@ export function MainNav({ className }: MainNavProps) {
[
agentV2Enabled,
canManageAgents,
- canUseAppDeploy,
isCurrentWorkspaceDatasetOperator,
systemFeatures.enable_marketplace,
t,
diff --git a/web/app/components/main-nav/layout.tsx b/web/app/components/main-nav/layout.tsx
index e6b79fe335b..0c82a31fb57 100644
--- a/web/app/components/main-nav/layout.tsx
+++ b/web/app/components/main-nav/layout.tsx
@@ -1,18 +1,13 @@
'use client'
import type { ReactNode } from 'react'
-import { useSuspenseQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
-import {
- isCurrentWorkspaceDatasetOperatorAtom,
- isCurrentWorkspaceEditorAtom,
-} from '@/context/workspace-state'
+import { isCurrentWorkspaceDatasetOperatorAtom } from '@/context/workspace-state'
import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag'
-import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { usePathname } from '@/next/navigation'
import { MainNav } from '.'
import { shouldHideMainNavigation, shouldUseDetailSidebar } from './routes'
@@ -45,12 +40,9 @@ const MainNavLayout = ({ children, detailSidebar }: MainNavLayoutProps) => {
const { t } = useTranslation('common')
const pathname = usePathname()
const isCurrentWorkspaceDatasetOperator = useAtomValue(isCurrentWorkspaceDatasetOperatorAtom)
- const isCurrentWorkspaceEditor = useAtomValue(isCurrentWorkspaceEditorAtom)
- const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
const hideMainNavigation = shouldHideMainNavigation(pathname)
const useDetailSidebar = shouldUseDetailSidebar(pathname, {
agentV2Enabled: isAgentV2Enabled(),
- canUseAppDeploy: isCurrentWorkspaceEditor && systemFeatures.enable_app_deploy,
isCurrentWorkspaceDatasetOperator,
})
diff --git a/web/app/components/main-nav/routes.ts b/web/app/components/main-nav/routes.ts
index 22062086106..7d308a1cdea 100644
--- a/web/app/components/main-nav/routes.ts
+++ b/web/app/components/main-nav/routes.ts
@@ -4,7 +4,6 @@ type MainNavRouteVisibility = (options: MainNavRouteVisibilityOptions) => boolea
const DATASET_COLLECTION_ROUTES = new Set(['create', 'create-from-pipeline', 'connect'])
const DATASET_DOCUMENT_CREATION_ROUTES = new Set(['create', 'create-from-pipeline'])
-const DEPLOYMENT_COLLECTION_ROUTES = new Set(['create'])
export type MainNavRouteConfig = {
key: string
@@ -19,14 +18,13 @@ export type MainNavRouteConfig = {
export type MainNavRouteVisibilityOptions = {
agentV2Enabled: boolean
canManageAgents: boolean
- canUseAppDeploy: boolean
isCurrentWorkspaceDatasetOperator: boolean
marketplaceEnabled: boolean
}
export type DetailSidebarVisibilityOptions = Pick<
MainNavRouteVisibilityOptions,
- 'agentV2Enabled' | 'canUseAppDeploy' | 'isCurrentWorkspaceDatasetOperator'
+ 'agentV2Enabled' | 'isCurrentWorkspaceDatasetOperator'
>
const VISIBLE_TO_ALL: MainNavRouteVisibility = () => true
@@ -147,14 +145,6 @@ function isAgentDetailPathname(pathname: string) {
return section === 'agents' && !!agentId
}
-function isDeploymentDetailPathname(pathname: string) {
- const [section, appInstanceId] = pathname.split('/').filter(Boolean)
-
- return (
- section === 'deployments' && !!appInstanceId && !DEPLOYMENT_COLLECTION_ROUTES.has(appInstanceId)
- )
-}
-
function isSnippetDetailPathname(pathname: string) {
const [section, snippetId] = pathname.split('/').filter(Boolean)
@@ -168,7 +158,5 @@ export function shouldUseDetailSidebar(pathname: string, options: DetailSidebarV
if (isAppDetailPathname(pathname)) return true
- if (options.agentV2Enabled && isAgentDetailPathname(pathname)) return true
-
- return options.canUseAppDeploy && isDeploymentDetailPathname(pathname)
+ return options.agentV2Enabled && isAgentDetailPathname(pathname)
}
diff --git a/web/app/components/next-route-state/atoms.ts b/web/app/components/next-route-state/atoms.ts
deleted file mode 100644
index 833380d0b3d..00000000000
--- a/web/app/components/next-route-state/atoms.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { atom } from 'jotai'
-
-export type NextRouteParams = Record
-
-type NextRouteState = {
- pathname: string
- params: NextRouteParams
-}
-
-// Mirrors Next router state. NextRouteStateBridge force-hydrates this atom on
-// render so feature atoms can read route state without calling router hooks.
-const nextRouteStateAtom = atom({
- pathname: '',
- params: {},
-})
-
-function normalizedParamEntries(params: NextRouteParams) {
- return Object.keys(params)
- .sort()
- .map((key) => {
- const value = params[key]
- return [key, Array.isArray(value) ? [...value] : value] as const
- })
-}
-
-function normalizeNextRouteParams(params: NextRouteParams): NextRouteParams {
- return Object.fromEntries(normalizedParamEntries(params)) as NextRouteParams
-}
-
-function routeParamsKey(params: NextRouteParams) {
- return JSON.stringify(normalizedParamEntries(params))
-}
-
-export const nextParamsAtom = atom((get) => get(nextRouteStateAtom).params)
-export const nextPathnameAtom = atom((get) => get(nextRouteStateAtom).pathname)
-
-export const setNextRouteStateAtom = atom(null, (get, set, routeState: NextRouteState) => {
- const nextParams = normalizeNextRouteParams(routeState.params)
- const currentRouteState = get(nextRouteStateAtom)
-
- if (
- currentRouteState.pathname !== routeState.pathname ||
- routeParamsKey(currentRouteState.params) !== routeParamsKey(nextParams)
- ) {
- set(nextRouteStateAtom, {
- pathname: routeState.pathname,
- params: nextParams,
- })
- }
-})
diff --git a/web/app/components/next-route-state/index.tsx b/web/app/components/next-route-state/index.tsx
deleted file mode 100644
index 0293b653038..00000000000
--- a/web/app/components/next-route-state/index.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import type { NextRouteParams } from './atoms'
-import { useHydrateAtoms } from 'jotai/utils'
-import { useParams, usePathname } from '@/next/navigation'
-import { setNextRouteStateAtom } from './atoms'
-
-export function NextRouteStateBridge({ children }: { children: ReactNode }) {
- const pathname = usePathname()
- const params = useParams()
-
- useHydrateAtoms(
- [
- [
- setNextRouteStateAtom,
- {
- pathname,
- params,
- },
- ],
- ] as const,
- { dangerouslyForceHydrate: true },
- )
-
- return children
-}
diff --git a/web/context/workspace-state.ts b/web/context/workspace-state.ts
index 5bc5432ae41..8c9460286dd 100644
--- a/web/context/workspace-state.ts
+++ b/web/context/workspace-state.ts
@@ -32,6 +32,11 @@ export const isCurrentWorkspaceManagerAtom = atom((get) => {
return get(workspaceRoleFlagsAtom).isCurrentWorkspaceManager
})
+/**
+ * Retained for future permission checks when RBAC is disabled.
+ *
+ * @public
+ */
export const isCurrentWorkspaceEditorAtom = atom((get) => {
return get(workspaceRoleFlagsAtom).isCurrentWorkspaceEditor
})
diff --git a/web/features/deployments/README.md b/web/features/deployments/README.md
deleted file mode 100644
index c226bfb2fdb..00000000000
--- a/web/features/deployments/README.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Deployments
-
-Deployment app instance, release, runtime target, access, and developer API feature modules.
-
-## Internal Module Dependency Graph
-
-The graph shows product module dependencies inside `web/features/deployments`. It omits route-state plumbing and shared support modules.
-
-```mermaid
-flowchart TD
- list["list"]
- detail["detail"]
- createGuide["create-guide"]
- createRelease["create-release"]
- deployDrawer["deploy-drawer"]
- deploymentActions["deployment-actions"]
-
- detailOverview["detail/overview"]
- detailInstances["detail/instances"]
- detailAccess["detail/access"]
- detailApiTokens["detail/api-tokens"]
- detailReleases["detail/releases"]
-
- accessChannels["detail/access/channels"]
- accessPermissions["detail/access/permissions"]
- accessSubjectSelector["detail/access/permissions/access-subject-selector"]
- apiTokenManagement["detail/api-tokens/api-token-management"]
- apiKeys["detail/api-tokens/api-keys"]
- apiDocs["detail/api-tokens/docs"]
- instanceEnvironmentList["detail/instances/environment-list"]
- instanceHeaderActions["detail/instances/header-actions"]
- instanceRowActions["detail/instances/row-actions"]
- overviewAccessSummary["detail/overview/access-summary"]
- overviewEnvironmentStatus["detail/overview/environment-status"]
- overviewReleaseSummary["detail/overview/release-summary"]
- releaseActions["detail/releases/release-actions"]
- releaseHistory["detail/releases/release-history"]
-
- list --> createGuide
- list --> createRelease
- list --> deployDrawer
- list --> deploymentActions
- list --> detail
-
- detail --> createRelease
- detail --> deploymentActions
- detail --> detailOverview
- detail --> detailInstances
- detail --> detailAccess
- detail --> detailApiTokens
- detail --> detailReleases
- detail --> instanceHeaderActions
-
- detailOverview --> overviewAccessSummary
- detailOverview --> overviewEnvironmentStatus
- detailOverview --> overviewReleaseSummary
-
- overviewEnvironmentStatus --> deployDrawer
- overviewReleaseSummary --> createRelease
-
- detailInstances --> detail
- detailInstances --> instanceEnvironmentList
- detailInstances --> instanceHeaderActions
- instanceEnvironmentList --> detailInstances
- instanceEnvironmentList --> instanceRowActions
- instanceHeaderActions --> deployDrawer
- instanceHeaderActions --> detail
- instanceRowActions --> deployDrawer
-
- detailAccess --> accessChannels
- detailAccess --> accessPermissions
- accessChannels --> detailAccess
- accessPermissions --> detailAccess
- accessPermissions --> accessSubjectSelector
-
- detailApiTokens --> apiTokenManagement
- apiTokenManagement --> detailApiTokens
- apiTokenManagement --> apiKeys
- apiTokenManagement --> apiDocs
- apiKeys --> detailApiTokens
-
- detailReleases --> releaseHistory
- releaseActions --> deployDrawer
- releaseHistory --> detailReleases
- releaseHistory --> releaseActions
-```
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| -------------------- | ------------------------------------------------------------- |
-| `list` | Owns the deployment app instance list surface. |
-| `detail` | Owns the deployment app instance detail shell and route tabs. |
-| `create-guide` | Owns the create deployment guide workflow. |
-| `create-release` | Owns release creation entry points and dialog state. |
-| `deploy-drawer` | Owns deployment target selection and submit workflow state. |
-| `deployment-actions` | Owns app instance edit and delete action surfaces. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/create-guide/README.md b/web/features/deployments/create-guide/README.md
deleted file mode 100644
index bdc24c614d1..00000000000
--- a/web/features/deployments/create-guide/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Deployment Create Guide
-
-Guided deployment creation workflow for selecting a source, defining the initial release, and optionally deploying to an environment.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| -------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| --------------------------------------------------- | -------------------------------------------------------------------------------- |
-| `app/components/app/create-from-dsl-modal/uploader` | Reuses the existing DSL file uploader for the import source step. |
-| `app/components/base/app-icon` | Renders app icons consistently in source app options. |
-| `app/components/base/skeleton` | Reuses the existing skeleton primitive for source and target loading states. |
-| `types/app` | Uses app types and mode enums to narrow selectable source apps to workflow apps. |
diff --git a/web/features/deployments/create-guide/index.tsx b/web/features/deployments/create-guide/index.tsx
deleted file mode 100644
index 929669a2de2..00000000000
--- a/web/features/deployments/create-guide/index.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-'use client'
-
-import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
-import { useTranslation } from 'react-i18next'
-import Link from '@/next/link'
-import { useRouter } from '@/next/navigation'
-import { CreateDeploymentGuideProvider } from './state/provider'
-import { CreateDeploymentGuideShell } from './ui/shell'
-
-export function CreateDeploymentGuide() {
- const { t } = useTranslation('deployments')
- const router = useRouter()
-
- return (
-
- )
-}
diff --git a/web/features/deployments/create-guide/link.tsx b/web/features/deployments/create-guide/link.tsx
deleted file mode 100644
index 7fd4dc90f08..00000000000
--- a/web/features/deployments/create-guide/link.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-'use client'
-
-import type { ComponentProps } from 'react'
-import Link from '@/next/link'
-
-const createDeploymentGuideHref = '/deployments/create'
-
-type CreateDeploymentGuideLinkProps = Omit, 'href'>
-
-export function CreateDeploymentGuideLink(props: CreateDeploymentGuideLinkProps) {
- return
-}
diff --git a/web/features/deployments/create-guide/state/__tests__/index.spec.ts b/web/features/deployments/create-guide/state/__tests__/index.spec.ts
deleted file mode 100644
index 4aa7035d039..00000000000
--- a/web/features/deployments/create-guide/state/__tests__/index.spec.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-import {
- dslFileAtom,
- effectiveMethodAtom,
- instanceNameAtom,
- methodAtom,
- releaseNameAtom,
- selectedAppAtom,
- stepAtom,
-} from '../primitives'
-import {
- dslDefaultAppNameAtom,
- dslReadErrorAtom,
- isReadingDslAtom,
- sourceAppsQueryAtom,
-} from '../source'
-import {
- continueFromSourceAtom,
- selectDslFileAtom,
- selectMethodAtom,
- sourceCanGoNextAtom,
-} from '../workflow'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
- retry?: boolean
-}
-
-type InfiniteQueryOptions = QueryOptions & {
- input?: (pageParam: number) => unknown
-}
-
-const queryOptionsMocks = vi.hoisted(() => ({
- sourceApps: vi.fn(),
-}))
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- apps: {
- get: {
- infiniteOptions: (options: InfiniteQueryOptions) => {
- queryOptionsMocks.sourceApps(options)
-
- return {
- ...options,
- queryKey: ['sourceApps'],
- queryFn: async () => ({ data: [], has_more: false, page: 1 }),
- }
- },
- },
- },
- enterprise: {
- appInstanceService: {
- listAppInstances: {
- infiniteOptions: (options: InfiniteQueryOptions) => ({
- ...options,
- queryKey: ['existingInstanceNames'],
- queryFn: async () => ({ appInstances: [], pagination: {} }),
- }),
- queryOptions: (options: QueryOptions) => ({
- ...options,
- queryKey: ['instanceNameConflict'],
- queryFn: async () => ({ appInstances: [] }),
- }),
- },
- },
- environmentService: {
- listEnvironments: {
- queryOptions: (options: QueryOptions) => ({
- ...options,
- queryKey: ['environments'],
- queryFn: async () => ({ environments: [] }),
- }),
- },
- },
- releaseService: {
- computeDeploymentOptions: {
- queryOptions: (options: QueryOptions) => ({
- ...options,
- queryKey: ['deploymentOptions'],
- queryFn: async () => ({ options: { credentialSlots: [], envVarSlots: [] } }),
- }),
- },
- precheckRelease: {
- queryOptions: (options: QueryOptions) => ({
- ...options,
- queryKey: ['precheckRelease'],
- queryFn: async () => ({ canCreate: false, unsupportedNodes: [] }),
- }),
- },
- },
- },
- },
-}))
-
-function workflowDsl() {
- return ['app:', ' mode: workflow', ' name: Imported guide'].join('\n')
-}
-
-describe('create deployment guide state', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should keep the guide on source app mode when DSL import is disabled', () => {
- const { store } = createQueryAtomTestStore()
-
- store.set(selectMethodAtom, 'importDsl')
-
- expect(store.get(methodAtom)).toBe('bindApp')
- expect(store.get(effectiveMethodAtom)).toBe('bindApp')
- })
-
- it('should keep source app loading enabled if stale state points to DSL import', () => {
- const { store } = createQueryAtomTestStore()
-
- store.set(methodAtom, 'importDsl')
-
- store.get(sourceAppsQueryAtom)
-
- expect(store.get(effectiveMethodAtom)).toBe('bindApp')
- expect(queryOptionsMocks.sourceApps).toHaveBeenLastCalledWith(
- expect.objectContaining({ enabled: true }),
- )
- })
-
- it('should continue from source app mode and auto-fill unique release metadata', () => {
- const { queryClient, store } = createQueryAtomTestStore()
- queryClient.setQueryData(['sourceApps'], {
- pages: [
- {
- data: [
- {
- id: 'source-app-1',
- name: 'Customer Service',
- mode: 'workflow',
- },
- ],
- },
- ],
- pageParams: [1],
- })
- queryClient.setQueryData(['precheckRelease'], {
- canCreate: true,
- unsupportedNodes: [],
- })
- queryClient.setQueryData(['deploymentOptions'], {
- options: {
- credentialSlots: [],
- envVarSlots: [],
- },
- })
- queryClient.setQueryData(['existingInstanceNames'], {
- pages: [
- {
- appInstances: [
- { displayName: 'Customer Service' },
- { displayName: 'Customer Service 1' },
- ],
- },
- ],
- pageParams: [1],
- })
-
- expect(store.get(sourceCanGoNextAtom)).toBe(true)
-
- store.set(continueFromSourceAtom, {
- defaultDslAppName: 'Imported DSL',
- defaultReleaseName: 'Initial Release',
- })
-
- expect(store.get(selectedAppAtom)).toMatchObject({
- id: 'source-app-1',
- name: 'Customer Service',
- })
- expect(store.get(instanceNameAtom)).toMatch(/^Customer Service-[a-z]{4}$/)
- expect(store.get(releaseNameAtom)).toBe('Initial Release')
- expect(store.get(stepAtom)).toBe('release')
- })
-
- it('should read selected DSL file content through the file content query', () => {
- const { queryClient, store } = createQueryAtomTestStore()
- const text = vi.fn().mockResolvedValue(workflowDsl())
- const file = new File([], 'workflow.yml', { type: 'text/yaml' })
- Object.defineProperty(file, 'text', { value: text })
-
- store.set(selectDslFileAtom, file)
- queryClient.setQueryData(
- ['createGuideDslFileContent', 1, file, file.name, file.size, file.lastModified],
- workflowDsl(),
- )
-
- expect(text).not.toHaveBeenCalled()
- expect(store.get(dslFileAtom)).toBe(file)
- expect(store.get(dslDefaultAppNameAtom)).toBe('Imported guide')
- expect(store.get(isReadingDslAtom)).toBe(false)
- expect(store.get(dslReadErrorAtom)).toBe(false)
- })
-})
diff --git a/web/features/deployments/create-guide/state/environment.ts b/web/features/deployments/create-guide/state/environment.ts
deleted file mode 100644
index 91792bc28da..00000000000
--- a/web/features/deployments/create-guide/state/environment.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Environment } from '@dify/contracts/enterprise/types.gen'
-
-export function environmentMatchesIdentifier(environment: Environment, identifier: string) {
- const normalizedIdentifier = identifier.trim()
- if (!normalizedIdentifier) return false
-
- return environment.id === normalizedIdentifier || environment.displayName === normalizedIdentifier
-}
diff --git a/web/features/deployments/create-guide/state/primitives.ts b/web/features/deployments/create-guide/state/primitives.ts
deleted file mode 100644
index 9b6382371c3..00000000000
--- a/web/features/deployments/create-guide/state/primitives.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-'use client'
-
-import type { GuideMethod, GuideStep, WorkflowSourceApp } from './types'
-import type { EnvVarValues } from '@/features/deployments/shared/components/env-var-bindings'
-import type { RuntimeCredentialBindingSelections } from '@/features/deployments/shared/components/runtime-credential-bindings-utils'
-import type { UnsupportedDslNode } from '@/features/deployments/shared/domain/error'
-import { atom } from 'jotai'
-import { deploymentGuideMethod } from './utils'
-
-export const stepAtom = atom('source')
-export const methodAtom = atom('bindApp')
-export const effectiveMethodAtom = atom((get) => deploymentGuideMethod(get(methodAtom)))
-
-export const sourceSearchTextAtom = atom('')
-export const selectedAppAtom = atom(undefined)
-
-export const dslFileAtom = atom(undefined)
-export const dslFileReadVersionAtom = atom(0)
-
-export const instanceNameAtom = atom('')
-export const instanceDescriptionAtom = atom('')
-export const releaseNameAtom = atom('')
-export const releaseDescriptionAtom = atom('')
-export const autoFilledInstanceNameAtom = atom('')
-export const autoFilledReleaseNameAtom = atom('')
-
-export const selectedEnvironmentIdAtom = atom('')
-export const manualBindingSelectionsAtom = atom({})
-export const envVarValuesAtom = atom({})
-
-export const submissionUnsupportedDslNodesAtom = atom([])
-export const isCreatingDeploymentAtom = atom(false)
-export const isCreatingReleaseOnlyAtom = atom(false)
-
-export const isSubmittingDeploymentGuideAtom = atom(
- (get) => get(isCreatingDeploymentAtom) || get(isCreatingReleaseOnlyAtom),
-)
diff --git a/web/features/deployments/create-guide/state/provider.tsx b/web/features/deployments/create-guide/state/provider.tsx
deleted file mode 100644
index 3cb9593f139..00000000000
--- a/web/features/deployments/create-guide/state/provider.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { ScopeProvider } from 'jotai-scope'
-import { createDeploymentGuideScopedAtoms } from './scoped'
-
-export function CreateDeploymentGuideProvider({ children }: { children: ReactNode }) {
- return {children}
-}
diff --git a/web/features/deployments/create-guide/state/queries.ts b/web/features/deployments/create-guide/state/queries.ts
deleted file mode 100644
index 6fa3773179f..00000000000
--- a/web/features/deployments/create-guide/state/queries.ts
+++ /dev/null
@@ -1,225 +0,0 @@
-'use client'
-
-import type { Getter } from 'jotai/vanilla'
-import { keepPreviousData, skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithInfiniteQuery, atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { encodeDslContent } from '@/features/deployments/shared/domain/dsl'
-import { consoleQuery } from '@/service/client'
-import {
- effectiveMethodAtom,
- instanceNameAtom,
- submissionUnsupportedDslNodesAtom,
-} from './primitives'
-import { dslContentAtom, effectiveSelectedAppAtom, sourceReady } from './source'
-import { DEPLOYMENT_PAGE_SIZE, getNextPageParamFromPagination } from './utils'
-
-export const existingInstanceNamesQueryAtom = atomWithInfiniteQuery(() =>
- consoleQuery.enterprise.appInstanceService.listAppInstances.infiniteOptions({
- input: (pageParam) => ({
- query: {
- pageNumber: Number(pageParam),
- resultsPerPage: DEPLOYMENT_PAGE_SIZE,
- },
- }),
- getNextPageParam: (lastPage) => getNextPageParamFromPagination(lastPage.pagination),
- initialPageParam: 1,
- placeholderData: keepPreviousData,
- }),
-)
-
-export const instanceNameConflictQueryAtom = atomWithQuery((get) => {
- const submittedInstanceName = get(instanceNameAtom).trim()
-
- return consoleQuery.enterprise.appInstanceService.listAppInstances.queryOptions({
- input: {
- query: {
- pageNumber: 1,
- resultsPerPage: 1,
- displayName: submittedInstanceName,
- },
- },
- enabled: Boolean(submittedInstanceName),
- })
-})
-
-export const deployableEnvironmentsQueryAtom = atomWithQuery((get) => {
- return consoleQuery.enterprise.environmentService.listEnvironments.queryOptions({
- input: {
- query: {
- // The guide offers every deployable environment at once; environment
- // count is capped well below the 100-per-page maximum.
- pageNumber: 1,
- resultsPerPage: 100,
- },
- },
- enabled: sourceReady(get),
- })
-})
-
-export const deployableEnvironmentsDataAtom = selectAtom(
- deployableEnvironmentsQueryAtom,
- (query) => query.data,
-)
-export const deployableEnvironmentsIsErrorAtom = selectAtom(
- deployableEnvironmentsQueryAtom,
- (query) => query.isError,
-)
-export const deployableEnvironmentsIsLoadingAtom = selectAtom(
- deployableEnvironmentsQueryAtom,
- (query) => query.isLoading,
-)
-export const deployableEnvironmentsIsFetchingAtom = selectAtom(
- deployableEnvironmentsQueryAtom,
- (query) => query.isFetching,
-)
-
-const precheckReleaseQueryAtom = atomWithQuery((get) => {
- const method = get(effectiveMethodAtom)
- const effectiveSelectedApp = get(effectiveSelectedAppAtom)
- const dslContent = get(dslContentAtom)
- const encodedDslContent = dslContent.trim() ? encodeDslContent(dslContent) : undefined
- const enabled = sourceReady(get)
-
- // PrecheckRelease takes exactly one source arm (dsl | sourceAppId).
- const precheckReleaseQueryOptions =
- method === 'importDsl'
- ? consoleQuery.enterprise.releaseService.precheckRelease.queryOptions({
- input: encodedDslContent
- ? {
- body: {
- dsl: encodedDslContent,
- },
- }
- : skipToken,
- enabled,
- retry: false,
- })
- : consoleQuery.enterprise.releaseService.precheckRelease.queryOptions({
- input: effectiveSelectedApp?.id
- ? {
- body: {
- sourceAppId: effectiveSelectedApp.id,
- },
- }
- : skipToken,
- enabled: enabled && Boolean(effectiveSelectedApp?.id),
- retry: false,
- })
-
- return precheckReleaseQueryOptions
-})
-
-const precheckReleaseDataAtom = selectAtom(precheckReleaseQueryAtom, (query) => query.data)
-const precheckReleaseIsSuccessAtom = selectAtom(
- precheckReleaseQueryAtom,
- (query) => query.isSuccess,
-)
-const precheckReleaseIsLoadingAtom = selectAtom(
- precheckReleaseQueryAtom,
- (query) => query.isLoading,
-)
-const precheckReleaseIsFetchingAtom = selectAtom(
- precheckReleaseQueryAtom,
- (query) => query.isFetching,
-)
-
-function precheckReleaseReady(get: Getter) {
- const precheckRelease = get(precheckReleaseDataAtom)
-
- return (
- sourceReady(get) &&
- get(precheckReleaseIsSuccessAtom) &&
- Boolean(precheckRelease?.canCreate) &&
- (precheckRelease?.unsupportedNodes.length ?? 0) === 0 &&
- get(submissionUnsupportedDslNodesAtom).length === 0
- )
-}
-
-const deploymentOptionsQueryAtom = atomWithQuery((get) => {
- const method = get(effectiveMethodAtom)
- const effectiveSelectedApp = get(effectiveSelectedAppAtom)
- const dslContent = get(dslContentAtom)
- const encodedDslContent = dslContent.trim() ? encodeDslContent(dslContent) : undefined
- const enabled = precheckReleaseReady(get)
-
- // ComputeDeploymentOptions takes exactly one source arm (dsl | sourceAppId | releaseId).
- const deploymentOptionsQueryOptions =
- method === 'importDsl'
- ? consoleQuery.enterprise.releaseService.computeDeploymentOptions.queryOptions({
- input: encodedDslContent
- ? {
- body: {
- dsl: encodedDslContent,
- },
- }
- : skipToken,
- enabled,
- retry: false,
- })
- : consoleQuery.enterprise.releaseService.computeDeploymentOptions.queryOptions({
- input: effectiveSelectedApp?.id
- ? {
- body: {
- sourceAppId: effectiveSelectedApp.id,
- },
- }
- : skipToken,
- enabled: enabled && Boolean(effectiveSelectedApp?.id),
- retry: false,
- })
-
- return deploymentOptionsQueryOptions
-})
-
-export const deploymentOptionsDataAtom = selectAtom(
- deploymentOptionsQueryAtom,
- (query) => query.data,
-)
-export const deploymentOptionsIsErrorAtom = selectAtom(
- deploymentOptionsQueryAtom,
- (query) => query.isError,
-)
-export const deploymentOptionsIsLoadingAtom = selectAtom(
- deploymentOptionsQueryAtom,
- (query) => query.isLoading,
-)
-export const deploymentOptionsIsFetchingAtom = selectAtom(
- deploymentOptionsQueryAtom,
- (query) => query.isFetching,
-)
-const deploymentOptionsIsSuccessAtom = selectAtom(
- deploymentOptionsQueryAtom,
- (query) => query.isSuccess,
-)
-
-export const unsupportedDslNodesAtom = atom((get) => {
- const submissionUnsupportedDslNodes = get(submissionUnsupportedDslNodesAtom)
- if (submissionUnsupportedDslNodes.length > 0) return submissionUnsupportedDslNodes
-
- if (!sourceReady(get)) return []
-
- return get(precheckReleaseDataAtom)?.unsupportedNodes ?? []
-})
-
-const precheckReleaseReadyAtom = atom((get) => {
- return precheckReleaseReady(get)
-})
-
-export const deploymentOptionsReadyAtom = atom((get) => {
- return sourceReady(get) && get(precheckReleaseReadyAtom) && get(deploymentOptionsIsSuccessAtom)
-})
-
-export const deploymentOptionsContentCheckedAtom = atom((get) => {
- const isLoadingOptions =
- get(deploymentOptionsIsLoadingAtom) ||
- (get(deploymentOptionsIsFetchingAtom) && !get(deploymentOptionsDataAtom))
- const isCheckingReleaseContent =
- get(precheckReleaseIsLoadingAtom) ||
- (get(precheckReleaseIsFetchingAtom) && !get(precheckReleaseDataAtom))
-
- if (!sourceReady(get) || isCheckingReleaseContent || isLoadingOptions) return false
-
- return get(precheckReleaseReadyAtom) && get(deploymentOptionsIsSuccessAtom)
-})
diff --git a/web/features/deployments/create-guide/state/release.ts b/web/features/deployments/create-guide/state/release.ts
deleted file mode 100644
index 0ae13ddf26f..00000000000
--- a/web/features/deployments/create-guide/state/release.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-'use client'
-
-import { atom } from 'jotai'
-import {
- autoFilledInstanceNameAtom,
- autoFilledReleaseNameAtom,
- envVarValuesAtom,
- instanceDescriptionAtom,
- instanceNameAtom,
- manualBindingSelectionsAtom,
- releaseDescriptionAtom,
- releaseNameAtom,
- selectedEnvironmentIdAtom,
- stepAtom,
-} from './primitives'
-import {
- deploymentOptionsContentCheckedAtom,
- existingInstanceNamesQueryAtom,
- instanceNameConflictQueryAtom,
-} from './queries'
-import { sourceReady } from './source'
-
-export const hasInstanceNameConflictAtom = atom((get) => {
- const submittedInstanceName = get(instanceNameAtom).trim()
- const instanceNameConflictQuery = get(instanceNameConflictQueryAtom)
- const existingInstanceNamesQuery = get(existingInstanceNamesQueryAtom)
- const existingInstanceNames =
- existingInstanceNamesQuery.data?.pages.flatMap((page) =>
- page.appInstances.flatMap((appInstance) => {
- const name = appInstance.displayName.trim()
-
- return name ? [name] : []
- }),
- ) ?? []
-
- return Boolean(
- submittedInstanceName &&
- (existingInstanceNames.includes(submittedInstanceName) ||
- (instanceNameConflictQuery.data?.appInstances.some(
- (appInstance) => appInstance.displayName.trim() === submittedInstanceName,
- ) ??
- false)),
- )
-})
-
-export const submittedReleaseReadyAtom = atom((get) => {
- return Boolean(sourceReady(get) && get(instanceNameAtom).trim() && get(releaseNameAtom).trim())
-})
-
-export const releaseCanGoNextAtom = atom((get) => {
- const submittedInstanceName = get(instanceNameAtom).trim()
- const instanceNameConflictQuery = get(instanceNameConflictQueryAtom)
-
- return (
- Boolean(get(submittedReleaseReadyAtom)) &&
- !get(hasInstanceNameConflictAtom) &&
- !(Boolean(submittedInstanceName) && instanceNameConflictQuery.isLoading) &&
- get(deploymentOptionsContentCheckedAtom)
- )
-})
-
-export const setInstanceNameAtom = atom(null, (_get, set, value: string) => {
- set(instanceNameAtom, value)
- set(autoFilledInstanceNameAtom, '')
- set(stepAtom, 'release')
-})
-
-export const setInstanceDescriptionAtom = atom(null, (_get, set, value: string) => {
- set(instanceDescriptionAtom, value)
- set(stepAtom, 'release')
-})
-
-export const setReleaseNameAtom = atom(null, (_get, set, value: string) => {
- set(releaseNameAtom, value)
- set(autoFilledReleaseNameAtom, '')
- set(stepAtom, 'release')
-})
-
-export const setReleaseDescriptionAtom = atom(null, (_get, set, value: string) => {
- set(releaseDescriptionAtom, value)
- set(stepAtom, 'release')
-})
-
-export const continueFromReleaseAtom = atom(null, (get, set) => {
- if (!get(releaseCanGoNextAtom)) return
-
- set(selectedEnvironmentIdAtom, '')
- set(manualBindingSelectionsAtom, {})
- set(envVarValuesAtom, {})
- set(stepAtom, 'target')
-})
diff --git a/web/features/deployments/create-guide/state/scoped.ts b/web/features/deployments/create-guide/state/scoped.ts
deleted file mode 100644
index 0abe15b295f..00000000000
--- a/web/features/deployments/create-guide/state/scoped.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import {
- autoFilledInstanceNameAtom,
- autoFilledReleaseNameAtom,
- dslFileAtom,
- dslFileReadVersionAtom,
- envVarValuesAtom,
- instanceDescriptionAtom,
- instanceNameAtom,
- isCreatingDeploymentAtom,
- isCreatingReleaseOnlyAtom,
- manualBindingSelectionsAtom,
- methodAtom,
- releaseDescriptionAtom,
- releaseNameAtom,
- selectedAppAtom,
- selectedEnvironmentIdAtom,
- sourceSearchTextAtom,
- stepAtom,
- submissionUnsupportedDslNodesAtom,
-} from './primitives'
-
-export const createDeploymentGuideScopedAtoms = [
- stepAtom,
- methodAtom,
- sourceSearchTextAtom,
- selectedAppAtom,
- dslFileAtom,
- dslFileReadVersionAtom,
- instanceNameAtom,
- instanceDescriptionAtom,
- releaseNameAtom,
- releaseDescriptionAtom,
- autoFilledInstanceNameAtom,
- autoFilledReleaseNameAtom,
- selectedEnvironmentIdAtom,
- manualBindingSelectionsAtom,
- envVarValuesAtom,
- submissionUnsupportedDslNodesAtom,
- isCreatingDeploymentAtom,
- isCreatingReleaseOnlyAtom,
-]
diff --git a/web/features/deployments/create-guide/state/source.ts b/web/features/deployments/create-guide/state/source.ts
deleted file mode 100644
index 2130ff34df7..00000000000
--- a/web/features/deployments/create-guide/state/source.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-'use client'
-
-import type { Getter } from 'jotai/vanilla'
-import type { WorkflowSourceApp } from './types'
-import { keepPreviousData, queryOptions } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithInfiniteQuery, atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { dslAppName, isWorkflowDsl } from '@/features/deployments/shared/domain/dsl'
-import { consoleQuery } from '@/service/client'
-import { AppModeEnum } from '@/types/app'
-import {
- dslFileAtom,
- dslFileReadVersionAtom,
- effectiveMethodAtom,
- selectedAppAtom,
- sourceSearchTextAtom,
-} from './primitives'
-import { SOURCE_APPS_PAGE_SIZE } from './utils'
-
-const dslFileContentQueryAtom = atomWithQuery((get) => {
- const file = get(dslFileAtom)
- const fileReadVersion = get(dslFileReadVersionAtom)
-
- return queryOptions({
- queryKey: [
- 'createGuideDslFileContent',
- fileReadVersion,
- file,
- file?.name ?? '',
- file?.size ?? 0,
- file?.lastModified ?? 0,
- ],
- queryFn: async () => (file ? await file.text() : ''),
- enabled: Boolean(file),
- retry: false,
- })
-})
-
-export const dslContentAtom = atom((get) => {
- return get(dslFileContentQueryAtom).data ?? ''
-})
-
-export const isReadingDslAtom = atom((get) => {
- const file = get(dslFileAtom)
- const dslFileContentQuery = get(dslFileContentQueryAtom)
-
- return Boolean(file && (dslFileContentQuery.isLoading || dslFileContentQuery.isFetching))
-})
-
-export const dslReadErrorAtom = atom((get) => {
- return Boolean(get(dslFileAtom) && get(dslFileContentQueryAtom).isError)
-})
-
-export const dslDefaultAppNameAtom = atom((get) => {
- const dslContent = get(dslContentAtom)
-
- return dslContent ? dslAppName(dslContent) : ''
-})
-
-export const dslUnsupportedModeAtom = atom((get) => {
- const dslContent = get(dslContentAtom)
-
- return (
- get(effectiveMethodAtom) === 'importDsl' &&
- Boolean(dslContent.trim()) &&
- !get(isReadingDslAtom) &&
- !get(dslReadErrorAtom) &&
- !isWorkflowDsl(dslContent)
- )
-})
-
-export const importDslReadyAtom = atom((get) => {
- return (
- Boolean(get(dslContentAtom).trim()) &&
- !get(isReadingDslAtom) &&
- !get(dslReadErrorAtom) &&
- !get(dslUnsupportedModeAtom)
- )
-})
-
-export const sourceAppsQueryAtom = atomWithInfiniteQuery((get) => {
- const sourceSearchText = get(sourceSearchTextAtom)
-
- return consoleQuery.apps.get.infiniteOptions({
- input: (pageParam) => ({
- query: {
- page: Number(pageParam),
- limit: SOURCE_APPS_PAGE_SIZE,
- name: sourceSearchText,
- mode: AppModeEnum.WORKFLOW,
- },
- }),
- getNextPageParam: (lastPage) => (lastPage.has_more ? lastPage.page + 1 : undefined),
- initialPageParam: 1,
- placeholderData: keepPreviousData,
- enabled: get(effectiveMethodAtom) === 'bindApp',
- })
-})
-
-const sourceAppsDataAtom = selectAtom(sourceAppsQueryAtom, (query) => query.data)
-export const sourceAppsErrorAtom = selectAtom(sourceAppsQueryAtom, (query) => query.error)
-export const sourceAppsFetchNextPageAtom = selectAtom(
- sourceAppsQueryAtom,
- (query) => query.fetchNextPage,
-)
-export const sourceAppsHasNextPageAtom = selectAtom(
- sourceAppsQueryAtom,
- (query) => query.hasNextPage,
-)
-export const sourceAppsIsFetchingAtom = selectAtom(sourceAppsQueryAtom, (query) => query.isFetching)
-export const sourceAppsIsFetchingNextPageAtom = selectAtom(
- sourceAppsQueryAtom,
- (query) => query.isFetchingNextPage,
-)
-export const sourceAppsIsLoadingAtom = selectAtom(sourceAppsQueryAtom, (query) => query.isLoading)
-export const sourceAppsIsPlaceholderDataAtom = selectAtom(
- sourceAppsQueryAtom,
- (query) => query.isPlaceholderData,
-)
-
-export const sourceAppsAtom = atom((get): WorkflowSourceApp[] => {
- const apps = get(sourceAppsDataAtom)?.pages.flatMap((page) => page.data) ?? []
-
- return apps.flatMap((app) =>
- app.mode === AppModeEnum.WORKFLOW ? [{ ...app, mode: 'workflow' as const }] : [],
- )
-})
-
-export const effectiveSelectedAppAtom = atom((get) => {
- const selectedApp = get(selectedAppAtom)
- if (selectedApp) return selectedApp
-
- if (get(sourceAppsIsPlaceholderDataAtom)) return undefined
-
- return get(sourceAppsAtom)[0]
-})
-
-export function sourceReady(get: Getter) {
- const method = get(effectiveMethodAtom)
-
- return method === 'importDsl'
- ? get(importDslReadyAtom)
- : Boolean(get(effectiveSelectedAppAtom)?.id)
-}
diff --git a/web/features/deployments/create-guide/state/submission.ts b/web/features/deployments/create-guide/state/submission.ts
deleted file mode 100644
index 8dbbfceed2e..00000000000
--- a/web/features/deployments/create-guide/state/submission.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-'use client'
-
-import type { DeployRequest } from '@dify/contracts/enterprise/types.gen'
-import { atom } from 'jotai'
-import { atomWithMutation } from 'jotai-tanstack-query'
-import { selectedDeploymentRuntimeCredentials } from '@/features/deployments/shared/components/runtime-credential-bindings-utils'
-import { encodeDslContent, isWorkflowDsl } from '@/features/deployments/shared/domain/dsl'
-import { unsupportedDslNodeError } from '@/features/deployments/shared/domain/error'
-import { createDeploymentIdempotencyKey } from '@/features/deployments/shared/domain/idempotency'
-import { consoleQuery } from '@/service/client'
-import { environmentMatchesIdentifier } from './environment'
-import {
- effectiveMethodAtom,
- envVarValuesAtom,
- instanceDescriptionAtom,
- instanceNameAtom,
- isCreatingDeploymentAtom,
- isCreatingReleaseOnlyAtom,
- isSubmittingDeploymentGuideAtom,
- releaseDescriptionAtom,
- releaseNameAtom,
- selectedEnvironmentIdAtom,
- submissionUnsupportedDslNodesAtom,
-} from './primitives'
-import { deployableEnvironmentsQueryAtom, deploymentOptionsDataAtom } from './queries'
-import { submittedReleaseReadyAtom } from './release'
-import { dslContentAtom, effectiveSelectedAppAtom } from './source'
-import {
- canDeployAtom,
- canSkipDeploymentAtom,
- deployableEnvironmentsAtom,
- deploymentTargetBindingSelectionsAtom,
- deploymentTargetBindingSlotsAtom,
- deploymentTargetEnvVarSlotsAtom,
- requiredBindingsReadyAtom,
- requiredEnvVarsReadyAtom,
-} from './target'
-import { envVarInput } from './utils'
-
-const createAppInstanceMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.appInstanceService.createAppInstance.mutationOptions(),
-)
-
-const createReleaseMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.releaseService.createRelease.mutationOptions(),
-)
-
-const createInitialDeploymentMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.deploymentService.deploy.mutationOptions(),
-)
-
-export class CreateDeploymentGuideSubmissionBlockedError extends Error {
- reason: 'unsupportedDslMode' | 'deployFailed'
-
- constructor(reason: 'unsupportedDslMode' | 'deployFailed') {
- super(reason)
- this.reason = reason
- this.name = 'CreateDeploymentGuideSubmissionBlockedError'
- }
-}
-
-export const createDeploymentGuideSubmissionAtom = atom(
- null,
- async (
- get,
- set,
- {
- deployToEnvironment,
- }: {
- deployToEnvironment: boolean
- },
- ) => {
- const method = get(effectiveMethodAtom)
- const dslContent = get(dslContentAtom)
- const submittedInstanceName = get(instanceNameAtom).trim()
- const submittedReleaseName = get(releaseNameAtom).trim()
- const submittedReleaseDescription = get(releaseDescriptionAtom).trim()
-
- if (get(isSubmittingDeploymentGuideAtom) || !get(submittedReleaseReadyAtom)) return undefined
-
- const effectiveSelectedApp = get(effectiveSelectedAppAtom)
- const deployableEnvironmentsQuery = get(deployableEnvironmentsQueryAtom)
- const deploymentOptions = get(deploymentOptionsDataAtom)?.options
- const envVarSlots = get(deploymentTargetEnvVarSlotsAtom)
- const envVarValues = get(envVarValuesAtom)
- const bindingSlots = get(deploymentTargetBindingSlotsAtom)
- const bindingSelections = get(deploymentTargetBindingSelectionsAtom)
- const selectedEnvironmentId = get(selectedEnvironmentIdAtom)
- const effectiveSelectedEnvironmentId =
- selectedEnvironmentId || get(deployableEnvironmentsAtom)[0]?.id
- const selectedEnvironment = effectiveSelectedEnvironmentId
- ? get(deployableEnvironmentsAtom).find((env) =>
- environmentMatchesIdentifier(env, effectiveSelectedEnvironmentId),
- )
- : undefined
-
- if (deployToEnvironment && !selectedEnvironment && !selectedEnvironmentId.trim())
- return undefined
- if (method === 'bindApp' && !effectiveSelectedApp?.id) return undefined
- if (method === 'importDsl' && !dslContent.trim()) return undefined
- if (method === 'importDsl' && !isWorkflowDsl(dslContent))
- throw new CreateDeploymentGuideSubmissionBlockedError('unsupportedDslMode')
-
- set(submissionUnsupportedDslNodesAtom, [])
-
- try {
- if (!deployToEnvironment) {
- if (!get(canSkipDeploymentAtom)) return undefined
-
- set(isCreatingReleaseOnlyAtom, true)
-
- try {
- const createdAppInstance = await get(createAppInstanceMutationAtom).mutateAsync({
- body: {
- displayName: submittedInstanceName,
- description: get(instanceDescriptionAtom).trim() || undefined,
- },
- })
- const appInstanceId = createdAppInstance.appInstance.id
-
- if (method === 'importDsl') {
- await get(createReleaseMutationAtom).mutateAsync({
- body: {
- appInstanceId,
- dsl: encodeDslContent(dslContent),
- displayName: submittedReleaseName,
- description: submittedReleaseDescription || undefined,
- createAppInstance: false,
- },
- })
-
- return appInstanceId
- }
-
- if (!effectiveSelectedApp?.id) return undefined
-
- await get(createReleaseMutationAtom).mutateAsync({
- body: {
- appInstanceId,
- sourceAppId: effectiveSelectedApp.id,
- displayName: submittedReleaseName,
- description: submittedReleaseDescription || undefined,
- createAppInstance: false,
- },
- })
-
- return appInstanceId
- } finally {
- set(isCreatingReleaseOnlyAtom, false)
- }
- }
-
- if (!get(canDeployAtom)) return undefined
-
- set(isCreatingDeploymentAtom, true)
-
- try {
- const selectedEnvironmentIdentifier = selectedEnvironmentId.trim()
- const freshSelectedEnvironment =
- selectedEnvironment ||
- (selectedEnvironmentIdentifier
- ? (await deployableEnvironmentsQuery.refetch()).data?.environments.find((environment) =>
- environmentMatchesIdentifier(environment, selectedEnvironmentIdentifier),
- )
- : undefined)
- const targetEnvironmentId = freshSelectedEnvironment?.id
- if (!targetEnvironmentId)
- throw new CreateDeploymentGuideSubmissionBlockedError('deployFailed')
-
- if (!get(requiredBindingsReadyAtom)) throw new Error('Missing required deployment binding.')
- if (!get(requiredEnvVarsReadyAtom))
- throw new Error('Missing required deployment environment variable.')
-
- const envVars = envVarSlots.flatMap((slot) => envVarInput(slot, envVarValues[slot.key]))
- const commonDeploymentRequest = {
- newAppInstance: {
- displayName: submittedInstanceName,
- description: get(instanceDescriptionAtom).trim() || undefined,
- },
- environmentId: targetEnvironmentId,
- releaseName: submittedReleaseName,
- releaseDescription: submittedReleaseDescription || undefined,
- credentials: selectedDeploymentRuntimeCredentials(bindingSlots, bindingSelections),
- envVars,
- idempotencyKey: createDeploymentIdempotencyKey(),
- expectedDslDigest: deploymentOptions?.dslDigest,
- } satisfies Omit
- const deploymentRequest =
- method === 'importDsl'
- ? {
- ...commonDeploymentRequest,
- dsl: encodeDslContent(dslContent),
- }
- : effectiveSelectedApp?.id
- ? {
- ...commonDeploymentRequest,
- sourceAppId: effectiveSelectedApp.id,
- }
- : undefined
- if (!deploymentRequest) return undefined
-
- const response = await get(createInitialDeploymentMutationAtom).mutateAsync({
- body: deploymentRequest,
- })
-
- return response.appInstance.id
- } finally {
- set(isCreatingDeploymentAtom, false)
- }
- } catch (error) {
- const unsupportedError = await unsupportedDslNodeError(error)
- if (unsupportedError?.nodes.length) {
- set(submissionUnsupportedDslNodesAtom, unsupportedError.nodes)
-
- return undefined
- }
-
- throw error
- }
- },
-)
diff --git a/web/features/deployments/create-guide/state/target.ts b/web/features/deployments/create-guide/state/target.ts
deleted file mode 100644
index fc89b42004c..00000000000
--- a/web/features/deployments/create-guide/state/target.ts
+++ /dev/null
@@ -1,172 +0,0 @@
-'use client'
-
-import type {
- EnvVarBindingSlot,
- EnvVarValueSelection,
-} from '@/features/deployments/shared/components/env-var-bindings'
-import { atom } from 'jotai'
-import {
- envVarBindingSlotFromContract,
- envVarBindingValueType,
-} from '@/features/deployments/shared/components/env-var-bindings-utils'
-import {
- hasMissingRequiredRuntimeCredentialBinding,
- runtimeCredentialSlotKey,
- selectedRuntimeCredentialSelections,
-} from '@/features/deployments/shared/components/runtime-credential-bindings-utils'
-import { dslEnvVarSlots } from '@/features/deployments/shared/domain/dsl'
-import { environmentMatchesIdentifier } from './environment'
-import {
- effectiveMethodAtom,
- envVarValuesAtom,
- manualBindingSelectionsAtom,
- selectedEnvironmentIdAtom,
-} from './primitives'
-import {
- deployableEnvironmentsDataAtom,
- deploymentOptionsDataAtom,
- deploymentOptionsReadyAtom,
-} from './queries'
-import { submittedReleaseReadyAtom } from './release'
-import { dslContentAtom, sourceReady } from './source'
-import { envVarSelectionReady } from './utils'
-
-export const deployableEnvironmentsAtom = atom((get) => {
- const deployableEnvironments = get(deployableEnvironmentsDataAtom)
-
- return sourceReady(get) ? (deployableEnvironments?.environments ?? []) : []
-})
-
-const deployableEnvironmentsReadyAtom = atom((get) => {
- return sourceReady(get) && Boolean(get(deployableEnvironmentsDataAtom))
-})
-
-export const effectiveSelectedEnvironmentIdAtom = atom((get) => {
- return get(selectedEnvironmentIdAtom) || get(deployableEnvironmentsAtom)[0]?.id
-})
-
-export const deploymentTargetBindingSlotsAtom = atom((get) => {
- const deploymentOptions = get(deploymentOptionsDataAtom)
-
- return sourceReady(get)
- ? (deploymentOptions?.options?.credentialSlots?.filter((slot) =>
- runtimeCredentialSlotKey(slot),
- ) ?? [])
- : []
-})
-
-export const deploymentTargetBindingSelectionsAtom = atom((get) => {
- return selectedRuntimeCredentialSelections(
- get(deploymentTargetBindingSlotsAtom),
- get(manualBindingSelectionsAtom),
- )
-})
-
-export const requiredBindingsReadyAtom = atom((get) => {
- const bindingSelections = get(deploymentTargetBindingSelectionsAtom)
-
- return get(deploymentTargetBindingSlotsAtom).every(
- (slot) =>
- !hasMissingRequiredRuntimeCredentialBinding(
- slot,
- bindingSelections[runtimeCredentialSlotKey(slot)],
- ),
- )
-})
-
-export const deploymentTargetEnvVarSlotsAtom = atom((get) => {
- const method = get(effectiveMethodAtom)
- const deploymentOptions = get(deploymentOptionsDataAtom)
- const slots = sourceReady(get) ? deploymentOptions?.options?.envVarSlots : undefined
- const dslContent = get(dslContentAtom)
-
- // Deployment options own the canonical slot list; DSL metadata only enriches import-DSL defaults.
- const deploymentOptionEnvVarSlots =
- slots?.flatMap((slot): EnvVarBindingSlot[] => {
- const bindingSlot = envVarBindingSlotFromContract(slot)
- return bindingSlot ? [bindingSlot] : []
- }) ?? []
- const dslEnvVarMetadataSlots =
- method === 'importDsl' && dslContent
- ? dslEnvVarSlots(dslContent).flatMap((slot) => {
- const key = slot.key.trim()
- if (!key) return []
-
- return [
- {
- key,
- ...(slot.description ? { description: slot.description } : {}),
- ...(slot.defaultValue !== undefined
- ? { defaultValue: slot.defaultValue, hasDefaultValue: true }
- : {}),
- ...(slot.valueType ? { valueType: envVarBindingValueType(slot.valueType) } : {}),
- },
- ]
- })
- : []
-
- if (dslEnvVarMetadataSlots.length === 0) return deploymentOptionEnvVarSlots
-
- const metadataByKey = new Map(dslEnvVarMetadataSlots.map((slot) => [slot.key, slot] as const))
-
- return deploymentOptionEnvVarSlots.map((slot) => {
- const metadata = metadataByKey.get(slot.key)
- if (!metadata) return slot
-
- const nextSlot = { ...slot }
-
- if (!nextSlot.description && metadata.description) nextSlot.description = metadata.description
- if (!nextSlot.hasDefaultValue && metadata.defaultValue !== undefined) {
- nextSlot.defaultValue = metadata.defaultValue
- nextSlot.hasDefaultValue = true
- }
- if (nextSlot.valueType === 'string' && metadata.valueType)
- nextSlot.valueType = metadata.valueType
-
- return nextSlot
- })
-})
-
-export const requiredEnvVarsReadyAtom = atom((get) => {
- const envVarValues = get(envVarValuesAtom)
-
- return get(deploymentTargetEnvVarSlotsAtom).every((slot) =>
- envVarSelectionReady(slot, envVarValues[slot.key]),
- )
-})
-
-export const canDeployAtom = atom((get) => {
- const effectiveSelectedEnvironmentId = get(effectiveSelectedEnvironmentIdAtom)
- const selectedEnvironment = effectiveSelectedEnvironmentId
- ? get(deployableEnvironmentsAtom).find((env) =>
- environmentMatchesIdentifier(env, effectiveSelectedEnvironmentId),
- )
- : undefined
-
- return Boolean(
- selectedEnvironment?.id &&
- get(deployableEnvironmentsReadyAtom) &&
- get(deploymentOptionsReadyAtom) &&
- get(requiredBindingsReadyAtom) &&
- get(requiredEnvVarsReadyAtom) &&
- get(submittedReleaseReadyAtom),
- )
-})
-
-export const canSkipDeploymentAtom = atom((get) => {
- return get(submittedReleaseReadyAtom) && get(deploymentOptionsReadyAtom)
-})
-
-export const selectBindingAtom = atom(null, (get, set, slot: string, value: string) => {
- set(manualBindingSelectionsAtom, {
- ...get(manualBindingSelectionsAtom),
- [slot]: value,
- })
-})
-
-export const setEnvVarAtom = atom(null, (get, set, key: string, value: EnvVarValueSelection) => {
- set(envVarValuesAtom, {
- ...get(envVarValuesAtom),
- [key]: value,
- })
-})
diff --git a/web/features/deployments/create-guide/state/types.ts b/web/features/deployments/create-guide/state/types.ts
deleted file mode 100644
index a1ed1b32670..00000000000
--- a/web/features/deployments/create-guide/state/types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { AppPartial, GetAppsData } from '@dify/contracts/api/console/apps/types.gen'
-
-export type GuideMethod = 'bindApp' | 'importDsl'
-export type GuideStep = 'source' | 'release' | 'target'
-export type WorkflowSourceApp = AppPartial & {
- mode: Extract['mode']>, 'workflow'>
-}
diff --git a/web/features/deployments/create-guide/state/utils.ts b/web/features/deployments/create-guide/state/utils.ts
deleted file mode 100644
index 7ad4d1a2c7b..00000000000
--- a/web/features/deployments/create-guide/state/utils.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import type { EnvVarInput, Pagination } from '@dify/contracts/enterprise/types.gen'
-import type { GuideMethod } from './types'
-import type {
- EnvVarBindingSlot,
- EnvVarValueSelection,
-} from '@/features/deployments/shared/components/env-var-bindings'
-import { EnvVarValueSource as ApiEnvVarValueSource } from '@dify/contracts/enterprise/types.gen'
-import { isDeploymentDslImportEnabled } from '@/features/deployments/shared/domain/feature-flags'
-
-export const DEPLOYMENT_PAGE_SIZE = 100
-export const SOURCE_APPS_PAGE_SIZE = 100
-
-export function getNextPageParamFromPagination(pagination?: Pagination) {
- const currentPage = pagination?.currentPage ?? 1
- const totalPages = pagination?.totalPages ?? 1
-
- return currentPage < totalPages ? currentPage + 1 : undefined
-}
-
-export function deploymentGuideMethod(method: GuideMethod): GuideMethod {
- return method === 'importDsl' && !isDeploymentDslImportEnabled ? 'bindApp' : method
-}
-
-const RANDOM_SUFFIX_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
-const RANDOM_SUFFIX_LENGTH = 4
-const RANDOM_SUFFIX_FALLBACK_LENGTH = 6
-const RANDOM_SUFFIX_MAX_ATTEMPTS = 16
-
-function randomLetterCombination(length: number) {
- const randomValues = new Uint8Array(length)
-
- if (globalThis.crypto) {
- globalThis.crypto.getRandomValues(randomValues)
- } else {
- randomValues.forEach((_, index) => {
- randomValues[index] = Math.floor(Math.random() * 256)
- })
- }
-
- return Array.from(
- randomValues,
- (value) => RANDOM_SUFFIX_ALPHABET[value % RANDOM_SUFFIX_ALPHABET.length],
- ).join('')
-}
-
-export function availableInstanceName(sourceName: string, existingNameSet: Set) {
- if (!existingNameSet.has(sourceName)) return sourceName
-
- for (let attempt = 0; attempt < RANDOM_SUFFIX_MAX_ATTEMPTS; attempt++) {
- const candidate = `${sourceName}-${randomLetterCombination(RANDOM_SUFFIX_LENGTH)}`
- if (!existingNameSet.has(candidate)) return candidate
- }
-
- return `${sourceName}-${randomLetterCombination(RANDOM_SUFFIX_FALLBACK_LENGTH)}`
-}
-
-function envVarValueSource(slot: EnvVarBindingSlot, selection: EnvVarValueSelection | undefined) {
- return (
- selection?.valueSource ??
- (slot.hasDefaultValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT
- : slot.hasLastValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT
- : ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL)
- )
-}
-
-export function envVarSelectionReady(
- slot: EnvVarBindingSlot,
- selection: EnvVarValueSelection | undefined,
-) {
- const valueSource = envVarValueSource(slot, selection)
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT)
- return Boolean(slot.hasLastValue)
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT)
- return Boolean(slot.hasDefaultValue)
- if (!selection?.value) return false
-
- return slot.valueType !== 'number' || !Number.isNaN(Number(selection.value))
-}
-
-export function envVarInput(
- slot: EnvVarBindingSlot,
- selection: EnvVarValueSelection | undefined,
-): EnvVarInput[] {
- const valueSource = envVarValueSource(slot, selection)
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT) {
- return slot.hasLastValue ? [{ key: slot.key, valueSource }] : []
- }
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT) {
- return slot.hasDefaultValue ? [{ key: slot.key, valueSource }] : []
- }
-
- if (!selection?.value || (slot.valueType === 'number' && Number.isNaN(Number(selection.value))))
- return []
-
- return [
- {
- key: slot.key,
- value: selection.value,
- valueSource,
- },
- ]
-}
diff --git a/web/features/deployments/create-guide/state/workflow.ts b/web/features/deployments/create-guide/state/workflow.ts
deleted file mode 100644
index 71f5ad2324c..00000000000
--- a/web/features/deployments/create-guide/state/workflow.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-'use client'
-
-import type { WorkflowSourceApp } from './types'
-import { atom } from 'jotai'
-import {
- autoFilledInstanceNameAtom,
- autoFilledReleaseNameAtom,
- dslFileAtom,
- dslFileReadVersionAtom,
- effectiveMethodAtom,
- envVarValuesAtom,
- instanceNameAtom,
- manualBindingSelectionsAtom,
- methodAtom,
- releaseNameAtom,
- selectedAppAtom,
- selectedEnvironmentIdAtom,
- sourceSearchTextAtom,
- stepAtom,
- submissionUnsupportedDslNodesAtom,
-} from './primitives'
-import { deploymentOptionsContentCheckedAtom, existingInstanceNamesQueryAtom } from './queries'
-import { dslDefaultAppNameAtom, effectiveSelectedAppAtom, importDslReadyAtom } from './source'
-import { availableInstanceName, deploymentGuideMethod } from './utils'
-
-export const sourceCanGoNextAtom = atom((get) => {
- const method = get(effectiveMethodAtom)
- const effectiveSelectedApp = get(effectiveSelectedAppAtom)
- const importDslReady = method === 'importDsl' && get(importDslReadyAtom)
- const bindAppReady = method === 'bindApp' && Boolean(effectiveSelectedApp?.id)
-
- return (importDslReady || bindAppReady) && get(deploymentOptionsContentCheckedAtom)
-})
-
-export const setSourceSearchTextAtom = atom(null, (get, set, value: string) => {
- if (get(sourceSearchTextAtom) === value) return
-
- set(sourceSearchTextAtom, value)
- set(selectedAppAtom, undefined)
- set(selectedEnvironmentIdAtom, '')
- set(manualBindingSelectionsAtom, {})
- set(envVarValuesAtom, {})
- set(submissionUnsupportedDslNodesAtom, [])
-})
-
-export const selectSourceAppAtom = atom(null, (_get, set, app: WorkflowSourceApp) => {
- set(selectedAppAtom, app)
- set(selectedEnvironmentIdAtom, '')
- set(manualBindingSelectionsAtom, {})
- set(envVarValuesAtom, {})
- set(submissionUnsupportedDslNodesAtom, [])
-})
-
-export const continueFromSourceAtom = atom(
- null,
- (
- get,
- set,
- {
- defaultDslAppName,
- defaultReleaseName,
- }: {
- defaultDslAppName: string
- defaultReleaseName: string
- },
- ) => {
- if (!get(sourceCanGoNextAtom)) return
-
- const method = get(effectiveMethodAtom)
- const effectiveSelectedApp = get(effectiveSelectedAppAtom)
- if (method === 'bindApp' && effectiveSelectedApp) set(selectSourceAppAtom, effectiveSelectedApp)
-
- const sourceName =
- method === 'importDsl'
- ? get(dslDefaultAppNameAtom) || defaultDslAppName
- : effectiveSelectedApp?.name
- const nextInstanceName = sourceName?.trim()
-
- if (nextInstanceName) {
- const currentInstanceName = get(instanceNameAtom).trim()
- const autoFilledInstanceName = get(autoFilledInstanceNameAtom)
- const existingInstanceNamesQuery = get(existingInstanceNamesQueryAtom)
- const existingNameSet = new Set(
- existingInstanceNamesQuery.data?.pages.flatMap((page) =>
- page.appInstances.flatMap((appInstance) => {
- const name = appInstance.displayName.trim()
-
- return name ? [name] : []
- }),
- ) ?? [],
- )
-
- if (!currentInstanceName || currentInstanceName === autoFilledInstanceName) {
- const nextAvailableInstanceName = availableInstanceName(nextInstanceName, existingNameSet)
- set(instanceNameAtom, nextAvailableInstanceName)
- set(autoFilledInstanceNameAtom, nextAvailableInstanceName)
- }
- }
-
- const currentReleaseName = get(releaseNameAtom).trim()
- const autoFilledReleaseName = get(autoFilledReleaseNameAtom)
- if (!currentReleaseName || currentReleaseName === autoFilledReleaseName) {
- set(releaseNameAtom, defaultReleaseName)
- set(autoFilledReleaseNameAtom, defaultReleaseName)
- }
- set(stepAtom, 'release')
- },
-)
-
-export const selectDslFileAtom = atom(null, (get, set, dslFile?: File) => {
- set(selectedEnvironmentIdAtom, '')
- set(manualBindingSelectionsAtom, {})
- set(envVarValuesAtom, {})
- set(submissionUnsupportedDslNodesAtom, [])
-
- set(dslFileReadVersionAtom, get(dslFileReadVersionAtom) + 1)
- set(dslFileAtom, dslFile)
-})
-
-export const selectMethodAtom = atom(
- null,
- (_get, set, method: Parameters[0]) => {
- set(methodAtom, deploymentGuideMethod(method))
- set(selectedEnvironmentIdAtom, '')
- set(manualBindingSelectionsAtom, {})
- set(envVarValuesAtom, {})
- set(submissionUnsupportedDslNodesAtom, [])
- set(stepAtom, 'source')
- },
-)
diff --git a/web/features/deployments/create-guide/ui/__tests__/source-step.spec.tsx b/web/features/deployments/create-guide/ui/__tests__/source-step.spec.tsx
deleted file mode 100644
index 17c488f5fe2..00000000000
--- a/web/features/deployments/create-guide/ui/__tests__/source-step.spec.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import { act, render, screen } from '@testing-library/react'
-import { Provider } from 'jotai'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { SourceStepContent } from '../source-step'
-
-const mocks = vi.hoisted(() => {
- const sourceAppsQuery = {
- data: { pages: [{ data: [] }] },
- error: null,
- fetchNextPage: vi.fn(),
- hasNextPage: false,
- isFetching: false,
- isFetchingNextPage: false,
- isLoading: false,
- isPlaceholderData: false,
- }
-
- return { sourceAppsQuery }
-})
-
-type ObserverRecord = {
- callback: IntersectionObserverCallback
- options?: IntersectionObserverInit
-}
-
-const observers: ObserverRecord[] = []
-
-function getInfiniteScrollObserver() {
- return observers.find(({ options }) => options?.rootMargin === '0px 0px 160px 0px')
-}
-
-vi.mock('@/features/deployments/create-guide/state/primitives', async () => {
- const { atom } = await import('jotai')
- const methodAtom = atom<'bindApp' | 'importDsl'>('bindApp')
-
- return {
- dslFileAtom: atom(undefined),
- effectiveMethodAtom: atom((get) => get(methodAtom)),
- methodAtom,
- sourceSearchTextAtom: atom(''),
- }
-})
-
-vi.mock('@/features/deployments/create-guide/state/source', async () => {
- const { atom } = await import('jotai')
-
- return {
- dslReadErrorAtom: atom(false),
- dslUnsupportedModeAtom: atom(false),
- effectiveSelectedAppAtom: atom(undefined),
- isReadingDslAtom: atom(false),
- sourceAppsAtom: atom(() => mocks.sourceAppsQuery.data.pages.flatMap((page) => page.data)),
- sourceAppsErrorAtom: atom(() => mocks.sourceAppsQuery.error),
- sourceAppsFetchNextPageAtom: atom(() => mocks.sourceAppsQuery.fetchNextPage),
- sourceAppsHasNextPageAtom: atom(() => mocks.sourceAppsQuery.hasNextPage),
- sourceAppsIsFetchingAtom: atom(() => mocks.sourceAppsQuery.isFetching),
- sourceAppsIsFetchingNextPageAtom: atom(() => mocks.sourceAppsQuery.isFetchingNextPage),
- sourceAppsIsLoadingAtom: atom(() => mocks.sourceAppsQuery.isLoading),
- sourceAppsIsPlaceholderDataAtom: atom(() => mocks.sourceAppsQuery.isPlaceholderData),
- sourceAppsQueryAtom: atom(mocks.sourceAppsQuery),
- }
-})
-
-vi.mock('@/features/deployments/create-guide/state/workflow', async () => {
- const { atom } = await import('jotai')
- const { methodAtom } = await import('@/features/deployments/create-guide/state/primitives')
- const emptyActionAtom = atom(null, () => undefined)
-
- return {
- continueFromSourceAtom: emptyActionAtom,
- selectDslFileAtom: emptyActionAtom,
- selectMethodAtom: atom(null, (_get, set, value: 'bindApp' | 'importDsl') => {
- set(methodAtom, value)
- }),
- selectSourceAppAtom: emptyActionAtom,
- setSourceSearchTextAtom: emptyActionAtom,
- sourceCanGoNextAtom: atom(false),
- }
-})
-
-vi.mock('@/features/deployments/create-guide/state/queries', async () => {
- const { atom } = await import('jotai')
-
- return {
- unsupportedDslNodesAtom: atom([]),
- }
-})
-
-describe('SourceStepContent', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mocks.sourceAppsQuery.fetchNextPage.mockReset()
- observers.length = 0
- vi.stubGlobal(
- 'IntersectionObserver',
- class MockIntersectionObserver {
- readonly root = null
- readonly rootMargin = ''
- readonly scrollMargin = ''
- readonly thresholds: ReadonlyArray = []
- readonly disconnect = vi.fn()
- readonly observe = vi.fn()
- readonly takeRecords = () => []
- readonly unobserve = vi.fn()
-
- constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
- observers.push({ callback, options })
- }
- },
- )
- Object.assign(mocks.sourceAppsQuery, {
- data: { pages: [{ data: [] }] },
- error: null,
- hasNextPage: false,
- isFetching: false,
- isFetchingNextPage: false,
- isLoading: false,
- isPlaceholderData: false,
- })
- })
-
- afterEach(() => {
- vi.unstubAllGlobals()
- })
-
- it('should hide the import DSL option when deployment DSL import is disabled', () => {
- render(
-
-
- ,
- )
-
- expect(screen.getByText(/createGuide\.methods\.bindApp\.title/)).toBeInTheDocument()
- expect(screen.queryByText(/createGuide\.methods\.importDsl\.title/)).not.toBeInTheDocument()
- expect(
- screen.queryByText(/createGuide\.methods\.importDsl\.description/),
- ).not.toBeInTheDocument()
- expect(
- screen.getByRole('textbox', { name: /createGuide\.source\.sourceApp/ }),
- ).toBeInTheDocument()
- })
-
- it('should use infinite scroll to load more source apps', () => {
- Object.assign(mocks.sourceAppsQuery, {
- data: {
- pages: [
- {
- data: [
- {
- id: 'app-1',
- name: 'Workflow App',
- },
- ],
- },
- ],
- },
- hasNextPage: true,
- })
-
- render(
-
-
- ,
- )
-
- act(() => {
- getInfiniteScrollObserver()?.callback(
- [{ isIntersecting: true } as IntersectionObserverEntry],
- {} as IntersectionObserver,
- )
- })
-
- expect(mocks.sourceAppsQuery.fetchNextPage).toHaveBeenCalledWith({ cancelRefetch: false })
- expect(
- screen.queryByRole('button', { name: /createModal\.loadMoreApps/ }),
- ).not.toBeInTheDocument()
- })
-})
diff --git a/web/features/deployments/create-guide/ui/layout.tsx b/web/features/deployments/create-guide/ui/layout.tsx
deleted file mode 100644
index 1e8ffecb3e6..00000000000
--- a/web/features/deployments/create-guide/ui/layout.tsx
+++ /dev/null
@@ -1,220 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import type { GuideStep } from '@/features/deployments/create-guide/state/types'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- ScrollArea,
- ScrollAreaContent,
- ScrollAreaScrollbar,
- ScrollAreaThumb,
- ScrollAreaViewport,
-} from '@langgenius/dify-ui/scroll-area'
-import { useTranslation } from 'react-i18next'
-import { TitleTooltip } from '@/features/deployments/shared/components/title-tooltip'
-
-const GUIDE_PROGRESS_STEPS: GuideStep[] = ['source', 'release', 'target']
-
-function GuideStepIntro({ activeStep }: { activeStep: GuideStep }) {
- const { t } = useTranslation('deployments')
-
- let title: string
- let description: string
-
- if (activeStep === 'source') {
- title = t(($) => $['createGuide.source.title'])
- description = t(($) => $['createGuide.method.description'])
- } else if (activeStep === 'release') {
- title = t(($) => $['createGuide.release.title'])
- description = t(($) => $['createGuide.release.description'])
- } else if (activeStep === 'target') {
- title = t(($) => $['createGuide.target.title'])
- description = t(($) => $['createGuide.target.description'])
- } else {
- return null
- }
-
- return (
-
-
{title}
-
{description}
-
- )
-}
-
-function GuideProgress({ activeStep }: { activeStep: GuideStep }) {
- const { t } = useTranslation('deployments')
- const activeIndex = GUIDE_PROGRESS_STEPS.indexOf(activeStep)
-
- return (
-
- {GUIDE_PROGRESS_STEPS.map((step, index) => {
- const isActive = step === activeStep
- const isComplete = index < activeIndex
- const label = t(($) => $[`createGuide.steps.${step}`])
-
- return (
-
- -
-
- {label}
-
-
- )
- })}
-
- )
-}
-
-function GuideProgressSummary({ activeStep }: { activeStep: GuideStep }) {
- const { t } = useTranslation('deployments')
- const activeIndex = GUIDE_PROGRESS_STEPS.indexOf(activeStep)
- const activeStepNumber = activeIndex + 1
-
- let activeStepLabel: string
- if (activeStep === 'source') activeStepLabel = t(($) => $['createGuide.steps.source'])
- else if (activeStep === 'release') activeStepLabel = t(($) => $['createGuide.steps.release'])
- else if (activeStep === 'target') activeStepLabel = t(($) => $['createGuide.steps.target'])
- else return null
-
- if (activeIndex < 0) return null
-
- return (
-
-
- {activeStepLabel}
-
- {activeStepNumber}/{GUIDE_PROGRESS_STEPS.length}
-
-
-
- {GUIDE_PROGRESS_STEPS.map((step, index) => (
-
- ))}
-
-
- )
-}
-
-export function StepShell({
- title,
- description,
- descriptionClassName,
- hideHeader,
- className,
- children,
-}: {
- title: string
- description: string
- descriptionClassName?: string
- hideHeader?: boolean
- className?: string
- children: ReactNode
-}) {
- return (
-
- {!hideHeader && (
-
-
{title}
-
- {description}
-
-
- )}
- {children}
-
- )
-}
-
-export function GuideCard({
- children,
- actions,
- contentScrollable = true,
-}: {
- children: ReactNode
- actions: ReactNode
- contentScrollable?: boolean
-}) {
- return (
-
- {contentScrollable ? (
-
-
- {children}
-
-
-
-
-
- ) : (
-
{children}
- )}
- {actions}
-
- )
-}
-
-export function GuideFrame({
- activeStep,
- children,
-}: {
- activeStep: GuideStep
- children: ReactNode
-}) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
-
$['createGuide.title'])}
- className="flex h-full w-full max-w-210 flex-col px-5 sm:px-8 lg:px-10"
- >
-
-
-
- {t(($) => $['createGuide.title'])}
-
-
-
-
-
-
-
-
-
- {children}
-
-
-
- )
-}
diff --git a/web/features/deployments/create-guide/ui/release-step.tsx b/web/features/deployments/create-guide/ui/release-step.tsx
deleted file mode 100644
index b76b465a3d6..00000000000
--- a/web/features/deployments/create-guide/ui/release-step.tsx
+++ /dev/null
@@ -1,222 +0,0 @@
-'use client'
-
-import { Button } from '@langgenius/dify-ui/button'
-import { Input } from '@langgenius/dify-ui/input'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import {
- effectiveMethodAtom,
- instanceDescriptionAtom,
- instanceNameAtom,
- releaseDescriptionAtom,
- releaseNameAtom,
- selectedAppAtom,
- stepAtom,
-} from '@/features/deployments/create-guide/state/primitives'
-import {
- continueFromReleaseAtom,
- hasInstanceNameConflictAtom,
- releaseCanGoNextAtom,
- setInstanceDescriptionAtom,
- setInstanceNameAtom,
- setReleaseDescriptionAtom,
- setReleaseNameAtom,
-} from '@/features/deployments/create-guide/state/release'
-import { dslDefaultAppNameAtom } from '@/features/deployments/create-guide/state/source'
-import { StepShell } from './layout'
-
-const releaseTextareaClassName =
- 'min-h-16 w-full resize-none appearance-none rounded-md border border-transparent bg-components-input-bg-normal p-2 px-3 system-sm-regular text-components-input-text-filled caret-primary-600 outline-hidden placeholder:text-components-input-text-placeholder hover:border-components-input-border-hover hover:bg-components-input-bg-hover focus:border-components-input-border-active focus:bg-components-input-bg-active focus:shadow-xs'
-
-export function ReleaseStepContent() {
- const { t } = useTranslation('deployments')
-
- return (
- $['createGuide.release.title'])}
- description={t(($) => $['createGuide.release.description'])}
- hideHeader
- >
-
-
-
-
-
- )
-}
-
-function DeploymentInfoSection() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['createGuide.release.deployInfo'])}
-
-
-
-
- )
-}
-
-function InitialReleaseSection() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['createGuide.release.firstVersion'])}
-
-
-
-
- )
-}
-
-function InstanceNameField() {
- const { t } = useTranslation('deployments')
- const instanceName = useAtomValue(instanceNameAtom)
- const setInstanceName = useSetAtom(setInstanceNameAtom)
- const method = useAtomValue(effectiveMethodAtom)
- const selectedApp = useAtomValue(selectedAppAtom)
- const dslDefaultAppName = useAtomValue(dslDefaultAppNameAtom)
- const instanceNamePlaceholder =
- method === 'importDsl'
- ? dslDefaultAppName || t(($) => $['createGuide.dsl.defaultAppName'])
- : selectedApp?.name
- const hasInstanceNameConflict = useAtomValue(hasInstanceNameConflictAtom)
- const instanceNameError = hasInstanceNameConflict
- ? t(($) => $['createGuide.release.instanceNameConflict'])
- : undefined
- const instanceNameErrorId = 'create-guide-instance-name-error'
-
- return (
-
-
-
setInstanceName(event.target.value)}
- placeholder={instanceNamePlaceholder}
- required
- aria-invalid={instanceNameError ? true : undefined}
- aria-describedby={instanceNameError ? instanceNameErrorId : undefined}
- className="h-9"
- />
- {instanceNameError && (
-
- {instanceNameError}
-
- )}
-
- )
-}
-
-function InstanceDescriptionField() {
- const { t } = useTranslation('deployments')
- const instanceDescription = useAtomValue(instanceDescriptionAtom)
- const setInstanceDescription = useSetAtom(setInstanceDescriptionAtom)
-
- return (
-
-
- {t(($) => $['createGuide.release.instanceDescription'])}
-
-
- )
-}
-
-function ReleaseNameField() {
- const { t } = useTranslation('deployments')
- const releaseName = useAtomValue(releaseNameAtom)
- const setReleaseName = useSetAtom(setReleaseNameAtom)
-
- return (
-
-
- setReleaseName(event.target.value)}
- placeholder={t(($) => $['createGuide.release.defaultName'])}
- required
- className="h-9"
- />
-
- )
-}
-
-function ReleaseDescriptionField() {
- const { t } = useTranslation('deployments')
- const releaseDescription = useAtomValue(releaseDescriptionAtom)
- const setReleaseDescription = useSetAtom(setReleaseDescriptionAtom)
-
- return (
-
-
- {t(($) => $['createGuide.release.releaseDescription'])}
-
-
- )
-}
-
-function OptionalFieldLabel({ children, htmlFor }: { children: string; htmlFor: string }) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
-
- {t(($) => $['versions.optional'])}
-
-
- )
-}
-
-export function ReleaseActionButtons() {
- const { t } = useTranslation('deployments')
- const canGoNext = useAtomValue(releaseCanGoNextAtom)
- const setStep = useSetAtom(stepAtom)
- const continueFromRelease = useSetAtom(continueFromReleaseAtom)
-
- return (
- <>
-
-
- >
- )
-}
diff --git a/web/features/deployments/create-guide/ui/shell.tsx b/web/features/deployments/create-guide/ui/shell.tsx
deleted file mode 100644
index 936a74667fc..00000000000
--- a/web/features/deployments/create-guide/ui/shell.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-'use client'
-
-import { useAtomValue } from 'jotai'
-import { stepAtom } from '@/features/deployments/create-guide/state/primitives'
-import { GuideCard, GuideFrame } from './layout'
-import { ReleaseActionButtons, ReleaseStepContent } from './release-step'
-import { SourceActionButtons, SourceStepContent } from './source-step'
-import {
- TargetBackButton,
- TargetDeployButton,
- TargetSkipDeploymentButton,
- TargetStepContent,
-} from './target-step'
-
-export function CreateDeploymentGuideShell() {
- const step = useAtomValue(stepAtom)
-
- return (
-
- }>
-
-
-
- )
-}
-
-function CreateDeploymentGuideStepContent() {
- const step = useAtomValue(stepAtom)
-
- if (step === 'source') {
- return (
-
-
-
- )
- }
-
- if (step === 'release') {
- return (
-
-
-
- )
- }
-
- return (
-
-
-
- )
-}
-
-function CreateDeploymentGuideActionBar() {
- const step = useAtomValue(stepAtom)
-
- return (
-
- {step === 'source' && }
- {step === 'release' && }
- {step === 'target' && (
- <>
-
-
-
- >
- )}
-
- )
-}
diff --git a/web/features/deployments/create-guide/ui/source-step.tsx b/web/features/deployments/create-guide/ui/source-step.tsx
deleted file mode 100644
index 0b4ff8c41a2..00000000000
--- a/web/features/deployments/create-guide/ui/source-step.tsx
+++ /dev/null
@@ -1,418 +0,0 @@
-'use client'
-
-import type {
- GuideMethod,
- WorkflowSourceApp,
-} from '@/features/deployments/create-guide/state/types'
-import { zIconType } from '@dify/contracts/api/console/apps/zod.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import { Input } from '@langgenius/dify-ui/input'
-import { RadioGroup, RadioItem } from '@langgenius/dify-ui/radio'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useRef } from 'react'
-import { useTranslation } from 'react-i18next'
-import { Uploader } from '@/app/components/app/create-from-dsl-modal/uploader'
-import AppIcon from '@/app/components/base/app-icon'
-import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-sentinel'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import {
- dslFileAtom,
- effectiveMethodAtom,
- sourceSearchTextAtom,
-} from '@/features/deployments/create-guide/state/primitives'
-import { unsupportedDslNodesAtom } from '@/features/deployments/create-guide/state/queries'
-import {
- dslReadErrorAtom,
- dslUnsupportedModeAtom,
- effectiveSelectedAppAtom,
- isReadingDslAtom,
- sourceAppsAtom,
- sourceAppsErrorAtom,
- sourceAppsFetchNextPageAtom,
- sourceAppsHasNextPageAtom,
- sourceAppsIsFetchingAtom,
- sourceAppsIsFetchingNextPageAtom,
- sourceAppsIsLoadingAtom,
- sourceAppsIsPlaceholderDataAtom,
-} from '@/features/deployments/create-guide/state/source'
-import {
- continueFromSourceAtom,
- selectDslFileAtom,
- selectMethodAtom,
- selectSourceAppAtom,
- setSourceSearchTextAtom,
- sourceCanGoNextAtom,
-} from '@/features/deployments/create-guide/state/workflow'
-import { DeploymentStateMessage } from '@/features/deployments/shared/components/empty-state'
-import { TitleTooltip } from '@/features/deployments/shared/components/title-tooltip'
-import { UnsupportedDslNodesAlert } from '@/features/deployments/shared/components/unsupported-dsl-nodes-alert'
-import { isDeploymentDslImportEnabled } from '@/features/deployments/shared/domain/feature-flags'
-import { StepShell } from './layout'
-
-const sourceAppSkeletonKeys = ['first-source-app', 'second-source-app', 'third-source-app']
-
-export function SourceStepContent() {
- const method = useAtomValue(effectiveMethodAtom)
- const unsupportedDslNodes = useAtomValue(unsupportedDslNodesAtom)
-
- return (
-
-
- {method === 'bindApp' && }
- {method === 'importDsl' && }
-
-
- )
-}
-
-function SourceMethodSection() {
- const { t } = useTranslation('deployments')
- const method = useAtomValue(effectiveMethodAtom)
- const selectMethod = useSetAtom(selectMethodAtom)
-
- return (
- $['createGuide.steps.method'])}
- description={t(($) => $['createGuide.method.description'])}
- descriptionClassName="lg:hidden"
- hideHeader
- >
-
- aria-label={t(($) => $['createGuide.steps.method'])}
- value={method}
- onValueChange={selectMethod}
- className="flex flex-col items-stretch gap-2 sm:flex-row"
- >
- $['createGuide.methods.bindApp.title'])}
- description={t(($) => $['createGuide.methods.bindApp.description'])}
- />
- {isDeploymentDslImportEnabled && (
- $['createGuide.methods.importDsl.title'])}
- description={t(($) => $['createGuide.methods.importDsl.description'])}
- />
- )}
-
-
- )
-}
-
-function SourceMethodCard({
- value,
- icon,
- title,
- description,
- badge,
-}: {
- value: GuideMethod
- icon: string
- title: string
- description: string
- badge?: string
-}) {
- return (
-
- value={value}
- nativeButton
- render={}
- className={cn(
- `relative box-content h-21 w-full cursor-pointer rounded-xl border-[0.5px] border-components-option-card-option-border bg-components-panel-on-panel-item-bg p-3 text-left shadow-xs outline-hidden hover:shadow-md focus-visible:ring-2 focus-visible:ring-state-accent-solid sm:w-60`,
- 'data-checked:border-components-option-card-option-selected-border data-checked:bg-components-option-card-option-selected-bg data-checked:shadow-md data-checked:inset-ring-[0.5px] data-checked:inset-ring-components-option-card-option-selected-border',
- )}
- >
-
-
-
-
- {title}
- {badge && (
-
- {badge}
-
- )}
-
-
-
-
- {description}
-
-
-
-
- )
-}
-
-function SourceAppSelectionSection() {
- const { t } = useTranslation('deployments')
-
- return (
- $['createGuide.source.title'])}
- description={t(($) => $['createGuide.source.description'])}
- descriptionClassName="lg:hidden"
- hideHeader
- className="min-h-0 flex-1"
- >
-
-
-
-
-
- )
-}
-
-function SourceSearchInput() {
- const { t } = useTranslation('deployments')
- const sourceSearchText = useAtomValue(sourceSearchTextAtom)
- const setSourceSearchText = useSetAtom(setSourceSearchTextAtom)
-
- return (
-
-
- $['createGuide.source.sourceApp'])}
- value={sourceSearchText}
- onChange={(event) => setSourceSearchText(event.target.value)}
- placeholder={t(($) => $['createGuide.source.searchPlaceholder'])}
- className="h-9 pr-8 pl-8"
- />
- {sourceSearchText && (
-
- )}
-
- )
-}
-
-function SourceAppList() {
- const { t } = useTranslation('deployments')
- const selectSourceApp = useSetAtom(selectSourceAppAtom)
- const effectiveSelectedApp = useAtomValue(effectiveSelectedAppAtom)
- const sourceApps = useAtomValue(sourceAppsAtom)
- const sourceAppsError = useAtomValue(sourceAppsErrorAtom)
- const sourceAppsFetchNextPage = useAtomValue(sourceAppsFetchNextPageAtom)
- const sourceAppsHasNextPage = useAtomValue(sourceAppsHasNextPageAtom)
- const sourceAppsIsFetching = useAtomValue(sourceAppsIsFetchingAtom)
- const sourceAppsIsFetchingNextPage = useAtomValue(sourceAppsIsFetchingNextPageAtom)
- const sourceAppsIsLoading = useAtomValue(sourceAppsIsLoadingAtom)
- const sourceAppsIsPlaceholderData = useAtomValue(sourceAppsIsPlaceholderDataAtom)
- const scrollContainerRef = useRef(null)
- const sourceAppsLoading =
- sourceAppsIsLoading ||
- sourceAppsIsPlaceholderData ||
- (sourceAppsIsFetching && sourceApps.length === 0)
- const canLoadMore = !sourceAppsIsFetching && !sourceAppsError
-
- return (
-
- {sourceAppsLoading ? (
-
- ) : sourceApps.length === 0 ? (
-
- {t(($) => $['createGuide.source.empty'])}
-
- ) : (
-
- {sourceApps.map((app) => (
-
selectSourceApp(app)}
- />
- ))}
- {sourceAppsIsFetchingNextPage && (
-
- {t(($) => $['createModal.loadingApps'])}
-
- )}
- {sourceAppsHasNextPage && (
- {
- void sourceAppsFetchNextPage({ cancelRefetch: false })
- }}
- preloadDistance={160}
- scrollContainerRef={scrollContainerRef}
- />
- )}
-
- )}
-
- )
-}
-
-function SourceAppSkeleton() {
- return (
-
- {sourceAppSkeletonKeys.map((key) => (
-
-
-
-
-
-
-
- ))}
-
- )
-}
-
-function SourceAppOption({
- app,
- onSelect,
- selected,
-}: {
- app: WorkflowSourceApp
- onSelect: () => void
- selected: boolean
-}) {
- const appIconType = zIconType.safeParse(app.icon_type).data ?? null
-
- return (
-
- )
-}
-
-function DslUploadSection() {
- const { t } = useTranslation('deployments')
- const dslFile = useAtomValue(dslFileAtom)
- const selectDslFile = useSetAtom(selectDslFileAtom)
-
- return (
- $['createGuide.dsl.title'])}
- description={t(($) => $['createGuide.dsl.description'])}
- hideHeader
- >
-
-
-
-
-
- {t(($) => $['createGuide.dsl.dropTitle'])}
-
-
- {t(($) => $['createGuide.dsl.dropDescription'])}
-
-
-
-
-
-
-
- )
-}
-
-function DslReadStatus() {
- const { t } = useTranslation('deployments')
- const isReadingDsl = useAtomValue(isReadingDslAtom)
- const dslReadError = useAtomValue(dslReadErrorAtom)
- const dslUnsupportedMode = useAtomValue(dslUnsupportedModeAtom)
-
- return (
- <>
- {isReadingDsl && (
-
- {t(($) => $['createGuide.dsl.reading'])}
-
- )}
- {dslReadError && (
-
- {t(($) => $['createGuide.dsl.readFailed'])}
-
- )}
- {dslUnsupportedMode && (
-
- {t(($) => $['createGuide.dsl.unsupportedMode'])}
-
- )}
- >
- )
-}
-
-export function SourceActionButtons() {
- const { t } = useTranslation('deployments')
- const canGoNext = useAtomValue(sourceCanGoNextAtom)
- const continueFromSource = useSetAtom(continueFromSourceAtom)
-
- return (
-
- )
-}
diff --git a/web/features/deployments/create-guide/ui/target-step.tsx b/web/features/deployments/create-guide/ui/target-step.tsx
deleted file mode 100644
index f50cff3f941..00000000000
--- a/web/features/deployments/create-guide/ui/target-step.tsx
+++ /dev/null
@@ -1,389 +0,0 @@
-'use client'
-
-import type { Environment } from '@dify/contracts/enterprise/types.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import { RadioControl, RadioGroup, RadioItem } from '@langgenius/dify-ui/radio'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import {
- envVarValuesAtom,
- isCreatingReleaseOnlyAtom,
- isSubmittingDeploymentGuideAtom,
- selectedEnvironmentIdAtom,
- stepAtom,
-} from '@/features/deployments/create-guide/state/primitives'
-import {
- deployableEnvironmentsIsErrorAtom,
- deployableEnvironmentsIsFetchingAtom,
- deployableEnvironmentsIsLoadingAtom,
- deploymentOptionsDataAtom,
- deploymentOptionsIsErrorAtom,
- deploymentOptionsIsFetchingAtom,
- deploymentOptionsIsLoadingAtom,
- unsupportedDslNodesAtom,
-} from '@/features/deployments/create-guide/state/queries'
-import {
- createDeploymentGuideSubmissionAtom,
- CreateDeploymentGuideSubmissionBlockedError,
-} from '@/features/deployments/create-guide/state/submission'
-import {
- canDeployAtom,
- canSkipDeploymentAtom,
- deployableEnvironmentsAtom,
- deploymentTargetBindingSelectionsAtom,
- deploymentTargetBindingSlotsAtom,
- deploymentTargetEnvVarSlotsAtom,
- effectiveSelectedEnvironmentIdAtom,
- selectBindingAtom,
- setEnvVarAtom,
-} from '@/features/deployments/create-guide/state/target'
-import { EnvVarBindingsPanel } from '@/features/deployments/shared/components/env-var-bindings'
-import { RuntimeCredentialBindingsPanel } from '@/features/deployments/shared/components/runtime-credential-bindings'
-import { TitleTooltip } from '@/features/deployments/shared/components/title-tooltip'
-import { UnsupportedDslNodesAlert } from '@/features/deployments/shared/components/unsupported-dsl-nodes-alert'
-import { deploymentErrorMessage } from '@/features/deployments/shared/domain/error'
-import { useRouter } from '@/next/navigation'
-import { StepShell } from './layout'
-
-const targetEnvironmentSkeletonKeys = ['first-target-environment', 'second-target-environment']
-const targetBindingSkeletonKeys = ['first-target-binding', 'second-target-binding']
-
-export function TargetStepContent() {
- const { t } = useTranslation('deployments')
- const unsupportedDslNodes = useAtomValue(unsupportedDslNodesAtom)
-
- return (
- $['createGuide.target.title'])}
- description={t(($) => $['createGuide.target.description'])}
- hideHeader
- >
-
-
-
-
-
-
-
- )
-}
-
-function TargetEnvironmentSection() {
- const { t } = useTranslation('deployments')
- const environmentsIsError = useAtomValue(deployableEnvironmentsIsErrorAtom)
- const environmentsIsFetching = useAtomValue(deployableEnvironmentsIsFetchingAtom)
- const environmentsIsLoading = useAtomValue(deployableEnvironmentsIsLoadingAtom)
- const environments = useAtomValue(deployableEnvironmentsAtom)
- const effectiveSelectedEnvironmentId = useAtomValue(effectiveSelectedEnvironmentIdAtom)
- const isEnvironmentLoading =
- environmentsIsLoading || (environmentsIsFetching && environments.length === 0)
- const selectEnvironment = useSetAtom(selectedEnvironmentIdAtom)
- const hasEnvironmentOptions = environments.length > 0
-
- return (
-
-
- {t(($) => $['createGuide.target.environment'])}
-
- {hasEnvironmentOptions ? (
-
- aria-label={t(($) => $['createGuide.target.environment'])}
- value={effectiveSelectedEnvironmentId}
- onValueChange={selectEnvironment}
- className="grid grid-cols-1 items-stretch gap-3 lg:grid-cols-2"
- >
- {environments.map((environment) => (
-
- ))}
-
- ) : isEnvironmentLoading ? (
-
- ) : (
-
- {environmentsIsError
- ? t(($) => $['createGuide.target.loadEnvironmentsFailed'])
- : t(($) => $['createGuide.target.noEnvironmentOptions'])}
-
- )}
-
- )
-}
-
-function EnvironmentOptionRow({ environment }: { environment: Environment }) {
- const { t } = useTranslation('deployments')
- const summary =
- environment.description.trim() ||
- `${t(($) => $[`mode.${environment.mode}`])} · ${t(($) => $[`backend.${environment.backend}`])}`
-
- return (
-
- value={environment.id}
- nativeButton
- render={}
- className={cn(
- 'group flex cursor-pointer items-center gap-3 rounded-xl border p-3 outline-hidden',
- 'border-components-option-card-option-border bg-components-option-card-option-bg hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs',
- 'focus-visible:ring-2 focus-visible:ring-state-accent-solid',
- 'data-checked:border-state-accent-solid data-checked:bg-state-accent-hover data-checked:shadow-xs',
- )}
- >
-
-
-
- {environment.displayName}
-
-
-
- {summary}
-
-
-
-
- )
-}
-
-function TargetBindingSection() {
- const { t } = useTranslation('deployments')
- const deploymentOptions = useAtomValue(deploymentOptionsDataAtom)
- const deploymentOptionsIsError = useAtomValue(deploymentOptionsIsErrorAtom)
- const deploymentOptionsIsFetching = useAtomValue(deploymentOptionsIsFetchingAtom)
- const deploymentOptionsIsLoading = useAtomValue(deploymentOptionsIsLoadingAtom)
- const bindingSlots = useAtomValue(deploymentTargetBindingSlotsAtom)
- const bindingSelections = useAtomValue(deploymentTargetBindingSelectionsAtom)
- const isBindingError = deploymentOptionsIsError
- const isBindingLoading =
- deploymentOptionsIsLoading || (deploymentOptionsIsFetching && !deploymentOptions)
- const selectBinding = useSetAtom(selectBindingAtom)
- const unsupportedDslNodes = useAtomValue(unsupportedDslNodesAtom)
- const shouldRender = !(isBindingError && unsupportedDslNodes.length > 0)
-
- if (!shouldRender) return null
-
- if (isBindingLoading || isBindingError) {
- return (
-
-
-
- {t(($) => $['createGuide.target.bindings'])}
-
-
- {t(($) => $['createGuide.target.bindingHint'])}
-
-
- {isBindingLoading ? (
-
- ) : (
-
- {t(($) => $['createGuide.target.loadBindingsFailed'])}
-
- )}
-
- )
- }
-
- return (
- $['createGuide.target.bindings'])}
- hint={t(($) => $['createGuide.target.bindingHint'])}
- noBindingRequiredLabel={t(($) => $['createGuide.target.noBindingRequired'])}
- noCredentialCandidatesLabel={t(($) => $['createGuide.target.noCredentialCandidates'])}
- selectCredentialLabel={t(($) => $['createGuide.target.selectCredential'])}
- missingRequiredLabel={t(($) => $['createGuide.target.missingRequiredBinding'])}
- bindingCountLabel={t(($) => $['createGuide.target.bindingCount'], {
- count: bindingSlots.length,
- })}
- onChange={selectBinding}
- listScrollable={false}
- className="border-components-option-card-option-border bg-components-option-card-option-bg"
- />
- )
-}
-
-function TargetEnvVarSection() {
- const { t } = useTranslation('deployments')
- const setEnvVar = useSetAtom(setEnvVarAtom)
- const envVarValues = useAtomValue(envVarValuesAtom)
- const deploymentOptions = useAtomValue(deploymentOptionsDataAtom)
- const deploymentOptionsIsError = useAtomValue(deploymentOptionsIsErrorAtom)
- const deploymentOptionsIsFetching = useAtomValue(deploymentOptionsIsFetchingAtom)
- const deploymentOptionsIsLoading = useAtomValue(deploymentOptionsIsLoadingAtom)
- const envVarSlots = useAtomValue(deploymentTargetEnvVarSlotsAtom)
- const isBindingError = deploymentOptionsIsError
- const isBindingLoading =
- deploymentOptionsIsLoading || (deploymentOptionsIsFetching && !deploymentOptions)
-
- if (isBindingLoading || isBindingError) return null
-
- return (
- $['createGuide.target.envVars'])}
- hint={t(($) => $['createGuide.target.envVarHint'])}
- envVarPlaceholder={t(($) => $['createGuide.target.envVarPlaceholder'])}
- literalSourceLabel={t(($) => $['createGuide.target.envVarSource.literal'])}
- defaultSourceLabel={t(($) => $['createGuide.target.envVarSource.default'])}
- lastDeploymentSourceLabel={t(($) => $['createGuide.target.envVarSource.lastDeployment'])}
- valueTypeLabels={{
- string: t(($) => $['createGuide.target.envVarType.string']),
- number: t(($) => $['createGuide.target.envVarType.number']),
- secret: t(($) => $['createGuide.target.envVarType.secret']),
- }}
- sourceAriaLabel={(key) => t(($) => $['createGuide.target.envVarSource.ariaLabel'], { key })}
- envVarCountLabel={t(($) => $['createGuide.target.envVarCount'], {
- count: envVarSlots.length,
- })}
- onChange={setEnvVar}
- listScrollable={false}
- className="border-components-option-card-option-border bg-components-option-card-option-bg"
- />
- )
-}
-
-function TargetEnvironmentSkeleton() {
- return (
-
- {targetEnvironmentSkeletonKeys.map((key) => (
-
-
-
-
-
-
-
- ))}
-
- )
-}
-
-function TargetBindingSkeleton() {
- return (
-
- {targetBindingSkeletonKeys.map((key) => (
-
-
-
-
-
-
-
- ))}
-
- )
-}
-
-export function TargetBackButton() {
- const { t } = useTranslation('deployments')
- const setStep = useSetAtom(stepAtom)
- const isSubmitting = useAtomValue(isSubmittingDeploymentGuideAtom)
-
- return (
-
- )
-}
-
-export function TargetSkipDeploymentButton() {
- const { t } = useTranslation('deployments')
- const router = useRouter()
- const canSkipDeployment = useAtomValue(canSkipDeploymentAtom)
- const submitCreateDeploymentGuide = useSetAtom(createDeploymentGuideSubmissionAtom)
- const isSubmitting = useAtomValue(isSubmittingDeploymentGuideAtom)
- const isSkippingDeployment = useAtomValue(isCreatingReleaseOnlyAtom)
- const label = isSkippingDeployment
- ? t(($) => $['createGuide.actions.creating'])
- : t(($) => $['createGuide.actions.skipDeploy'])
-
- async function handleSkipDeployment() {
- if (!canSkipDeployment) return
-
- try {
- const appInstanceId = await submitCreateDeploymentGuide({ deployToEnvironment: false })
- if (appInstanceId) router.push(`/deployments/${appInstanceId}/overview`)
- } catch (error) {
- await showSubmissionError({
- error,
- fallbackMessage: t(($) => $['createGuide.errors.createReleaseFailed']),
- unsupportedDslModeMessage: t(($) => $['createGuide.dsl.unsupportedMode']),
- })
- }
- }
-
- return (
-
- )
-}
-
-export function TargetDeployButton() {
- const { t } = useTranslation('deployments')
- const router = useRouter()
- const canDeploy = useAtomValue(canDeployAtom)
- const submitCreateDeploymentGuide = useSetAtom(createDeploymentGuideSubmissionAtom)
- const isSubmitting = useAtomValue(isSubmittingDeploymentGuideAtom)
- const isSkippingDeployment = useAtomValue(isCreatingReleaseOnlyAtom)
- const label =
- isSubmitting && !isSkippingDeployment
- ? t(($) => $['createGuide.actions.deploying'])
- : t(($) => $['createGuide.actions.createAndDeploy'])
-
- async function handleDeploy() {
- if (!canDeploy) return
-
- try {
- const appInstanceId = await submitCreateDeploymentGuide({ deployToEnvironment: true })
- if (appInstanceId) router.push(`/deployments/${appInstanceId}/overview`)
- } catch (error) {
- await showSubmissionError({
- error,
- fallbackMessage: t(($) => $['createGuide.errors.deployFailed']),
- unsupportedDslModeMessage: t(($) => $['createGuide.dsl.unsupportedMode']),
- })
- }
- }
-
- return (
-
- )
-}
-
-async function showSubmissionError({
- error,
- fallbackMessage,
- unsupportedDslModeMessage,
-}: {
- error: unknown
- fallbackMessage: string
- unsupportedDslModeMessage: string
-}) {
- if (error instanceof CreateDeploymentGuideSubmissionBlockedError) {
- toast.error(error.reason === 'unsupportedDslMode' ? unsupportedDslModeMessage : fallbackMessage)
- return
- }
-
- toast.error((await deploymentErrorMessage(error)) || fallbackMessage)
-}
diff --git a/web/features/deployments/create-release/README.md b/web/features/deployments/create-release/README.md
deleted file mode 100644
index 504e2a9f38b..00000000000
--- a/web/features/deployments/create-release/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Deployment Create Release
-
-Release creation dialog for selecting a source app or DSL file and creating a new release for an existing deployment app instance.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| -------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| --------------------------------------------------- | -------------------------------------------------------------------------------- |
-| `app/components/app/create-from-dsl-modal/uploader` | Reuses the existing DSL file uploader for the DSL release source. |
-| `app/components/base/app-icon` | Renders source app icons consistently in the source app picker. |
-| `app/components/base/skeleton` | Reuses skeleton primitives for source app picker loading rows. |
-| `types/app` | Uses app types and mode enums to narrow selectable source apps to workflow apps. |
diff --git a/web/features/deployments/create-release/index.tsx b/web/features/deployments/create-release/index.tsx
deleted file mode 100644
index 6d3dba8c7c5..00000000000
--- a/web/features/deployments/create-release/index.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-'use client'
-
-import type { ButtonProps } from '@langgenius/dify-ui/button'
-import { Button } from '@langgenius/dify-ui/button'
-import { Dialog, DialogTrigger } from '@langgenius/dify-ui/dialog'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { useTranslation } from 'react-i18next'
-import {
- createReleaseAppInstanceIdAtom,
- createReleaseDialogOpenAtom,
- createReleaseLocalAtoms,
- isCreatingReleaseAtom,
- openCreateReleaseDialogAtom,
- requestCloseCreateReleaseDialogAtom,
-} from './state'
-import { CreateReleaseDialogContent } from './ui/dialog'
-
-function CreateReleaseScopedControl({
- variant,
- size,
- label,
- className,
-}: {
- variant: ButtonProps['variant']
- size: ButtonProps['size']
- label?: string
- className?: string
-}) {
- const { t } = useTranslation('deployments')
- const open = useAtomValue(createReleaseDialogOpenAtom)
- const isCreatingRelease = useAtomValue(isCreatingReleaseAtom)
- const openDialog = useSetAtom(openCreateReleaseDialogAtom)
- const requestCloseDialog = useSetAtom(requestCloseCreateReleaseDialogAtom)
-
- function handleDialogOpenChange(nextOpen: boolean) {
- if (nextOpen) {
- openDialog()
- return
- }
-
- if (!isCreatingRelease) requestCloseDialog()
- }
-
- return (
-
- )
-}
-
-export function CreateReleaseControl({
- appInstanceId,
- variant = 'primary',
- size = 'small',
- label,
- className,
-}: {
- appInstanceId: string
- variant?: ButtonProps['variant']
- size?: ButtonProps['size']
- label?: string
- className?: string
-}) {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/create-release/state/__tests__/dsl-enabled.spec.ts b/web/features/deployments/create-release/state/__tests__/dsl-enabled.spec.ts
deleted file mode 100644
index 87b17b9848d..00000000000
--- a/web/features/deployments/create-release/state/__tests__/dsl-enabled.spec.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-import type { QueryClient } from '@tanstack/react-query'
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
-}
-
-type InfiniteQueryOptions = QueryOptions & {
- input?: (pageParam: number) => unknown
-}
-
-const mockSourceAppsInfiniteOptions = vi.hoisted(() => vi.fn())
-const mockPrecheckReleaseQueryOptions = vi.hoisted(() => vi.fn())
-const mockCreateRelease = vi.hoisted(() => vi.fn())
-
-vi.mock('../../../shared/domain/feature-flags', () => ({
- isDeploymentDslImportEnabled: true,
-}))
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- apps: {
- get: {
- infiniteOptions: (options: InfiniteQueryOptions) => {
- mockSourceAppsInfiniteOptions(options)
-
- return {
- ...options,
- queryKey: ['sourceApps', options.input],
- queryFn: async () => ({
- data: [],
- has_more: false,
- limit: 20,
- page: 1,
- total: 0,
- }),
- }
- },
- },
- },
- enterprise: {
- releaseService: {
- listReleaseSummaries: {
- key: ({ input }: { input?: unknown } = {}) =>
- input === undefined ? ['listReleaseSummaries'] : ['listReleaseSummaries', input],
- },
- listReleases: {
- key: ({ input }: { input?: unknown } = {}) =>
- input === undefined ? ['listReleases'] : ['listReleases', input],
- },
- precheckRelease: {
- queryOptions: (options: QueryOptions) => {
- mockPrecheckReleaseQueryOptions(options)
-
- return {
- ...options,
- queryKey: ['precheckRelease', options.input],
- }
- },
- },
- createRelease: {
- mutationOptions: () => ({
- mutationKey: ['createRelease'],
- mutationFn: mockCreateRelease,
- }),
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../index')
-}
-
-async function mountedStore() {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- const unsubscribe = store.sub(state.createReleaseFormIsSubmittingAtom, () => undefined)
-
- return {
- queryClient,
- state,
- store,
- unsubscribe,
- }
-}
-
-function workflowDsl() {
- return ['app:', ' mode: workflow', ' name: Release source'].join('\n')
-}
-
-function setDslFileContentResult(queryClient: QueryClient, file: File, fileReadVersion: number) {
- queryClient.setQueryData(
- ['createReleaseDslFileContent', fileReadVersion, file, file.name, file.size, file.lastModified],
- workflowDsl(),
- )
-}
-
-function setPrecheckReleaseResult(
- queryClient: QueryClient,
- input: {
- body: {
- appInstanceId: string
- dsl: string
- }
- },
-) {
- queryClient.setQueryData(['precheckRelease', input], {
- gateCommitId: 'gate-commit-1',
- canCreate: true,
- unsupportedNodes: [],
- })
-}
-
-describe('create release state with DSL import enabled', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockCreateRelease.mockReset()
- })
-
- it('should enable source app search with the current search text while creating from an app', async () => {
- const { state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- store.set(state.createReleaseSourceAppSearchTextAtom, 'customer')
-
- store.get(state.createReleaseSourceAppsQueryAtom)
- const sourceAppsQuery = mockSourceAppsInfiniteOptions.mock.lastCall?.[0] as InfiniteQueryOptions
-
- expect(sourceAppsQuery.enabled).toBe(true)
- expect(sourceAppsQuery.input?.(2)).toEqual({
- query: {
- page: 2,
- limit: 20,
- name: 'customer',
- mode: 'workflow',
- },
- })
-
- unsubscribe()
- })
-
- it('should skip DSL release precheck input until DSL content is ready', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- store.set(state.selectCreateReleaseSourceModeAtom, 'dsl')
- store.get(state.isCheckingCreateReleaseContentAtom)
-
- expect(mockPrecheckReleaseQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: false,
- input: skipToken,
- }),
- )
-
- unsubscribe()
- })
-
- it('should submit a DSL release with encoded workflow content', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const response = {
- release: {
- displayName: 'Release from DSL',
- },
- }
- const file = new File([workflowDsl()], 'workflow.yml', { type: 'text/yaml' })
- mockCreateRelease.mockResolvedValue(response)
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- store.set(state.selectCreateReleaseSourceModeAtom, 'dsl')
- store.set(state.updateCreateReleaseDslFileAtom, file)
- setDslFileContentResult(queryClient, file, 2)
- const encodedDslContent = store.get(state.createReleaseEncodedDslContentAtom)
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- dsl: encodedDslContent,
- },
- })
- store.set(state.createReleaseNameFieldAtom, ' Release from DSL ')
- store.set(state.createReleaseDescriptionFieldAtom, ' Imported workflow ')
-
- const result = await store.set(state.submitCreateReleaseFormAtom)
-
- expect(result).toBe(response)
- expect(encodedDslContent).not.toBe('')
- expect(mockCreateRelease.mock.calls[0]?.[0]).toEqual({
- body: {
- appInstanceId: 'app-instance-1',
- displayName: 'Release from DSL',
- description: 'Imported workflow',
- createAppInstance: false,
- dsl: encodedDslContent,
- },
- })
-
- unsubscribe()
- })
-})
diff --git a/web/features/deployments/create-release/state/__tests__/index.spec.ts b/web/features/deployments/create-release/state/__tests__/index.spec.ts
deleted file mode 100644
index 790e105467c..00000000000
--- a/web/features/deployments/create-release/state/__tests__/index.spec.ts
+++ /dev/null
@@ -1,513 +0,0 @@
-import type { QueryClient } from '@tanstack/react-query'
-import type { CreateReleaseFormValues } from '../index'
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { consoleQuery } from '@/service/client'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
-}
-
-const mockPrecheckReleaseQueryOptions = vi.hoisted(() => vi.fn())
-const mockCreateRelease = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- apps: {
- byAppId: {
- get: {
- queryOptions: ({ enabled, input }: QueryOptions) => ({
- enabled,
- input,
- queryKey: ['appById', input],
- }),
- },
- },
- },
- enterprise: {
- releaseService: {
- listReleaseSummaries: {
- key: ({ input }: { input?: unknown } = {}) =>
- input === undefined ? ['listReleaseSummaries'] : ['listReleaseSummaries', input],
- queryOptions: ({ enabled, input }: QueryOptions) => ({
- enabled,
- input,
- queryKey: ['listReleaseSummaries', input],
- }),
- },
- listReleases: {
- key: ({ input }: { input?: unknown } = {}) =>
- input === undefined ? ['listReleases'] : ['listReleases', input],
- queryOptions: ({ enabled, input }: QueryOptions) => ({
- enabled,
- input,
- queryKey: ['listReleases', input],
- }),
- },
- precheckRelease: {
- queryOptions: ({ enabled, input }: QueryOptions) => {
- mockPrecheckReleaseQueryOptions({ enabled, input })
-
- return {
- enabled,
- input,
- queryKey: ['precheckRelease', input],
- }
- },
- },
- createRelease: {
- mutationOptions: () => ({
- mutationKey: ['createRelease'],
- mutationFn: mockCreateRelease,
- }),
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../index')
-}
-
-async function mountedStore() {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- const unsubscribe = store.sub(state.createReleaseFormIsSubmittingAtom, () => undefined)
-
- return {
- queryClient,
- state,
- store,
- unsubscribe,
- }
-}
-
-function sourceApp(
- overrides: Partial> = {},
-): NonNullable {
- return {
- id: 'source-app-1',
- name: 'Source App',
- mode: 'workflow',
- icon_url: null,
- ...overrides,
- }
-}
-
-function validationIssueMessage(error: unknown) {
- if (!error || typeof error !== 'object' || !('message' in error)) return undefined
-
- return typeof error.message === 'string' ? error.message : undefined
-}
-
-function hasValidationIssue(errors: unknown[], message: string) {
- return errors.some((error) => validationIssueMessage(error) === message)
-}
-
-function workflowDsl() {
- return ['app:', ' mode: workflow', ' name: Release source'].join('\n')
-}
-
-function setDefaultSourceApp(
- queryClient: QueryClient,
- appInstanceId: string,
- defaultSourceApp = sourceApp({ id: 'default-source-app', name: 'Default Source App' }),
-) {
- queryClient.setQueryData(
- [
- 'listReleases',
- {
- params: { appInstanceId },
- query: {
- pageNumber: 1,
- resultsPerPage: 1,
- },
- },
- ],
- {
- releases: [
- {
- displayName: 'Previous Release',
- sourceAppId: defaultSourceApp.id,
- },
- ],
- },
- )
- queryClient.setQueryData(
- ['appById', { params: { app_id: defaultSourceApp.id } }],
- defaultSourceApp,
- )
-}
-
-function setPrecheckReleaseResult(
- queryClient: QueryClient,
- input: {
- body: {
- appInstanceId: string
- dsl?: string
- sourceAppId?: string
- }
- },
- overrides: {
- canCreate?: boolean
- matchedRelease?: unknown
- unsupportedNodes?: Array<{ id?: string; type?: string }>
- } = {},
-) {
- queryClient.setQueryData(['precheckRelease', input], {
- gateCommitId: 'gate-commit-1',
- canCreate: true,
- unsupportedNodes: [],
- ...overrides,
- })
-}
-
-function setCachedReleaseSummaries(
- queryClient: QueryClient,
- appInstanceId: string,
- displayNames: string[],
-) {
- queryClient.setQueryData(
- consoleQuery.enterprise.releaseService.listReleaseSummaries.key({
- type: 'query',
- input: { params: { appInstanceId } },
- }),
- {
- releaseSummaries: displayNames.map((displayName) => ({
- release: {
- displayName,
- },
- })),
- pagination: {},
- },
- )
-}
-
-function setDslFileContentResult(queryClient: QueryClient, file: File, fileReadVersion: number) {
- queryClient.setQueryData(
- ['createReleaseDslFileContent', fileReadVersion, file, file.name, file.size, file.lastModified],
- workflowDsl(),
- )
-}
-
-describe('create release state', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockCreateRelease.mockReset()
- })
-
- it('should validate release name only when submitting', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- await store.set(state.submitCreateReleaseFormAtom)
-
- expect(mockCreateRelease).not.toHaveBeenCalled()
- expect(
- hasValidationIssue(
- store.get(state.createReleaseNameFieldAtom).meta?.errors ?? [],
- state.RELEASE_NAME_REQUIRED_ERROR,
- ),
- ).toBe(true)
-
- unsubscribe()
- })
-
- it('should submit after fixing release name following a submit validation error', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const response = {
- release: {
- displayName: 'Release 1',
- },
- }
- mockCreateRelease.mockResolvedValue(response)
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- })
-
- await store.set(state.submitCreateReleaseFormAtom)
- store.set(state.createReleaseNameFieldAtom, 'Release 1')
-
- const result = await store.set(state.submitCreateReleaseFormAtom)
-
- expect(result).toBe(response)
- expect(mockCreateRelease).toHaveBeenCalledTimes(1)
-
- unsubscribe()
- })
-
- it('should coerce DSL source mode to source app mode when DSL import is disabled', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- store.set(state.selectCreateReleaseSourceModeAtom, 'dsl')
-
- expect(store.get(state.createReleaseSourceModeFieldAtom).value).toBe('sourceApp')
- expect(store.get(state.createReleaseSourceModeAtom)).toBe('sourceApp')
-
- unsubscribe()
- })
-
- it('should derive default source app selection from the latest release source', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
-
- expect(store.get(state.createReleaseSelectedSourceAppAtom)).toEqual({
- id: 'default-source-app',
- name: 'Default Source App',
- mode: 'workflow',
- icon_url: null,
- })
- expect(store.get(state.createReleaseSelectedSourceAppAtom)?.id).toBe('default-source-app')
-
- unsubscribe()
- })
-
- it('should derive workflow DSL read state when selecting a DSL file', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const file = new File([workflowDsl()], 'workflow.yml', { type: 'text/yaml' })
-
- store.set(state.updateCreateReleaseDslFileAtom, file)
- setDslFileContentResult(queryClient, file, 1)
-
- expect(store.get(state.createReleaseDslFileFieldAtom).value).toBe(file)
- expect(store.get(state.createReleaseDslContentAtom)).toBe(workflowDsl())
- expect(store.get(state.createReleaseHasDslContentAtom)).toBe(true)
- expect(store.get(state.isReadingCreateReleaseDslAtom)).toBe(false)
- expect(store.get(state.createReleaseIsWorkflowDslContentAtom)).toBe(true)
- expect(store.get(state.createReleaseEncodedDslContentAtom)).not.toBe('')
-
- unsubscribe()
- })
-
- it('should reset DSL state when switching back to source app mode', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const file = new File([workflowDsl()], 'workflow.yml', { type: 'text/yaml' })
-
- store.set(state.updateCreateReleaseDslFileAtom, file)
- setDslFileContentResult(queryClient, file, 1)
- store.set(state.selectCreateReleaseSourceModeAtom, 'sourceApp')
-
- expect(store.get(state.createReleaseSourceModeFieldAtom).value).toBe('sourceApp')
- expect(store.get(state.createReleaseDslFileFieldAtom).value).toBeUndefined()
- expect(store.get(state.createReleaseDslContentAtom)).toBe('')
- expect(store.get(state.createReleaseDslReadErrorAtom)).toBe(false)
- expect(store.get(state.createReleaseEncodedDslContentAtom)).toBe('')
- expect(store.get(state.createReleaseHasDslContentAtom)).toBe(false)
- expect(store.get(state.isReadingCreateReleaseDslAtom)).toBe(false)
- expect(store.get(state.createReleaseIsWorkflowDslContentAtom)).toBe(false)
-
- unsubscribe()
- })
-
- it('should reset source app search text when opening or closing the dialog', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- store.set(state.createReleaseSourceAppSearchTextAtom, 'customer')
- store.set(state.openCreateReleaseDialogAtom)
-
- expect(store.get(state.createReleaseSourceAppSearchTextAtom)).toBe('')
-
- store.set(state.createReleaseSourceAppSearchTextAtom, 'support')
- store.set(state.closeCreateReleaseDialogAtom)
-
- expect(store.get(state.createReleaseSourceAppSearchTextAtom)).toBe('')
-
- unsubscribe()
- })
-
- it('should skip release content precheck input until source content is ready', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- store.get(state.isCheckingCreateReleaseContentAtom)
-
- expect(mockPrecheckReleaseQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: false,
- input: skipToken,
- }),
- )
-
- unsubscribe()
- })
-
- it('should capture DSL file read failures and clear them when opening or closing the dialog', async () => {
- const { state, store, unsubscribe } = await mountedStore()
- const file = new File(['broken'], 'broken.yml', { type: 'text/yaml' })
- vi.spyOn(file, 'text').mockRejectedValue(new Error('read failed'))
-
- store.set(state.updateCreateReleaseDslFileAtom, file)
- const unsubscribeDslReadError = store.sub(state.createReleaseDslReadErrorAtom, () => undefined)
-
- await vi.waitFor(() => {
- expect(store.get(state.createReleaseDslReadErrorAtom)).toBe(true)
- })
-
- store.set(state.openCreateReleaseDialogAtom)
- expect(store.get(state.createReleaseDialogOpenAtom)).toBe(true)
- expect(store.get(state.createReleaseDslReadErrorAtom)).toBe(false)
-
- store.set(state.closeCreateReleaseDialogAtom)
- expect(store.get(state.createReleaseDialogOpenAtom)).toBe(false)
-
- unsubscribeDslReadError()
- unsubscribe()
- })
-
- it('should derive content readiness from release content precheck', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- })
-
- expect(store.get(state.createReleaseContentReadyAtom)).toBe(true)
-
- store.set(state.createReleaseNameFieldAtom, 'Release 1')
-
- expect(store.get(state.createReleaseContentReadyAtom)).toBe(true)
-
- unsubscribe()
- })
-
- it('should detect existing release name conflicts from cached release summaries', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- store.set(state.createReleaseNameFieldAtom, ' Release 1 ')
- setCachedReleaseSummaries(queryClient, 'app-instance-1', ['Release 1'])
-
- expect(store.get(state.createReleaseHasNameConflictAtom)).toBe(true)
-
- unsubscribe()
- })
-
- it('should close the dialog through the close request action', async () => {
- const { state, store, unsubscribe } = await mountedStore()
-
- store.set(state.openCreateReleaseDialogAtom)
- store.set(state.requestCloseCreateReleaseDialogAtom)
-
- expect(store.get(state.createReleaseDialogOpenAtom)).toBe(false)
-
- unsubscribe()
- })
-
- it('should expose unsupported nodes from release content precheck', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(
- queryClient,
- {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- },
- {
- canCreate: false,
- unsupportedNodes: [{ id: 'precheck-node' }],
- },
- )
-
- expect(store.get(state.createReleaseUnsupportedDslNodesAtom)).toEqual([{ id: 'precheck-node' }])
-
- unsubscribe()
- })
-
- it('should submit source app release with the checked source and metadata', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const response = {
- release: {
- displayName: 'Release 1',
- },
- }
- mockCreateRelease.mockResolvedValue(response)
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- })
- store.set(state.createReleaseNameFieldAtom, ' Release 1 ')
- store.set(state.createReleaseDescriptionFieldAtom, ' Initial rollout ')
-
- const result = await store.set(state.submitCreateReleaseFormAtom)
-
- expect(result).toBe(response)
- expect(mockCreateRelease.mock.calls[0]?.[0]).toEqual({
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- displayName: 'Release 1',
- description: 'Initial rollout',
- createAppInstance: false,
- },
- })
-
- unsubscribe()
- })
-
- it('should block release submission when release name already exists', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- })
- setCachedReleaseSummaries(queryClient, 'app-instance-1', ['Release 1'])
- store.set(state.createReleaseNameFieldAtom, 'Release 1')
-
- const result = await store.set(state.submitCreateReleaseFormAtom)
-
- expect(result).toBeUndefined()
- expect(mockCreateRelease).not.toHaveBeenCalled()
-
- unsubscribe()
- })
-
- it('should propagate create release submission errors', async () => {
- const { queryClient, state, store, unsubscribe } = await mountedStore()
- const submitError = new Error('submit failed')
- mockCreateRelease.mockRejectedValue(submitError)
- store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
- store.set(state.openCreateReleaseDialogAtom)
- setDefaultSourceApp(queryClient, 'app-instance-1')
- setPrecheckReleaseResult(queryClient, {
- body: {
- appInstanceId: 'app-instance-1',
- sourceAppId: 'default-source-app',
- },
- })
- store.set(state.createReleaseNameFieldAtom, 'Release 1')
-
- await expect(store.set(state.submitCreateReleaseFormAtom)).rejects.toThrow(submitError)
-
- unsubscribe()
- })
-})
diff --git a/web/features/deployments/create-release/state/index.ts b/web/features/deployments/create-release/state/index.ts
deleted file mode 100644
index 6220aee613b..00000000000
--- a/web/features/deployments/create-release/state/index.ts
+++ /dev/null
@@ -1,575 +0,0 @@
-'use client'
-
-import type { AppPartial } from '@dify/contracts/api/console/apps/types.gen'
-import type {
- CreateReleaseResponse,
- ListReleasesResponse,
- ListReleaseSummariesResponse,
-} from '@dify/contracts/enterprise/types.gen'
-import type { Getter } from 'jotai/vanilla'
-import type { UnsupportedDslNode } from '../../shared/domain/error'
-import { keepPreviousData, queryOptions, skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithForm, createFormAtoms } from 'jotai-tanstack-form'
-import {
- atomWithInfiniteQuery,
- atomWithMutation,
- atomWithQuery,
- queryClientAtom,
-} from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import * as z from 'zod'
-import { consoleQuery } from '@/service/client'
-import { AppModeEnum } from '@/types/app'
-import { encodeDslContent, isWorkflowDsl } from '../../shared/domain/dsl'
-import { isDeploymentDslImportEnabled } from '../../shared/domain/feature-flags'
-
-export type ReleaseSourceMode = 'sourceApp' | 'dsl'
-
-export type SourceAppPickerValue = Pick<
- AppPartial,
- 'id' | 'name' | 'icon_type' | 'icon' | 'icon_background' | 'icon_url' | 'mode'
->
-
-export type CreateReleaseFormValues = {
- releaseSourceMode: ReleaseSourceMode
- sourceApp?: SourceAppPickerValue
- dslFile?: File
- releaseName: string
- releaseDescription: string
-}
-
-const DEFAULT_CREATE_RELEASE_FORM_VALUES: CreateReleaseFormValues = {
- releaseSourceMode: 'sourceApp',
- sourceApp: undefined,
- dslFile: undefined,
- releaseName: '',
- releaseDescription: '',
-}
-
-export const RELEASE_NAME_REQUIRED_ERROR = 'releaseNameRequired'
-
-const DEFAULT_SOURCE_RELEASE_PAGE_SIZE = 1
-const CREATE_RELEASE_SOURCE_APP_PAGE_SIZE = 20
-
-function deploymentReleaseSourceMode(mode: ReleaseSourceMode): ReleaseSourceMode {
- return mode === 'dsl' && !isDeploymentDslImportEnabled ? 'sourceApp' : mode
-}
-
-const createReleaseFormSchema = z.object({
- releaseSourceMode: z.union([z.literal('sourceApp'), z.literal('dsl')]),
- sourceApp: z.custom().optional(),
- dslFile: z.custom().optional(),
- releaseName: z.string().trim().min(1, RELEASE_NAME_REQUIRED_ERROR),
- releaseDescription: z.string(),
-})
-
-type CreateReleaseSubmit = (
- value: CreateReleaseFormValues,
-) => Promise | CreateReleaseResponse | undefined
-
-type CreateReleaseSubmitMeta = {
- createRelease: CreateReleaseSubmit
-}
-
-const noopCreateRelease: CreateReleaseSubmit = () => undefined
-
-// Form state
-export const createReleaseFormAtom = atomWithForm({
- defaultValues: DEFAULT_CREATE_RELEASE_FORM_VALUES,
- onSubmitMeta: {
- createRelease: noopCreateRelease,
- },
- validators: {
- onSubmit: createReleaseFormSchema,
- },
- onSubmit: ({ value, meta }) => meta.createRelease(value),
-})
-
-const createReleaseFormAtoms = createFormAtoms(createReleaseFormAtom)
-
-export const createReleaseFormIsSubmittingAtom = createReleaseFormAtoms.isSubmittingAtom
-export const createReleaseSourceModeFieldAtom =
- createReleaseFormAtoms.fieldAtom('releaseSourceMode')
-export const createReleaseSourceAppFieldAtom = createReleaseFormAtoms.fieldAtom('sourceApp')
-export const createReleaseDslFileFieldAtom = createReleaseFormAtoms.fieldAtom('dslFile')
-export const createReleaseNameFieldAtom = createReleaseFormAtoms.fieldAtom('releaseName')
-export const createReleaseDescriptionFieldAtom =
- createReleaseFormAtoms.fieldAtom('releaseDescription')
-
-// Dialog and source primitives
-export const createReleaseAppInstanceIdAtom = atom(undefined)
-export const createReleaseDialogOpenAtom = atom(false)
-const createReleaseDslFileReadVersionAtom = atom(0)
-
-function requiredAppInstanceId(get: Getter) {
- const appInstanceId = get(createReleaseAppInstanceIdAtom)
- if (!appInstanceId) throw new Error('Missing create release app instance id.')
-
- return appInstanceId
-}
-
-// Query and remote data
-const latestSourceReleaseQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(createReleaseAppInstanceIdAtom)
-
- return consoleQuery.enterprise.releaseService.listReleases.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- query: {
- pageNumber: 1,
- resultsPerPage: DEFAULT_SOURCE_RELEASE_PAGE_SIZE,
- },
- }
- : skipToken,
- enabled: Boolean(appInstanceId && get(createReleaseDialogOpenAtom)),
- })
-})
-
-function latestReleaseSourceAppId(get: Getter) {
- const latestReleaseQuery = get(latestSourceReleaseQueryAtom)
-
- return latestReleaseQuery.data?.releases[0]?.sourceAppId
-}
-
-const defaultSourceAppQueryAtom = atomWithQuery((get) => {
- const latestSourceAppId = latestReleaseSourceAppId(get)
-
- return consoleQuery.apps.byAppId.get.queryOptions({
- input: latestSourceAppId
- ? {
- params: { app_id: latestSourceAppId },
- }
- : skipToken,
- enabled: Boolean(get(createReleaseDialogOpenAtom) && latestSourceAppId),
- })
-})
-
-function defaultSourceApp(get: Getter) {
- const sourceApp = get(defaultSourceAppQueryAtom).data
-
- return sourceApp?.mode === AppModeEnum.WORKFLOW ? sourceApp : undefined
-}
-
-function submittedReleaseName(get: Getter) {
- return get(createReleaseNameFieldAtom).value.trim()
-}
-
-function cachedReleaseDisplayNames(get: Getter) {
- const appInstanceId = get(createReleaseAppInstanceIdAtom)
- if (!appInstanceId) return []
-
- const queryClient = get(queryClientAtom)
- const releaseSummaryQueries = queryClient.getQueriesData({
- queryKey: consoleQuery.enterprise.releaseService.listReleaseSummaries.key({
- type: 'query',
- input: { params: { appInstanceId } },
- }),
- })
- const releaseQueries = queryClient.getQueriesData({
- queryKey: consoleQuery.enterprise.releaseService.listReleases.key({
- type: 'query',
- input: { params: { appInstanceId } },
- }),
- })
-
- return [
- ...releaseSummaryQueries.flatMap(([, data]) => {
- return data?.releaseSummaries.map((summary) => summary.release.displayName) ?? []
- }),
- ...releaseQueries.flatMap(([, data]) => {
- return data?.releases.map((release) => release.displayName) ?? []
- }),
- ]
-}
-
-export const createReleaseHasNameConflictAtom = atom((get) => {
- const releaseName = submittedReleaseName(get)
- if (!releaseName) return false
-
- return cachedReleaseDisplayNames(get).some((displayName) => displayName.trim() === releaseName)
-})
-
-const createReleaseDslFileContentQueryAtom = atomWithQuery((get) => {
- const file = get(createReleaseDslFileFieldAtom).value
- const fileReadVersion = get(createReleaseDslFileReadVersionAtom)
-
- return queryOptions({
- queryKey: [
- 'createReleaseDslFileContent',
- fileReadVersion,
- file,
- file?.name ?? '',
- file?.size ?? 0,
- file?.lastModified ?? 0,
- ],
- queryFn: async () => (file ? await file.text() : ''),
- enabled: Boolean(file),
- retry: false,
- })
-})
-
-// Source derived state
-function effectiveCreateReleaseSourceMode(get: Getter) {
- return deploymentReleaseSourceMode(get(createReleaseSourceModeFieldAtom).value)
-}
-
-export const createReleaseSourceModeAtom = atom((get) => {
- return effectiveCreateReleaseSourceMode(get)
-})
-
-export const createReleaseSourceAppSearchTextAtom = atom('')
-
-export const createReleaseSourceAppsQueryAtom = atomWithInfiniteQuery((get) => {
- const searchText = get(createReleaseSourceAppSearchTextAtom)
-
- return consoleQuery.apps.get.infiniteOptions({
- input: (pageParam) => ({
- query: {
- page: Number(pageParam),
- limit: CREATE_RELEASE_SOURCE_APP_PAGE_SIZE,
- name: searchText,
- mode: AppModeEnum.WORKFLOW,
- },
- }),
- getNextPageParam: (lastPage) => (lastPage.has_more ? lastPage.page + 1 : undefined),
- initialPageParam: 1,
- placeholderData: keepPreviousData,
- enabled: Boolean(
- get(createReleaseDialogOpenAtom) &&
- effectiveCreateReleaseSourceMode(get) === 'sourceApp' &&
- isDeploymentDslImportEnabled,
- ),
- })
-})
-
-const createReleaseSourceAppsDataAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.data,
-)
-export const createReleaseSourceAppsErrorAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.error,
-)
-export const createReleaseSourceAppsFetchNextPageAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.fetchNextPage,
-)
-export const createReleaseSourceAppsHasNextPageAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.hasNextPage,
-)
-export const createReleaseSourceAppsIsFetchingAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.isFetching,
-)
-export const createReleaseSourceAppsIsFetchingNextPageAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.isFetchingNextPage,
-)
-export const createReleaseSourceAppsIsLoadingAtom = selectAtom(
- createReleaseSourceAppsQueryAtom,
- (query) => query.isLoading,
-)
-
-export const createReleaseSourceAppsAtom = atom((get) => {
- return get(createReleaseSourceAppsDataAtom)?.pages.flatMap((page) => page.data) ?? []
-})
-
-export const createReleaseDslContentAtom = atom((get) => {
- return get(createReleaseDslFileContentQueryAtom).data ?? ''
-})
-
-export const createReleaseDslReadErrorAtom = atom((get) => {
- return Boolean(
- get(createReleaseDslFileFieldAtom).value && get(createReleaseDslFileContentQueryAtom).isError,
- )
-})
-
-export const isReadingCreateReleaseDslAtom = atom((get) => {
- const file = get(createReleaseDslFileFieldAtom).value
- const dslFileContentQuery = get(createReleaseDslFileContentQueryAtom)
-
- return Boolean(file && (dslFileContentQuery.isLoading || dslFileContentQuery.isFetching))
-})
-
-export const createReleaseHasDslContentAtom = atom((get) => {
- return Boolean(get(createReleaseDslContentAtom).trim())
-})
-
-export const createReleaseIsWorkflowDslContentAtom = atom((get) => {
- const dslContent = get(createReleaseDslContentAtom)
-
- return get(createReleaseHasDslContentAtom) ? isWorkflowDsl(dslContent) : false
-})
-
-export const createReleaseEncodedDslContentAtom = atom((get) => {
- const dslContent = get(createReleaseDslContentAtom)
-
- return get(createReleaseHasDslContentAtom) && get(createReleaseIsWorkflowDslContentAtom)
- ? encodeDslContent(dslContent)
- : ''
-})
-
-export const createReleaseSelectedSourceAppAtom = atom((get) => {
- if (effectiveCreateReleaseSourceMode(get) !== 'sourceApp') return undefined
-
- const fieldSourceApp = get(createReleaseSourceAppFieldAtom).value
- const fallbackSourceApp = defaultSourceApp(get)
-
- if (!isDeploymentDslImportEnabled) return fallbackSourceApp
-
- return fieldSourceApp ?? fallbackSourceApp
-})
-
-function selectedSourceAppId(get: Getter) {
- return effectiveCreateReleaseSourceMode(get) === 'sourceApp'
- ? get(createReleaseSelectedSourceAppAtom)?.id
- : undefined
-}
-
-function hasUnsupportedDslMode(get: Getter) {
- if (effectiveCreateReleaseSourceMode(get) !== 'dsl') return false
-
- return (
- get(createReleaseHasDslContentAtom) &&
- !get(isReadingCreateReleaseDslAtom) &&
- !get(createReleaseDslReadErrorAtom) &&
- !get(createReleaseIsWorkflowDslContentAtom)
- )
-}
-
-export const createReleaseHasUnsupportedDslModeAtom = atom((get) => {
- return hasUnsupportedDslMode(get)
-})
-
-function canCheckReleaseSourceContent(get: Getter) {
- if (effectiveCreateReleaseSourceMode(get) === 'sourceApp')
- return Boolean(selectedSourceAppId(get))
- if (!isDeploymentDslImportEnabled) return false
-
- return Boolean(
- get(createReleaseHasDslContentAtom) &&
- !get(isReadingCreateReleaseDslAtom) &&
- !get(createReleaseDslReadErrorAtom) &&
- !hasUnsupportedDslMode(get),
- )
-}
-
-function canCheckReleaseContent(get: Getter) {
- return Boolean(
- get(createReleaseAppInstanceIdAtom) &&
- get(createReleaseDialogOpenAtom) &&
- canCheckReleaseSourceContent(get),
- )
-}
-
-// Release content check
-const precheckReleaseQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(createReleaseAppInstanceIdAtom)
- const releaseSourceMode = effectiveCreateReleaseSourceMode(get)
- const sourceAppId = selectedSourceAppId(get)
- const canCheck = canCheckReleaseContent(get)
-
- return consoleQuery.enterprise.releaseService.precheckRelease.queryOptions({
- input:
- canCheck && appInstanceId
- ? releaseSourceMode === 'dsl'
- ? {
- body: {
- appInstanceId,
- dsl: get(createReleaseEncodedDslContentAtom),
- },
- }
- : sourceAppId
- ? {
- body: {
- appInstanceId,
- sourceAppId,
- },
- }
- : skipToken
- : skipToken,
- enabled: canCheck,
- retry: false,
- })
-})
-
-export const isCheckingCreateReleaseContentAtom = atom((get) => {
- const canCheck = canCheckReleaseContent(get)
- const precheckReleaseQuery = get(precheckReleaseQueryAtom)
-
- return canCheck && (precheckReleaseQuery.isLoading || precheckReleaseQuery.isFetching)
-})
-
-export const createReleaseMatchedReleaseAtom = atom((get) => {
- return canCheckReleaseContent(get)
- ? get(precheckReleaseQueryAtom).data?.matchedRelease
- : undefined
-})
-
-export const createReleaseContentCheckFailedAtom = atom((get) => {
- return canCheckReleaseContent(get) && get(precheckReleaseQueryAtom).isError
-})
-
-export const createReleaseUnsupportedDslNodesAtom = atom((get): UnsupportedDslNode[] => {
- return canCheckReleaseContent(get)
- ? (get(precheckReleaseQueryAtom).data?.unsupportedNodes ?? [])
- : []
-})
-
-export const createReleaseContentReadyAtom = atom((get) => {
- const canCheck = canCheckReleaseContent(get)
- const precheckReleaseQuery = get(precheckReleaseQueryAtom)
-
- return (
- canCheck &&
- precheckReleaseQuery.isSuccess &&
- !get(isCheckingCreateReleaseContentAtom) &&
- !get(createReleaseContentCheckFailedAtom) &&
- Boolean(precheckReleaseQuery.data?.canCreate) &&
- get(createReleaseUnsupportedDslNodesAtom).length === 0
- )
-})
-
-// Actions
-const resetCreateReleaseDslFileAtom = atom(null, (get, set) => {
- set(createReleaseDslFileFieldAtom, undefined)
- set(createReleaseDslFileReadVersionAtom, get(createReleaseDslFileReadVersionAtom) + 1)
-})
-
-const resetCreateReleaseSourceAppSearchAtom = atom(null, (_get, set) => {
- set(createReleaseSourceAppSearchTextAtom, '')
-})
-
-export const openCreateReleaseDialogAtom = atom(null, (_get, set) => {
- set(resetCreateReleaseDslFileAtom)
- set(resetCreateReleaseSourceAppSearchAtom)
- set(createReleaseDialogOpenAtom, true)
-})
-
-export const closeCreateReleaseDialogAtom = atom(null, (_get, set) => {
- set(createReleaseDialogOpenAtom, false)
- set(resetCreateReleaseDslFileAtom)
- set(resetCreateReleaseSourceAppSearchAtom)
-})
-
-export const requestCloseCreateReleaseDialogAtom = atom(null, (get, set) => {
- if (get(createReleaseFormIsSubmittingAtom)) return
-
- set(closeCreateReleaseDialogAtom)
-})
-
-export const selectCreateReleaseSourceModeAtom = atom(
- null,
- (_get, set, releaseSourceMode: ReleaseSourceMode) => {
- const effectiveReleaseSourceMode = deploymentReleaseSourceMode(releaseSourceMode)
- set(createReleaseSourceModeFieldAtom, effectiveReleaseSourceMode)
-
- if (effectiveReleaseSourceMode === 'sourceApp') {
- set(resetCreateReleaseDslFileAtom)
- return
- }
-
- set(createReleaseSourceAppFieldAtom, undefined)
- },
-)
-
-export const updateCreateReleaseSourceAppAtom = atom(
- null,
- (_get, set, sourceApp: CreateReleaseFormValues['sourceApp']) => {
- set(createReleaseSourceAppFieldAtom, sourceApp)
- },
-)
-
-export const updateCreateReleaseDslFileAtom = atom(
- null,
- (get, set, dslFile: CreateReleaseFormValues['dslFile']) => {
- set(createReleaseDslFileFieldAtom, dslFile)
- set(createReleaseDslFileReadVersionAtom, get(createReleaseDslFileReadVersionAtom) + 1)
- },
-)
-
-// Submission
-const createReleaseMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.releaseService.createRelease.mutationOptions(),
-)
-
-export const isCreatingReleaseAtom = atom((get) => {
- return get(createReleaseMutationAtom).isPending
-})
-
-export class CreateReleaseSubmissionBlockedError extends Error {
- reason: 'unsupportedDslMode'
-
- constructor(reason: 'unsupportedDslMode') {
- super(reason)
- this.reason = reason
- this.name = 'CreateReleaseSubmissionBlockedError'
- }
-}
-
-const createReleaseSubmissionAtom = atom(null, async (get, set, value: CreateReleaseFormValues) => {
- const releaseSourceMode = effectiveCreateReleaseSourceMode(get)
- const sourceAppId = selectedSourceAppId(get)
- const submittedReleaseName = value.releaseName.trim()
-
- if (get(isCheckingCreateReleaseContentAtom) || !submittedReleaseName) return undefined
-
- if (get(createReleaseHasNameConflictAtom)) return undefined
-
- if (!canCheckReleaseSourceContent(get) || !get(createReleaseContentReadyAtom)) return undefined
-
- const appInstanceId = requiredAppInstanceId(get)
- const commonCreateReleaseRequest = {
- appInstanceId,
- displayName: submittedReleaseName,
- description: value.releaseDescription.trim() || undefined,
- createAppInstance: false,
- }
-
- if (releaseSourceMode === 'dsl') {
- if (!get(createReleaseIsWorkflowDslContentAtom))
- throw new CreateReleaseSubmissionBlockedError('unsupportedDslMode')
-
- return await get(createReleaseMutationAtom).mutateAsync({
- body: {
- ...commonCreateReleaseRequest,
- dsl: get(createReleaseEncodedDslContentAtom),
- },
- })
- }
-
- if (!sourceAppId) return undefined
-
- return await get(createReleaseMutationAtom).mutateAsync({
- body: {
- ...commonCreateReleaseRequest,
- sourceAppId,
- },
- })
-})
-
-export const submitCreateReleaseFormAtom = atom(null, (get, set) => {
- const form = get(createReleaseFormAtom)
- let submitResponse: CreateReleaseResponse | undefined
-
- return form.api
- .handleSubmit({
- createRelease: async (value) => {
- const response = await set(createReleaseSubmissionAtom, value)
- submitResponse = response
-
- return response
- },
- } satisfies CreateReleaseSubmitMeta)
- .then(() => submitResponse)
-})
-
-// Scoped atoms
-export const createReleaseLocalAtoms = [
- createReleaseDialogOpenAtom,
- createReleaseDslFileReadVersionAtom,
- createReleaseSourceAppSearchTextAtom,
-] as const
diff --git a/web/features/deployments/create-release/ui/__tests__/source-app-picker.spec.tsx b/web/features/deployments/create-release/ui/__tests__/source-app-picker.spec.tsx
deleted file mode 100644
index 99738f5c616..00000000000
--- a/web/features/deployments/create-release/ui/__tests__/source-app-picker.spec.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import { act, render, screen, waitFor } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { Provider } from 'jotai'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { SourceAppPicker } from '../source-app-picker'
-
-const mocks = vi.hoisted(() => {
- const sourceAppsQuery = {
- data: {
- pages: [
- {
- data: [
- {
- id: 'app-1',
- name: 'Workflow App',
- },
- ],
- },
- ],
- },
- error: null,
- fetchNextPage: vi.fn(),
- hasNextPage: true,
- isFetching: false,
- isFetchingNextPage: false,
- isLoading: false,
- }
-
- return { sourceAppsQuery }
-})
-
-type ObserverRecord = {
- callback: IntersectionObserverCallback
- options?: IntersectionObserverInit
-}
-
-const observers: ObserverRecord[] = []
-
-function getInfiniteScrollObserver() {
- return observers.find(({ options }) => options?.rootMargin === '0px 0px 160px 0px')
-}
-
-vi.mock('@/features/deployments/create-release/state', async () => {
- const { atom } = await import('jotai')
-
- return {
- createReleaseSourceAppsAtom: atom(() =>
- mocks.sourceAppsQuery.data.pages.flatMap((page) => page.data),
- ),
- createReleaseSourceAppsErrorAtom: atom(() => mocks.sourceAppsQuery.error),
- createReleaseSourceAppsFetchNextPageAtom: atom(() => mocks.sourceAppsQuery.fetchNextPage),
- createReleaseSourceAppsHasNextPageAtom: atom(() => mocks.sourceAppsQuery.hasNextPage),
- createReleaseSourceAppsIsFetchingAtom: atom(() => mocks.sourceAppsQuery.isFetching),
- createReleaseSourceAppsIsFetchingNextPageAtom: atom(
- () => mocks.sourceAppsQuery.isFetchingNextPage,
- ),
- createReleaseSourceAppsIsLoadingAtom: atom(() => mocks.sourceAppsQuery.isLoading),
- createReleaseSourceAppSearchTextAtom: atom(''),
- createReleaseSourceAppsQueryAtom: atom(mocks.sourceAppsQuery),
- }
-})
-
-function renderSourceAppPicker(disabled: boolean) {
- const queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- })
-
- return render(
-
-
- undefined}
- disabled={disabled}
- />
-
- ,
- )
-}
-
-describe('SourceAppPicker', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mocks.sourceAppsQuery.fetchNextPage.mockReset()
- observers.length = 0
- vi.stubGlobal(
- 'IntersectionObserver',
- class MockIntersectionObserver {
- readonly root = null
- readonly rootMargin = ''
- readonly scrollMargin = ''
- readonly thresholds: ReadonlyArray = []
- readonly disconnect = vi.fn()
- readonly observe = vi.fn()
- readonly takeRecords = () => []
- readonly unobserve = vi.fn()
-
- constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
- observers.push({ callback, options })
- }
- },
- )
- Object.assign(mocks.sourceAppsQuery, {
- data: {
- pages: [
- {
- data: [
- {
- id: 'app-1',
- name: 'Workflow App',
- },
- ],
- },
- ],
- },
- error: null,
- hasNextPage: true,
- isFetching: false,
- isFetchingNextPage: false,
- isLoading: false,
- })
- })
-
- afterEach(() => {
- vi.unstubAllGlobals()
- })
-
- it('should disable the switch control when disabled', () => {
- renderSourceAppPicker(true)
-
- expect(screen.getByText('Workflow 1')).toBeInTheDocument()
- expect(
- screen.getByRole('combobox', { name: 'deployments.versions.sourceAppOption' }),
- ).toBeDisabled()
- })
-
- it('should use infinite scroll to load more apps when the picker is open', async () => {
- const user = userEvent.setup()
-
- renderSourceAppPicker(false)
- expect(getInfiniteScrollObserver()).toBeUndefined()
-
- await user.click(screen.getByRole('combobox', { name: 'deployments.versions.sourceAppOption' }))
-
- await waitFor(() => {
- expect(getInfiniteScrollObserver()).toBeDefined()
- })
- act(() => {
- getInfiniteScrollObserver()?.callback(
- [{ isIntersecting: true } as IntersectionObserverEntry],
- {} as IntersectionObserver,
- )
- })
-
- expect(mocks.sourceAppsQuery.fetchNextPage).toHaveBeenCalledWith({ cancelRefetch: false })
- expect(
- screen.queryByRole('button', { name: /createModal\.loadMoreApps/ }),
- ).not.toBeInTheDocument()
- })
-
- it('should restore the selected app by business identity', async () => {
- const user = userEvent.setup()
-
- renderSourceAppPicker(false)
-
- await user.click(screen.getByRole('combobox', { name: 'deployments.versions.sourceAppOption' }))
-
- expect(screen.getByRole('option', { name: /Workflow App/ })).toHaveAttribute(
- 'aria-selected',
- 'true',
- )
- })
-})
diff --git a/web/features/deployments/create-release/ui/actions.tsx b/web/features/deployments/create-release/ui/actions.tsx
deleted file mode 100644
index 2a8dddd1e30..00000000000
--- a/web/features/deployments/create-release/ui/actions.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-'use client'
-
-import { Button } from '@langgenius/dify-ui/button'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import {
- createReleaseContentReadyAtom,
- createReleaseFormIsSubmittingAtom,
- createReleaseHasNameConflictAtom,
- createReleaseNameFieldAtom,
- isCheckingCreateReleaseContentAtom,
- requestCloseCreateReleaseDialogAtom,
-} from '../state'
-
-export function CreateReleaseActions() {
- const { t } = useTranslation('deployments')
- const requestCloseDialog = useSetAtom(requestCloseCreateReleaseDialogAtom)
- const isSubmitting = useAtomValue(createReleaseFormIsSubmittingAtom)
- const releaseContentReady = useAtomValue(createReleaseContentReadyAtom)
- const isCheckingReleaseContent = useAtomValue(isCheckingCreateReleaseContentAtom)
- const hasReleaseNameConflict = useAtomValue(createReleaseHasNameConflictAtom)
- const releaseNameField = useAtomValue(createReleaseNameFieldAtom)
- const hasReleaseName = Boolean(releaseNameField.value.trim())
-
- return (
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/create-release/ui/content-feedback.tsx b/web/features/deployments/create-release/ui/content-feedback.tsx
deleted file mode 100644
index 66c1d43543b..00000000000
--- a/web/features/deployments/create-release/ui/content-feedback.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-'use client'
-
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { UnsupportedDslNodesAlert } from '../../shared/components/unsupported-dsl-nodes-alert'
-import {
- createReleaseContentCheckFailedAtom,
- createReleaseMatchedReleaseAtom,
- createReleaseUnsupportedDslNodesAtom,
-} from '../state'
-
-export function ReleaseContentFeedback() {
- const { t } = useTranslation('deployments')
- const unsupportedDslNodes = useAtomValue(createReleaseUnsupportedDslNodesAtom)
- const matchedRelease = useAtomValue(createReleaseMatchedReleaseAtom)
- const releaseContentCheckFailed = useAtomValue(createReleaseContentCheckFailedAtom)
-
- return (
- <>
-
-
- {matchedRelease && (
-
- {t(($) => $['versions.releaseAlreadyExists'], { name: matchedRelease.displayName })}
-
- )}
-
- {releaseContentCheckFailed && (
-
- {t(($) => $['versions.releaseContentCheckFailed'])}
-
- )}
- >
- )
-}
diff --git a/web/features/deployments/create-release/ui/dialog.tsx b/web/features/deployments/create-release/ui/dialog.tsx
deleted file mode 100644
index 7e52d7528fd..00000000000
--- a/web/features/deployments/create-release/ui/dialog.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-'use client'
-
-import {
- DialogCloseButton,
- DialogContent,
- DialogDescription,
- DialogTitle,
-} from '@langgenius/dify-ui/dialog'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { useTranslation } from 'react-i18next'
-import { deploymentErrorMessage } from '../../shared/domain/error'
-import {
- closeCreateReleaseDialogAtom,
- createReleaseFormAtom,
- createReleaseFormIsSubmittingAtom,
- CreateReleaseSubmissionBlockedError,
- requestCloseCreateReleaseDialogAtom,
- submitCreateReleaseFormAtom,
-} from '../state'
-import { CreateReleaseActions } from './actions'
-import { ReleaseContentFeedback } from './content-feedback'
-import { ReleaseMetadataFields } from './metadata-fields'
-import { ReleaseSourceSection } from './source-section'
-
-function CreateReleaseCloseButton() {
- const isSubmitting = useAtomValue(createReleaseFormIsSubmittingAtom)
- const requestCloseDialog = useSetAtom(requestCloseCreateReleaseDialogAtom)
-
- return (
- {
- event.preventDefault()
- event.stopPropagation()
- requestCloseDialog()
- }}
- onClick={(event) => {
- event.preventDefault()
- event.stopPropagation()
- requestCloseDialog()
- }}
- />
- )
-}
-
-export function CreateReleaseDialogContent() {
- return (
-
-
-
-
-
- )
-}
-
-function CreateReleaseDialogSurface() {
- const closeDialog = useSetAtom(closeCreateReleaseDialogAtom)
- const submitCreateReleaseForm = useSetAtom(submitCreateReleaseFormAtom)
- const { t } = useTranslation('deployments')
-
- async function handleSubmit() {
- try {
- const response = await submitCreateReleaseForm()
- if (!response) return
-
- toast.success(t(($) => $['versions.createSuccess'], { name: response.release.displayName }))
- closeDialog()
- } catch (error) {
- if (error instanceof CreateReleaseSubmissionBlockedError) {
- toast.error(t(($) => $['versions.dslUnsupportedMode']))
- return
- }
-
- const message = await deploymentErrorMessage(error)
- toast.error(message || t(($) => $['versions.createFailed']))
- }
- }
-
- return (
- <>
-
-
- >
- )
-}
diff --git a/web/features/deployments/create-release/ui/metadata-fields.tsx b/web/features/deployments/create-release/ui/metadata-fields.tsx
deleted file mode 100644
index b6e67935f4e..00000000000
--- a/web/features/deployments/create-release/ui/metadata-fields.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-'use client'
-
-import { cn } from '@langgenius/dify-ui/cn'
-import { Input } from '@langgenius/dify-ui/input'
-import { Textarea } from '@langgenius/dify-ui/textarea'
-import { useAtom, useAtomValue } from 'jotai'
-import { useEffect, useRef } from 'react'
-import { useTranslation } from 'react-i18next'
-import {
- createReleaseDescriptionFieldAtom,
- createReleaseHasNameConflictAtom,
- createReleaseNameFieldAtom,
- RELEASE_NAME_REQUIRED_ERROR,
-} from '../state'
-
-const DESCRIPTION_MAX_LENGTH = 512
-const DESCRIPTION_WARN_THRESHOLD = 460
-
-function isValidationIssue(error: unknown): error is { message: string } {
- return Boolean(
- error && typeof error === 'object' && 'message' in error && typeof error.message === 'string',
- )
-}
-
-function hasReleaseNameRequiredError(errors: unknown[]) {
- return errors.some((error) => {
- if (error === RELEASE_NAME_REQUIRED_ERROR) return true
-
- if (Array.isArray(error))
- return error.some(
- (issue) => isValidationIssue(issue) && issue.message === RELEASE_NAME_REQUIRED_ERROR,
- )
-
- return isValidationIssue(error) && error.message === RELEASE_NAME_REQUIRED_ERROR
- })
-}
-
-export function ReleaseMetadataFields() {
- const { t } = useTranslation('deployments')
- const [releaseNameField, setReleaseNameField] = useAtom(createReleaseNameFieldAtom)
- const [releaseDescriptionField, setReleaseDescriptionField] = useAtom(
- createReleaseDescriptionFieldAtom,
- )
- const hasReleaseNameConflict = useAtomValue(createReleaseHasNameConflictAtom)
- const releaseNameInputRef = useRef(null)
- const releaseNameErrors = releaseNameField.meta?.errors ?? []
- const hasReleaseNameRequired = hasReleaseNameRequiredError(releaseNameErrors)
- const releaseNameError = hasReleaseNameRequired
- ? t(($) => $['versions.releaseNameRequired'])
- : hasReleaseNameConflict
- ? t(($) => $['versions.releaseNameConflict'])
- : ''
-
- useEffect(() => {
- releaseNameInputRef.current?.focus()
- }, [])
-
- return (
- <>
-
-
-
$['versions.releaseNamePlaceholder'])}
- maxLength={128}
- autoComplete="off"
- value={releaseNameField.value}
- aria-invalid={Boolean(releaseNameError) || undefined}
- aria-describedby={releaseNameError ? 'release-name-error' : undefined}
- onChange={(event) => {
- setReleaseNameField(event.target.value)
- }}
- className="h-9"
- />
- {releaseNameError && (
-
- {releaseNameError}
-
- )}
-
-
-
-
-
-
-
- {t(($) => $['versions.optional'])}
-
- = DESCRIPTION_WARN_THRESHOLD
- ? 'text-util-colors-warning-warning-700'
- : 'text-text-quaternary',
- )}
- >
- {releaseDescriptionField.value.length}/{DESCRIPTION_MAX_LENGTH}
-
-
-
-
- >
- )
-}
diff --git a/web/features/deployments/create-release/ui/source-app-picker.tsx b/web/features/deployments/create-release/ui/source-app-picker.tsx
deleted file mode 100644
index d1165cd727d..00000000000
--- a/web/features/deployments/create-release/ui/source-app-picker.tsx
+++ /dev/null
@@ -1,247 +0,0 @@
-'use client'
-import type { AppPartial } from '@dify/contracts/api/console/apps/types.gen'
-import type { SourceAppPickerValue } from '../state'
-import { zIconType } from '@dify/contracts/api/console/apps/zod.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Combobox,
- ComboboxContent,
- ComboboxEmpty,
- ComboboxInput,
- ComboboxInputGroup,
- ComboboxItem,
- ComboboxItemText,
- ComboboxList,
- ComboboxTrigger,
-} from '@langgenius/dify-ui/combobox'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useRef, useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import AppIcon from '@/app/components/base/app-icon'
-import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-sentinel'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import { TitleTooltip } from '../../shared/components/title-tooltip'
-import {
- createReleaseSourceAppsAtom,
- createReleaseSourceAppSearchTextAtom,
- createReleaseSourceAppsErrorAtom,
- createReleaseSourceAppsFetchNextPageAtom,
- createReleaseSourceAppsHasNextPageAtom,
- createReleaseSourceAppsIsFetchingAtom,
- createReleaseSourceAppsIsFetchingNextPageAtom,
- createReleaseSourceAppsIsLoadingAtom,
-} from '../state'
-
-const SOURCE_APP_PICKER_SKELETON_KEYS = [
- 'first-source-app',
- 'second-source-app',
- 'third-source-app',
-]
-
-function sourceAppSearchText(app: AppPartial) {
- return `${app.name} ${app.id}`.toLowerCase()
-}
-
-function isSameApp(app: AppPartial, selectedApp: AppPartial) {
- return app.id === selectedApp.id
-}
-
-function SourceAppTrigger({ app }: { app?: SourceAppPickerValue }) {
- const { t } = useTranslation('deployments')
- const appIconType = zIconType.safeParse(app?.icon_type).data ?? null
-
- return (
-
- {app && (
-
- )}
-
-
- {app?.name ?? t(($) => $['createModal.appPickerPlaceholder'])}
-
-
-
-
- )
-}
-
-function SourceAppOption({ app }: { app: AppPartial }) {
- const appIconType = zIconType.safeParse(app.icon_type).data ?? null
-
- return (
-
-
-
-
-
- {app.name}
- ({app.id.slice(0, 8)})
-
-
-
-
- )
-}
-
-function SourceAppPickerSkeleton() {
- return (
-
- {SOURCE_APP_PICKER_SKELETON_KEYS.map((key) => (
-
-
-
-
- ))}
-
- )
-}
-
-export function SourceAppPicker({
- value,
- onChange,
- disabled = false,
-}: {
- value?: SourceAppPickerValue
- onChange: (app: AppPartial) => void
- disabled?: boolean
-}) {
- const { t } = useTranslation('deployments')
- const [isShow, setIsShow] = useState(false)
- const searchText = useAtomValue(createReleaseSourceAppSearchTextAtom)
- const setSearchText = useSetAtom(createReleaseSourceAppSearchTextAtom)
- const apps = useAtomValue(createReleaseSourceAppsAtom)
- const sourceAppsError = useAtomValue(createReleaseSourceAppsErrorAtom)
- const sourceAppsFetchNextPage = useAtomValue(createReleaseSourceAppsFetchNextPageAtom)
- const sourceAppsHasNextPage = useAtomValue(createReleaseSourceAppsHasNextPageAtom)
- const sourceAppsIsFetching = useAtomValue(createReleaseSourceAppsIsFetchingAtom)
- const sourceAppsIsFetchingNextPage = useAtomValue(createReleaseSourceAppsIsFetchingNextPageAtom)
- const sourceAppsIsLoading = useAtomValue(createReleaseSourceAppsIsLoadingAtom)
- const scrollContainerRef = useRef(null)
- const selectedApp = apps.find((app) => app.id === value?.id) ?? null
- const canLoadMore = isShow && !disabled && !sourceAppsIsFetching && !sourceAppsError
-
- return (
-
- items={apps}
- value={selectedApp}
- open={!disabled && isShow}
- inputValue={searchText}
- isItemEqualToValue={isSameApp}
- onOpenChange={(open) => {
- setIsShow(disabled ? false : open)
- }}
- onInputValueChange={(value) => {
- if (!disabled) setSearchText(value)
- }}
- onValueChange={(app) => {
- if (disabled) return
- if (!app) return
- onChange(app)
- setIsShow(false)
- }}
- itemToStringLabel={(app) => {
- if (!app) return ''
-
- return app.name
- }}
- itemToStringValue={(app) => {
- if (!app) return ''
-
- return app.id
- }}
- filter={(app, query) => sourceAppSearchText(app).includes(query.toLowerCase())}
- disabled={disabled}
- >
- $['versions.sourceAppOption'])}
- icon={false}
- className="block h-auto w-full border-0 bg-transparent p-0 text-left hover:bg-transparent focus-visible:bg-transparent data-open:bg-transparent"
- >
-
-
-
-
-
-
-
- $['createModal.appSearchPlaceholder'])}
- placeholder={t(($) => $['createModal.appSearchPlaceholder'])}
- className="block h-4.5 grow px-1 py-0 text-[13px] text-text-primary"
- />
-
-
-
- {(sourceAppsIsLoading || sourceAppsIsFetchingNextPage) && apps.length === 0 && (
-
- )}
-
className="max-h-none p-0">
- {(app) => }
-
- {!(sourceAppsIsLoading || sourceAppsIsFetchingNextPage) && (
-
{t(($) => $['createModal.appSearchEmpty'])}
- )}
- {sourceAppsIsFetchingNextPage && apps.length > 0 && (
-
- {t(($) => $['createModal.loadingApps'])}
-
- )}
- {sourceAppsHasNextPage && (
-
{
- void sourceAppsFetchNextPage({ cancelRefetch: false })
- }}
- preloadDistance={160}
- scrollContainerRef={scrollContainerRef}
- />
- )}
-
-
-
-
- )
-}
diff --git a/web/features/deployments/create-release/ui/source-section.tsx b/web/features/deployments/create-release/ui/source-section.tsx
deleted file mode 100644
index eacdfc210f9..00000000000
--- a/web/features/deployments/create-release/ui/source-section.tsx
+++ /dev/null
@@ -1,125 +0,0 @@
-'use client'
-
-import type { ReleaseSourceMode } from '../state'
-import { SegmentedControl, SegmentedControlItem } from '@langgenius/dify-ui/segmented-control'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { Uploader } from '@/app/components/app/create-from-dsl-modal/uploader'
-import { isDeploymentDslImportEnabled } from '../../shared/domain/feature-flags'
-import {
- createReleaseDslFileFieldAtom,
- createReleaseDslReadErrorAtom,
- createReleaseHasUnsupportedDslModeAtom,
- createReleaseSelectedSourceAppAtom,
- createReleaseSourceModeAtom,
- isReadingCreateReleaseDslAtom,
- selectCreateReleaseSourceModeAtom,
- updateCreateReleaseDslFileAtom,
- updateCreateReleaseSourceAppAtom,
-} from '../state'
-import { SourceAppPicker } from './source-app-picker'
-
-function selectedReleaseSourceMode(value: readonly ReleaseSourceMode[] | undefined) {
- return value?.[0]
-}
-
-export function ReleaseSourceSection() {
- const { t } = useTranslation('deployments')
- const releaseSourceMode = useAtomValue(createReleaseSourceModeAtom)
- const selectReleaseSourceMode = useSetAtom(selectCreateReleaseSourceModeAtom)
-
- return (
-
-
-
- {isDeploymentDslImportEnabled && (
-
- aria-labelledby="release-source-mode-label"
- value={[releaseSourceMode]}
- onValueChange={(value) => {
- const nextMode = selectedReleaseSourceMode(value)
- if (!nextMode || nextMode === releaseSourceMode) return
-
- selectReleaseSourceMode(nextMode)
- }}
- className="shrink-0"
- >
-
-
- {t(($) => $['versions.sourceAppOption'])}
-
-
-
- {t(($) => $['versions.manualDslOption'])}
-
-
- )}
-
-
-
- {releaseSourceMode === 'sourceApp' ? : }
-
-
- )
-}
-
-function SourceAppField() {
- const sourceApp = useAtomValue(createReleaseSelectedSourceAppAtom)
- const updateSourceApp = useSetAtom(updateCreateReleaseSourceAppAtom)
- const sourceAppLocked = !isDeploymentDslImportEnabled
-
- return (
-
-
-
- )
-}
-
-function DslFileField() {
- const { t } = useTranslation('deployments')
- const dslFileField = useAtomValue(createReleaseDslFileFieldAtom)
- const isReadingDsl = useAtomValue(isReadingCreateReleaseDslAtom)
- const dslReadError = useAtomValue(createReleaseDslReadErrorAtom)
- const updateDslFile = useSetAtom(updateCreateReleaseDslFileAtom)
-
- return (
-
-
{
- void updateDslFile(file)
- }}
- className="mt-0"
- />
- {isReadingDsl && (
-
- {t(($) => $['versions.dslReading'])}
-
- )}
- {dslReadError && (
-
- {t(($) => $['versions.dslReadFailed'])}
-
- )}
-
-
- )
-}
-
-function DslUnsupportedModeError() {
- const { t } = useTranslation('deployments')
- const hasUnsupportedDslMode = useAtomValue(createReleaseHasUnsupportedDslModeAtom)
-
- if (!hasUnsupportedDslMode) return null
-
- return (
-
- {t(($) => $['versions.dslUnsupportedMode'])}
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/README.md b/web/features/deployments/deploy-drawer/README.md
deleted file mode 100644
index 6e21080b393..00000000000
--- a/web/features/deployments/deploy-drawer/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Deploy Drawer
-
-Drawer workflow for choosing a release, selecting an environment, binding runtime credentials, and starting a deployment.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| -------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------------------------ | ------------------------------------------------------------ |
-| `app/components/base/skeleton` | Reuses skeleton primitives for drawer form loading sections. |
diff --git a/web/features/deployments/deploy-drawer/index.tsx b/web/features/deployments/deploy-drawer/index.tsx
deleted file mode 100644
index 38fe39f9a7a..00000000000
--- a/web/features/deployments/deploy-drawer/index.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-'use client'
-
-import {
- Drawer,
- DrawerBackdrop,
- DrawerCloseButton,
- DrawerContent,
- DrawerPopup,
- DrawerPortal,
- DrawerViewport,
-} from '@langgenius/dify-ui/drawer'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import {
- closeDeployDrawerAtom,
- deployDrawerAppInstanceIdAtom,
- deployDrawerEnvironmentIdAtom,
- deployDrawerOpenAtom,
- deployDrawerReleaseIdAtom,
-} from './state'
-import { DeployForm } from './ui/form'
-
-export function DeployDrawer() {
- const { t } = useTranslation('deployments')
- const open = useAtomValue(deployDrawerOpenAtom)
- const drawerAppInstanceId = useAtomValue(deployDrawerAppInstanceIdAtom)
- const drawerEnvironmentId = useAtomValue(deployDrawerEnvironmentIdAtom)
- const drawerReleaseId = useAtomValue(deployDrawerReleaseIdAtom)
- const closeDeployDrawer = useSetAtom(closeDeployDrawerAtom)
- const formKey = `${drawerAppInstanceId ?? 'none'}-${drawerEnvironmentId ?? 'any'}-${drawerReleaseId ?? 'new'}-${open ? '1' : '0'}`
-
- return (
- !next && closeDeployDrawer()}
- >
-
-
-
-
- $['deployDrawer.close'])}
- className="absolute top-4 right-5 size-6 rounded-md"
- />
-
- {!drawerAppInstanceId ? (
- {t(($) => $['deployDrawer.notFound'])}
- ) : (
-
- )}
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/state/__tests__/index.spec.ts b/web/features/deployments/deploy-drawer/state/__tests__/index.spec.ts
deleted file mode 100644
index 93ebb7daaa1..00000000000
--- a/web/features/deployments/deploy-drawer/state/__tests__/index.spec.ts
+++ /dev/null
@@ -1,438 +0,0 @@
-import type {
- CredentialCandidate,
- CredentialSlot,
- Environment,
- EnvironmentDeployment,
- EnvVarSlot,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import type { QueryClient } from '@tanstack/react-query'
-import {
- EnvVarValueSource,
- EnvVarValueType,
- PluginCategory,
- RuntimeInstanceStatus,
-} from '@dify/contracts/enterprise/types.gen'
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type DeploymentOptions = {
- credentialSlots: CredentialSlot[]
- envVarSlots: EnvVarSlot[]
-}
-
-const mockReleaseDeploymentViewQueryOptions = vi.hoisted(() => vi.fn())
-const mockPromoteMutation = vi.hoisted(() => vi.fn())
-const mockRollbackMutation = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- releaseService: {
- computeReleaseDeploymentView: {
- queryOptions: ({ enabled, input }: { enabled: boolean; input: unknown }) => {
- mockReleaseDeploymentViewQueryOptions({ enabled, input })
- return {
- enabled,
- input,
- queryKey: ['computeReleaseDeploymentView', input],
- queryFn: async () => undefined,
- }
- },
- },
- computeDeploymentOptions: {
- queryOptions: ({ enabled, input }: { enabled: boolean; input: unknown }) => ({
- enabled,
- input,
- queryKey: ['computeDeploymentOptions', input],
- queryFn: async () => undefined,
- }),
- },
- },
- deploymentService: {
- promote: {
- mutationOptions: () => ({
- mutationKey: ['promote'],
- mutationFn: mockPromoteMutation,
- }),
- },
- rollback: {
- mutationOptions: () => ({
- mutationKey: ['rollback'],
- mutationFn: mockRollbackMutation,
- }),
- },
- },
- },
- },
-}))
-
-vi.mock('@langgenius/dify-ui/toast', () => ({
- toast: {
- error: vi.fn(),
- },
-}))
-
-vi.mock('../../shared/domain/idempotency', () => ({
- createDeploymentIdempotencyKey: () => 'deploy-idempotency-key',
-}))
-
-async function loadState() {
- return await import('../index')
-}
-
-function environment(overrides: Partial = {}): Environment {
- return {
- id: 'environment-1',
- displayName: 'Production',
- description: '',
- mode: 'ENVIRONMENT_MODE_SHARED',
- backend: 'RUNTIME_BACKEND_K8S',
- status: 'ENVIRONMENT_STATUS_READY',
- statusMessage: '',
- cpuCount: 1,
- createdAt: '2026-01-01T00:00:00.000Z',
- updatedAt: '2026-01-01T00:00:00.000Z',
- ...overrides,
- } as Environment
-}
-
-function release(overrides: Partial = {}): Release {
- return {
- id: 'release-1',
- appInstanceId: 'app-instance-1',
- displayName: 'Release 1',
- description: '',
- sourceAppId: 'source-app-1',
- createdAt: '2026-01-01T00:00:00.000Z',
- updatedAt: '2026-01-01T00:00:00.000Z',
- createdBy: {
- id: 'account-1',
- displayName: 'Owner',
- },
- ...overrides,
- } as Release
-}
-
-function credentialCandidate(overrides: Partial = {}): CredentialCandidate {
- return {
- credentialId: 'credential-1',
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- displayName: 'Primary key',
- fromEnterprise: false,
- ...overrides,
- }
-}
-
-function credentialSlot(overrides: Partial = {}): CredentialSlot {
- return {
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- candidates: [
- credentialCandidate({ credentialId: 'credential-1' }),
- credentialCandidate({ credentialId: 'credential-2', displayName: 'Backup key' }),
- ],
- lastCredentialId: '',
- ...overrides,
- }
-}
-
-function envVarSlot(overrides: Partial = {}): EnvVarSlot {
- return {
- key: 'API_KEY',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_STRING,
- description: '',
- ...overrides,
- }
-}
-
-function runtimeRow(overrides: Partial = {}): EnvironmentDeployment {
- return {
- environment: environment(),
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- currentRelease: release({ id: 'release-1', createdAt: '2026-01-01T00:00:00.000Z' }),
- desiredRelease: release({ id: 'release-1', createdAt: '2026-01-01T00:00:00.000Z' }),
- ...overrides,
- } as EnvironmentDeployment
-}
-
-function deployConfig() {
- return {
- appInstanceId: 'app-instance-1',
- environments: [
- environment({ id: 'environment-1', displayName: 'Production' }),
- environment({ id: 'environment-2', displayName: 'Staging' }),
- ],
- releases: [
- release({ id: 'release-2', displayName: 'Release 2', createdAt: '2026-01-02T00:00:00.000Z' }),
- release({ id: 'release-1', displayName: 'Release 1', createdAt: '2026-01-01T00:00:00.000Z' }),
- ],
- runtimeRows: [runtimeRow()],
- defaultReleaseId: 'release-2',
- }
-}
-
-function setQueryOptions(
- queryClient: QueryClient,
- options: DeploymentOptions,
- releaseId = 'release-2',
- environmentId = 'environment-1',
-) {
- queryClient.setQueryData(
- [
- 'computeDeploymentOptions',
- {
- body: {
- releaseId,
- environmentId,
- },
- },
- ],
- {
- options,
- },
- )
-}
-
-describe('deploy drawer state', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should open and close the deploy drawer with route identity', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.set(state.openDeployDrawerAtom, {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- releaseId: 'release-2',
- })
-
- expect(store.get(state.deployDrawerOpenAtom)).toBe(true)
- expect(store.get(state.deployDrawerAppInstanceIdAtom)).toBe('app-instance-1')
- expect(store.get(state.deployDrawerEnvironmentIdAtom)).toBe('environment-1')
- expect(store.get(state.deployDrawerReleaseIdAtom)).toBe('release-2')
-
- store.set(state.closeDeployDrawerAtom)
-
- expect(store.get(state.deployDrawerOpenAtom)).toBe(false)
- expect(store.get(state.deployDrawerAppInstanceIdAtom)).toBeUndefined()
- expect(store.get(state.deployDrawerEnvironmentIdAtom)).toBeUndefined()
- expect(store.get(state.deployDrawerReleaseIdAtom)).toBeUndefined()
- })
-
- it('should disable release deployment view query with skipToken until form app instance exists', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.releaseDeploymentViewQueryAtom)
- expect(mockReleaseDeploymentViewQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
-
- store.set(state.deployFormAppInstanceIdAtom, 'app-instance-1')
-
- store.get(state.releaseDeploymentViewQueryAtom)
- expect(mockReleaseDeploymentViewQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- })
-
- it('should derive default environment and release selections from config', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
- store.set(state.deployReadyFormConfigAtom, {
- ...deployConfig(),
- lockedEnvId: 'environment-2',
- presetReleaseId: 'release-1',
- releaseEmptyLabel: 'No releases',
- })
-
- expect(store.get(state.deploySelectedEnvironmentIdAtom)).toBe('environment-2')
- expect(store.get(state.deployLockedEnvironmentIdAtom)).toBe('environment-2')
- expect(store.get(state.deployLockedEnvironmentAtom)?.displayName).toBe('Staging')
- expect(store.get(state.deploySelectedReleaseIdAtom)).toBe('release-1')
- expect(store.get(state.deployDisplayedReleaseAtom)?.id).toBe('release-1')
- expect(store.get(state.deployIsExistingReleaseAtom)).toBe(true)
- expect(store.get(state.deployReleaseRowsAtom)).toHaveLength(2)
- expect(store.get(state.deployEnvironmentRowsAtom)).toHaveLength(2)
- expect(store.get(state.deployReleaseEmptyLabelAtom)).toBe('No releases')
- expect(store.get(state.deployHasSelectedEnvironmentAtom)).toBe(true)
- })
-
- it('should reset bindings, env vars, and validation state when target changes', async () => {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- const slot = credentialSlot()
- store.set(state.deployReadyFormConfigAtom, deployConfig())
- setQueryOptions(queryClient, {
- credentialSlots: [slot],
- envVarSlots: [envVarSlot()],
- })
-
- store.set(
- state.selectDeployBindingAtom,
- 'langgenius/openai:PLUGIN_CATEGORY_MODEL',
- 'credential-1',
- )
- store.set(state.setDeployEnvVarAtom, 'API_KEY', {
- value: 'secret',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- })
- store.set(state.showDeployValidationErrorsAtom)
-
- expect(store.get(state.deploySelectedBindingsAtom)).toEqual({
- 'langgenius/openai:PLUGIN_CATEGORY_MODEL': 'credential-1',
- })
- expect(store.get(state.deployEnvVarValuesAtom)).toEqual({
- API_KEY: {
- value: 'secret',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- },
- })
- expect(store.get(state.deployShowValidationErrorsAtom)).toBe(true)
-
- store.set(state.selectDeployEnvironmentAtom, 'environment-2')
-
- expect(store.get(state.deploySelectedEnvironmentIdAtom)).toBe('environment-2')
- expect(store.get(state.deploySelectedBindingsAtom)).toEqual({})
- expect(store.get(state.deployEnvVarValuesAtom)).toEqual({})
- expect(store.get(state.deployShowValidationErrorsAtom)).toBe(false)
-
- store.set(state.selectDeployReleaseAtom, 'release-1')
- expect(store.get(state.deploySelectedReleaseIdAtom)).toBe('release-1')
- })
-
- it('should derive binding and env var readiness from deployment options', async () => {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- const slot = credentialSlot({
- lastCredentialId: 'credential-2',
- })
- store.set(state.deployReadyFormConfigAtom, deployConfig())
- setQueryOptions(queryClient, {
- credentialSlots: [slot],
- envVarSlots: [
- envVarSlot({
- key: 'PORT',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_NUMBER,
- defaultValue: '8080',
- }),
- ],
- })
-
- expect(store.get(state.deployBindingSlotsAtom)).toEqual([slot])
- expect(store.get(state.deployEnvVarSlotsAtom)).toMatchObject([
- {
- key: 'PORT',
- valueType: 'number',
- hasDefaultValue: true,
- hasLastValue: false,
- },
- ])
- expect(store.get(state.deploySelectedBindingsAtom)).toEqual({
- 'langgenius/openai:PLUGIN_CATEGORY_MODEL': 'credential-2',
- })
- expect(store.get(state.canAttemptDeployAtom)).toBe(true)
- expect(store.get(state.canSubmitDeployAtom)).toBe(true)
- })
-
- it('should block submit until required literal env vars are valid', async () => {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- store.set(state.deployReadyFormConfigAtom, deployConfig())
- setQueryOptions(queryClient, {
- credentialSlots: [
- credentialSlot({
- candidates: [credentialCandidate({ credentialId: 'credential-1' })],
- }),
- ],
- envVarSlots: [
- envVarSlot({
- key: 'PORT',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_NUMBER,
- }),
- ],
- })
-
- expect(store.get(state.canAttemptDeployAtom)).toBe(true)
- expect(store.get(state.canSubmitDeployAtom)).toBe(false)
-
- store.set(state.setDeployEnvVarAtom, 'PORT', {
- value: 'abc',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- })
- expect(store.get(state.canSubmitDeployAtom)).toBe(false)
-
- store.set(state.setDeployEnvVarAtom, 'PORT', {
- value: '3000',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- })
- expect(store.get(state.canSubmitDeployAtom)).toBe(true)
- })
-
- it('should submit a promote deployment with selected credentials and env vars', async () => {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- store.set(state.deployReadyFormConfigAtom, deployConfig())
- setQueryOptions(queryClient, {
- credentialSlots: [
- credentialSlot({
- candidates: [credentialCandidate({ credentialId: 'credential-1' })],
- }),
- ],
- envVarSlots: [
- envVarSlot({
- key: 'API_KEY',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_SECRET,
- }),
- ],
- })
- store.set(state.setDeployEnvVarAtom, 'API_KEY', {
- value: 'secret',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- })
-
- store.set(state.deployReleaseSubmissionAtom, {
- deployFailedMessage: 'Deploy failed',
- })
-
- await vi.waitFor(() => {
- expect(mockPromoteMutation).toHaveBeenCalledWith(
- {
- params: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- },
- body: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- releaseId: 'release-2',
- credentials: [
- {
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- credentialId: 'credential-1',
- },
- ],
- envVars: [
- {
- key: 'API_KEY',
- value: 'secret',
- valueSource: EnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- },
- ],
- idempotencyKey: expect.any(String),
- },
- },
- expect.any(Object),
- )
- })
- expect(store.get(state.deployDrawerOpenAtom)).toBe(false)
- })
-})
diff --git a/web/features/deployments/deploy-drawer/state/index.ts b/web/features/deployments/deploy-drawer/state/index.ts
deleted file mode 100644
index 0ad440ba59c..00000000000
--- a/web/features/deployments/deploy-drawer/state/index.ts
+++ /dev/null
@@ -1,521 +0,0 @@
-'use client'
-
-import type {
- Environment,
- EnvironmentDeployment,
- EnvVarInput,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import type { Getter } from 'jotai'
-import type {
- EnvVarBindingSlot,
- EnvVarValues,
- EnvVarValueSelection,
-} from '../../shared/components/env-var-bindings'
-import type { RuntimeCredentialBindingSelections } from '../../shared/components/runtime-credential-bindings-utils'
-import { EnvVarValueSource as ApiEnvVarValueSource } from '@dify/contracts/enterprise/types.gen'
-import { toast } from '@langgenius/dify-ui/toast'
-import { skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { envVarBindingSlotFromContract } from '../../shared/components/env-var-bindings-utils'
-import {
- hasMissingRequiredRuntimeCredentialBinding,
- runtimeCredentialSlotKey,
- selectedDeploymentRuntimeCredentials,
- selectedRuntimeCredentialSelections,
-} from '../../shared/components/runtime-credential-bindings-utils'
-import { createDeploymentIdempotencyKey } from '../../shared/domain/idempotency'
-import { releaseDeploymentAction } from '../../shared/domain/release-action'
-
-type OpenDeployDrawerParams = {
- appInstanceId: string
- environmentId?: string
- releaseId?: string
-}
-
-export const deployDrawerOpenAtom = atom(false)
-export const deployDrawerAppInstanceIdAtom = atom(undefined)
-export const deployDrawerEnvironmentIdAtom = atom(undefined)
-export const deployDrawerReleaseIdAtom = atom(undefined)
-export const deployFormAppInstanceIdAtom = atom(undefined)
-
-export const openDeployDrawerAtom = atom(null, (_get, set, params: OpenDeployDrawerParams) => {
- set(deployDrawerAppInstanceIdAtom, params.appInstanceId)
- set(deployDrawerEnvironmentIdAtom, params.environmentId)
- set(deployDrawerReleaseIdAtom, params.releaseId)
- set(deployDrawerOpenAtom, true)
-})
-
-export const closeDeployDrawerAtom = atom(null, (_get, set) => {
- set(deployDrawerOpenAtom, false)
- set(deployDrawerAppInstanceIdAtom, undefined)
- set(deployDrawerEnvironmentIdAtom, undefined)
- set(deployDrawerReleaseIdAtom, undefined)
-})
-
-export type DeployReadyFormConfig = {
- appInstanceId: string
- environments: Environment[]
- releases: Release[]
- runtimeRows: EnvironmentDeployment[]
- defaultReleaseId?: string
- lockedEnvId?: string
- presetReleaseId?: string
- releaseEmptyLabel?: string
-}
-
-export const deployReadyFormConfigAtom = atom(undefined)
-
-export const releaseDeploymentViewQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deployFormAppInstanceIdAtom)
-
- return consoleQuery.enterprise.releaseService.computeReleaseDeploymentView.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- })
-})
-
-export const releaseDeploymentViewAtom = selectAtom(
- releaseDeploymentViewQueryAtom,
- (query) => query.data,
-)
-export const releaseDeploymentViewIsLoadingAtom = selectAtom(
- releaseDeploymentViewQueryAtom,
- (query) => query.isLoading,
-)
-export const releaseDeploymentViewIsErrorAtom = selectAtom(
- releaseDeploymentViewQueryAtom,
- (query) => query.isError,
-)
-
-const selectedEnvIdAtom = atom(undefined)
-const selectedReleaseIdAtom = atom(undefined)
-const manualBindingsAtom = atom({})
-export const deployEnvVarValuesAtom = atom({})
-const showValidationErrorsAtom = atom(false)
-export const deployReadyFormLocalAtoms = [
- selectedEnvIdAtom,
- selectedReleaseIdAtom,
- manualBindingsAtom,
- deployEnvVarValuesAtom,
- showValidationErrorsAtom,
-] as const
-
-function formConfig(get: Getter) {
- const config = get(deployReadyFormConfigAtom)
- if (!config) throw new Error('Missing deploy ready form config.')
-
- return config
-}
-
-const resetDeployBindingsAtom = atom(null, (_get, set) => {
- set(manualBindingsAtom, {})
- set(deployEnvVarValuesAtom, {})
- set(showValidationErrorsAtom, false)
-})
-
-export const selectDeployEnvironmentAtom = atom(null, (_get, set, environmentId: string) => {
- set(selectedEnvIdAtom, environmentId)
- set(resetDeployBindingsAtom)
-})
-
-export const selectDeployReleaseAtom = atom(null, (_get, set, releaseId: string) => {
- set(selectedReleaseIdAtom, releaseId)
- set(resetDeployBindingsAtom)
-})
-
-export const showDeployValidationErrorsAtom = atom(null, (_get, set) => {
- set(showValidationErrorsAtom, true)
-})
-
-export const deployShowValidationErrorsAtom = atom((get) => {
- return get(showValidationErrorsAtom)
-})
-
-const deployPresetReleaseAtom = atom((get) => {
- const config = formConfig(get)
- return config.presetReleaseId
- ? config.releases.find((r) => r.id === config.presetReleaseId)
- : undefined
-})
-
-export const deployDisplayedReleaseAtom = atom((get): Release | undefined => {
- return get(deployPresetReleaseAtom)
-})
-
-export const deployIsExistingReleaseAtom = atom((get) => {
- const config = formConfig(get)
- return Boolean(config.presetReleaseId)
-})
-
-export const deployReleaseRowsAtom = atom((get) => {
- return formConfig(get).releases
-})
-
-export const deployReleaseEmptyLabelAtom = atom((get) => {
- return formConfig(get).releaseEmptyLabel
-})
-
-export const deployEnvironmentRowsAtom = atom((get) => {
- return formConfig(get).environments
-})
-
-export const deployLockedEnvironmentIdAtom = atom((get) => {
- return formConfig(get).lockedEnvId
-})
-
-export const deploySelectedEnvironmentIdAtom = atom((get) => {
- const config = formConfig(get)
- return get(selectedEnvIdAtom) ?? config.lockedEnvId ?? config.environments[0]?.id
-})
-
-const deploySelectedEnvironmentAtom = atom((get) => {
- const config = formConfig(get)
- const selectedEnvironmentId = get(deploySelectedEnvironmentIdAtom)
- return selectedEnvironmentId
- ? config.environments.find((env) => env.id === selectedEnvironmentId)
- : undefined
-})
-
-export const deploySelectedReleaseIdAtom = atom((get) => {
- const config = formConfig(get)
- const displayedRelease = get(deployDisplayedReleaseAtom)
- return get(selectedReleaseIdAtom) ?? displayedRelease?.id ?? config.defaultReleaseId
-})
-
-const deploySelectedReleaseAtom = atom((get) => {
- const config = formConfig(get)
- const selectedReleaseId = get(deploySelectedReleaseIdAtom)
- return selectedReleaseId
- ? config.releases.find((release) => release.id === selectedReleaseId)
- : undefined
-})
-
-const deployTargetReleaseAtom = atom((get) => {
- return get(deployDisplayedReleaseAtom) ?? get(deploySelectedReleaseAtom)
-})
-
-export const deployLockedEnvironmentAtom = atom((get) => {
- const config = formConfig(get)
- return config.lockedEnvId
- ? config.environments.find((environment) => environment.id === config.lockedEnvId)
- : undefined
-})
-
-export const deployTargetReleaseIdAtom = atom((get) => {
- const targetRelease = get(deployTargetReleaseAtom)
- return targetRelease?.id ?? get(deploySelectedReleaseIdAtom)
-})
-
-export const deployHasSelectedEnvironmentAtom = atom((get) => {
- return Boolean(get(deploySelectedEnvironmentAtom))
-})
-
-const releaseDeploymentOptionsQueryAtom = atomWithQuery((get) => {
- const hasSelectedEnvironment = get(deployHasSelectedEnvironmentAtom)
- const releaseId = get(deployTargetReleaseIdAtom)
- const selectedEnvironmentId = get(deploySelectedEnvironmentIdAtom)
- const hasRequiredInput = Boolean(releaseId && selectedEnvironmentId)
-
- return consoleQuery.enterprise.releaseService.computeDeploymentOptions.queryOptions({
- input:
- releaseId && selectedEnvironmentId
- ? {
- body: {
- releaseId,
- environmentId: selectedEnvironmentId,
- },
- }
- : skipToken,
- enabled: hasRequiredInput && hasSelectedEnvironment,
- retry: false,
- })
-})
-
-const releaseDeploymentOptionsAtom = selectAtom(
- releaseDeploymentOptionsQueryAtom,
- (query) => query.data,
-)
-const releaseDeploymentOptionsIsLoadingAtom = selectAtom(
- releaseDeploymentOptionsQueryAtom,
- (query) => query.isLoading,
-)
-const releaseDeploymentOptionsIsFetchingAtom = selectAtom(
- releaseDeploymentOptionsQueryAtom,
- (query) => query.isFetching,
-)
-const releaseDeploymentOptionsIsErrorAtom = selectAtom(
- releaseDeploymentOptionsQueryAtom,
- (query) => query.isError,
-)
-
-export const deployBindingSlotsAtom = atom((get) => {
- const deploymentOptions = get(releaseDeploymentOptionsAtom)
-
- return (
- deploymentOptions?.options.credentialSlots.filter((slot) => runtimeCredentialSlotKey(slot)) ??
- []
- )
-})
-
-export const deployEnvVarSlotsAtom = atom((get): EnvVarBindingSlot[] => {
- const deploymentOptions = get(releaseDeploymentOptionsAtom)
-
- return (
- deploymentOptions?.options.envVarSlots.flatMap((slot): EnvVarBindingSlot[] => {
- const bindingSlot = envVarBindingSlotFromContract(slot)
- return bindingSlot ? [bindingSlot] : []
- }) ?? []
- )
-})
-
-export const deployIsBindingOptionsLoadingAtom = atom((get) => {
- const releaseId = get(deployTargetReleaseIdAtom)
-
- return Boolean(
- releaseId &&
- get(deployHasSelectedEnvironmentAtom) &&
- (get(releaseDeploymentOptionsIsLoadingAtom) || get(releaseDeploymentOptionsIsFetchingAtom)),
- )
-})
-
-export const deployHasBindingOptionsErrorAtom = atom((get) => {
- return get(releaseDeploymentOptionsIsErrorAtom)
-})
-
-const deployIsBindingOptionsReadyAtom = atom((get) => {
- const releaseId = get(deployTargetReleaseIdAtom)
-
- return Boolean(
- releaseId &&
- get(deployHasSelectedEnvironmentAtom) &&
- get(releaseDeploymentOptionsAtom) &&
- !get(deployIsBindingOptionsLoadingAtom) &&
- !get(deployHasBindingOptionsErrorAtom),
- )
-})
-
-function deployEnvVarValueSource(
- slot: EnvVarBindingSlot,
- selection: EnvVarValueSelection | undefined,
-) {
- return (
- selection?.valueSource ??
- (slot.hasLastValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT
- : slot.hasDefaultValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT
- : ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL)
- )
-}
-
-function deployEnvVarInput(
- slot: EnvVarBindingSlot,
- selection: EnvVarValueSelection | undefined,
-): EnvVarInput[] {
- const valueSource = deployEnvVarValueSource(slot, selection)
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT) {
- return slot.hasLastValue ? [{ key: slot.key, valueSource }] : []
- }
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT) {
- return slot.hasDefaultValue ? [{ key: slot.key, valueSource }] : []
- }
-
- if (!selection?.value || (slot.valueType === 'number' && Number.isNaN(Number(selection.value))))
- return []
-
- return [
- {
- key: slot.key,
- value: selection.value,
- valueSource,
- },
- ]
-}
-
-function deployEnvVarSelectionReady(
- slot: EnvVarBindingSlot,
- selection: EnvVarValueSelection | undefined,
-) {
- const valueSource = deployEnvVarValueSource(slot, selection)
-
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT)
- return Boolean(slot.hasLastValue)
- if (valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT)
- return Boolean(slot.hasDefaultValue)
- if (!selection?.value) return false
-
- return slot.valueType !== 'number' || !Number.isNaN(Number(selection.value))
-}
-
-export const deploySelectedBindingsAtom = atom((get) => {
- return selectedRuntimeCredentialSelections(get(deployBindingSlotsAtom), get(manualBindingsAtom))
-})
-
-const deployDeploymentCredentialsAtom = atom((get) => {
- return selectedDeploymentRuntimeCredentials(
- get(deployBindingSlotsAtom),
- get(deploySelectedBindingsAtom),
- )
-})
-
-const deployDeploymentEnvVarsAtom = atom((get) => {
- const envVarValues = get(deployEnvVarValuesAtom)
-
- return get(deployEnvVarSlotsAtom).flatMap((slot) =>
- deployEnvVarInput(slot, envVarValues[slot.key]),
- )
-})
-
-const deployRequiredBindingsReadyAtom = atom((get) => {
- const selectedBindings = get(deploySelectedBindingsAtom)
-
- return get(deployBindingSlotsAtom).every(
- (slot) =>
- !hasMissingRequiredRuntimeCredentialBinding(
- slot,
- selectedBindings[runtimeCredentialSlotKey(slot)],
- ),
- )
-})
-
-const deployRequiredEnvVarsReadyAtom = atom((get) => {
- const envVarValues = get(deployEnvVarValuesAtom)
-
- return get(deployEnvVarSlotsAtom).every((slot) =>
- deployEnvVarSelectionReady(slot, envVarValues[slot.key]),
- )
-})
-
-export const selectDeployBindingAtom = atom(null, (get, set, slot: string, value: string) => {
- set(manualBindingsAtom, {
- ...get(manualBindingsAtom),
- [slot]: value,
- })
-})
-
-export const setDeployEnvVarAtom = atom(
- null,
- (get, set, key: string, value: EnvVarValueSelection) => {
- set(deployEnvVarValuesAtom, {
- ...get(deployEnvVarValuesAtom),
- [key]: value,
- })
- },
-)
-
-const promoteReleaseMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.deploymentService.promote.mutationOptions(),
-)
-
-const rollbackReleaseMutationAtom = atomWithMutation(() =>
- consoleQuery.enterprise.deploymentService.rollback.mutationOptions(),
-)
-
-export const isDeployReleaseSubmittingAtom = atom((get) => {
- return get(promoteReleaseMutationAtom).isPending || get(rollbackReleaseMutationAtom).isPending
-})
-
-export const canAttemptDeployAtom = atom((get) => {
- return Boolean(
- get(deploySelectedEnvironmentIdAtom) &&
- get(deploySelectedEnvironmentAtom) &&
- get(deployTargetReleaseIdAtom) &&
- get(deployIsBindingOptionsReadyAtom) &&
- !get(isDeployReleaseSubmittingAtom),
- )
-})
-
-export const canSubmitDeployAtom = atom((get) => {
- return Boolean(
- get(canAttemptDeployAtom) &&
- get(deployRequiredBindingsReadyAtom) &&
- get(deployRequiredEnvVarsReadyAtom),
- )
-})
-
-export const deployReleaseSubmissionAtom = atom(
- null,
- (
- get,
- set,
- {
- deployFailedMessage,
- }: {
- deployFailedMessage: string
- },
- ) => {
- const config = formConfig(get)
- const selectedEnvironmentId = get(deploySelectedEnvironmentIdAtom)
- const targetRelease = get(deployTargetReleaseAtom)
- const targetReleaseId = get(deployTargetReleaseIdAtom)
-
- if (!targetReleaseId || !selectedEnvironmentId) return
-
- const idempotencyKey = createDeploymentIdempotencyKey()
- const currentRelease = config.runtimeRows.find(
- (row) => row.environment.id === selectedEnvironmentId,
- )?.currentRelease
- const action = releaseDeploymentAction({
- targetRelease,
- currentRelease,
- releaseRows: config.releases,
- isExistingRelease: true,
- })
- const mutationOptions = {
- onSuccess: () => {
- set(closeDeployDrawerAtom)
- },
- onError: () => {
- toast.error(deployFailedMessage)
- },
- }
-
- if (action === 'rollback') {
- get(rollbackReleaseMutationAtom).mutate(
- {
- params: {
- appInstanceId: config.appInstanceId,
- environmentId: selectedEnvironmentId,
- },
- body: {
- appInstanceId: config.appInstanceId,
- environmentId: selectedEnvironmentId,
- targetReleaseId,
- idempotencyKey,
- },
- },
- mutationOptions,
- )
- return
- }
-
- const deploymentEnvVars = get(deployDeploymentEnvVarsAtom)
- get(promoteReleaseMutationAtom).mutate(
- {
- params: {
- appInstanceId: config.appInstanceId,
- environmentId: selectedEnvironmentId,
- },
- body: {
- appInstanceId: config.appInstanceId,
- environmentId: selectedEnvironmentId,
- releaseId: targetReleaseId,
- credentials: get(deployDeploymentCredentialsAtom),
- envVars: deploymentEnvVars.length > 0 ? deploymentEnvVars : undefined,
- idempotencyKey,
- },
- },
- mutationOptions,
- )
- },
-)
diff --git a/web/features/deployments/deploy-drawer/state/release-options.ts b/web/features/deployments/deploy-drawer/state/release-options.ts
deleted file mode 100644
index ba743eac90b..00000000000
--- a/web/features/deployments/deploy-drawer/state/release-options.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import type { EnvironmentDeployment, Release } from '@dify/contracts/enterprise/types.gen'
-
-export function currentReleaseIdForEnvironment(
- rows: EnvironmentDeployment[],
- targetEnvironmentId?: string,
-) {
- if (!targetEnvironmentId) return undefined
-
- return rows.find((row) => row.environment.id === targetEnvironmentId)?.currentRelease?.id
-}
-
-export function selectableDeployReleases({
- releases,
- lockedEnvId,
- currentReleaseId,
- presetReleaseId,
-}: {
- releases: Release[]
- lockedEnvId?: string
- currentReleaseId?: string
- presetReleaseId?: string
-}) {
- if (!lockedEnvId || presetReleaseId || !currentReleaseId) return releases
-
- return releases.filter((release) => release.id !== currentReleaseId)
-}
diff --git a/web/features/deployments/deploy-drawer/ui/form-sections.tsx b/web/features/deployments/deploy-drawer/ui/form-sections.tsx
deleted file mode 100644
index 5832451e051..00000000000
--- a/web/features/deployments/deploy-drawer/ui/form-sections.tsx
+++ /dev/null
@@ -1,195 +0,0 @@
-'use client'
-
-import type { CredentialSlot, Environment } from '@dify/contracts/enterprise/types.gen'
-import type { RuntimeCredentialBindingSelections } from '../../shared/components/runtime-credential-bindings-utils'
-import { DrawerDescription, DrawerTitle } from '@langgenius/dify-ui/drawer'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonContainer, SkeletonRectangle } from '@/app/components/base/skeleton'
-import { DeploymentStateMessage } from '../../shared/components/empty-state'
-import { RuntimeCredentialBindingsPanel } from '../../shared/components/runtime-credential-bindings'
-import { formatDate, releaseCommit } from '../../shared/domain/release'
-import {
- deployDisplayedReleaseAtom,
- deployEnvironmentRowsAtom,
- deployIsExistingReleaseAtom,
- deployLockedEnvironmentAtom,
- deployLockedEnvironmentIdAtom,
- deployReleaseEmptyLabelAtom,
- deployReleaseRowsAtom,
- deploySelectedEnvironmentIdAtom,
- deploySelectedReleaseIdAtom,
- selectDeployEnvironmentAtom,
- selectDeployReleaseAtom,
-} from '../state'
-import { DeploymentSelect, EnvironmentRow, Field } from './select'
-
-export const DEPLOY_DRAWER_BINDING_LIST_CLASS_NAME = 'max-h-none overflow-visible'
-
-function environmentOptionLabel(
- env: Environment,
- t: ReturnType>['t'],
-) {
- const description = env.description.trim()
- if (description) return `${env.displayName} · ${description}`
-
- return `${env.displayName} · ${t(($) => $[`mode.${env.mode}`])} · ${t(($) => $[`backend.${env.backend}`])}`
-}
-
-export function BindingOptionsPanel({
- slots,
- selections,
- isLoading,
- hasError,
- bindingCountLabel,
- showMissingRequired,
- onChange,
-}: {
- slots: CredentialSlot[]
- selections: RuntimeCredentialBindingSelections
- isLoading: boolean
- hasError: boolean
- bindingCountLabel: string
- showMissingRequired: boolean
- onChange: (slot: string, value: string) => void
-}) {
- const { t } = useTranslation('deployments')
-
- if (isLoading) {
- return (
-
-
-
-
-
-
-
- )
- }
-
- if (hasError) {
- return (
-
- {t(($) => $['deployDrawer.bindingOptionsFailed'])}
-
- )
- }
-
- return (
- $['deployDrawer.runtimeCredentials'])}
- hint={t(($) => $['deployDrawer.bindingSelectionHint'])}
- noBindingRequiredLabel={t(($) => $['deployDrawer.noBindingRequired'])}
- noCredentialCandidatesLabel={t(($) => $['deployDrawer.noCredentialCandidates'])}
- selectCredentialLabel={t(($) => $['deployDrawer.selectCredential'])}
- missingRequiredLabel={t(($) => $['deployDrawer.missingRequiredBinding'])}
- bindingCountLabel={bindingCountLabel}
- showMissingRequired={showMissingRequired}
- listClassName={DEPLOY_DRAWER_BINDING_LIST_CLASS_NAME}
- onChange={onChange}
- />
- )
-}
-
-export function DeployFormHeader() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['deployDrawer.title'])}
-
-
- {t(($) => $['deployDrawer.description'])}
-
-
- )
-}
-
-export function ReleaseField() {
- const { t } = useTranslation('deployments')
- const displayedRelease = useAtomValue(deployDisplayedReleaseAtom)
- const emptyLabel = useAtomValue(deployReleaseEmptyLabelAtom)
- const isExistingRelease = useAtomValue(deployIsExistingReleaseAtom)
- const releases = useAtomValue(deployReleaseRowsAtom)
- const selectedReleaseId = useAtomValue(deploySelectedReleaseIdAtom)
- const selectRelease = useSetAtom(selectDeployReleaseAtom)
-
- return (
- $['deployDrawer.releaseLabel'])}>
- {isExistingRelease && displayedRelease ? (
-
-
-
-
- {displayedRelease.displayName}
-
- ·
-
- {releaseCommit(displayedRelease)}
-
-
-
- {formatDate(displayedRelease.createdAt)}
-
-
-
- {t(($) => $['deployDrawer.existingReleaseHint'])}
-
-
- ) : releases.length === 0 ? (
-
- {emptyLabel ?? t(($) => $['deployDrawer.noReleaseAvailable'])}
-
- ) : (
- ({
- value: release.id,
- label: `${release.displayName} · ${releaseCommit(release)}`,
- }))}
- ariaLabel={t(($) => $['deployDrawer.releaseLabel'])}
- placeholder={t(($) => $['deployDrawer.selectRelease'])}
- />
- )}
-
- )
-}
-
-export function EnvironmentField() {
- const { t } = useTranslation('deployments')
- const environments = useAtomValue(deployEnvironmentRowsAtom)
- const lockedEnv = useAtomValue(deployLockedEnvironmentAtom)
- const lockedEnvId = useAtomValue(deployLockedEnvironmentIdAtom)
- const selectedEnvironmentId = useAtomValue(deploySelectedEnvironmentIdAtom)
- const selectEnvironment = useSetAtom(selectDeployEnvironmentAtom)
-
- return (
- $['deployDrawer.targetEnv'])}
- hint={lockedEnvId ? t(($) => $['deployDrawer.lockedHint']) : undefined}
- >
- {lockedEnv ? (
-
- ) : environments.length === 0 ? (
-
- {t(($) => $['deployDrawer.noNewEnvironmentAvailable'])}
-
- ) : (
- ({
- value: env.id,
- label: environmentOptionLabel(env, t),
- }))}
- ariaLabel={t(($) => $['deployDrawer.targetEnv'])}
- placeholder={t(($) => $['deployDrawer.selectEnv'])}
- />
- )}
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/ui/form-skeleton.tsx b/web/features/deployments/deploy-drawer/ui/form-skeleton.tsx
deleted file mode 100644
index 722b06b4fd5..00000000000
--- a/web/features/deployments/deploy-drawer/ui/form-skeleton.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-'use client'
-
-import { SkeletonContainer, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-
-const DEPLOY_FORM_FIELD_SKELETON_KEYS = ['environment', 'release']
-
-export function DeployFormSkeleton() {
- return (
-
-
-
-
-
-
-
-
-
-
- {DEPLOY_FORM_FIELD_SKELETON_KEYS.map((key) => (
-
-
-
-
- ))}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/ui/form.tsx b/web/features/deployments/deploy-drawer/ui/form.tsx
deleted file mode 100644
index 18af453bb98..00000000000
--- a/web/features/deployments/deploy-drawer/ui/form.tsx
+++ /dev/null
@@ -1,285 +0,0 @@
-'use client'
-
-import type {
- Environment,
- EnvironmentDeployment,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { useTranslation } from 'react-i18next'
-import { EnvVarBindingsPanel } from '../../shared/components/env-var-bindings'
-import { isAvailableDeploymentTarget } from '../../shared/domain/runtime-status'
-import {
- canAttemptDeployAtom,
- canSubmitDeployAtom,
- closeDeployDrawerAtom,
- deployBindingSlotsAtom,
- deployEnvVarSlotsAtom,
- deployEnvVarValuesAtom,
- deployFormAppInstanceIdAtom,
- deployHasBindingOptionsErrorAtom,
- deployHasSelectedEnvironmentAtom,
- deployIsBindingOptionsLoadingAtom,
- deployReadyFormConfigAtom,
- deployReadyFormLocalAtoms,
- deployReleaseSubmissionAtom,
- deploySelectedBindingsAtom,
- deployShowValidationErrorsAtom,
- deployTargetReleaseIdAtom,
- isDeployReleaseSubmittingAtom,
- releaseDeploymentViewAtom,
- releaseDeploymentViewIsErrorAtom,
- releaseDeploymentViewIsLoadingAtom,
- selectDeployBindingAtom,
- setDeployEnvVarAtom,
- showDeployValidationErrorsAtom,
-} from '../state'
-import { currentReleaseIdForEnvironment, selectableDeployReleases } from '../state/release-options'
-import {
- BindingOptionsPanel,
- DEPLOY_DRAWER_BINDING_LIST_CLASS_NAME,
- DeployFormHeader,
- EnvironmentField,
- ReleaseField,
-} from './form-sections'
-import { DeployFormSkeleton } from './form-skeleton'
-
-type DeployFormProps = {
- appInstanceId: string
- lockedEnvId?: string
- presetReleaseId?: string
-}
-
-type DeployReadyFormProps = DeployFormProps & {
- environments: Environment[]
- releases: Release[]
- runtimeRows: EnvironmentDeployment[]
- defaultReleaseId?: string
- releaseEmptyLabel?: string
-}
-
-function DeployRuntimeCredentialBindingsSection() {
- const { t } = useTranslation('deployments')
- const bindingSlots = useAtomValue(deployBindingSlotsAtom)
- const selectedBindings = useAtomValue(deploySelectedBindingsAtom)
- const isBindingOptionsLoading = useAtomValue(deployIsBindingOptionsLoadingAtom)
- const hasBindingOptionsError = useAtomValue(deployHasBindingOptionsErrorAtom)
- const showValidationErrors = useAtomValue(deployShowValidationErrorsAtom)
- const selectBinding = useSetAtom(selectDeployBindingAtom)
-
- return (
- $['deployDrawer.bindingCount'], { count: bindingSlots.length })}
- showMissingRequired={showValidationErrors}
- onChange={selectBinding}
- />
- )
-}
-
-function DeployEnvVarBindingsSection() {
- const { t } = useTranslation('deployments')
- const envVarSlots = useAtomValue(deployEnvVarSlotsAtom)
- const envVarValues = useAtomValue(deployEnvVarValuesAtom)
- const isBindingOptionsLoading = useAtomValue(deployIsBindingOptionsLoadingAtom)
- const hasBindingOptionsError = useAtomValue(deployHasBindingOptionsErrorAtom)
- const showValidationErrors = useAtomValue(deployShowValidationErrorsAtom)
- const setDeployEnvVar = useSetAtom(setDeployEnvVarAtom)
-
- if (isBindingOptionsLoading || hasBindingOptionsError) return null
-
- return (
- $['deployDrawer.envVars'])}
- hint={t(($) => $['deployDrawer.envVarHint'])}
- envVarPlaceholder={t(($) => $['deployDrawer.envVarPlaceholder'])}
- literalSourceLabel={t(($) => $['deployDrawer.envVarSource.literal'])}
- defaultSourceLabel={t(($) => $['deployDrawer.envVarSource.default'])}
- lastDeploymentSourceLabel={t(($) => $['deployDrawer.envVarSource.lastDeployment'])}
- valueTypeLabels={{
- string: t(($) => $['deployDrawer.envVarType.string']),
- number: t(($) => $['deployDrawer.envVarType.number']),
- secret: t(($) => $['deployDrawer.envVarType.secret']),
- }}
- sourceAriaLabel={(key) => t(($) => $['deployDrawer.envVarSource.ariaLabel'], { key })}
- defaultSourcePriority="lastDeployment"
- envVarCountLabel={t(($) => $['deployDrawer.envVarCount'], { count: envVarSlots.length })}
- missingRequiredLabel={t(($) => $['deployDrawer.missingRequiredEnvVar'])}
- listClassName={DEPLOY_DRAWER_BINDING_LIST_CLASS_NAME}
- showMissingRequired={showValidationErrors}
- onChange={setDeployEnvVar}
- />
- )
-}
-
-function DeployBindingsSection() {
- const targetReleaseId = useAtomValue(deployTargetReleaseIdAtom)
- const hasSelectedEnvironment = useAtomValue(deployHasSelectedEnvironmentAtom)
-
- if (!targetReleaseId || !hasSelectedEnvironment) return null
-
- return (
- <>
-
-
- >
- )
-}
-
-function DeployFormBody() {
- return (
-
- )
-}
-
-function DeployFooter() {
- const { t } = useTranslation('deployments')
- const closeDeployDrawer = useSetAtom(closeDeployDrawerAtom)
- const showValidationErrors = useSetAtom(showDeployValidationErrorsAtom)
- const submitDeployRelease = useSetAtom(deployReleaseSubmissionAtom)
- const canAttemptDeploy = useAtomValue(canAttemptDeployAtom)
- const canDeploy = useAtomValue(canSubmitDeployAtom)
- const isSubmitting = useAtomValue(isDeployReleaseSubmittingAtom)
- const submitLabel = isSubmitting
- ? t(($) => $['deployDrawer.deploying'])
- : t(($) => $['deployDrawer.deploy'])
-
- function handleDeploy() {
- showValidationErrors()
-
- if (!canDeploy) return
-
- submitDeployRelease({
- deployFailedMessage: t(($) => $['deployDrawer.deployFailed']),
- })
- }
-
- return (
-
-
-
-
- )
-}
-
-function deployReadyFormStoreKey({
- appInstanceId,
- environments,
- releases,
- runtimeRows,
- defaultReleaseId,
- lockedEnvId,
- presetReleaseId,
-}: DeployReadyFormProps) {
- return [
- appInstanceId,
- lockedEnvId ?? 'any',
- presetReleaseId ?? 'new',
- defaultReleaseId ?? 'none',
- environments.map((env) => env.id).join(','),
- releases.map((release) => release.id).join(','),
- runtimeRows.map((row) => `${row.environment.id}:${row.currentRelease?.id ?? 'none'}`).join(','),
- ].join('|')
-}
-
-function DeployReadyForm(config: DeployReadyFormProps) {
- return (
-
-
-
-
-
-
-
- )
-}
-
-function DeployFormContent({ appInstanceId, lockedEnvId, presetReleaseId }: DeployFormProps) {
- const { t } = useTranslation('deployments')
- const deploymentView = useAtomValue(releaseDeploymentViewAtom)
- const isLoading = useAtomValue(releaseDeploymentViewIsLoadingAtom)
- const isError = useAtomValue(releaseDeploymentViewIsErrorAtom)
-
- if (isLoading) {
- return
- }
-
- if (isError) {
- return (
-
- {t(($) => $['common.loadFailed'])}
-
- )
- }
-
- if (!deploymentView) {
- return (
-
- {t(($) => $['common.loadFailed'])}
-
- )
- }
-
- const runtimeRows = deploymentView.environmentDeployments
- const environments = runtimeRows
- .filter((row) => lockedEnvId || isAvailableDeploymentTarget(row))
- .map((row) => row.environment)
- const releaseRows = deploymentView.releases
- const currentReleaseId = currentReleaseIdForEnvironment(runtimeRows, lockedEnvId)
- const releases = selectableDeployReleases({
- releases: releaseRows,
- lockedEnvId,
- currentReleaseId,
- presetReleaseId,
- })
- const defaultReleaseId = releases[0]?.id
- const releaseEmptyLabel =
- lockedEnvId && !presetReleaseId && currentReleaseId
- ? t(($) => $['deployDrawer.noOtherReleaseAvailable'])
- : undefined
- const readyFormConfig = {
- appInstanceId,
- environments,
- releases,
- runtimeRows,
- defaultReleaseId,
- releaseEmptyLabel,
- lockedEnvId,
- presetReleaseId,
- }
- const formKey = deployReadyFormStoreKey(readyFormConfig)
-
- return
-}
-
-export function DeployForm(props: DeployFormProps) {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/ui/select.tsx b/web/features/deployments/deploy-drawer/ui/select.tsx
deleted file mode 100644
index 65e4e2f8f2c..00000000000
--- a/web/features/deployments/deploy-drawer/ui/select.tsx
+++ /dev/null
@@ -1,145 +0,0 @@
-'use client'
-
-import type { Environment, EnvironmentStatus } from '@dify/contracts/enterprise/types.gen'
-import { EnvironmentStatus as EnvironmentStatusEnum } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectItemIndicator,
- SelectItemText,
- SelectTrigger,
-} from '@langgenius/dify-ui/select'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
-import { useTranslation } from 'react-i18next'
-import { TitleTooltip } from '../../shared/components/title-tooltip'
-import { ModeBadge } from './status-badge'
-
-export function Field({
- label,
- hint,
- children,
-}: {
- label: string
- hint?: string
- children: React.ReactNode
-}) {
- return (
-
-
-
{label}
- {hint &&
{hint}}
-
- {children}
-
- )
-}
-
-type SelectOption = {
- value?: string
- label: string
- disabled?: boolean
- disabledReason?: string
-}
-
-type SelectProps = {
- value?: string
- onChange: (value: string) => void
- options: SelectOption[]
- ariaLabel?: string
- placeholder?: string
-}
-
-export function DeploymentSelect({
- value,
- onChange,
- options,
- ariaLabel,
- placeholder,
-}: SelectProps) {
- const { t } = useTranslation('deployments')
- const selectedOption = options.find((option) => option.value === value)
-
- return (
-
- )
-}
-
-function EnvironmentHealthDot({ status }: { status: EnvironmentStatus }) {
- const { t } = useTranslation('deployments')
- const label = t(($) => $[`health.${status}`])
- const isReady = status === EnvironmentStatusEnum.ENVIRONMENT_STATUS_READY
-
- return (
-
-
-
-
- }
- />
- {label}
-
- )
-}
-
-export function EnvironmentRow({ env }: { env: Environment }) {
- const { t } = useTranslation('deployments')
- const summary = env.description.trim() || t(($) => $[`backend.${env.backend}`])
-
- return (
-
-
-
-
- {env.displayName}
-
-
-
{summary}
-
-
- )
-}
diff --git a/web/features/deployments/deploy-drawer/ui/status-badge.tsx b/web/features/deployments/deploy-drawer/ui/status-badge.tsx
deleted file mode 100644
index 3a7a898ce94..00000000000
--- a/web/features/deployments/deploy-drawer/ui/status-badge.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-'use client'
-import type { EnvironmentMode } from '@dify/contracts/enterprise/types.gen'
-import { EnvironmentMode as EnvironmentModeEnum } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useTranslation } from 'react-i18next'
-
-const baseBadge =
- 'inline-flex items-center gap-1 rounded-md border px-2 py-0.5 system-xs-medium whitespace-nowrap'
-
-export function ModeBadge({ mode, className }: { mode: EnvironmentMode; className?: string }) {
- const { t } = useTranslation('deployments')
- const style =
- mode === EnvironmentModeEnum.ENVIRONMENT_MODE_SHARED
- ? 'border-util-colors-green-green-200 bg-util-colors-green-green-50 text-util-colors-green-green-700'
- : 'border-util-colors-blue-blue-200 bg-util-colors-blue-blue-50 text-util-colors-blue-blue-700'
- return {t(($) => $[`mode.${mode}`])}
-}
diff --git a/web/features/deployments/deployment-actions/README.md b/web/features/deployments/deployment-actions/README.md
deleted file mode 100644
index 97b2f518cf9..00000000000
--- a/web/features/deployments/deployment-actions/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Deployment Actions
-
-Action menu and edit/delete dialogs for deployment app instances.
-
-## Internal Modules
-
-None.
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/deployment-actions/__tests__/delete-dialog.spec.tsx b/web/features/deployments/deployment-actions/__tests__/delete-dialog.spec.tsx
deleted file mode 100644
index 0a7ad1d0543..00000000000
--- a/web/features/deployments/deployment-actions/__tests__/delete-dialog.spec.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import type { DeploymentActionAppInstance } from '../types'
-import { render, screen } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { ScopeProvider } from 'jotai-scope'
-import { DeleteDeploymentDialog } from '../delete-dialog'
-import { deleteDeploymentDialogOpenAtom, deploymentActionAppInstanceAtom } from '../state'
-
-const deleteMutationMock = vi.hoisted(() => ({
- isPending: false,
- mutate: vi.fn(),
-}))
-
-const useMutationMock = vi.hoisted(() =>
- vi.fn(() => ({
- isPending: deleteMutationMock.isPending,
- mutate: deleteMutationMock.mutate,
- })),
-)
-
-const routerMock = vi.hoisted(() => ({
- push: vi.fn(),
-}))
-
-const toastMock = vi.hoisted(() => ({
- error: vi.fn(),
- success: vi.fn(),
-}))
-
-vi.mock('@tanstack/react-query', () => ({
- useMutation: useMutationMock,
-}))
-
-vi.mock('@langgenius/dify-ui/toast', () => ({
- toast: toastMock,
-}))
-
-vi.mock('@/next/navigation', () => ({
- useRouter: () => routerMock,
-}))
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appInstanceService: {
- deleteAppInstance: {
- mutationOptions: () => ({ mutationKey: ['deleteAppInstance'] }),
- },
- },
- },
- },
-}))
-
-function createAppInstance(
- overrides: Partial = {},
-): DeploymentActionAppInstance {
- return {
- id: 'app-instance-1',
- displayName: 'Deployment 1',
- description: 'Initial description',
- ...overrides,
- }
-}
-
-function renderDialog({
- appInstance = createAppInstance(),
- open = true,
-}: {
- appInstance?: DeploymentActionAppInstance
- open?: boolean
-} = {}) {
- render(
-
-
- ,
- )
-}
-
-describe('DeleteDeploymentDialog', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- deleteMutationMock.isPending = false
- })
-
- describe('Delete action', () => {
- it('should not mount the delete mutation before the dialog is opened', () => {
- renderDialog({ open: false })
-
- expect(useMutationMock).not.toHaveBeenCalled()
- })
-
- it('should delete the deployment through the component mutation', async () => {
- const user = userEvent.setup()
- renderDialog()
-
- await user.click(screen.getByRole('button', { name: 'deployments.settings.delete' }))
-
- expect(deleteMutationMock.mutate).toHaveBeenCalledWith(
- {
- params: {
- appInstanceId: 'app-instance-1',
- },
- },
- expect.objectContaining({
- onSuccess: expect.any(Function),
- onError: expect.any(Function),
- onSettled: expect.any(Function),
- }),
- )
- })
- })
-})
diff --git a/web/features/deployments/deployment-actions/__tests__/edit-dialog.spec.tsx b/web/features/deployments/deployment-actions/__tests__/edit-dialog.spec.tsx
deleted file mode 100644
index 3303764feb9..00000000000
--- a/web/features/deployments/deployment-actions/__tests__/edit-dialog.spec.tsx
+++ /dev/null
@@ -1,138 +0,0 @@
-import type { DeploymentActionAppInstance } from '../types'
-import { render, screen, within } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { ScopeProvider } from 'jotai-scope'
-import { EditDeploymentDialog } from '../edit-dialog'
-import { deploymentActionAppInstanceAtom, editDeploymentDialogOpenAtom } from '../state'
-
-const updateMutationMock = vi.hoisted(() => ({
- isPending: false,
- mutate: vi.fn(),
-}))
-
-const useMutationMock = vi.hoisted(() =>
- vi.fn(() => ({
- isPending: updateMutationMock.isPending,
- mutate: updateMutationMock.mutate,
- })),
-)
-
-const toastMock = vi.hoisted(() => ({
- error: vi.fn(),
- success: vi.fn(),
-}))
-
-vi.mock('@tanstack/react-query', () => ({
- useMutation: useMutationMock,
-}))
-
-vi.mock('@langgenius/dify-ui/toast', () => ({
- toast: toastMock,
-}))
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appInstanceService: {
- updateAppInstance: {
- mutationOptions: () => ({ mutationKey: ['updateAppInstance'] }),
- },
- },
- },
- },
-}))
-
-function createAppInstance(
- overrides: Partial = {},
-): DeploymentActionAppInstance {
- return {
- id: 'app-instance-1',
- displayName: 'Deployment 1',
- description: 'Initial description',
- ...overrides,
- }
-}
-
-function renderDialog({
- appInstance = createAppInstance(),
- open = true,
-}: {
- appInstance?: DeploymentActionAppInstance
- open?: boolean
-} = {}) {
- render(
-
-
- ,
- )
-}
-
-describe('EditDeploymentDialog', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- updateMutationMock.isPending = false
- })
-
- describe('Form submission', () => {
- it('should not mount the update mutation before the dialog is opened', () => {
- renderDialog({ open: false })
-
- expect(useMutationMock).not.toHaveBeenCalled()
- })
-
- it('should render form values from the passed app instance', () => {
- renderDialog()
-
- const dialog = screen.getByRole('dialog', { name: 'deployments.card.menu.editInfo' })
- expect(
- within(dialog).getByRole('textbox', { name: 'deployments.settings.name' }),
- ).toHaveValue('Deployment 1')
- expect(
- within(dialog).getByRole('textbox', { name: 'deployments.settings.description' }),
- ).toHaveValue('Initial description')
- })
-
- it('should submit trimmed deployment metadata through the component mutation', async () => {
- const user = userEvent.setup()
- renderDialog()
-
- const dialog = screen.getByRole('dialog', { name: 'deployments.card.menu.editInfo' })
- await user.clear(within(dialog).getByRole('textbox', { name: 'deployments.settings.name' }))
- await user.type(
- within(dialog).getByRole('textbox', { name: 'deployments.settings.name' }),
- ' Deployment 2 ',
- )
- await user.clear(
- within(dialog).getByRole('textbox', { name: 'deployments.settings.description' }),
- )
- await user.type(
- within(dialog).getByRole('textbox', { name: 'deployments.settings.description' }),
- ' Updated description ',
- )
- await user.click(within(dialog).getByRole('button', { name: 'deployments.settings.save' }))
-
- expect(updateMutationMock.mutate).toHaveBeenCalledWith(
- {
- params: {
- appInstanceId: 'app-instance-1',
- },
- body: {
- appInstanceId: 'app-instance-1',
- displayName: 'Deployment 2',
- description: 'Updated description',
- },
- },
- expect.objectContaining({
- onSuccess: expect.any(Function),
- onError: expect.any(Function),
- }),
- )
- })
- })
-})
diff --git a/web/features/deployments/deployment-actions/delete-dialog.tsx b/web/features/deployments/deployment-actions/delete-dialog.tsx
deleted file mode 100644
index 47a2cdc569b..00000000000
--- a/web/features/deployments/deployment-actions/delete-dialog.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-'use client'
-
-import {
- AlertDialog,
- AlertDialogActions,
- AlertDialogCancelButton,
- AlertDialogConfirmButton,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogTitle,
-} from '@langgenius/dify-ui/alert-dialog'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useAtom, useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
-import { deleteDeploymentDialogOpenAtom, deploymentActionAppInstanceAtom } from './state'
-
-function DeleteDeploymentDialogContent() {
- const { t } = useTranslation('deployments')
- const router = useRouter()
- const appInstance = useAtomValue(deploymentActionAppInstanceAtom)
- const setOpen = useSetAtom(deleteDeploymentDialogOpenAtom)
- const deleteInstance = useMutation(
- consoleQuery.enterprise.appInstanceService.deleteAppInstance.mutationOptions(),
- )
- const displayName = appInstance.displayName || appInstance.id
-
- function handleDelete() {
- deleteInstance.mutate(
- {
- params: {
- appInstanceId: appInstance.id,
- },
- },
- {
- onSuccess: () => {
- toast.success(t(($) => $['settings.deleted']))
- router.push('/deployments')
- },
- onError: () => {
- toast.error(t(($) => $['settings.deleteFailed']))
- },
- onSettled: () => {
- setOpen(false)
- },
- },
- )
- }
-
- return (
- <>
-
-
- {t(($) => $['settings.deleteConfirmTitle'])}
-
-
- {t(($) => $['settings.deleteConfirmDesc'], { name: displayName })}
-
-
-
-
- {t(($) => $['createModal.cancel'])}
-
-
- {t(($) => $['settings.delete'])}
-
-
- >
- )
-}
-
-export function DeleteDeploymentDialog() {
- const [open, setOpen] = useAtom(deleteDeploymentDialogOpenAtom)
-
- return (
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/deployment-actions/edit-dialog.tsx b/web/features/deployments/deployment-actions/edit-dialog.tsx
deleted file mode 100644
index fec78827ef8..00000000000
--- a/web/features/deployments/deployment-actions/edit-dialog.tsx
+++ /dev/null
@@ -1,160 +0,0 @@
-'use client'
-
-import { Button } from '@langgenius/dify-ui/button'
-import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
-import { Field, FieldControl, FieldError, FieldLabel } from '@langgenius/dify-ui/field'
-import { Form } from '@langgenius/dify-ui/form'
-import { Textarea } from '@langgenius/dify-ui/textarea'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useAtom, useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { deploymentActionAppInstanceAtom, editDeploymentDialogOpenAtom } from './state'
-
-type EditDeploymentFormValues = {
- name: string
- description: string
-}
-
-function normalizedEditDeploymentFormValues(value: EditDeploymentFormValues) {
- return {
- name: value.name.trim(),
- description: value.description.trim(),
- }
-}
-
-function canSubmitEditDeploymentForm(
- initialValues: EditDeploymentFormValues,
- value: EditDeploymentFormValues,
-) {
- const normalizedValues = normalizedEditDeploymentFormValues(value)
-
- return Boolean(
- normalizedValues.name &&
- (normalizedValues.name !== initialValues.name ||
- normalizedValues.description !== initialValues.description),
- )
-}
-
-function EditDeploymentForm() {
- const { t } = useTranslation('deployments')
- const nameLabel = t(($) => $['settings.name'])
- const appInstance = useAtomValue(deploymentActionAppInstanceAtom)
- const appInstanceId = appInstance.id
- const initialValues = {
- name: appInstance.displayName,
- description: appInstance.description,
- }
- const setOpen = useSetAtom(editDeploymentDialogOpenAtom)
- const updateInstance = useMutation(
- consoleQuery.enterprise.appInstanceService.updateAppInstance.mutationOptions(),
- )
-
- function handleClose() {
- if (updateInstance.isPending) return
-
- setOpen(false)
- }
-
- function handleSubmit(values: EditDeploymentFormValues) {
- if (!canSubmitEditDeploymentForm(initialValues, values)) return
-
- const normalizedValues = normalizedEditDeploymentFormValues(values)
-
- updateInstance.mutate(
- {
- params: {
- appInstanceId,
- },
- body: {
- appInstanceId,
- displayName: normalizedValues.name,
- description: normalizedValues.description,
- },
- },
- {
- onSuccess: () => {
- toast.success(t(($) => $['settings.updated']))
- setOpen(false)
- },
- onError: () => {
- toast.error(t(($) => $['settings.updateFailed']))
- },
- },
- )
- }
-
- return (
- <>
-
-
- >
- )
-}
-
-function EditDeploymentDialogContent() {
- const { t } = useTranslation('deployments')
- const appInstance = useAtomValue(deploymentActionAppInstanceAtom)
-
- return (
- <>
-
-
- {t(($) => $['card.menu.editInfo'])}
-
-
-
-
-
- >
- )
-}
-
-export function EditDeploymentDialog() {
- const [open, setOpen] = useAtom(editDeploymentDialogOpenAtom)
-
- return (
-
- )
-}
diff --git a/web/features/deployments/deployment-actions/index.tsx b/web/features/deployments/deployment-actions/index.tsx
deleted file mode 100644
index c4d118e160f..00000000000
--- a/web/features/deployments/deployment-actions/index.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-'use client'
-
-import type { DropdownMenuContentProps } from '@langgenius/dify-ui/dropdown-menu'
-import type { DeploymentActionAppInstance } from './types'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuSeparator,
- DropdownMenuTrigger,
-} from '@langgenius/dify-ui/dropdown-menu'
-import { useSetAtom } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { useTranslation } from 'react-i18next'
-import { DeleteDeploymentDialog } from './delete-dialog'
-import { EditDeploymentDialog } from './edit-dialog'
-import {
- deploymentActionAppInstanceAtom,
- deploymentActionsLocalAtoms,
- openDeleteDeploymentDialogAtom,
- openEditDeploymentDialogAtom,
-} from './state'
-
-const ACTION_TRIGGER_CLASS_NAME = cn(
- 'inline-flex size-8 items-center justify-center rounded-lg bg-components-panel-bg text-text-tertiary shadow-xs outline-hidden',
- 'hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid',
- 'data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary',
-)
-
-type DeploymentActionsMenuProps = {
- appInstance: DeploymentActionAppInstance
- className?: string
- triggerClassName?: string
- placement: DropdownMenuContentProps['placement']
- sideOffset?: DropdownMenuContentProps['sideOffset']
-}
-
-function DeploymentActionsMenuContent({
- className,
- triggerClassName,
- placement,
- sideOffset,
-}: Omit) {
- const { t } = useTranslation('deployments')
- const openEditDialog = useSetAtom(openEditDeploymentDialogAtom)
- const openDeleteDialog = useSetAtom(openDeleteDeploymentDialogAtom)
-
- return (
- event.stopPropagation()}
- onKeyDown={(event) => event.stopPropagation()}
- >
-
- $['card.moreActions'])}
- className={cn(ACTION_TRIGGER_CLASS_NAME, triggerClassName)}
- >
-
-
-
-
-
-
- {t(($) => $['card.menu.editInfo'])}
-
-
-
-
-
- {t(($) => $['card.menu.delete'])}
-
-
-
-
-
-
- )
-}
-
-export function DeploymentActionsMenu({ appInstance, ...props }: DeploymentActionsMenuProps) {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/deployment-actions/state.ts b/web/features/deployments/deployment-actions/state.ts
deleted file mode 100644
index f596885fdb9..00000000000
--- a/web/features/deployments/deployment-actions/state.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-'use client'
-
-import type { DeploymentActionAppInstance } from './types'
-import { atom } from 'jotai'
-import { atomWithLazy } from 'jotai/utils'
-
-export const deploymentActionAppInstanceAtom = atomWithLazy(() => {
- throw new Error('Missing deployment action app instance.')
-})
-
-export const editDeploymentDialogOpenAtom = atom(false)
-export const deleteDeploymentDialogOpenAtom = atom(false)
-
-export const openEditDeploymentDialogAtom = atom(null, (_get, set) => {
- set(deleteDeploymentDialogOpenAtom, false)
- set(editDeploymentDialogOpenAtom, true)
-})
-
-export const openDeleteDeploymentDialogAtom = atom(null, (_get, set) => {
- set(editDeploymentDialogOpenAtom, false)
- set(deleteDeploymentDialogOpenAtom, true)
-})
-
-export const deploymentActionsLocalAtoms = [
- editDeploymentDialogOpenAtom,
- deleteDeploymentDialogOpenAtom,
-] as const
diff --git a/web/features/deployments/deployment-actions/types.ts b/web/features/deployments/deployment-actions/types.ts
deleted file mode 100644
index 48f1c180f26..00000000000
--- a/web/features/deployments/deployment-actions/types.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { AppInstance } from '@dify/contracts/enterprise/types.gen'
-
-export type DeploymentActionAppInstance = Pick
diff --git a/web/features/deployments/detail/README.md b/web/features/deployments/detail/README.md
deleted file mode 100644
index e1bfa0a99ce..00000000000
--- a/web/features/deployments/detail/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Deployment Detail Shell
-
-Detail shell for the deployment app instance routes, including sidebar navigation, route headers, and route-level action slots.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------------------- | ------------------------------------------------------------------------------ |
-| `create-release` | Opens release creation from the detail header. |
-| `deployment-actions` | Reuses app instance action menu behavior in the detail sidebar. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads route identity used by detail query and tab atoms. |
-| `detail/api-tokens` | Renders the developer API header switch for the API tokens route. |
-| `detail/instances/header-actions` | Renders the new deployment header action for the instances route. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------------------------------ | ----------------------------------------------------------------- |
-| `app/components/goto-anything/atoms` | Opens the global search command from the detail sidebar shortcut. |
diff --git a/web/features/deployments/detail/__tests__/index.spec.tsx b/web/features/deployments/detail/__tests__/index.spec.tsx
deleted file mode 100644
index 711ed5c949c..00000000000
--- a/web/features/deployments/detail/__tests__/index.spec.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import type { Mock } from 'vitest'
-import { render, screen } from '@testing-library/react'
-import { Provider as JotaiProvider } from 'jotai'
-import { NextRouteStateBridge } from '@/app/components/next-route-state'
-import { useParams, usePathname } from '@/next/navigation'
-import { InstanceDetail } from '..'
-import { DeploymentDetailTop } from '../deployment-sidebar'
-
-vi.mock('@/next/navigation', async (importOriginal) => {
- const actual = await importOriginal()
- return {
- ...actual,
- useParams: vi.fn(),
- usePathname: vi.fn(),
- }
-})
-
-vi.mock('@/hooks/use-document-title', () => ({
- default: vi.fn(),
-}))
-
-vi.mock('../api-tokens/developer-api-header-switch', () => ({
- DeveloperApiHeaderSwitch: () => null,
-}))
-
-vi.mock('../instances/header-actions/new-deployment-button', () => ({
- NewDeploymentHeaderAction: () => null,
-}))
-
-vi.mock('../../create-release', () => ({
- CreateReleaseControl: () => null,
-}))
-
-function renderInstanceDetail() {
- ;(usePathname as Mock).mockReturnValue('/deployments/app-instance-1/overview')
- ;(useParams as Mock).mockReturnValue({
- appInstanceId: 'app-instance-1',
- })
-
- return render(
-
-
-
- Deployment detail content
-
-
- ,
- )
-}
-
-describe('InstanceDetail', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should render detail content without owning navigation landmarks', () => {
- renderInstanceDetail()
-
- expect(screen.getByText('Deployment detail content')).toBeInTheDocument()
- expect(screen.queryByRole('main')).not.toBeInTheDocument()
- expect(screen.queryByRole('complementary', { name: 'Detail sidebar' })).not.toBeInTheDocument()
- })
-})
-
-describe('DeploymentDetailTop', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('links the combined home control to home', () => {
- render(
-
-
- ,
- )
-
- expect(screen.getByRole('link', { name: 'common.mainNav.home' })).toHaveAttribute('href', '/')
- expect(screen.getByRole('link', { name: 'common.menus.deployments' })).toHaveAttribute(
- 'href',
- '/deployments',
- )
- expect(screen.queryByRole('button', { name: 'common.operation.back' })).not.toBeInTheDocument()
- })
-})
diff --git a/web/features/deployments/detail/__tests__/state.spec.ts b/web/features/deployments/detail/__tests__/state.spec.ts
deleted file mode 100644
index 2939619d00c..00000000000
--- a/web/features/deployments/detail/__tests__/state.spec.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
- refetchInterval?: (query: { state: { data?: unknown } }) => number | false
-}
-
-const mockGetAppInstanceQueryOptions = vi.hoisted(() => vi.fn())
-const mockListEnvironmentDeploymentsQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appInstanceService: {
- getAppInstance: {
- queryOptions: (options: QueryOptions) => {
- mockGetAppInstanceQueryOptions(options)
- return {
- ...options,
- queryKey: ['getAppInstance', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- deploymentService: {
- listEnvironmentDeployments: {
- queryOptions: (options: QueryOptions) => {
- mockListEnvironmentDeploymentsQueryOptions(options)
- return {
- ...options,
- queryKey: ['listEnvironmentDeployments', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
- tab = 'overview',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/${tab}`,
- params: { appInstanceId },
- })
-}
-
-function deploymentRow(id: string, overrides: Partial = {}) {
- return {
- environment: {
- id,
- displayName: id,
- },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- currentRelease: {
- id: `release-${id}`,
- },
- desiredRelease: undefined,
- currentDeployment: {
- id: `deployment-${id}`,
- },
- ...overrides,
- } as EnvironmentDeployment
-}
-
-describe('deployment detail state', () => {
- beforeEach(() => {
- mockGetAppInstanceQueryOptions.mockClear()
- mockListEnvironmentDeploymentsQueryOptions.mockClear()
- })
-
- it('should disable detail queries with skipToken until a route app instance exists', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.deploymentDetailAppInstanceQueryAtom)
- expect(mockGetAppInstanceQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
- store.get(state.deploymentEnvironmentDeploymentsQueryAtom)
- expect(mockListEnvironmentDeploymentsQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: false,
- input: skipToken,
- }),
- )
- })
-
- it('should build detail query inputs from route identity', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- setDeploymentRoute(store)
-
- store.get(state.deploymentDetailAppInstanceQueryAtom)
- expect(mockGetAppInstanceQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
-
- store.get(state.deploymentEnvironmentDeploymentsQueryAtom)
- expect(mockListEnvironmentDeploymentsQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- refetchInterval: expect.any(Function),
- }),
- )
- })
-
- it('should derive active detail tab from route pathname', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- setDeploymentRoute(store, 'app-instance-1', 'releases')
- expect(store.get(state.deploymentDetailActiveTabAtom)).toBe('releases')
-
- setDeploymentRoute(store, 'app-instance-1', 'unknown')
- expect(store.get(state.deploymentDetailActiveTabAtom)).toBe('overview')
- })
-
- it('should derive runtime instance rows from environment deployments', async () => {
- const state = await loadState()
- const { queryClient, store } = createQueryAtomTestStore()
- setDeploymentRoute(store)
- queryClient.setQueryData(
- ['listEnvironmentDeployments', { params: { appInstanceId: 'app-instance-1' } }],
- {
- environmentDeployments: [
- deploymentRow('running'),
- deploymentRow('undeployed', {
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED,
- currentRelease: undefined,
- desiredRelease: undefined,
- currentDeployment: undefined,
- }),
- ],
- },
- )
-
- expect(
- store.get(state.deploymentRuntimeInstanceRowsAtom).map((row) => row.environment.id),
- ).toEqual(['running'])
- })
-})
diff --git a/web/features/deployments/detail/access/README.md b/web/features/deployments/detail/access/README.md
deleted file mode 100644
index c115b2faf94..00000000000
--- a/web/features/deployments/detail/access/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Access
-
-Access route composition for webapp channels and environment permission sections.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------------- | ------------------------------------------------------------------ |
-| `route-state` | Reads the route app instance identity for access settings queries. |
-| `detail/access/channels` | Renders access channel endpoint settings. |
-| `detail/access/permissions` | Renders environment access policy settings. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/access/__tests__/state.spec.ts b/web/features/deployments/detail/access/__tests__/state.spec.ts
deleted file mode 100644
index ed7f76cc78c..00000000000
--- a/web/features/deployments/detail/access/__tests__/state.spec.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
-}
-
-const mockAccessSettingsQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- accessService: {
- getAccessSettings: {
- queryOptions: (options: QueryOptions) => {
- mockAccessSettingsQueryOptions(options)
- return {
- ...options,
- queryKey: ['getAccessSettings', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/access`,
- params: { appInstanceId },
- })
-}
-
-describe('deployment access state', () => {
- beforeEach(() => {
- mockAccessSettingsQueryOptions.mockClear()
- })
-
- it('should gate access queries until a route app instance exists', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.accessSettingsQueryAtom)
- expect(mockAccessSettingsQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
-
- setDeploymentRoute(store)
- store.get(state.accessSettingsQueryAtom)
-
- expect(mockAccessSettingsQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- })
-})
diff --git a/web/features/deployments/detail/access/channels/README.md b/web/features/deployments/detail/access/channels/README.md
deleted file mode 100644
index bd23f161fc9..00000000000
--- a/web/features/deployments/detail/access/channels/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment Access Channels
-
-Access channels section for viewing webapp and developer API endpoints and toggling webapp access.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for access-channel mutations. |
-| `detail/access` | Reads access route query data for channel settings. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------------------------ | --------------------------------------------------------------- |
-| `app/components/base/skeleton` | Reuses skeleton primitives for channel endpoint loading states. |
diff --git a/web/features/deployments/detail/access/channels/section.tsx b/web/features/deployments/detail/access/channels/section.tsx
deleted file mode 100644
index 35d35346f1c..00000000000
--- a/web/features/deployments/detail/access/channels/section.tsx
+++ /dev/null
@@ -1,250 +0,0 @@
-'use client'
-
-import type { AccessChannels, AccessEndpoint } from '@dify/contracts/enterprise/types.gen'
-import type { ReactNode } from 'react'
-import { Switch, SwitchSkeleton } from '@langgenius/dify-ui/switch'
-import { useMutation } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import {
- DeploymentEmptyState,
- DeploymentNoticeState,
- DeploymentStateMessage,
-} from '../../../shared/components/empty-state'
-import { CopyPill, EndpointRow } from '../../../shared/components/endpoint'
-import { Section } from '../../../shared/components/section'
-import {
- accessSettingsAtom,
- accessSettingsIsErrorAtom,
- accessSettingsIsLoadingAtom,
-} from '../state'
-import { getUrlOrigin } from './url'
-
-const ACCESS_CHANNEL_SKELETON_SECTIONS = [{ key: 'webapp' }, { key: 'cli' }]
-
-function AccessChannelsSwitch({
- checked,
- accessChannels,
- disabled,
-}: {
- checked: boolean
- accessChannels?: AccessChannels
- disabled?: boolean
-}) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const toggleAccessChannel = useMutation(
- consoleQuery.enterprise.accessService.updateAccessChannels.mutationOptions(),
- )
-
- return (
- $['access.channels.title'])}
- checked={checked}
- disabled={disabled || !appInstanceId}
- loading={toggleAccessChannel.isPending}
- onCheckedChange={(enabled) => {
- if (!appInstanceId) return
-
- toggleAccessChannel.mutate({
- params: { appInstanceId },
- body: {
- appInstanceId,
- webAppEnabled: enabled,
- developerApiEnabled: accessChannels?.developerApiEnabled ?? false,
- },
- })
- }}
- />
- )
-}
-
-function AccessChannelsSkeleton() {
- return (
-
- {ACCESS_CHANNEL_SKELETON_SECTIONS.map((section) => (
-
-
-
-
- ))}
-
- )
-}
-
-function ChannelInfo({
- icon,
- title,
- description,
-}: {
- icon: ReactNode
- title: string
- description?: string
-}) {
- return (
-
-
- {icon}
-
-
-
- {title}
-
- {description &&
{description}
}
-
-
- )
-}
-
-function ChannelRow({ info, children }: { info: ReactNode; children: ReactNode }) {
- return (
-
- )
-}
-
-export function AccessChannelsSection() {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const accessSettings = useAtomValue(accessSettingsAtom)
- const isLoading = useAtomValue(accessSettingsIsLoadingAtom)
- const isError = useAtomValue(accessSettingsIsErrorAtom)
- const accessChannels = accessSettings?.accessChannels
- const webAppEndpoints: AccessEndpoint[] | undefined = accessSettings?.webAppEndpoints
- const cliEndpoint: AccessEndpoint | undefined = accessSettings?.cliEndpoint
- const runEnabled = accessChannels?.webAppEnabled ?? false
- const webappRows =
- webAppEndpoints?.flatMap((endpoint) => {
- const endpointUrl = endpoint.endpointUrl
- if (!endpointUrl) return []
-
- return [
- {
- endpoint,
- endpointUrl,
- },
- ]
- }) ?? []
- const cliDomain = getUrlOrigin(cliEndpoint?.endpointUrl)
- const cliDocsUrl = cliDomain ? `${cliDomain}/cli` : undefined
-
- return (
- $['access.channels.title'])}
- action={
- isLoading ? (
-
- ) : (
-
-
- {runEnabled ? t(($) => $['overview.enabled']) : t(($) => $['overview.disabled'])}
-
-
-
- )
- }
- >
- {isLoading ? (
-
- ) : isError || !appInstanceId ? (
-
- {t(($) => $['common.loadFailed'])}
-
- ) : runEnabled ? (
-
-
}
- title={t(($) => $['access.runAccess.webapp'])}
- description={t(($) => $['access.runAccess.webappDesc'])}
- />
- }
- >
- {webappRows.length > 0 ? (
-
- {webappRows.map(({ endpoint, endpointUrl }) => (
- $['access.runAccess.urlLabel'])}
- value={endpointUrl}
- openLabel={t(($) => $['access.runAccess.openWebapp'])}
- />
- ))}
-
- ) : (
-
- {t(($) => $['access.runAccess.webappEmpty'])}
-
- )}
-
-
}
- title={t(($) => $['access.cli.title'])}
- description={t(($) => $['access.cli.description'])}
- />
- }
- >
- {cliDomain ? (
-
- ) : (
-
{t(($) => $['access.cli.empty'])}
- )}
-
-
- ) : (
- $['access.channels.disabled'])}
- description={t(($) => $['access.channels.disabledHint'])}
- />
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/access/channels/url.ts b/web/features/deployments/detail/access/channels/url.ts
deleted file mode 100644
index 6825b4bd53e..00000000000
--- a/web/features/deployments/detail/access/channels/url.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export function getUrlOrigin(url?: string) {
- if (!url) return undefined
- try {
- return new URL(url).origin
- } catch {
- return url
- }
-}
diff --git a/web/features/deployments/detail/access/index.tsx b/web/features/deployments/detail/access/index.tsx
deleted file mode 100644
index c434cf2a6b8..00000000000
--- a/web/features/deployments/detail/access/index.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-'use client'
-
-import { AccessChannelsSection } from './channels/section'
-import { AccessPermissionsSection } from './permissions/section'
-
-export function DeploymentAccess() {
- return (
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/README.md b/web/features/deployments/detail/access/permissions/README.md
deleted file mode 100644
index 7698db4dd9f..00000000000
--- a/web/features/deployments/detail/access/permissions/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Deployment Access Permissions
-
-Environment permission section for viewing and editing access policies on deployment environments.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------------------------------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for access-policy mutations. |
-| `detail/access` | Reads access route query data for environment access policies. |
-| `detail/access/permissions/access-subject-selector` | Selects specific members and groups for access policies. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------------------------ | --------------------------------------------------------- |
-| `app/components/base/skeleton` | Reuses skeleton primitives for permission loading states. |
diff --git a/web/features/deployments/detail/access/permissions/__tests__/access-control-dialog.spec.tsx b/web/features/deployments/detail/access/permissions/__tests__/access-control-dialog.spec.tsx
deleted file mode 100644
index 075fa7565ce..00000000000
--- a/web/features/deployments/detail/access/permissions/__tests__/access-control-dialog.spec.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import type { ReactElement } from 'react'
-import { AccessSubjectType } from '@dify/contracts/enterprise/types.gen'
-import { fireEvent, screen } from '@testing-library/react'
-import { describe, expect, it, vi } from 'vitest'
-import { renderWithConsoleQuery } from '@/test/console/query-data'
-import { DeploymentAccessControlDialog } from '../access-control-dialog'
-
-const mockUseSearchAccessSubjects = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/access-control/use-access-subjects', () => ({
- useSearchAccessSubjects: (...args: unknown[]) => mockUseSearchAccessSubjects(...args),
-}))
-
-const render = (ui: ReactElement, allowPublicAccess = true) =>
- renderWithConsoleQuery(ui, {
- systemFeatures: { webapp_auth: { allow_public_access: allowPublicAccess } },
- })
-
-describe('DeploymentAccessControlDialog', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockUseSearchAccessSubjects.mockReturnValue({
- data: { pages: [] },
- fetchNextPage: vi.fn(),
- isFetchingNextPage: false,
- isLoading: false,
- })
- })
-
- it('should submit the selected deployment access subjects', () => {
- const handleSubmit = vi.fn()
-
- render(
- ,
- )
-
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(handleSubmit).toHaveBeenCalledWith('specific', [
- {
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Group One',
- memberCount: 2,
- },
- {
- id: 'member-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: 'Member One',
- },
- ])
- })
-
- describe('public access control', () => {
- it('should allow selecting the public option when public access is allowed', () => {
- const handleSubmit = vi.fn()
-
- render(
- ,
- true,
- )
-
- const publicOption = screen.getByRole('radio', {
- name: 'app.accessControlDialog.accessItems.anyone',
- })
- expect(publicOption).not.toHaveAttribute('data-disabled')
-
- fireEvent.click(publicOption)
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(handleSubmit).toHaveBeenCalledWith('anyone', [])
- })
-
- it('should disable the public option and show a tooltip when public access is disabled', () => {
- const handleSubmit = vi.fn()
-
- render(
- ,
- false,
- )
-
- const publicOption = screen.getByRole('radio', {
- name: 'app.accessControlDialog.accessItems.anyone',
- })
- expect(publicOption).toHaveAttribute('data-disabled')
- expect(
- screen.getByRole('button', {
- name: 'app.accessControlDialog.webAppPublicAccessDisabledTip',
- }),
- ).toBeInTheDocument()
-
- fireEvent.click(publicOption)
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(handleSubmit).toHaveBeenCalledWith('organization', [])
- })
- })
-})
diff --git a/web/features/deployments/detail/access/permissions/__tests__/access-policy.spec.ts b/web/features/deployments/detail/access/permissions/__tests__/access-policy.spec.ts
deleted file mode 100644
index 0dc3b4de175..00000000000
--- a/web/features/deployments/detail/access/permissions/__tests__/access-policy.spec.ts
+++ /dev/null
@@ -1,208 +0,0 @@
-import type { AccessPolicy, Subject } from '@dify/contracts/enterprise/types.gen'
-import { AccessMode, AccessSubjectType } from '@dify/contracts/enterprise/types.gen'
-import { describe, expect, it } from 'vitest'
-import { AccessMode as AppAccessMode, SubjectType } from '@/models/access-control'
-import {
- accessControlSelectionFromSubjects,
- accessModeToPermissionKey,
- appAccessModeToPermissionKey,
- normalizeResolvedSubject,
- permissionKeyToAccessMode,
- permissionKeyToAppAccessMode,
- policySubjects,
- selectedSubjectsFromPolicy,
- subjectsFromAccessControlSelection,
-} from '../access-policy'
-
-function policy(overrides: Partial): AccessPolicy {
- return {
- id: 'policy-1',
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- mode: AccessMode.ACCESS_MODE_PRIVATE_ALL,
- subjects: [],
- createdAt: '2026-01-01T00:00:00.000Z',
- updatedAt: '2026-01-01T00:00:00.000Z',
- ...overrides,
- }
-}
-
-describe('access policy mode mapping', () => {
- it('should map API access modes to deployment permission keys', () => {
- expect(accessModeToPermissionKey(AccessMode.ACCESS_MODE_PRIVATE)).toBe('specific')
- expect(accessModeToPermissionKey(AccessMode.ACCESS_MODE_PUBLIC)).toBe('anyone')
- expect(accessModeToPermissionKey(AccessMode.ACCESS_MODE_PRIVATE_ALL)).toBe('organization')
- expect(accessModeToPermissionKey()).toBe('organization')
- })
-
- it('should map permission keys to API and app access modes', () => {
- expect(permissionKeyToAccessMode('organization')).toBe(AccessMode.ACCESS_MODE_PRIVATE_ALL)
- expect(permissionKeyToAccessMode('specific')).toBe(AccessMode.ACCESS_MODE_PRIVATE)
- expect(permissionKeyToAccessMode('anyone')).toBe(AccessMode.ACCESS_MODE_PUBLIC)
-
- expect(permissionKeyToAppAccessMode('organization')).toBe(AppAccessMode.ORGANIZATION)
- expect(permissionKeyToAppAccessMode('specific')).toBe(AppAccessMode.SPECIFIC_GROUPS_MEMBERS)
- expect(permissionKeyToAppAccessMode('anyone')).toBe(AppAccessMode.PUBLIC)
-
- expect(appAccessModeToPermissionKey(AppAccessMode.SPECIFIC_GROUPS_MEMBERS)).toBe('specific')
- expect(appAccessModeToPermissionKey(AppAccessMode.PUBLIC)).toBe('anyone')
- expect(appAccessModeToPermissionKey(AppAccessMode.ORGANIZATION)).toBe('organization')
- })
-})
-
-describe('access policy subject conversion', () => {
- it('should normalize resolved group and account subjects', () => {
- expect(
- normalizeResolvedSubject({
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- groupData: {
- id: 'group-1',
- name: 'Admins',
- groupSize: 3,
- },
- }),
- ).toEqual({
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Admins',
- memberCount: 3,
- })
-
- expect(
- normalizeResolvedSubject({
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- accountData: {
- id: 'account-1',
- email: 'member@example.com',
- },
- }),
- ).toEqual({
- id: 'account-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: 'member@example.com',
- })
- })
-
- it('should normalize resolved subjects that use app access-control subject types', () => {
- expect(
- normalizeResolvedSubject({
- subjectId: 'group-1',
- subjectType: SubjectType.GROUP,
- groupData: {
- id: 'group-1',
- name: 'Admins',
- groupSize: 3,
- },
- }),
- ).toEqual({
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Admins',
- memberCount: 3,
- })
-
- expect(
- normalizeResolvedSubject({
- subjectId: 'account-1',
- subjectType: SubjectType.ACCOUNT,
- accountData: {
- id: 'account-1',
- name: 'Member',
- email: 'member@example.com',
- },
- }),
- ).toEqual({
- id: 'account-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: 'Member',
- })
- })
-
- it('should ignore unsupported subjects and subjects without ids', () => {
- expect(
- normalizeResolvedSubject({ subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP }),
- ).toBeUndefined()
- expect(
- normalizeResolvedSubject({ subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT }),
- ).toBeUndefined()
- expect(
- normalizeResolvedSubject({
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_UNSPECIFIED,
- } as Subject),
- ).toBeUndefined()
- })
-
- it('should preserve labels when reading selected subjects from policy', () => {
- expect(
- selectedSubjectsFromPolicy(
- policy({
- subjects: [
- { subjectId: 'group-1', subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP },
- { subjectId: 'account-1', subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT },
- ],
- }),
- [
- {
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Admins',
- memberCount: 3,
- },
- ],
- ),
- ).toEqual([
- {
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Admins',
- memberCount: 3,
- },
- {
- id: 'account-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- },
- ])
-
- expect(selectedSubjectsFromPolicy()).toEqual([])
- })
-
- it('should convert between deployment subjects and access-control selections', () => {
- const subjects = [
- {
- id: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: 'Admins',
- memberCount: 3,
- },
- {
- id: 'account-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: 'Member',
- },
- ]
-
- expect(policySubjects(subjects)).toEqual([
- { subjectId: 'group-1', subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP },
- { subjectId: 'account-1', subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT },
- ])
-
- const selection = accessControlSelectionFromSubjects(subjects)
- expect(selection.groups).toEqual([
- {
- id: 'group-1',
- name: 'Admins',
- groupSize: 3,
- },
- ])
- expect(selection.members).toEqual([
- {
- id: 'account-1',
- name: 'Member',
- email: 'Member',
- avatar: '',
- avatarUrl: '',
- },
- ])
- expect(subjectsFromAccessControlSelection(selection)).toEqual(subjects)
- })
-})
diff --git a/web/features/deployments/detail/access/permissions/__tests__/permissions.spec.tsx b/web/features/deployments/detail/access/permissions/__tests__/permissions.spec.tsx
deleted file mode 100644
index 5fa3b8b14c8..00000000000
--- a/web/features/deployments/detail/access/permissions/__tests__/permissions.spec.tsx
+++ /dev/null
@@ -1,300 +0,0 @@
-import type {
- AccessPolicy,
- Environment,
- EnvironmentAccessPolicy,
-} from '@dify/contracts/enterprise/types.gen'
-import type { Atom, WritableAtom } from 'jotai'
-import type { ReactNode } from 'react'
-import { AccessMode, AccessSubjectType } from '@dify/contracts/enterprise/types.gen'
-import { fireEvent, render, screen } from '@testing-library/react'
-import { createStore, Provider as JotaiProvider } from 'jotai'
-import { describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import {
- accessSettingsAtom,
- accessSettingsIsErrorAtom,
- accessSettingsIsLoadingAtom,
-} from '../../state'
-import { EnvironmentPermissionRow } from '../environment-permission-row'
-import { AccessPermissionsSection } from '../section'
-
-const mockMutate = vi.hoisted(() => vi.fn())
-
-vi.mock('../../state', async () => {
- const { atom } = await import('jotai')
-
- return {
- accessSettingsAtom: atom(undefined),
- accessSettingsIsLoadingAtom: atom(false),
- accessSettingsIsErrorAtom: atom(false),
- }
-})
-
-vi.mock('@tanstack/react-query', async (importOriginal) => {
- const actual = await importOriginal()
-
- return {
- ...actual,
- useInfiniteQuery: () => ({
- data: { pages: [] },
- fetchNextPage: vi.fn(),
- isFetchingNextPage: false,
- isLoading: false,
- }),
- useMutation: () => ({
- isPending: false,
- mutate: mockMutate,
- }),
- useSuspenseQuery: () => ({
- data: {
- webapp_auth: { allow_public_access: true },
- },
- }),
- }
-})
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- accessService: {
- updateAccessPolicy: {
- mutationOptions: () => ({ mutationKey: ['updateAccessPolicy'] }),
- },
- },
- },
- systemFeatures: {
- get: {
- queryKey: () => ['console', 'systemFeatures'],
- queryOptions: (options?: Record) => ({
- queryKey: ['console', 'systemFeatures'],
- ...options,
- }),
- },
- },
- },
-}))
-
-function setTestAtom(
- store: ReturnType,
- target: Atom,
- value: Value,
-) {
- store.set(target as WritableAtom, value)
-}
-
-function renderWithAtomStore(
- children: ReactNode,
- accessSettings?: {
- environmentPolicies: EnvironmentAccessPolicy[]
- },
-) {
- const store = createStore()
- store.set(setNextRouteStateAtom, {
- pathname: '/deployments/app-instance-1/access',
- params: { appInstanceId: 'app-instance-1' },
- })
- setTestAtom(store, accessSettingsAtom, accessSettings)
- setTestAtom(store, accessSettingsIsLoadingAtom, false)
- setTestAtom(store, accessSettingsIsErrorAtom, false)
-
- return render({children})
-}
-
-function createEnvironment(overrides: Partial = {}): Environment {
- return {
- id: 'environment-1',
- displayName: 'Production',
- ...overrides,
- } as Environment
-}
-
-function createAccessPolicy(): AccessPolicy {
- return {
- id: 'policy-1',
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- mode: AccessMode.ACCESS_MODE_PRIVATE_ALL,
- subjects: [],
- createdAt: '2026-01-01T00:00:00.000Z',
- updatedAt: '2026-01-01T00:00:00.000Z',
- }
-}
-
-function createSpecificAccessPolicy(): AccessPolicy {
- return {
- ...createAccessPolicy(),
- mode: AccessMode.ACCESS_MODE_PRIVATE,
- subjects: [
- {
- subjectId: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- },
- {
- subjectId: 'member-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- },
- ],
- }
-}
-
-function createEnvironmentAccessPolicy(): EnvironmentAccessPolicy {
- return {
- environment: createEnvironment(),
- policy: createAccessPolicy(),
- resolvedSubjects: [],
- }
-}
-
-describe('EnvironmentPermissionRow', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockMutate.mockImplementation((_variables: unknown, options?: { onError?: () => void }) => {
- options?.onError?.()
- })
- })
-
- it('should keep the previous permission visible when updating the policy fails', () => {
- renderWithAtomStore(
- ,
- )
-
- fireEvent.click(
- screen.getByRole('button', { name: /deployments\.access\.permissions\.editAriaLabel/ }),
- )
- fireEvent.click(
- screen.getByRole('radio', { name: 'app.accessControlDialog.accessItems.anyone' }),
- )
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(mockMutate).toHaveBeenCalled()
- expect(screen.getByText('deployments.access.permission.organization')).toBeInTheDocument()
- })
-
- it('should show the updated policy after success', () => {
- mockMutate.mockImplementation((_variables: unknown, options?: { onSuccess?: () => void }) => {
- options?.onSuccess?.()
- })
-
- renderWithAtomStore(
- ,
- )
-
- fireEvent.click(
- screen.getByRole('button', { name: /deployments\.access\.permissions\.editAriaLabel/ }),
- )
- fireEvent.click(
- screen.getByRole('radio', { name: 'app.accessControlDialog.accessItems.anyone' }),
- )
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(mockMutate).toHaveBeenCalledWith(
- {
- params: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- },
- body: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- mode: AccessMode.ACCESS_MODE_PUBLIC,
- subjects: [],
- },
- },
- expect.objectContaining({
- onError: expect.any(Function),
- onSuccess: expect.any(Function),
- }),
- )
- expect(screen.getByText('deployments.access.permission.anyone')).toBeInTheDocument()
- })
-
- it('should submit specific subjects with the deployment access subject type', () => {
- mockMutate.mockImplementation((_variables: unknown, options?: { onSuccess?: () => void }) => {
- options?.onSuccess?.()
- })
-
- renderWithAtomStore(
- ,
- )
-
- fireEvent.click(
- screen.getByRole('button', { name: /deployments\.access\.permissions\.editAriaLabel/ }),
- )
- fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
-
- expect(mockMutate).toHaveBeenCalledWith(
- {
- params: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- },
- body: {
- appInstanceId: 'app-instance-1',
- environmentId: 'environment-1',
- mode: AccessMode.ACCESS_MODE_PRIVATE,
- subjects: [
- {
- subjectId: 'group-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- },
- {
- subjectId: 'member-1',
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- },
- ],
- },
- },
- expect.objectContaining({
- onError: expect.any(Function),
- onSuccess: expect.any(Function),
- }),
- )
- })
-
- it('should show specific subject counts in the access summary', () => {
- renderWithAtomStore(
- ,
- )
-
- const editButton = screen.getByRole('button', {
- name: /deployments\.access\.permissions\.editAriaLabel/,
- })
-
- expect(editButton).toHaveTextContent('deployments.access.permission.specific')
- expect(editButton).toHaveTextContent('deployments.access.members.groupCount:{"count":1}')
- expect(editButton).toHaveTextContent('deployments.access.members.memberCount:{"count":1}')
- })
-})
-
-// Access permissions render as simple environment rows without a table header.
-describe('AccessPermissionsSection', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should render permission rows without column headers', () => {
- renderWithAtomStore(, {
- environmentPolicies: [createEnvironmentAccessPolicy()],
- })
-
- expect(screen.getByText('Production')).toBeInTheDocument()
- expect(
- screen.queryByText('deployments.access.permissions.col.environment'),
- ).not.toBeInTheDocument()
- expect(
- screen.queryByText('deployments.access.permissions.col.permission'),
- ).not.toBeInTheDocument()
- })
-})
diff --git a/web/features/deployments/detail/access/permissions/access-control-dialog.tsx b/web/features/deployments/detail/access/permissions/access-control-dialog.tsx
deleted file mode 100644
index 86007c76311..00000000000
--- a/web/features/deployments/detail/access/permissions/access-control-dialog.tsx
+++ /dev/null
@@ -1,260 +0,0 @@
-'use client'
-
-import type { PropsWithChildren } from 'react'
-import type { AccessPermissionKind, SelectableAccessSubject } from './access-policy'
-import type { AccessSubjectSelectionValue } from './access-subject-selector/types'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Dialog,
- DialogCloseButton,
- DialogContent,
- DialogDescription,
- DialogTitle,
-} from '@langgenius/dify-ui/dialog'
-import { RadioGroup, RadioItem } from '@langgenius/dify-ui/radio'
-import { useSuspenseQuery } from '@tanstack/react-query'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
-import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { AccessMode as AppAccessMode } from '@/models/access-control'
-import {
- accessControlSelectionFromSubjects,
- appAccessModeToPermissionKey,
- permissionKeyToAppAccessMode,
- subjectsFromAccessControlSelection,
-} from './access-policy'
-import { AccessSubjectAddButton } from './access-subject-selector/add-button'
-import { AccessSubjectSelectionList } from './access-subject-selector/selection-list'
-
-export function DeploymentAccessControlDialog({
- open,
- initialKind,
- initialSubjects,
- saving,
- onClose,
- onSubmit,
-}: {
- open: boolean
- initialKind: AccessPermissionKind
- initialSubjects: SelectableAccessSubject[]
- saving?: boolean
- onClose: () => void
- onSubmit: (kind: AccessPermissionKind, subjects: SelectableAccessSubject[]) => void
-}) {
- const draftKey = [
- initialKind,
- initialSubjects.map((subject) => `${subject.subjectType}:${subject.id}`).join(','),
- ].join(':')
-
- return (
-
- )
-}
-
-function DeploymentAccessControlDialogBody({
- initialKind,
- initialSubjects,
- saving,
- onClose,
- onSubmit,
-}: {
- initialKind: AccessPermissionKind
- initialSubjects: SelectableAccessSubject[]
- saving?: boolean
- onClose: () => void
- onSubmit: (kind: AccessPermissionKind, subjects: SelectableAccessSubject[]) => void
-}) {
- const { t } = useTranslation('deployments')
- const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
- const [currentMenu, setCurrentMenu] = useState(() => permissionKeyToAppAccessMode(initialKind))
- const [specificSelection, setSpecificSelection] = useState(() =>
- accessControlSelectionFromSubjects(initialSubjects),
- )
- const specificSelected = currentMenu === AppAccessMode.SPECIFIC_GROUPS_MEMBERS
- const publicAccessDisabled = !systemFeatures.webapp_auth.allow_public_access
- const selectedSubjectCount = specificSelection.groups.length + specificSelection.members.length
- const specificEmpty = specificSelected && selectedSubjectCount === 0
- const publicSelectedDisabled = currentMenu === AppAccessMode.PUBLIC && publicAccessDisabled
- const confirmDisabled = saving || (specificSelected && specificEmpty) || publicSelectedDisabled
-
- const handleConfirm = () => {
- if (confirmDisabled) return
-
- onSubmit(
- appAccessModeToPermissionKey(currentMenu),
- specificSelected ? subjectsFromAccessControlSelection(specificSelection) : [],
- )
- }
-
- return (
-
-
-
- {t(($) => $['access.permissions.editTitle'])}
-
-
- {t(($) => $['access.permissions.editDescription'])}
-
-
-
- value={currentMenu}
- onValueChange={setCurrentMenu}
- className="flex flex-col items-stretch gap-y-1 px-6 pb-3"
- aria-labelledby="access-control-options-label"
- disabled={saving}
- >
-
-
- {t(($) => $['accessControlDialog.accessLabel'], { ns: 'app' })}
-
-
-
-
-
-
-
- {t(($) => $['accessControlDialog.accessItems.organization'], { ns: 'app' })}
-
-
-
-
-
-
-
-
-
-
-
- {t(($) => $['accessControlDialog.accessItems.anyone'], { ns: 'app' })}
-
- {publicAccessDisabled && (
-
$['accessControlDialog.webAppPublicAccessDisabledTip'], {
- ns: 'app',
- })}
- className="size-3.5 shrink-0 text-text-warning-secondary hover:text-text-warning-secondary"
- >
- {t(($) => $['accessControlDialog.webAppPublicAccessDisabledTip'], { ns: 'app' })}
-
- )}
-
-
-
-
-
-
-
-
- )
-}
-
-function AccessControlItem({
- type,
- children,
- disabled,
-}: PropsWithChildren<{
- type: AppAccessMode
- disabled?: boolean
-}>) {
- return (
-
- value={type}
- disabled={disabled}
- render={}
- className={cn(
- 'cursor-pointer rounded-[10px] border-[0.5px] border-components-option-card-option-border bg-components-option-card-option-bg shadow-xs transition-colors',
- 'hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover',
- 'focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden',
- 'data-checked:border-components-option-card-option-selected-border data-checked:bg-components-option-card-option-selected-bg data-checked:inset-ring-[0.5px] data-checked:inset-ring-components-option-card-option-selected-border',
- 'data-disabled:cursor-not-allowed data-disabled:opacity-60 data-disabled:hover:border-components-option-card-option-border data-disabled:hover:bg-components-option-card-option-bg',
- )}
- >
- {children}
-
- )
-}
-
-function SpecificGroupsOrMembersOption({
- selected,
- selection,
- onSelectionChange,
-}: {
- selected: boolean
- selection: AccessSubjectSelectionValue
- onSelectionChange: (selection: AccessSubjectSelectionValue) => void
-}) {
- const { t } = useTranslation()
-
- if (!selected) {
- return (
-
-
-
-
- {t(($) => $['accessControlDialog.accessItems.specific'], { ns: 'app' })}
-
-
-
- )
- }
-
- return (
-
-
-
-
-
- {t(($) => $['accessControlDialog.accessItems.specific'], { ns: 'app' })}
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/access-policy.ts b/web/features/deployments/detail/access/permissions/access-policy.ts
deleted file mode 100644
index a364efb02a7..00000000000
--- a/web/features/deployments/detail/access/permissions/access-policy.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import type {
- AccessPolicy,
- AccessMode as AccessPolicyMode,
- AccessSubject,
- AccessSubjectType as AccessSubjectTypeValue,
- Subject,
-} from '@dify/contracts/enterprise/types.gen'
-import type { AccessSubjectSelectionValue } from './access-subject-selector/types'
-import type { AccessControlAccount, AccessControlGroup } from '@/models/access-control'
-import { AccessMode, AccessSubjectType } from '@dify/contracts/enterprise/types.gen'
-import { AccessMode as AppAccessMode, SubjectType as AppSubjectType } from '@/models/access-control'
-
-export type AccessPermissionKind = 'organization' | 'specific' | 'anyone'
-
-export const permissionIcon: Record = {
- organization: 'i-ri-building-line',
- specific: 'i-ri-lock-line',
- anyone: 'i-ri-global-line',
-}
-
-export type SelectableAccessSubject = {
- id: string
- subjectType: AccessSubjectTypeValue
- name?: string
- memberCount?: number
-}
-
-export function accessModeToPermissionKey(mode?: AccessPolicy['mode']): AccessPermissionKind {
- if (mode === AccessMode.ACCESS_MODE_PRIVATE) return 'specific'
- if (mode === AccessMode.ACCESS_MODE_PUBLIC) return 'anyone'
- return 'organization'
-}
-
-export function permissionKeyToAccessMode(key: AccessPermissionKind): AccessPolicyMode {
- if (key === 'organization') return AccessMode.ACCESS_MODE_PRIVATE_ALL
- if (key === 'specific') return AccessMode.ACCESS_MODE_PRIVATE
- return AccessMode.ACCESS_MODE_PUBLIC
-}
-
-export function permissionKeyToAppAccessMode(key: AccessPermissionKind): AppAccessMode {
- if (key === 'organization') return AppAccessMode.ORGANIZATION
- if (key === 'specific') return AppAccessMode.SPECIFIC_GROUPS_MEMBERS
- return AppAccessMode.PUBLIC
-}
-
-export function appAccessModeToPermissionKey(mode: AppAccessMode): AccessPermissionKind {
- if (mode === AppAccessMode.SPECIFIC_GROUPS_MEMBERS) return 'specific'
- if (mode === AppAccessMode.PUBLIC) return 'anyone'
- return 'organization'
-}
-
-export function normalizeResolvedSubject(subject: Subject): SelectableAccessSubject | undefined {
- const isGroupSubject =
- subject.subjectType === AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP ||
- subject.subjectType === AppSubjectType.GROUP
- const isAccountSubject =
- subject.subjectType === AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT ||
- subject.subjectType === AppSubjectType.ACCOUNT
-
- if (isGroupSubject) {
- const id = subject.subjectId || subject.groupData?.id
- if (!id) return undefined
-
- return {
- id,
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: subject.groupData?.name,
- memberCount: subject.groupData?.groupSize,
- }
- }
-
- if (isAccountSubject) {
- const id = subject.subjectId || subject.accountData?.id
- if (!id) return undefined
-
- return {
- id,
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: subject.accountData?.name || subject.accountData?.email,
- }
- }
-
- return undefined
-}
-
-function getSubjectLabel(subject: SelectableAccessSubject) {
- return subject.name || subject.id
-}
-
-export function policySubjects(subjects: SelectableAccessSubject[]): AccessSubject[] {
- return subjects.map((subject) => ({
- subjectId: subject.id,
- subjectType: subject.subjectType,
- }))
-}
-
-export function selectedSubjectsFromPolicy(
- policy?: AccessPolicy,
- labelSubjects: SelectableAccessSubject[] = [],
-) {
- if (!policy) return []
-
- return policy.subjects.map((subject): SelectableAccessSubject => {
- const matchedSubject = labelSubjects.find(
- (labelSubject) =>
- labelSubject.id === subject.subjectId && labelSubject.subjectType === subject.subjectType,
- )
- return {
- id: subject.subjectId,
- subjectType: subject.subjectType,
- name: matchedSubject?.name,
- memberCount: matchedSubject?.memberCount,
- }
- })
-}
-
-function selectableSubjectToGroup(subject: SelectableAccessSubject): AccessControlGroup {
- return {
- id: subject.id,
- name: getSubjectLabel(subject),
- groupSize: subject.memberCount ?? 0,
- }
-}
-
-function selectableSubjectToAccount(subject: SelectableAccessSubject): AccessControlAccount {
- const label = getSubjectLabel(subject)
-
- return {
- id: subject.id,
- name: label,
- email: label,
- avatar: '',
- avatarUrl: '',
- }
-}
-
-export function accessControlSelectionFromSubjects(
- subjects: SelectableAccessSubject[],
-): AccessSubjectSelectionValue {
- return {
- groups: subjects
- .filter((subject) => subject.subjectType === AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP)
- .map(selectableSubjectToGroup),
- members: subjects
- .filter((subject) => subject.subjectType === AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT)
- .map(selectableSubjectToAccount),
- }
-}
-
-export function subjectsFromAccessControlSelection(
- value: AccessSubjectSelectionValue,
-): SelectableAccessSubject[] {
- return [
- ...value.groups.map(
- (group): SelectableAccessSubject => ({
- id: group.id,
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- name: group.name,
- memberCount: group.groupSize,
- }),
- ),
- ...value.members.map(
- (member): SelectableAccessSubject => ({
- id: member.id,
- subjectType: AccessSubjectType.ACCESS_SUBJECT_TYPE_ACCOUNT,
- name: member.name || member.email,
- }),
- ),
- ]
-}
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/README.md b/web/features/deployments/detail/access/permissions/access-subject-selector/README.md
deleted file mode 100644
index b24197f788e..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment Access Subject Selector
-
-Subject selector used by access permission dialogs to search, add, and display members or groups.
-
-## Internal Modules
-
-None.
-
-## External Modules
-
-| Module | Why this module uses it |
-| -------------------------------------------- | ---------------------------------------------------------------------------------- |
-| `app/components/base/loading` | Reuses the inline loading indicator while access-subject search is pending. |
-| `app/components/base/skeleton` | Reuses skeleton primitives for selected subject loading rows. |
-| `context/app-context` | Reads the current user id to label the current user in selectable subject options. |
-| `models/access-control` | Reuses access-control subject types and group models for selector values. |
-| `service/access-control/use-access-subjects` | Searches users and groups for access-policy subject selection. |
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/__tests__/add-button.spec.tsx b/web/features/deployments/detail/access/permissions/access-subject-selector/__tests__/add-button.spec.tsx
deleted file mode 100644
index f4fa7cee0e4..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/__tests__/add-button.spec.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import type { AccessControlAccount, Subject } from '@/models/access-control'
-import { screen, waitFor } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { SubjectType } from '@/models/access-control'
-import { renderWithAccountProfile as render } from '@/test/console/account-profile'
-import { AccessSubjectAddButton } from '../add-button'
-
-const mockUseSearchAccessSubjects = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/access-control/use-access-subjects', () => ({
- useSearchAccessSubjects: (...args: unknown[]) => mockUseSearchAccessSubjects(...args),
-}))
-
-const groupSubject: Subject = {
- subjectId: 'group-1',
- subjectType: SubjectType.GROUP,
- groupData: {
- id: 'group-1',
- name: 'Group One',
- groupSize: 2,
- },
-}
-
-const member: AccessControlAccount = {
- id: 'account-1',
- name: 'Member One',
- email: 'member@example.com',
- avatar: '',
- avatarUrl: '',
-}
-
-const memberSubject: Subject = {
- subjectId: member.id,
- subjectType: SubjectType.ACCOUNT,
- accountData: member,
-}
-
-function lastSearchParams() {
- return mockUseSearchAccessSubjects.mock.calls.at(-1)?.[0] as { groupId?: string } | undefined
-}
-
-// The add menu owns transient browsing state; reopening should start from the root group list.
-describe('AccessSubjectAddButton', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockUseSearchAccessSubjects.mockReturnValue({
- data: {
- pages: [
- {
- subjects: [groupSubject, memberSubject],
- hasMore: false,
- },
- ],
- },
- fetchNextPage: vi.fn(),
- isFetchingNextPage: false,
- isLoading: false,
- })
- })
-
- it('should reset expanded group browsing when the add menu reopens', async () => {
- const user = userEvent.setup()
-
- render()
-
- const addButton = screen.getByRole('combobox', { name: 'common.operation.add' })
-
- await user.click(addButton)
- await user.click(
- await screen.findByRole('button', {
- name: 'app.accessControlDialog.operateGroupAndMember.expand',
- }),
- )
-
- await waitFor(() => {
- expect(lastSearchParams()).toMatchObject({ groupId: 'group-1' })
- })
-
- await user.click(addButton)
- await waitFor(() => {
- expect(addButton).toHaveAttribute('aria-expanded', 'false')
- })
-
- await user.click(addButton)
-
- await waitFor(() => {
- expect(lastSearchParams()?.groupId).toBeUndefined()
- })
- })
-
- it('should keep group and member selected state in sync with checkbox icon DOM', async () => {
- const user = userEvent.setup()
- const group = groupSubject.groupData
- const onChange = vi.fn()
- const { rerender } = render(
- ,
- )
-
- await user.click(screen.getByRole('combobox', { name: 'common.operation.add' }))
-
- const groupOption = await screen.findByRole('option', { name: /Group One/ })
- const memberOption = screen.getByRole('option', { name: /Member One/ })
- const expandButton = screen.getByRole('button', {
- name: 'app.accessControlDialog.operateGroupAndMember.expand',
- })
- expect(groupOption).toHaveClass('mx-0', 'pl-2')
- expect(memberOption).toHaveClass('mx-0', 'pl-2', 'pr-3')
- expect(groupOption).toHaveAttribute('data-selected')
- expect(groupOption.querySelector('.i-ri-check-line')).toBeInTheDocument()
- expect(memberOption).not.toHaveAttribute('data-selected')
- expect(memberOption.querySelector('.i-ri-check-line')).not.toBeInTheDocument()
- expect(expandButton).toBeDisabled()
-
- rerender(
- ,
- )
-
- await waitFor(() => {
- expect(groupOption).not.toHaveAttribute('data-selected')
- expect(groupOption.querySelector('.i-ri-check-line')).not.toBeInTheDocument()
- expect(memberOption).toHaveAttribute('data-selected')
- expect(memberOption.querySelector('.i-ri-check-line')).toBeInTheDocument()
- expect(expandButton).not.toBeDisabled()
- })
- })
-})
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/add-button.tsx b/web/features/deployments/detail/access/permissions/access-subject-selector/add-button.tsx
deleted file mode 100644
index 5a456a5b1e9..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/add-button.tsx
+++ /dev/null
@@ -1,218 +0,0 @@
-'use client'
-
-import type { ComboboxChangeEventDetails } from '@langgenius/dify-ui/combobox'
-import type { AccessSubjectSelectionProps } from './types'
-import type { AccessControlGroup, Subject } from '@/models/access-control'
-import {
- Combobox,
- ComboboxContent,
- ComboboxEmpty,
- ComboboxInput,
- ComboboxInputGroup,
- ComboboxList,
- ComboboxStatus,
- ComboboxTrigger,
-} from '@langgenius/dify-ui/combobox'
-import { useDebounce } from 'ahooks'
-import { useEffect, useRef, useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import Loading from '@/app/components/base/loading'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import { useSearchAccessSubjects } from '@/service/access-control/use-access-subjects'
-import { SelectedGroupsBreadCrumb, SubjectItem } from './subject-options'
-import {
- getSubjectLabel,
- getSubjectValue,
- isSameSubject,
- selectionValueToSubjects,
- subjectsToSelectionValue,
-} from './utils'
-
-type AccessSubjectAddButtonProps = AccessSubjectSelectionProps & {
- disabled?: boolean
-}
-
-export function AccessSubjectAddButton({
- selectedGroups,
- selectedMembers,
- onChange,
- disabled,
-}: AccessSubjectAddButtonProps) {
- const { t } = useTranslation()
- const [open, setOpen] = useState(false)
- const [keyword, setKeyword] = useState('')
- const [breadcrumbGroups, setBreadcrumbGroups] = useState([])
- const scrollRootRef = useRef(null)
- const anchorRef = useRef(null)
- const debouncedKeyword = useDebounce(keyword, { wait: 500 })
-
- const lastAvailableGroup = breadcrumbGroups[breadcrumbGroups.length - 1]
- const { isLoading, isFetchingNextPage, fetchNextPage, data } = useSearchAccessSubjects(
- {
- keyword: debouncedKeyword,
- groupId: lastAvailableGroup?.id,
- resultsPerPage: 10,
- },
- open && !disabled,
- )
- const pages = data?.pages ?? []
- const subjects = pages.flatMap((page) => page.subjects ?? [])
- const selectedSubjects = selectionValueToSubjects({
- groups: selectedGroups,
- members: selectedMembers,
- })
- const hasResults = pages.length > 0 && subjects.length > 0
- const shouldShowBreadcrumb = hasResults || breadcrumbGroups.length > 0
- const hasMore = pages[pages.length - 1]?.hasMore ?? false
-
- useEffect(() => {
- let observer: IntersectionObserver | undefined
- if (anchorRef.current) {
- observer = new IntersectionObserver(
- (entries) => {
- if (entries[0]!.isIntersecting && !isLoading && !isFetchingNextPage && hasMore)
- fetchNextPage()
- },
- { root: scrollRootRef.current, rootMargin: '20px' },
- )
- observer.observe(anchorRef.current)
- }
- return () => observer?.disconnect()
- }, [fetchNextPage, hasMore, isFetchingNextPage, isLoading])
-
- const closeMenu = () => {
- setKeyword('')
- setBreadcrumbGroups([])
- setOpen(false)
- }
-
- const handleOpenChange = (nextOpen: boolean) => {
- if (nextOpen && disabled) return
- if (!nextOpen) {
- closeMenu()
- return
- }
-
- setOpen(true)
- }
-
- const handleInputValueChange = (inputValue: string, details: ComboboxChangeEventDetails) => {
- if (!disabled && details.reason !== 'item-press') setKeyword(inputValue)
- }
-
- const handleValueChange = (nextSubjects: Subject[]) => {
- onChange(subjectsToSelectionValue(nextSubjects))
- }
-
- return (
-
- multiple
- open={open}
- value={selectedSubjects}
- inputValue={keyword}
- items={subjects}
- disabled={disabled}
- itemToStringLabel={getSubjectLabel}
- itemToStringValue={getSubjectValue}
- isItemEqualToValue={isSameSubject}
- filter={null}
- onOpenChange={handleOpenChange}
- onInputValueChange={handleInputValueChange}
- onValueChange={handleValueChange}
- >
- $['operation.add'], { ns: 'common' })}
- icon={false}
- size="small"
- disabled={disabled}
- onClick={() => {
- if (open) closeMenu()
- }}
- className="h-6 w-auto min-w-13 shrink-0 rounded-md border-0 bg-transparent px-2 py-0 text-xs font-medium text-components-button-secondary-accent-text hover:bg-state-accent-hover focus-visible:bg-state-accent-hover data-popup-open:bg-state-accent-hover"
- >
-
-
- {t(($) => $['operation.add'], { ns: 'common' })}
-
-
-
-
-
-
-
- $['accessControlDialog.operateGroupAndMember.searchPlaceholder'],
- { ns: 'app' },
- )}
- placeholder={t(
- ($) => $['accessControlDialog.operateGroupAndMember.searchPlaceholder'],
- { ns: 'app' },
- )}
- className="block h-4.5 grow px-1 py-0 text-[13px] text-text-primary"
- />
-
-
- {isLoading ? (
-
-
-
- ) : (
- <>
- {shouldShowBreadcrumb && (
-
-
-
- )}
- {hasResults ? (
- <>
-
className="max-h-none p-1">
- {(subject) => (
- setBreadcrumbGroups([...breadcrumbGroups, group])}
- />
- )}
-
- {isFetchingNextPage &&
}
-
- >
- ) : (
-
- {t(($) => $['accessControlDialog.operateGroupAndMember.noResult'], { ns: 'app' })}
-
- )}
- >
- )}
-
-
-
- )
-}
-
-function SubjectOptionsSkeleton() {
- return (
-
- {[0, 1, 2, 3, 4].map((index) => (
-
-
-
-
-
-
- ))}
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/selection-list.tsx b/web/features/deployments/detail/access/permissions/access-subject-selector/selection-list.tsx
deleted file mode 100644
index 6c627f4eabc..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/selection-list.tsx
+++ /dev/null
@@ -1,226 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import type { AccessSubjectSelectionProps } from './types'
-import type { AccessControlAccount, AccessControlGroup } from '@/models/access-control'
-import { Avatar } from '@langgenius/dify-ui/avatar'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-
-type AccessSubjectSelectionListProps = AccessSubjectSelectionProps & {
- loading?: boolean
- className?: string
-}
-
-export function AccessSubjectSelectionList({
- selectedGroups,
- selectedMembers,
- onChange,
- loading,
- className,
-}: AccessSubjectSelectionListProps) {
- return (
-
- {loading ? (
-
- ) : (
-
- )}
-
- )
-}
-
-function AccessSubjectSelectionListSkeleton() {
- const { t } = useTranslation()
-
- return (
- $.loading, { ns: 'common' })}
- className="flex flex-col gap-y-2"
- >
-
-
- {[0, 1].map((index) => (
-
- ))}
-
-
-
- {[0, 1, 2].map((index) => (
-
- ))}
-
-
- )
-}
-
-function SelectedItemSkeleton({ withMeta = false }: { withMeta?: boolean }) {
- return (
-
-
-
- {withMeta && }
-
-
- )
-}
-
-function RenderGroupsAndMembers({
- selectedGroups,
- selectedMembers,
- onChange,
-}: AccessSubjectSelectionProps) {
- const { t } = useTranslation()
- if (selectedGroups.length <= 0 && selectedMembers.length <= 0) {
- return (
-
-
- {t(($) => $['accessControlDialog.noGroupsOrMembers'], { ns: 'app' })}
-
-
- )
- }
-
- return (
- <>
-
- {t(($) => $['accessControlDialog.groups'], {
- ns: 'app',
- count: selectedGroups.length ?? 0,
- })}
-
-
- {selectedGroups.map((group) => (
-
- ))}
-
-
- {t(($) => $['accessControlDialog.members'], {
- ns: 'app',
- count: selectedMembers.length ?? 0,
- })}
-
-
- {selectedMembers.map((member) => (
-
- ))}
-
- >
- )
-}
-
-type SelectedGroupItemProps = AccessSubjectSelectionProps & {
- group: AccessControlGroup
-}
-
-function SelectedGroupItem({
- group,
- selectedGroups,
- selectedMembers,
- onChange,
-}: SelectedGroupItemProps) {
- const handleRemoveGroup = () => {
- onChange({
- groups: selectedGroups.filter((selectedGroup) => selectedGroup.id !== group.id),
- members: selectedMembers,
- })
- }
-
- return (
-
- }
- onRemove={handleRemoveGroup}
- >
- {group.name}
- {group.groupSize}
-
- )
-}
-
-type SelectedMemberItemProps = AccessSubjectSelectionProps & {
- member: AccessControlAccount
-}
-
-function SelectedMemberItem({
- member,
- selectedGroups,
- selectedMembers,
- onChange,
-}: SelectedMemberItemProps) {
- const handleRemoveMember = () => {
- onChange({
- groups: selectedGroups,
- members: selectedMembers.filter((selectedMember) => selectedMember.id !== member.id),
- })
- }
-
- return (
- }
- onRemove={handleRemoveMember}
- >
- {member.name}
-
- )
-}
-
-type SelectedBaseItemProps = {
- icon: ReactNode
- children: ReactNode
- onRemove?: () => void
-}
-
-function SelectedBaseItem({ icon, onRemove, children }: SelectedBaseItemProps) {
- const { t } = useTranslation()
-
- return (
-
-
- {children}
-
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/subject-options.tsx b/web/features/deployments/detail/access/permissions/access-subject-selector/subject-options.tsx
deleted file mode 100644
index 7db803f9f15..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/subject-options.tsx
+++ /dev/null
@@ -1,225 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import type {
- AccessControlAccount,
- AccessControlGroup,
- Subject,
- SubjectAccount,
- SubjectGroup,
-} from '@/models/access-control'
-import { Avatar } from '@langgenius/dify-ui/avatar'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import { ComboboxItem, ComboboxItemText } from '@langgenius/dify-ui/combobox'
-import { useSuspenseQuery } from '@tanstack/react-query'
-import { useTranslation } from 'react-i18next'
-import { userProfileQueryOptions } from '@/features/account-profile/client'
-import { SubjectType } from '@/models/access-control'
-
-export function SubjectItem({
- subject,
- selectedGroups,
- onExpandGroup,
-}: {
- subject: Subject
- selectedGroups: AccessControlGroup[]
- onExpandGroup: (group: AccessControlGroup) => void
-}) {
- if (subject.subjectType === SubjectType.GROUP) {
- return (
-
- )
- }
-
- return
-}
-
-export function SelectedGroupsBreadCrumb({
- selectedGroupsForBreadcrumb,
- onChange,
-}: {
- selectedGroupsForBreadcrumb: AccessControlGroup[]
- onChange: (groups: AccessControlGroup[]) => void
-}) {
- const { t } = useTranslation()
-
- const handleBreadCrumbClick = (index: number) => {
- const newGroups = selectedGroupsForBreadcrumb.slice(0, index + 1)
- onChange(newGroups)
- }
- const handleReset = () => {
- onChange([])
- }
- const hasBreadcrumb = selectedGroupsForBreadcrumb.length > 0
-
- return (
-
- {hasBreadcrumb ? (
-
- ) : (
-
- {t(($) => $['accessControlDialog.operateGroupAndMember.allMembers'], { ns: 'app' })}
-
- )}
- {selectedGroupsForBreadcrumb.map((group, index) => {
- const isLastGroup = index === selectedGroupsForBreadcrumb.length - 1
-
- return (
-
- /
- {isLastGroup ? (
- {group.name}
- ) : (
-
- )}
-
- )
- })}
-
- )
-}
-
-type GroupItemProps = {
- group: AccessControlGroup
- subject: Subject
- selectedGroups: AccessControlGroup[]
- onExpandGroup: (group: AccessControlGroup) => void
-}
-
-function GroupItem({ group, subject, selectedGroups, onExpandGroup }: GroupItemProps) {
- const { t } = useTranslation()
- const isChecked = selectedGroups.some((selectedGroup) => selectedGroup.id === group.id)
-
- return (
-
-
- {(selected) => (
- <>
-
-
-
- {group.name}
- {group.groupSize}
-
- >
- )}
-
-
-
- )
-}
-
-type MemberItemProps = {
- member: AccessControlAccount
- subject: Subject
-}
-
-function MemberItem({ member, subject }: MemberItemProps) {
- const { data: currentUserEmail } = useSuspenseQuery({
- ...userProfileQueryOptions(),
- select: (data) => data.profile.email,
- })
- const { t } = useTranslation()
- return (
-
- {(selected) => (
- <>
-
-
-
- {member.name}
- {currentUserEmail === member.email && (
-
- ({t(($) => $.you, { ns: 'common' })})
-
- )}
-
- {member.email}
- >
- )}
-
- )
-}
-
-type ComboboxBaseItemProps = {
- className?: string
- subject: Subject
- children: (selected: boolean) => ReactNode
-}
-
-function ComboboxBaseItem({ children, className, subject }: ComboboxBaseItemProps) {
- return (
- (
-
- {children(state.selected)}
-
- )}
- />
- )
-}
-
-function SelectionBox({ checked }: { checked: boolean }) {
- return (
-
- {checked && }
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/types.ts b/web/features/deployments/detail/access/permissions/access-subject-selector/types.ts
deleted file mode 100644
index c0e680144e5..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/types.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { AccessControlAccount, AccessControlGroup } from '@/models/access-control'
-
-export type AccessSubjectSelectionValue = {
- groups: AccessControlGroup[]
- members: AccessControlAccount[]
-}
-
-export type AccessSubjectSelectionProps = {
- selectedGroups: AccessControlGroup[]
- selectedMembers: AccessControlAccount[]
- onChange: (value: AccessSubjectSelectionValue) => void
-}
diff --git a/web/features/deployments/detail/access/permissions/access-subject-selector/utils.ts b/web/features/deployments/detail/access/permissions/access-subject-selector/utils.ts
deleted file mode 100644
index be0f46ed053..00000000000
--- a/web/features/deployments/detail/access/permissions/access-subject-selector/utils.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import type { AccessSubjectSelectionValue } from './types'
-import type {
- AccessControlAccount,
- AccessControlGroup,
- Subject,
- SubjectAccount,
- SubjectGroup,
-} from '@/models/access-control'
-import { SubjectType } from '@/models/access-control'
-
-function groupToSubject(group: AccessControlGroup): SubjectGroup {
- return {
- subjectId: group.id,
- subjectType: SubjectType.GROUP,
- groupData: group,
- }
-}
-
-function memberToSubject(member: AccessControlAccount): SubjectAccount {
- return {
- subjectId: member.id,
- subjectType: SubjectType.ACCOUNT,
- accountData: member,
- }
-}
-
-export function getSubjectLabel(subject: Subject) {
- if (subject.subjectType === SubjectType.GROUP) return (subject as SubjectGroup).groupData.name
-
- return (subject as SubjectAccount).accountData.name
-}
-
-export function getSubjectValue(subject: Subject) {
- return `${subject.subjectType}:${subject.subjectId}`
-}
-
-export function isSameSubject(item: Subject, value: Subject) {
- return item.subjectId === value.subjectId && item.subjectType === value.subjectType
-}
-
-export function selectionValueToSubjects({ groups, members }: AccessSubjectSelectionValue) {
- return [...groups.map(groupToSubject), ...members.map(memberToSubject)]
-}
-
-export function subjectsToSelectionValue(subjects: Subject[]): AccessSubjectSelectionValue {
- const groups: AccessControlGroup[] = []
- const members: AccessControlAccount[] = []
-
- subjects.forEach((subject) => {
- if (subject.subjectType === SubjectType.GROUP) groups.push((subject as SubjectGroup).groupData)
- else members.push((subject as SubjectAccount).accountData)
- })
-
- return { groups, members }
-}
diff --git a/web/features/deployments/detail/access/permissions/environment-permission-row.tsx b/web/features/deployments/detail/access/permissions/environment-permission-row.tsx
deleted file mode 100644
index 7e1747a9276..00000000000
--- a/web/features/deployments/detail/access/permissions/environment-permission-row.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-'use client'
-
-import type { AccessPolicy, Environment, Subject } from '@dify/contracts/enterprise/types.gen'
-import type { AccessPermissionKind, SelectableAccessSubject } from './access-policy'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { DeploymentAccessControlDialog } from './access-control-dialog'
-import {
- accessModeToPermissionKey,
- normalizeResolvedSubject,
- permissionKeyToAccessMode,
- policySubjects,
- selectedSubjectsFromPolicy,
-} from './access-policy'
-import { PermissionSummaryButton } from './permission-summary-button'
-
-type AccessPermissionDraft = {
- fingerprint: string
- kind: AccessPermissionKind
- subjects: SelectableAccessSubject[]
-}
-
-type EnvironmentPermissionRowProps = {
- disabled?: boolean
- environment: Environment
- summaryPolicy?: AccessPolicy
- resolvedSubjects?: Subject[]
-}
-
-export function EnvironmentPermissionRow({
- disabled,
- environment,
- summaryPolicy,
- resolvedSubjects = [],
-}: EnvironmentPermissionRowProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const environmentId = environment.id
- const setEnvironmentAccessPolicy = useMutation(
- consoleQuery.enterprise.accessService.updateAccessPolicy.mutationOptions(),
- )
- const policy = summaryPolicy
- const policyKind = accessModeToPermissionKey(policy?.mode)
- const policyFingerprint = policy
- ? `${policy.mode}:${policy.subjects.map((subject) => `${subject.subjectType}:${subject.subjectId}`).join(',')}`
- : 'no-policy'
- const [draft, setDraft] = useState()
- const [dialogOpen, setDialogOpen] = useState(false)
- const subjectLabelCandidates = [
- ...(draft?.subjects ?? []),
- ...resolvedSubjects.flatMap((subject) => {
- const normalizedSubject = normalizeResolvedSubject(subject)
- return normalizedSubject ? [normalizedSubject] : []
- }),
- ]
- const hasDraft = draft?.fingerprint === policyFingerprint
- const permissionKind = hasDraft && draft ? draft.kind : policyKind
- const policySelectedSubjects =
- policyKind === 'specific' ? selectedSubjectsFromPolicy(policy, subjectLabelCandidates) : []
- const subjects = hasDraft && draft ? draft.subjects : policySelectedSubjects
- const isSaving = setEnvironmentAccessPolicy.isPending
- const controlsDisabled = disabled || isSaving || !appInstanceId
- const envName = environment.displayName
-
- const persistPolicy = (
- nextKind: AccessPermissionKind,
- nextSubjects: SelectableAccessSubject[],
- options?: {
- onSuccess?: () => void
- },
- ) => {
- if (!appInstanceId) return false
-
- if (nextKind === 'specific' && nextSubjects.length === 0) return false
-
- setEnvironmentAccessPolicy.mutate(
- {
- params: {
- appInstanceId,
- environmentId,
- },
- body: {
- appInstanceId,
- environmentId,
- mode: permissionKeyToAccessMode(nextKind),
- subjects: nextKind === 'specific' ? policySubjects(nextSubjects) : [],
- },
- },
- {
- onSuccess: options?.onSuccess,
- onError: () => {
- toast.error(t(($) => $['access.permission.updateFailed']))
- },
- },
- )
- return true
- }
-
- const handlePermissionSubmit = (
- nextKind: AccessPermissionKind,
- normalizedSubjects: SelectableAccessSubject[],
- ) => {
- persistPolicy(nextKind, normalizedSubjects, {
- onSuccess: () => {
- setDraft({
- fingerprint: policyFingerprint,
- kind: nextKind,
- subjects: normalizedSubjects,
- })
- setDialogOpen(false)
- },
- })
- }
-
- return (
-
-
- {envName}
-
-
setDialogOpen(true)}
- />
- setDialogOpen(false)}
- onSubmit={handlePermissionSubmit}
- />
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/permission-summary-button.tsx b/web/features/deployments/detail/access/permissions/permission-summary-button.tsx
deleted file mode 100644
index 9ae869afbdb..00000000000
--- a/web/features/deployments/detail/access/permissions/permission-summary-button.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-'use client'
-
-import type { AccessPermissionKind, SelectableAccessSubject } from './access-policy'
-import { AccessSubjectType } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useTranslation } from 'react-i18next'
-import { permissionIcon } from './access-policy'
-
-export function PermissionSummaryButton({
- value,
- subjects,
- disabled,
- loading,
- environmentLabel,
- onClick,
-}: {
- value: AccessPermissionKind
- subjects?: SelectableAccessSubject[]
- disabled?: boolean
- loading?: boolean
- environmentLabel: string
- onClick: () => void
-}) {
- const { t } = useTranslation('deployments')
- const groupCount =
- subjects?.filter(
- (subject) => subject.subjectType === AccessSubjectType.ACCESS_SUBJECT_TYPE_GROUP,
- ).length ?? 0
- const memberCount = (subjects?.length ?? 0) - groupCount
- const countLabels = [
- ...(groupCount > 0 ? [t(($) => $['access.members.groupCount'], { count: groupCount })] : []),
- ...(memberCount > 0 ? [t(($) => $['access.members.memberCount'], { count: memberCount })] : []),
- ]
- const specificSubjectLabel =
- value === 'specific'
- ? subjects && subjects.length > 0
- ? countLabels.join(' · ')
- : t(($) => $['access.permission.specificDesc'])
- : undefined
- const IconClassName = loading
- ? 'i-ri-loader-2-line animate-spin motion-reduce:animate-none'
- : permissionIcon[value]
-
- return (
-
- )
-}
diff --git a/web/features/deployments/detail/access/permissions/section.tsx b/web/features/deployments/detail/access/permissions/section.tsx
deleted file mode 100644
index 40b89649958..00000000000
--- a/web/features/deployments/detail/access/permissions/section.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-'use client'
-
-import type { EnvironmentAccessPolicy } from '@dify/contracts/enterprise/types.gen'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import {
- DeploymentEmptyState,
- DeploymentStateMessage,
-} from '../../../shared/components/empty-state'
-import { Section } from '../../../shared/components/section'
-import {
- accessSettingsAtom,
- accessSettingsIsErrorAtom,
- accessSettingsIsLoadingAtom,
-} from '../state'
-import { EnvironmentPermissionRow } from './environment-permission-row'
-
-const ACCESS_PERMISSIONS_SKELETON_KEYS = ['production', 'staging', 'development']
-
-function AccessPermissionsSkeleton() {
- return (
-
- {ACCESS_PERMISSIONS_SKELETON_KEYS.map((key) => (
-
-
-
-
- ))}
-
- )
-}
-
-export function AccessPermissionsSection() {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const accessSettings = useAtomValue(accessSettingsAtom)
- const isLoading = useAtomValue(accessSettingsIsLoadingAtom)
- const isError = useAtomValue(accessSettingsIsErrorAtom)
- const environmentPolicies: EnvironmentAccessPolicy[] | undefined =
- accessSettings?.environmentPolicies
- const policyRows = environmentPolicies ?? []
-
- return (
- $['access.permissions.title'])} showDivider={false}>
- {isLoading ? (
-
- ) : isError || !appInstanceId ? (
-
- {t(($) => $['common.loadFailed'])}
-
- ) : policyRows.length === 0 ? (
- $['access.runAccess.noEnvsTitle'])}
- description={t(($) => $['access.runAccess.noEnvs'])}
- />
- ) : (
-
- {policyRows.map((environmentPolicy) => {
- const environment = environmentPolicy.environment
- return (
-
- )
- })}
-
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/access/state.ts b/web/features/deployments/detail/access/state.ts
deleted file mode 100644
index b83d2b059c9..00000000000
--- a/web/features/deployments/detail/access/state.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-'use client'
-
-import { skipToken } from '@tanstack/react-query'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-
-export const accessSettingsQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
-
- return consoleQuery.enterprise.accessService.getAccessSettings.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- })
-})
-
-export const accessSettingsAtom = selectAtom(accessSettingsQueryAtom, (query) => query.data)
-export const accessSettingsIsLoadingAtom = selectAtom(
- accessSettingsQueryAtom,
- (query) => query.isLoading,
-)
-export const accessSettingsIsErrorAtom = selectAtom(
- accessSettingsQueryAtom,
- (query) => query.isError,
-)
diff --git a/web/features/deployments/detail/api-tokens/README.md b/web/features/deployments/detail/api-tokens/README.md
deleted file mode 100644
index 8559dd6a3e8..00000000000
--- a/web/features/deployments/detail/api-tokens/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Deployment API Tokens
-
-API tokens route for API token management, endpoint display, and API documentation drawer.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ---------------------------------------- | -------------------------------------------------------------------------- |
-| `route-state` | Reads the route app instance identity for API token queries. |
-| `detail/api-tokens/api-token-management` | Renders API endpoint display, API key creation, and API docs entry points. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/api-tokens/__tests__/state.spec.ts b/web/features/deployments/detail/api-tokens/__tests__/state.spec.ts
deleted file mode 100644
index d7134e95562..00000000000
--- a/web/features/deployments/detail/api-tokens/__tests__/state.spec.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
-}
-
-const mockDeveloperApiSettingsQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- accessService: {
- getDeveloperApiSettings: {
- queryOptions: (options: QueryOptions) => {
- mockDeveloperApiSettingsQueryOptions(options)
- return {
- ...options,
- queryKey: ['getDeveloperApiSettings', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/api-tokens`,
- params: { appInstanceId },
- })
-}
-
-describe('deployment API tokens state', () => {
- beforeEach(() => {
- mockDeveloperApiSettingsQueryOptions.mockClear()
- })
-
- it('should gate API token queries until a route app instance exists', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.developerApiSettingsQueryAtom)
- expect(mockDeveloperApiSettingsQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
-
- setDeploymentRoute(store)
- store.get(state.developerApiSettingsQueryAtom)
-
- expect(mockDeveloperApiSettingsQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- })
-})
diff --git a/web/features/deployments/detail/api-tokens/api-keys/README.md b/web/features/deployments/detail/api-tokens/api-keys/README.md
deleted file mode 100644
index 30efc77723c..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment API Keys
-
-API key creation, listing, and generated token presentation for the API tokens route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ------------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for API key mutations. |
-| `detail/api-tokens` | Uses API-token-owned query state and table styles. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/api-tokens/api-keys/__tests__/api-key-generate-menu.spec.tsx b/web/features/deployments/detail/api-tokens/api-keys/__tests__/api-key-generate-menu.spec.tsx
deleted file mode 100644
index 21044e7dd7a..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/__tests__/api-key-generate-menu.spec.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import type { Environment } from '@dify/contracts/enterprise/types.gen'
-import type { ReactNode } from 'react'
-import { fireEvent, render, screen } from '@testing-library/react'
-import { createStore, Provider as JotaiProvider } from 'jotai'
-import { describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { ApiKeyGenerateMenu } from '../api-key-generate-menu'
-
-const mockMutate = vi.hoisted(() => vi.fn())
-
-vi.mock('@tanstack/react-query', () => ({
- useMutation: () => ({
- isPending: false,
- mutate: mockMutate,
- }),
-}))
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- accessService: {
- createApiKey: {
- mutationOptions: () => ({ mutationKey: ['createApiKey'] }),
- },
- },
- },
- },
-}))
-
-function createEnvironment(): Environment {
- return {
- id: 'environment-1',
- displayName: 'Production',
- } as Environment
-}
-
-function renderMenu(appInstanceId?: string) {
- const store = createStore()
- store.set(setNextRouteStateAtom, {
- pathname: '/deployments/app-instance-1/api-tokens',
- params: appInstanceId ? { appInstanceId } : {},
- })
-
- const wrapper = ({ children }: { children: ReactNode }) => (
- {children}
- )
-
- return render(
- ,
- { wrapper },
- )
-}
-
-describe('ApiKeyGenerateMenu', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should show the required name error when submitting an empty name', () => {
- renderMenu('app-instance-1')
-
- fireEvent.click(screen.getByRole('button', { name: 'deployments.access.api.newKey' }))
- fireEvent.change(screen.getByLabelText('deployments.access.api.nameLabel'), {
- target: { value: ' ' },
- })
- fireEvent.click(screen.getByRole('button', { name: 'deployments.access.api.createKey' }))
-
- expect(screen.getByText('deployments.access.api.nameRequired')).toBeInTheDocument()
- expect(mockMutate).not.toHaveBeenCalled()
- })
-
- it('should clear the required name error when typing a valid name', () => {
- renderMenu('app-instance-1')
-
- fireEvent.click(screen.getByRole('button', { name: 'deployments.access.api.newKey' }))
- const nameInput = screen.getByLabelText('deployments.access.api.nameLabel')
-
- fireEvent.change(nameInput, {
- target: { value: ' ' },
- })
- fireEvent.click(screen.getByRole('button', { name: 'deployments.access.api.createKey' }))
- expect(screen.getByText('deployments.access.api.nameRequired')).toBeInTheDocument()
-
- fireEvent.change(nameInput, {
- target: { value: 'Production key' },
- })
-
- expect(screen.queryByText('deployments.access.api.nameRequired')).not.toBeInTheDocument()
- })
-
- it('should disable the trigger when route app instance is missing', () => {
- renderMenu(undefined)
-
- expect(screen.getByRole('button', { name: 'deployments.access.api.newKey' })).toBeDisabled()
- })
-})
diff --git a/web/features/deployments/detail/api-tokens/api-keys/api-key-generate-menu.tsx b/web/features/deployments/detail/api-tokens/api-keys/api-key-generate-menu.tsx
deleted file mode 100644
index d653add882e..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/api-key-generate-menu.tsx
+++ /dev/null
@@ -1,239 +0,0 @@
-'use client'
-
-import type { Environment } from '@dify/contracts/enterprise/types.gen'
-import type { ButtonProps } from '@langgenius/dify-ui/button'
-import type { FormEvent, ReactNode } from 'react'
-import { Button } from '@langgenius/dify-ui/button'
-import {
- Dialog,
- DialogCloseButton,
- DialogContent,
- DialogDescription,
- DialogTitle,
-} from '@langgenius/dify-ui/dialog'
-import { Input } from '@langgenius/dify-ui/input'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectItemIndicator,
- SelectItemText,
- SelectLabel,
- SelectTrigger,
-} from '@langgenius/dify-ui/select'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
-import { useEffect, useId, useRef, useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { generateApiTokenName } from './api-token-name'
-
-export function ApiKeyGenerateMenu({
- environments,
- onCreatedToken,
- triggerVariant = 'secondary',
- triggerClassName,
- children,
-}: {
- environments: Environment[]
- onCreatedToken: (token: string) => void
- triggerVariant?: ButtonProps['variant']
- triggerClassName?: string
- children?: (props: { trigger: ReactNode }) => ReactNode
-}) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const nameInputId = useId()
- const nameInputRef = useRef(null)
- const [createDialogOpen, setCreateDialogOpen] = useState(false)
- const [selectedEnvironmentId, setSelectedEnvironmentId] = useState()
- const [draftName, setDraftName] = useState('')
- const [nameError, setNameError] = useState(false)
- const generateApiKey = useMutation(
- consoleQuery.enterprise.accessService.createApiKey.mutationOptions(),
- )
- const selectableEnvironments = environments
- const selectedEnvironment = selectedEnvironmentId
- ? selectableEnvironments.find((env) => env.id === selectedEnvironmentId)
- : undefined
- const disabled = !appInstanceId || selectableEnvironments.length === 0
- const isCreating = generateApiKey.isPending
-
- useEffect(() => {
- if (createDialogOpen) nameInputRef.current?.focus()
- }, [createDialogOpen])
-
- function handleOpenCreateDialog() {
- const firstEnvironment = selectableEnvironments[0]
- if (!firstEnvironment) return
-
- setSelectedEnvironmentId(firstEnvironment.id)
- setDraftName(generateApiTokenName())
- setNameError(false)
- setCreateDialogOpen(true)
- }
-
- function handleEnvironmentChange(environmentId: string) {
- setSelectedEnvironmentId(environmentId)
- setNameError(false)
- }
-
- function handleDraftNameChange(nextDraftName: string) {
- setDraftName(nextDraftName)
- if (nameError && nextDraftName.trim()) setNameError(false)
- }
-
- function resetCreateDialog() {
- setCreateDialogOpen(false)
- setSelectedEnvironmentId(undefined)
- setDraftName('')
- setNameError(false)
- }
-
- function handleDialogOpenChange(nextOpen: boolean) {
- if (nextOpen || isCreating) return
-
- resetCreateDialog()
- }
-
- function handleGenerateApiKey(event: FormEvent) {
- event.preventDefault()
-
- const name = draftName.trim()
-
- if (!appInstanceId || !selectedEnvironmentId || !name) {
- setNameError(true)
- return
- }
-
- generateApiKey.mutate(
- {
- params: {
- appInstanceId,
- environmentId: selectedEnvironmentId,
- },
- body: {
- appInstanceId,
- environmentId: selectedEnvironmentId,
- displayName: name,
- },
- },
- {
- onSuccess: (response) => {
- if (response.token) onCreatedToken(response.token)
- resetCreateDialog()
- },
- onError: () => {
- toast.error(t(($) => $['access.api.createFailed']))
- },
- },
- )
- }
-
- const trigger = (
-
- )
-
- return (
- <>
- {children ? children({ trigger }) : trigger}
-
- >
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/api-keys/api-key-list.tsx b/web/features/deployments/detail/api-tokens/api-keys/api-key-list.tsx
deleted file mode 100644
index c3f61bdeda5..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/api-key-list.tsx
+++ /dev/null
@@ -1,250 +0,0 @@
-'use client'
-
-import type { ApiKey, Environment } from '@dify/contracts/enterprise/types.gen'
-import {
- AlertDialog,
- AlertDialogActions,
- AlertDialogCancelButton,
- AlertDialogConfirmButton,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogTitle,
-} from '@langgenius/dify-ui/alert-dialog'
-import { cn } from '@langgenius/dify-ui/cn'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../../shared/components/detail-table'
-import { API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES } from '../table-styles'
-
-function ApiKeyName({ apiKey }: { apiKey: ApiKey }) {
- return {apiKey.displayName}
-}
-
-function EnvironmentBadge({ environment }: { environment?: Environment }) {
- return (
-
- {environment?.displayName ?? '—'}
-
- )
-}
-
-function ApiKeyValue({ value }: { value: string }) {
- return (
-
- )
-}
-
-function RevokeApiKeyButton({ apiKey }: { apiKey: ApiKey }) {
- const { t } = useTranslation('deployments')
- const [showRevokeConfirm, setShowRevokeConfirm] = useState(false)
- const revokeApiKey = useMutation(
- consoleQuery.enterprise.accessService.deleteApiKey.mutationOptions(),
- )
- const isRevoking = revokeApiKey.isPending
- const apiKeyName = apiKey.displayName
-
- function handleRevoke() {
- if (isRevoking) return
-
- revokeApiKey.mutate(
- {
- params: {
- appInstanceId: apiKey.appInstanceId,
- environmentId: apiKey.environmentId,
- apiKeyId: apiKey.id,
- },
- },
- {
- onSuccess: () => {
- setShowRevokeConfirm(false)
- toast.success(t(($) => $['access.api.revokeSuccess']))
- },
- onError: () => {
- toast.error(t(($) => $['access.api.revokeFailed']))
- },
- },
- )
- }
-
- function handleRevokeConfirmOpenChange(open: boolean) {
- if (isRevoking) return
-
- setShowRevokeConfirm(open)
- }
-
- return (
- <>
-
-
-
-
-
- {t(($) => $['access.api.revokeConfirmTitle'])}
-
-
- {t(($) => $['access.api.revokeConfirmDescription'], { name: apiKeyName })}
-
-
-
-
- {t(($) => $['operation.cancel'], { ns: 'common' })}
-
-
- {t(($) => $['access.revoke'])}
-
-
-
-
- >
- )
-}
-
-function ApiKeyMobileRow({ apiKey, environment }: { apiKey: ApiKey; environment?: Environment }) {
- const { t } = useTranslation('deployments')
- const displayValue = apiKey.maskedToken
-
- return (
-
-
-
-
-
- {t(($) => $['access.api.table.key'])}
-
-
-
-
-
- )
-}
-
-function ApiKeyDesktopRow({ apiKey, environment }: { apiKey: ApiKey; environment?: Environment }) {
- const displayValue = apiKey.maskedToken
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function ApiKeyTableHeader() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
-
- {t(($) => $['access.api.table.name'])}
-
-
- {t(($) => $['access.api.table.environment'])}
-
-
- {t(($) => $['access.api.table.key'])}
-
-
- {t(($) => $['access.api.table.action'])}
-
-
-
- )
-}
-
-export function ApiKeyList({
- apiKeys,
- environments,
-}: {
- apiKeys: ApiKey[]
- environments: Environment[]
-}) {
- const environmentById = new Map(environments.map((environment) => [environment.id, environment]))
-
- return (
- <>
-
- {apiKeys.map((apiKey) => (
-
- ))}
-
-
-
-
-
- {apiKeys.map((apiKey) => (
-
- ))}
-
-
-
- >
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/api-keys/api-token-name.ts b/web/features/deployments/detail/api-tokens/api-keys/api-token-name.ts
deleted file mode 100644
index 0f494a7a733..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/api-token-name.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-const API_TOKEN_NAME_ADJECTIVES = [
- 'ancient',
- 'autumn',
- 'bright',
- 'calm',
- 'crystal',
- 'gentle',
- 'golden',
- 'hidden',
- 'holy',
- 'quiet',
- 'rapid',
- 'silver',
-]
-
-const API_TOKEN_NAME_NOUNS = [
- 'brook',
- 'cloud',
- 'field',
- 'forest',
- 'harbor',
- 'lake',
- 'meadow',
- 'moon',
- 'river',
- 'stone',
- 'valley',
- 'wave',
-]
-
-function randomListItem(items: string[]) {
- return items[Math.floor(Math.random() * items.length)]!
-}
-
-export function generateApiTokenName() {
- const suffix = Math.floor(1000 + Math.random() * 9000)
-
- return `${randomListItem(API_TOKEN_NAME_ADJECTIVES)}-${randomListItem(API_TOKEN_NAME_NOUNS)}-${suffix}`
-}
diff --git a/web/features/deployments/detail/api-tokens/api-keys/created-token-dialog.tsx b/web/features/deployments/detail/api-tokens/api-keys/created-token-dialog.tsx
deleted file mode 100644
index 9e71316ce0b..00000000000
--- a/web/features/deployments/detail/api-tokens/api-keys/created-token-dialog.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-'use client'
-
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Dialog,
- DialogCloseButton,
- DialogContent,
- DialogDescription,
- DialogTitle,
-} from '@langgenius/dify-ui/dialog'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useClipboard } from 'foxact/use-clipboard'
-import { useTranslation } from 'react-i18next'
-import { CopyPill } from '../../../shared/components/endpoint'
-
-function buildCurlExample(apiUrl: string, token: string) {
- return `curl -X POST '${apiUrl}' \\
---header 'Authorization: Bearer ${token}' \\
---header 'Content-Type: application/json' \\
---data-raw '{
- "inputs": {},
- "response_mode": "streaming",
- "user": "abc-123"
-}'`
-}
-
-function CurlExample({ apiUrl, token }: { apiUrl: string; token: string }) {
- const { t } = useTranslation('deployments')
- const curlExample = buildCurlExample(apiUrl, token)
- const { copied, copy } = useClipboard({
- onCopyError: () => {
- toast.error(t(($) => $['access.copyFailed']))
- },
- })
-
- return (
-
-
-
- {t(($) => $['access.api.curlExampleTitle'])}
-
-
-
-
- {curlExample}
-
-
- )
-}
-
-export function CreatedApiTokenDialog({
- token,
- apiUrl,
- onDismiss,
-}: {
- token: string
- apiUrl?: string
- onDismiss: () => void
-}) {
- const { t } = useTranslation('deployments')
-
- return (
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/api-token-management/README.md b/web/features/deployments/detail/api-tokens/api-token-management/README.md
deleted file mode 100644
index 196f5586ffe..00000000000
--- a/web/features/deployments/detail/api-tokens/api-token-management/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment API Token Management
-
-API token management section for API endpoint display, token creation, and token listing.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ---------------------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for API token mutations. |
-| `detail/api-tokens` | Reads API tokens route query data and table styles. |
-| `detail/api-tokens/api-keys` | Renders API key creation, listing, and created-token surfaces. |
-| `detail/api-tokens/docs` | Opens API documentation for the current endpoint. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/api-tokens/api-token-management/section.tsx b/web/features/deployments/detail/api-tokens/api-token-management/section.tsx
deleted file mode 100644
index a2ab939c869..00000000000
--- a/web/features/deployments/detail/api-tokens/api-token-management/section.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-'use client'
-
-import type { ApiKey, Environment } from '@dify/contracts/enterprise/types.gen'
-import type { ReactNode } from 'react'
-import { Button } from '@langgenius/dify-ui/button'
-import { useAtomValue } from 'jotai'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import {
- DeploymentEmptyState,
- DeploymentStateMessage,
-} from '../../../shared/components/empty-state'
-import { CopyPill } from '../../../shared/components/endpoint'
-import { ApiKeyGenerateMenu } from '../api-keys/api-key-generate-menu'
-import { ApiKeyList } from '../api-keys/api-key-list'
-import { CreatedApiTokenDialog } from '../api-keys/created-token-dialog'
-import { DeveloperApiDocsDrawer } from '../docs/docs-drawer'
-import {
- developerApiSettingsAtom,
- developerApiSettingsIsErrorAtom,
- developerApiSettingsIsLoadingAtom,
-} from '../state'
-import { DeveloperApiSkeleton } from './skeleton'
-
-type CreatedApiToken = {
- appInstanceId: string
- token: string
-}
-
-function ApiKeyListSection({
- apiKeys,
- environments,
- action,
-}: {
- apiKeys: ApiKey[]
- environments: Environment[]
- action?: ReactNode
-}) {
- const { t } = useTranslation('deployments')
- const hasAction = Boolean(action)
-
- return (
-
-
-
- {t(($) => $['access.api.keyList'])}
-
- {hasAction && (
-
- {action}
-
- )}
-
-
-
- )
-}
-
-function DeveloperApiEndpoint({ apiUrl }: { apiUrl: string }) {
- const { t } = useTranslation('deployments')
- const [apiDocsOpen, setApiDocsOpen] = useState(false)
-
- return (
-
- $['access.api.endpoint'])}
- value={apiUrl}
- className="min-w-0 flex-1"
- />
-
-
-
- )
-}
-
-export function DeveloperApiSection() {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const [createdApiToken, setCreatedApiToken] = useState()
- const developerApiSettings = useAtomValue(developerApiSettingsAtom)
- const isLoading = useAtomValue(developerApiSettingsIsLoadingAtom)
- const isError = useAtomValue(developerApiSettingsIsErrorAtom)
- const accessChannels = developerApiSettings?.accessChannels
- const apiEnabled = accessChannels?.developerApiEnabled ?? false
- const apiUrl = developerApiSettings?.developerApiUrl.apiUrl
- const apiKeys: ApiKey[] = developerApiSettings?.apiKeys ?? []
- const environments = developerApiSettings?.environments ?? []
- const visibleCreatedApiToken =
- createdApiToken && createdApiToken.appInstanceId === appInstanceId
- ? createdApiToken.token
- : undefined
- const hasSelectableEnvironment = environments.some((environment) => Boolean(environment.id))
-
- if (isLoading) return
-
- if (isError || !appInstanceId)
- return (
-
- {t(($) => $['common.loadFailed'])}
-
- )
-
- if (!apiEnabled) {
- return (
- $['access.api.disabled'])}
- description={t(($) => $['access.api.disabledHint'])}
- />
- )
- }
-
- return (
-
- {apiUrl &&
}
- {hasSelectableEnvironment ? (
-
setCreatedApiToken({ appInstanceId, token })}
- >
- {({ trigger }) =>
- apiKeys.length === 0 ? (
- $['access.api.noKeysTitle'])}
- description={t(($) => $['access.api.noKeys'])}
- action={trigger}
- />
- ) : (
-
- )
- }
-
- ) : apiKeys.length === 0 ? (
-
$['access.api.emptyTitle'])}
- description={t(($) => $['access.api.empty'])}
- />
- ) : (
-
- )}
- {visibleCreatedApiToken && (
- setCreatedApiToken(undefined)}
- />
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/api-token-management/skeleton.tsx b/web/features/deployments/detail/api-tokens/api-token-management/skeleton.tsx
deleted file mode 100644
index 0ed084d9557..00000000000
--- a/web/features/deployments/detail/api-tokens/api-token-management/skeleton.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-'use client'
-
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../../shared/components/detail-table'
-import { API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES } from '../table-styles'
-
-const DEVELOPER_API_KEY_SKELETON_KEYS = ['primary-key', 'secondary-key']
-
-export function DeveloperApiSkeleton() {
- return (
-
- )
-}
-
-function ApiUrlSkeleton() {
- return (
-
- )
-}
-
-function ApiKeyTableSkeleton() {
- return (
- <>
-
- {DEVELOPER_API_KEY_SKELETON_KEYS.map((key) => (
-
-
-
- ))}
-
-
-
-
-
- {DEVELOPER_API_KEY_SKELETON_KEYS.map((key) => (
-
- ))}
-
-
-
- >
- )
-}
-
-function ApiKeyTableHeaderSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
-
- {t(($) => $['access.api.table.name'])}
-
-
- {t(($) => $['access.api.table.environment'])}
-
-
- {t(($) => $['access.api.table.key'])}
-
-
- {t(($) => $['access.api.table.action'])}
-
-
-
- )
-}
-
-function ApiKeyDesktopRowSkeleton() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/developer-api-header-switch.tsx b/web/features/deployments/detail/api-tokens/developer-api-header-switch.tsx
deleted file mode 100644
index 9c69863b2c9..00000000000
--- a/web/features/deployments/detail/api-tokens/developer-api-header-switch.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-'use client'
-
-import type { AccessChannels } from '@dify/contracts/enterprise/types.gen'
-import { Switch, SwitchSkeleton } from '@langgenius/dify-ui/switch'
-import { useMutation } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-import {
- developerApiSettingsAtom,
- developerApiSettingsIsErrorAtom,
- developerApiSettingsIsLoadingAtom,
-} from './state'
-
-function DeveloperApiSwitch({
- checked,
- accessChannels,
- disabled,
-}: {
- checked: boolean
- accessChannels?: AccessChannels
- disabled?: boolean
-}) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const toggleDeveloperAPI = useMutation(
- consoleQuery.enterprise.accessService.updateAccessChannels.mutationOptions(),
- )
-
- return (
- $['access.api.developerTitle'])}
- checked={checked}
- disabled={disabled || !appInstanceId}
- loading={toggleDeveloperAPI.isPending}
- onCheckedChange={(enabled) => {
- if (!appInstanceId) return
-
- toggleDeveloperAPI.mutate({
- params: { appInstanceId },
- body: {
- appInstanceId,
- webAppEnabled: accessChannels?.webAppEnabled ?? false,
- developerApiEnabled: enabled,
- },
- })
- }}
- />
- )
-}
-
-export function DeveloperApiHeaderSwitch() {
- const { t } = useTranslation('deployments')
- const developerApiSettings = useAtomValue(developerApiSettingsAtom)
- const isLoading = useAtomValue(developerApiSettingsIsLoadingAtom)
- const isError = useAtomValue(developerApiSettingsIsErrorAtom)
- const accessChannels = developerApiSettings?.accessChannels
- const apiEnabled = accessChannels?.developerApiEnabled ?? false
-
- if (isLoading) return
-
- return (
-
-
- {apiEnabled ? t(($) => $['overview.enabled']) : t(($) => $['overview.disabled'])}
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/docs/README.md b/web/features/deployments/detail/api-tokens/docs/README.md
deleted file mode 100644
index a8b91cdec53..00000000000
--- a/web/features/deployments/detail/api-tokens/docs/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Deployment API Token Docs
-
-API documentation drawer for the API tokens route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ------------- | ------------------------------------------------------------- |
-| `route-state` | Reads the route app instance identity for documentation copy. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| --------------------------------- | ----------------------------------------------------------- |
-| `app/components/develop/template` | Reuses localized workflow API documentation templates. |
-| `context/i18n` | Reads the current locale for documentation template choice. |
-| `hooks/use-theme` | Reads the current theme for documentation rendering. |
-| `i18n-config/language` | Maps the current locale to the documentation language. |
-| `types/app` | Uses app and theme enums for documentation rendering. |
diff --git a/web/features/deployments/detail/api-tokens/docs/docs-drawer.tsx b/web/features/deployments/detail/api-tokens/docs/docs-drawer.tsx
deleted file mode 100644
index 9953925d3f9..00000000000
--- a/web/features/deployments/detail/api-tokens/docs/docs-drawer.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-'use client'
-
-import type { App } from '@/types/app'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Drawer,
- DrawerBackdrop,
- DrawerCloseButton,
- DrawerContent,
- DrawerDescription,
- DrawerPopup,
- DrawerPortal,
- DrawerTitle,
- DrawerViewport,
-} from '@langgenius/dify-ui/drawer'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import TemplateWorkflowEn from '@/app/components/develop/template/template_workflow.en.mdx'
-import TemplateWorkflowJa from '@/app/components/develop/template/template_workflow.ja.mdx'
-import TemplateWorkflowZh from '@/app/components/develop/template/template_workflow.zh.mdx'
-import { useLocale } from '@/context/i18n'
-import useTheme from '@/hooks/use-theme'
-import { getDocLanguage } from '@/i18n-config/language'
-import { AppModeEnum, Theme } from '@/types/app'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-
-type PromptVariable = { key: string; name: string }
-type WorkflowApiDocAppDetail = Pick
-
-type WorkflowDocTemplateProps = {
- appDetail: WorkflowApiDocAppDetail
- variables: PromptVariable[]
- inputs: Record
-}
-
-const EMPTY_VARIABLES: PromptVariable[] = []
-const EMPTY_INPUTS: Record = {}
-
-function WorkflowDocTemplate({
- docLanguage,
- appDetail,
- variables,
- inputs,
-}: WorkflowDocTemplateProps & {
- docLanguage: string
-}) {
- if (docLanguage === 'zh') {
- return
- }
- if (docLanguage === 'ja') {
- return
- }
-
- return
-}
-
-export function DeveloperApiDocsDrawer({
- open,
- apiBaseUrl,
- onOpenChange,
-}: {
- open: boolean
- apiBaseUrl: string
- onOpenChange: (open: boolean) => void
-}) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const locale = useLocale()
- const { theme } = useTheme()
- const docLanguage = getDocLanguage(locale)
-
- if (!appInstanceId) return null
-
- const appDetail: WorkflowApiDocAppDetail = {
- id: appInstanceId,
- mode: AppModeEnum.WORKFLOW,
- api_base_url: apiBaseUrl,
- }
-
- return (
-
-
-
-
-
- $['access.api.docsClose'])}
- className="absolute top-4 right-5 size-6 rounded-md"
- />
-
-
-
- {t(($) => $['access.api.docsTitle'])}
-
-
- {t(($) => $['access.api.docsDescription'])}
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/index.tsx b/web/features/deployments/detail/api-tokens/index.tsx
deleted file mode 100644
index c42aedfa9be..00000000000
--- a/web/features/deployments/detail/api-tokens/index.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-'use client'
-
-import { DeveloperApiSection } from './api-token-management/section'
-
-export function DeploymentApiTokens() {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/api-tokens/state.ts b/web/features/deployments/detail/api-tokens/state.ts
deleted file mode 100644
index 475e7c00c69..00000000000
--- a/web/features/deployments/detail/api-tokens/state.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-'use client'
-
-import { skipToken } from '@tanstack/react-query'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-
-export const developerApiSettingsQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
-
- return consoleQuery.enterprise.accessService.getDeveloperApiSettings.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- })
-})
-
-export const developerApiSettingsAtom = selectAtom(
- developerApiSettingsQueryAtom,
- (query) => query.data,
-)
-export const developerApiSettingsIsLoadingAtom = selectAtom(
- developerApiSettingsQueryAtom,
- (query) => query.isLoading,
-)
-export const developerApiSettingsIsErrorAtom = selectAtom(
- developerApiSettingsQueryAtom,
- (query) => query.isError,
-)
diff --git a/web/features/deployments/detail/api-tokens/table-styles.ts b/web/features/deployments/detail/api-tokens/table-styles.ts
deleted file mode 100644
index 879c8492639..00000000000
--- a/web/features/deployments/detail/api-tokens/table-styles.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES = {
- action: 'w-16 py-1.5 whitespace-nowrap',
- environment: 'whitespace-nowrap',
- key: '',
- name: 'whitespace-nowrap',
-}
diff --git a/web/features/deployments/detail/deployment-sidebar.tsx b/web/features/deployments/detail/deployment-sidebar.tsx
deleted file mode 100644
index 88a6122e3e3..00000000000
--- a/web/features/deployments/detail/deployment-sidebar.tsx
+++ /dev/null
@@ -1,307 +0,0 @@
-'use client'
-
-import type { ComponentProps, PropsWithoutRef } from 'react'
-import type { InstanceDetailTabKey } from './tabs'
-import type { NavIcon } from '@/app/components/app-sidebar/nav-link'
-import { cn } from '@langgenius/dify-ui/cn'
-import { DialogTrigger } from '@langgenius/dify-ui/dialog'
-import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
-import { formatForDisplay } from '@tanstack/react-hotkeys'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import NavLink from '@/app/components/app-sidebar/nav-link'
-import Divider from '@/app/components/base/divider'
-import SidebarLeftArrowIcon from '@/app/components/base/icons/src/vender/SidebarLeftArrowIcon'
-import { SkeletonContainer, SkeletonRectangle } from '@/app/components/base/skeleton'
-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'
-import Link from '@/next/link'
-import { usePathname } from '@/next/navigation'
-import { DeploymentActionsMenu } from '../deployment-actions'
-import { deploymentRouteAppInstanceIdAtom } from '../route-state'
-import { TitleTooltip } from '../shared/components/title-tooltip'
-import {
- deploymentDetailAppInstanceAtom,
- deploymentDetailAppInstanceIsErrorAtom,
- deploymentDetailAppInstanceIsLoadingAtom,
-} from './state'
-
-type TabDef = {
- key: InstanceDetailTabKey
- icon: NavIcon
- selectedIcon: NavIcon
- hidden?: boolean
-}
-
-type TailwindNavIconProps = PropsWithoutRef> & {
- title?: string
- titleId?: string
-}
-
-function OverviewIcon({ className }: TailwindNavIconProps) {
- return
-}
-function OverviewSelectedIcon({ className }: TailwindNavIconProps) {
- return
-}
-function DeployIcon({ className }: TailwindNavIconProps) {
- return
-}
-function DeploySelectedIcon({ className }: TailwindNavIconProps) {
- return
-}
-function VersionsIcon({ className }: TailwindNavIconProps) {
- return
-}
-function VersionsSelectedIcon({ className }: TailwindNavIconProps) {
- return
-}
-function AccessIcon({ className }: TailwindNavIconProps) {
- return
-}
-function AccessSelectedIcon({ className }: TailwindNavIconProps) {
- return
-}
-function ApiIcon({ className }: TailwindNavIconProps) {
- return
-}
-function ApiSelectedIcon({ className }: TailwindNavIconProps) {
- return
-}
-
-const DEPLOYMENT_TABS: TabDef[] = [
- { key: 'overview', icon: OverviewIcon, selectedIcon: OverviewSelectedIcon },
- { key: 'instances', icon: DeployIcon, selectedIcon: DeploySelectedIcon },
- { key: 'releases', icon: VersionsIcon, selectedIcon: VersionsSelectedIcon },
- { key: 'access', icon: AccessIcon, selectedIcon: AccessSelectedIcon, hidden: true },
- { key: 'api-tokens', icon: ApiIcon, selectedIcon: ApiSelectedIcon },
-]
-
-function DeploymentIcon({ expand }: { expand: boolean }) {
- return (
-
-
-
- )
-}
-
-function DeploymentDetailInstanceInfo({
- appInstanceId,
- expand,
-}: {
- appInstanceId: string
- expand: boolean
-}) {
- const { t } = useTranslation('deployments')
- const overview = useAtomValue(deploymentDetailAppInstanceAtom)
- const isOverviewLoading = useAtomValue(deploymentDetailAppInstanceIsLoadingAtom)
- const isOverviewError = useAtomValue(deploymentDetailAppInstanceIsErrorAtom)
- const app = overview?.appInstance
- const isLoading = !app && isOverviewLoading
- const isUnavailable = !app || isOverviewError
- const instanceName = app ? app.displayName : appInstanceId
-
- return (
-
- {isLoading ? (
- <>
-
- {expand && (
-
-
-
-
- )}
- >
- ) : isUnavailable ? (
- <>
-
-
-
- {expand && (
-
-
-
- {t(($) => $['detail.notFound'])}
-
-
-
-
- {appInstanceId}
-
-
-
- )}
- >
- ) : (
- <>
-
- {expand && (
- <>
-
-
-
-
- {instanceName}
-
-
-
- {app.description && (
-
-
- {app.description}
-
-
- )}
-
-
- >
- )}
- >
- )}
-
- )
-}
-
-export function DeploymentDetailTop({
- expand = true,
- onToggle,
-}: {
- expand?: boolean
- onToggle?: () => void
-}) {
- const { t } = useTranslation()
-
- if (!expand) {
- return (
-
- {onToggle && (
- }
- className="size-8 rounded-[10px] border-0 bg-transparent px-0 text-text-tertiary shadow-none hover:border-0 hover:bg-state-base-hover hover:text-text-secondary"
- />
- )}
-
- )
- }
-
- return (
-
-
- $['mainNav.home'], { ns: 'common' })}
- className="flex shrink-0 items-center rounded-lg py-2 pr-1.5 pl-0.5 text-text-tertiary transition-colors hover:bg-background-default-hover hover:text-text-secondary"
- >
-
-
-
- /
-
- {t(($) => $['menus.deployments'], { ns: 'common' })}
-
-
-
- $['gotoAnything.searchTitle'], { ns: 'app' })}
- className="flex size-8 shrink-0 items-center justify-center overflow-hidden rounded-[10px] text-text-tertiary transition-colors hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden"
- >
-
-
- }
- />
- }
- />
-
- {t(($) => $['gotoAnything.quickAction'], { ns: 'app' })}
-
- {GOTO_ANYTHING_HOTKEY.split('+').map((key) => (
- {formatForDisplay(key)}
- ))}
-
-
-
- {onToggle && (
-
}
- className="size-8 rounded-[10px] border-0 bg-transparent px-0 text-text-tertiary shadow-none hover:border-0 hover:bg-state-base-hover hover:text-text-secondary"
- />
- )}
-
- )
-}
-
-export function DeploymentDetailSection({ expand = true }: { expand?: boolean }) {
- const { t } = useTranslation('deployments')
- const pathname = usePathname()
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
-
- if (!appInstanceId) return null
-
- return (
-
- {!expand && (
-
- )}
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/detail-sidebar.tsx b/web/features/deployments/detail/detail-sidebar.tsx
deleted file mode 100644
index b924b792cdf..00000000000
--- a/web/features/deployments/detail/detail-sidebar.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-'use client'
-
-import { DetailSidebarFrame } from '@/app/components/detail-sidebar'
-import { DeploymentDetailSection, DeploymentDetailTop } from './deployment-sidebar'
-
-export function DeploymentDetailSidebar() {
- return (
- (
-
- )}
- renderSection={({ expand }) => }
- />
- )
-}
diff --git a/web/features/deployments/detail/index.tsx b/web/features/deployments/detail/index.tsx
deleted file mode 100644
index e6a722db5cc..00000000000
--- a/web/features/deployments/detail/index.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import useDocumentTitle from '@/hooks/use-document-title'
-import Link from '@/next/link'
-import { CreateReleaseControl } from '../create-release'
-import { deploymentRouteAppInstanceIdAtom } from '../route-state'
-import { DeveloperApiHeaderSwitch } from './api-tokens/developer-api-header-switch'
-import { NewDeploymentHeaderAction } from './instances/header-actions/new-deployment-button'
-import { deploymentDetailActiveTabAtom } from './state'
-import { INSTANCE_DETAIL_TAB_KEYS } from './tabs'
-
-function MobileDetailTabs() {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const activeTab = useAtomValue(deploymentDetailActiveTabAtom)
-
- if (!appInstanceId) return null
-
- return (
-
- )
-}
-
-export function InstanceDetail({ children }: { children: ReactNode }) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const activeTab = useAtomValue(deploymentDetailActiveTabAtom)
-
- useDocumentTitle(t(($) => $['documentTitle.detail']))
-
- if (!appInstanceId) return null
-
- return (
-
-
-
-
-
-
-
-
-
- {t(($) => $[`tabs.${activeTab}.name`])}
-
- {activeTab === 'api-tokens' && (
-
-
-
- )}
-
-
- {t(($) => $[`tabs.${activeTab}.description`])}
-
-
- {(activeTab === 'instances' || activeTab === 'releases') && (
-
- {activeTab === 'instances' ? (
-
- ) : (
-
- )}
-
- )}
-
-
-
- {children}
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/instances/README.md b/web/features/deployments/detail/instances/README.md
deleted file mode 100644
index d358348eca3..00000000000
--- a/web/features/deployments/detail/instances/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Deployment Instances
-
-Instances route for listing environment deployments and running deployment row actions.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ----------------------------------- | ----------------------------------------------------------------------------------- |
-| `detail` | Reads detail-owned query state and runtime instance rows before composing sections. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `detail/instances/environment-list` | Renders environment deployment rows. |
-| `detail/instances/header-actions` | Renders the new deployment action for empty instances. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------------------------ | --------------------------------------------------------------- |
-| `app/components/base/skeleton` | Reuses skeleton primitives for deployment table loading states. |
diff --git a/web/features/deployments/detail/instances/environment-list/README.md b/web/features/deployments/detail/instances/environment-list/README.md
deleted file mode 100644
index cc4154c4202..00000000000
--- a/web/features/deployments/detail/instances/environment-list/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Instances Environment List
-
-Environment list section for rendering deployment rows and row-level status summaries on the instances route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ------------------------------ | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `detail/instances` | Uses instances-owned table column class names for deployment rows. |
-| `detail/instances/row-actions` | Renders row-level deployment actions for each environment. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/instances/environment-list/deployment-environment-list.tsx b/web/features/deployments/detail/instances/environment-list/deployment-environment-list.tsx
deleted file mode 100644
index a2841973e67..00000000000
--- a/web/features/deployments/detail/instances/environment-list/deployment-environment-list.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import { useTranslation } from 'react-i18next'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../../shared/components/detail-table'
-import { releaseCommit } from '../../../shared/domain/release'
-import { isUndeployedDeploymentRow } from '../../../shared/domain/runtime-status'
-import { DeploymentRowActions } from '../row-actions/deployment-row-actions'
-import { DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES } from '../table-styles'
-import { DeploymentStatusSummary } from './deployment-status-summary'
-
-function EnvironmentSummary({
- environment,
-}: {
- environment: EnvironmentDeployment['environment']
-}) {
- return {environment.displayName}
-}
-
-function CurrentReleaseSummary({ release }: { release: EnvironmentDeployment['currentRelease'] }) {
- if (!release) return —
-
- const commit = releaseCommit(release)
-
- return (
-
-
- {release.displayName}
- {commit !== '—' && (
- {commit}
- )}
-
-
- )
-}
-
-function CurrentReleaseMobileSummary({
- release,
-}: {
- release: EnvironmentDeployment['currentRelease']
-}) {
- const { t } = useTranslation('deployments')
-
- if (!release) return null
-
- return (
-
-
- {t(($) => $['deployTab.col.currentRelease'])}
-
-
-
- )
-}
-
-function DeploymentEnvironmentMobileRow({ row }: { row: EnvironmentDeployment }) {
- const envId = row.environment.id
- const release = row.currentRelease
-
- return (
-
-
-
-
-
-
- {!isUndeployedDeploymentRow(row) &&
}
-
-
-
-
-
- )
-}
-
-function DeploymentEnvironmentDesktopRows({ rows }: { rows: EnvironmentDeployment[] }) {
- return (
- <>
- {rows.map((row) => {
- const envId = row.environment.id
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
- })}
- >
- )
-}
-
-export function DeploymentEnvironmentList({ rows }: { rows: EnvironmentDeployment[] }) {
- const { t } = useTranslation('deployments')
-
- return (
- <>
-
- {rows.map((row) => (
-
- ))}
-
-
-
-
-
-
- {t(($) => $['deployTab.col.environment'])}
-
-
- {t(($) => $['deployTab.col.status'])}
-
-
- {t(($) => $['deployTab.col.currentRelease'])}
-
-
- {t(($) => $['deployTab.col.actions'])}
-
-
-
-
-
-
-
-
- >
- )
-}
diff --git a/web/features/deployments/detail/instances/environment-list/deployment-status-summary.tsx b/web/features/deployments/detail/instances/environment-list/deployment-status-summary.tsx
deleted file mode 100644
index b16f2435863..00000000000
--- a/web/features/deployments/detail/instances/environment-list/deployment-status-summary.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { useTranslation } from 'react-i18next'
-import { isUndeployedDeploymentRow } from '../../../shared/domain/runtime-status'
-import { DeploymentStatusBadge } from '../../../shared/ui/deployment-status-badge'
-
-export function DeploymentStatusSummary({ row }: { row: EnvironmentDeployment }) {
- const { t } = useTranslation('deployments')
- const status = row.status
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING) {
- return (
- $[`status.${status}`])}
- variant="status-dot"
- />
- )
- }
-
- if (isUndeployedDeploymentRow(row)) {
- return (
- $[`status.${RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED}`])}
- variant="status-dot"
- />
- )
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING) {
- const targetRelease = row.desiredRelease ?? row.currentRelease
- if (!targetRelease) {
- return (
- $[`status.${RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING}`])}
- variant="status-dot"
- />
- )
- }
-
- return (
- $['deployTab.status.deployingRelease'], {
- release: targetRelease.displayName,
- })}
- variant="status-dot"
- />
- )
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED) {
- const hasRunningRelease = Boolean(row.currentRelease)
- return (
-
- $[
- hasRunningRelease
- ? 'deployTab.status.runningWithFailed'
- : 'deployTab.status.deployFailed'
- ],
- )}
- variant="status-dot"
- />
- )
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DRIFTED) {
- const hasRunningRelease = Boolean(row.currentRelease)
- return (
- $['deployTab.status.runningOutOfSync'])
- : t(($) => $['status.RUNTIME_INSTANCE_STATUS_DRIFTED'])
- }
- variant="status-dot"
- />
- )
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_INVALID) {
- return (
- $[`status.${status}`])}
- variant="status-dot"
- />
- )
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED) {
- return (
- $[`status.${status}`])}
- variant="status-dot"
- />
- )
- }
-
- return (
- $[`status.${RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY}`])}
- variant="status-dot"
- />
- )
-}
diff --git a/web/features/deployments/detail/instances/header-actions/README.md b/web/features/deployments/detail/instances/header-actions/README.md
deleted file mode 100644
index d48ed8714a5..00000000000
--- a/web/features/deployments/detail/instances/header-actions/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Instances Header Actions
-
-Header action for opening the deploy drawer from the instances route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------- | ----------------------------------------------------------------------- |
-| `deploy-drawer` | Opens the deploy drawer for the first available undeployed environment. |
-| `route-state` | Reads the route app instance identity for deployment actions. |
-| `detail` | Reads detail-owned query state and runtime instance rows. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/instances/header-actions/new-deployment-button.tsx b/web/features/deployments/detail/instances/header-actions/new-deployment-button.tsx
deleted file mode 100644
index bd8a0d5979d..00000000000
--- a/web/features/deployments/detail/instances/header-actions/new-deployment-button.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-'use client'
-
-import { Button } from '@langgenius/dify-ui/button'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { openDeployDrawerAtom } from '../../../deploy-drawer/state'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import {
- deploymentEnvironmentDeploymentsIsErrorAtom,
- deploymentEnvironmentDeploymentsIsLoadingAtom,
- deploymentRuntimeInstanceRowsAtom,
-} from '../../state'
-
-export function NewDeploymentButton() {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
-
- return (
-
- )
-}
-
-export function NewDeploymentHeaderAction() {
- const isLoading = useAtomValue(deploymentEnvironmentDeploymentsIsLoadingAtom)
- const hasError = useAtomValue(deploymentEnvironmentDeploymentsIsErrorAtom)
- const rows = useAtomValue(deploymentRuntimeInstanceRowsAtom)
-
- if (isLoading || hasError || rows.length === 0) return null
-
- return
-}
diff --git a/web/features/deployments/detail/instances/index.tsx b/web/features/deployments/detail/instances/index.tsx
deleted file mode 100644
index be92c485cbe..00000000000
--- a/web/features/deployments/detail/instances/index.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-'use client'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../shared/components/detail-table'
-import { DeploymentEmptyState, DeploymentStateMessage } from '../../shared/components/empty-state'
-import {
- deploymentEnvironmentDeploymentsIsErrorAtom,
- deploymentEnvironmentDeploymentsIsLoadingAtom,
- deploymentRuntimeInstanceRowsAtom,
-} from '../state'
-import { DeploymentEnvironmentList } from './environment-list/deployment-environment-list'
-import { NewDeploymentButton } from './header-actions/new-deployment-button'
-import { DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES } from './table-styles'
-
-const DEPLOYMENT_TABLE_ROW_SKELETON_KEYS = ['production', 'staging']
-
-function DeploymentEnvironmentListSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
- <>
-
- {DEPLOYMENT_TABLE_ROW_SKELETON_KEYS.map((key) => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ))}
-
-
-
-
-
-
- {t(($) => $['deployTab.col.environment'])}
-
-
- {t(($) => $['deployTab.col.status'])}
-
-
- {t(($) => $['deployTab.col.currentRelease'])}
-
-
- {t(($) => $['deployTab.col.actions'])}
-
-
-
-
- {DEPLOYMENT_TABLE_ROW_SKELETON_KEYS.map((key) => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ))}
-
-
-
- >
- )
-}
-
-export function DeploymentInstances() {
- const { t } = useTranslation('deployments')
- const isLoading = useAtomValue(deploymentEnvironmentDeploymentsIsLoadingAtom)
- const hasError = useAtomValue(deploymentEnvironmentDeploymentsIsErrorAtom)
- const rows = useAtomValue(deploymentRuntimeInstanceRowsAtom)
-
- return (
-
- {isLoading ? (
-
- ) : hasError ? (
-
- {t(($) => $['common.loadFailed'])}
-
- ) : rows.length === 0 ? (
- $['deployTab.emptyTitle'])}
- description={t(($) => $['deployTab.emptyDescription'])}
- action={}
- />
- ) : (
-
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/instances/row-actions/README.md b/web/features/deployments/detail/instances/row-actions/README.md
deleted file mode 100644
index 8fad4a09abd..00000000000
--- a/web/features/deployments/detail/instances/row-actions/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Instances Row Actions
-
-Row action menu and dialogs for deploying, redeploying, and undeploying an environment deployment.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------- | ------------------------------------------------------------------------------ |
-| `deploy-drawer` | Opens the deploy drawer from row-level deploy and redeploy flows. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for deployment mutations. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/instances/row-actions/__tests__/deployment-row-actions-menu.spec.tsx b/web/features/deployments/detail/instances/row-actions/__tests__/deployment-row-actions-menu.spec.tsx
deleted file mode 100644
index 3f773bdb6b2..00000000000
--- a/web/features/deployments/detail/instances/row-actions/__tests__/deployment-row-actions-menu.spec.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { render, screen } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { DeploymentActionsDropdown } from '../deployment-row-actions-menu'
-
-const commonProps = {
- currentReleaseId: 'release-1',
- deployActionLabel: 'Deploy',
- isDeployFailed: false,
- isDeploymentInProgress: false,
- isUndeployed: false,
- onDeploy: vi.fn(),
- onRequestUndeploy: vi.fn(),
- onViewError: vi.fn(),
-}
-
-describe('DeploymentActionsDropdown', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('should keep disabled item state and action behavior in sync', async () => {
- const user = userEvent.setup()
- const { rerender } = render(
- ,
- )
-
- await user.click(screen.getByLabelText('deployments.deployTab.moreActions'))
- const undeployItem = screen.getByRole('menuitem', {
- name: 'deployments.deployTab.undeploy',
- })
- expect(undeployItem).toHaveAttribute('data-disabled')
- expect(undeployItem).toHaveAttribute('aria-disabled', 'true')
- expect(undeployItem).toHaveClass('data-disabled:cursor-not-allowed', 'data-disabled:opacity-60')
-
- await user.click(undeployItem)
- expect(commonProps.onRequestUndeploy).not.toHaveBeenCalled()
-
- rerender()
-
- expect(undeployItem).not.toHaveAttribute('data-disabled')
- expect(undeployItem).toHaveAttribute('aria-disabled', 'false')
-
- await user.click(undeployItem)
- expect(commonProps.onRequestUndeploy).toHaveBeenCalledTimes(1)
- })
-})
diff --git a/web/features/deployments/detail/instances/row-actions/deployment-error-dialog.tsx b/web/features/deployments/detail/instances/row-actions/deployment-error-dialog.tsx
deleted file mode 100644
index 1f0f1b55cdf..00000000000
--- a/web/features/deployments/detail/instances/row-actions/deployment-error-dialog.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import {
- AlertDialog,
- AlertDialogActions,
- AlertDialogCancelButton,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogTitle,
-} from '@langgenius/dify-ui/alert-dialog'
-import { useTranslation } from 'react-i18next'
-
-function DeploymentErrorDetails({ error }: { error?: EnvironmentDeployment['error'] }) {
- const { t } = useTranslation('deployments')
- const message = error?.message?.trim() || t(($) => $['deployTab.panel.unknownError'])
- const metadata = [
- ...(error?.phase ? [{ label: t(($) => $['deployTab.errorPhase']), value: error.phase }] : []),
- ...(error?.code ? [{ label: t(($) => $['deployTab.errorCode']), value: error.code }] : []),
- ]
-
- return (
-
-
- {t(($) => $['deployTab.errorMessage'])}
-
-
- {message}
-
- {metadata.length > 0 && (
-
- {metadata.map((item) => (
-
- {item.label}
- {item.value}
-
- ))}
-
- )}
-
- )
-}
-
-export function DeploymentErrorDialog({
- open,
- row,
- onOpenChange,
-}: {
- open: boolean
- row: EnvironmentDeployment
- onOpenChange: (open: boolean) => void
-}) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
-
-
- {t(($) => $['deployTab.errorDialogTitle'], { name: row.environment.displayName })}
-
-
- {t(($) => $['deployTab.errorDialogDesc'])}
-
-
-
-
-
- {t(($) => $['deployTab.closeError'])}
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/instances/row-actions/deployment-row-actions-menu.tsx b/web/features/deployments/detail/instances/row-actions/deployment-row-actions-menu.tsx
deleted file mode 100644
index 9664b972314..00000000000
--- a/web/features/deployments/detail/instances/row-actions/deployment-row-actions-menu.tsx
+++ /dev/null
@@ -1,136 +0,0 @@
-'use client'
-
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuSeparator,
- DropdownMenuTrigger,
-} from '@langgenius/dify-ui/dropdown-menu'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME } from '../../../shared/components/detail-table-styles'
-
-export function DeploymentActionsDropdown({
- currentReleaseId,
- deployActionLabel,
- failedReleaseId,
- isDeployFailed,
- isDeploymentInProgress,
- isUndeployed,
- undeployActionDisabled,
- onDeploy,
- onRequestUndeploy,
- onViewError,
-}: {
- currentReleaseId?: string
- deployActionLabel: string
- failedReleaseId?: string
- isDeployFailed: boolean
- isDeploymentInProgress: boolean
- isUndeployed: boolean
- undeployActionDisabled: boolean
- onDeploy: (releaseId?: string) => void
- onRequestUndeploy: () => void
- onViewError: () => void
-}) {
- const { t } = useTranslation('deployments')
- const [open, setOpen] = useState(false)
-
- if (isDeploymentInProgress) return null
-
- function handleDeployAction(releaseId?: string) {
- onDeploy(releaseId)
- setOpen(false)
- }
-
- function handleViewError() {
- onViewError()
- setOpen(false)
- }
-
- function handleRequestUndeploy() {
- if (undeployActionDisabled) return
-
- onRequestUndeploy()
- setOpen(false)
- }
-
- return (
-
- $['deployTab.moreActions'])}
- className={DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME}
- >
-
-
- {open && (
-
- {isDeployFailed ? (
- <>
-
-
-
- {t(($) => $['deployTab.viewError'])}
-
-
- handleDeployAction(failedReleaseId)}
- >
-
-
- {failedReleaseId
- ? t(($) => $['deployTab.retry'])
- : t(($) => $['deployTab.deployOtherVersion'])}
-
-
- >
- ) : (
- <>
- {!isUndeployed && currentReleaseId && (
- handleDeployAction(currentReleaseId)}
- >
-
-
- {t(($) => $['deployTab.redeploy'])}
-
-
- )}
- handleDeployAction()}>
-
- {deployActionLabel}
-
- >
- )}
- {!isUndeployed && (
- <>
-
-
-
- {t(($) => $['deployTab.undeploy'])}
-
- >
- )}
-
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/instances/row-actions/deployment-row-actions.tsx b/web/features/deployments/detail/instances/row-actions/deployment-row-actions.tsx
deleted file mode 100644
index a106fff014e..00000000000
--- a/web/features/deployments/detail/instances/row-actions/deployment-row-actions.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { useMutation } from '@tanstack/react-query'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { openDeployDrawerAtom } from '../../../deploy-drawer/state'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { createDeploymentIdempotencyKey } from '../../../shared/domain/idempotency'
-import {
- isRuntimeDeploymentInProgress,
- isUndeployedDeploymentRow,
-} from '../../../shared/domain/runtime-status'
-import { DeploymentErrorDialog } from './deployment-error-dialog'
-import { DeploymentActionsDropdown } from './deployment-row-actions-menu'
-import { UndeployDeploymentDialog } from './undeploy-deployment-dialog'
-
-export function DeploymentRowActions({
- envId,
- row,
-}: {
- envId: string
- row: EnvironmentDeployment
-}) {
- const { t } = useTranslation('deployments')
- const routeAppInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
- const undeployDeployment = useMutation(
- consoleQuery.enterprise.deploymentService.undeploy.mutationOptions(),
- )
- const [showUndeployConfirm, setShowUndeployConfirm] = useState(false)
- const [showErrorDetail, setShowErrorDetail] = useState(false)
- const isUndeployed = isUndeployedDeploymentRow(row)
- const status = row.status
- const isUndeployRequesting = undeployDeployment.isPending
- const undeployActionDisabled = isUndeployRequesting
- const isDeploymentInProgress = isRuntimeDeploymentInProgress(status)
- const isDeployFailed = status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED
- const currentReleaseId = row.currentRelease?.id
- const failedReleaseId = row.desiredRelease?.id ?? row.currentRelease?.id
- const deployActionLabel = isUndeployed
- ? t(($) => $['deployDrawer.deploy'])
- : t(($) => $['deployTab.deployOtherVersion'])
-
- if (!routeAppInstanceId) return null
-
- const appInstanceId = routeAppInstanceId
-
- function handleDeployAction(releaseId?: string) {
- openDeployDrawer({ appInstanceId, environmentId: envId, releaseId })
- }
-
- function handleUndeploy() {
- if (isUndeployRequesting) return
-
- undeployDeployment.mutate(
- {
- params: { appInstanceId, environmentId: envId },
- body: {
- appInstanceId,
- environmentId: envId,
- idempotencyKey: createDeploymentIdempotencyKey(),
- },
- },
- {
- onSettled: () => {
- setShowUndeployConfirm(false)
- },
- },
- )
- }
-
- return (
- e.stopPropagation()}
- onKeyDown={(e) => e.stopPropagation()}
- >
- setShowUndeployConfirm(true)}
- onViewError={() => setShowErrorDetail(true)}
- />
-
- {isDeployFailed && (
-
- )}
-
- {!isUndeployed && !isDeploymentInProgress && (
-
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/instances/row-actions/undeploy-deployment-dialog.tsx b/web/features/deployments/detail/instances/row-actions/undeploy-deployment-dialog.tsx
deleted file mode 100644
index 928a04e255b..00000000000
--- a/web/features/deployments/detail/instances/row-actions/undeploy-deployment-dialog.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen'
-import {
- AlertDialog,
- AlertDialogActions,
- AlertDialogCancelButton,
- AlertDialogConfirmButton,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogTitle,
-} from '@langgenius/dify-ui/alert-dialog'
-import { useTranslation } from 'react-i18next'
-
-export function UndeployDeploymentDialog({
- disabled,
- isRequesting,
- open,
- row,
- onConfirm,
- onOpenChange,
-}: {
- disabled: boolean
- isRequesting: boolean
- open: boolean
- row: EnvironmentDeployment
- onConfirm: () => void
- onOpenChange: (open: boolean) => void
-}) {
- const { t } = useTranslation('deployments')
-
- function handleOpenChange(nextOpen: boolean) {
- if (isRequesting) return
-
- onOpenChange(nextOpen)
- }
-
- return (
-
-
-
-
- {t(($) => $['deployTab.undeployConfirmTitle'], { name: row.environment.displayName })}
-
-
- {t(($) => $['deployTab.undeployConfirmDesc'])}
-
-
-
-
- {t(($) => $['deployDrawer.cancel'])}
-
-
- {t(($) => $['deployTab.confirmUndeploy'])}
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/instances/table-styles.ts b/web/features/deployments/detail/instances/table-styles.ts
deleted file mode 100644
index aabaa9c9039..00000000000
--- a/web/features/deployments/detail/instances/table-styles.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES = {
- actions: 'w-14 py-1.5 whitespace-nowrap',
- currentRelease: '',
- environment: 'whitespace-nowrap',
- status: 'whitespace-nowrap',
-}
diff --git a/web/features/deployments/detail/overview/README.md b/web/features/deployments/detail/overview/README.md
deleted file mode 100644
index aafa58594e8..00000000000
--- a/web/features/deployments/detail/overview/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment Overview
-
-Overview route for release summary, environment status, and access summaries on a deployment app instance.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ------------------------------------ | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for overview query, links, and actions. |
-| `detail/overview/access-summary` | Renders access and API token status summary sections. |
-| `detail/overview/environment-status` | Renders environment deployment status tiles. |
-| `detail/overview/release-summary` | Renders latest release summary and release creation entry point. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/overview/__tests__/state.spec.ts b/web/features/deployments/detail/overview/__tests__/state.spec.ts
deleted file mode 100644
index d97c2e0fd3e..00000000000
--- a/web/features/deployments/detail/overview/__tests__/state.spec.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
-}
-
-const mockOverviewQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appInstanceService: {
- getAppInstanceOverview: {
- queryOptions: (options: QueryOptions) => {
- mockOverviewQueryOptions(options)
- return {
- ...options,
- queryKey: ['getAppInstanceOverview', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/overview`,
- params: { appInstanceId },
- })
-}
-
-describe('deployment overview state', () => {
- beforeEach(() => {
- mockOverviewQueryOptions.mockClear()
- })
-
- it('should disable overview query with skipToken until route state is ready', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.deploymentOverviewQueryAtom)
-
- expect(mockOverviewQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
- })
-
- it('should build overview query input from route identity', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- setDeploymentRoute(store)
- store.get(state.deploymentOverviewQueryAtom)
-
- expect(mockOverviewQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- })
-})
diff --git a/web/features/deployments/detail/overview/access-summary/README.md b/web/features/deployments/detail/overview/access-summary/README.md
deleted file mode 100644
index 7d431372afd..00000000000
--- a/web/features/deployments/detail/overview/access-summary/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Deployment Overview Access Summary
-
-Access summary section for showing webapp and API token status on the overview route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ----------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for access summary links. |
-| `detail/overview` | Reuses overview card and icon styling shared by overview sections. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/overview/access-summary/access-status-section.tsx b/web/features/deployments/detail/overview/access-summary/access-status-section.tsx
deleted file mode 100644
index 85b62983eeb..00000000000
--- a/web/features/deployments/detail/overview/access-summary/access-status-section.tsx
+++ /dev/null
@@ -1,244 +0,0 @@
-'use client'
-
-import type { AccessChannels, ApiKeySummary } from '@dify/contracts/enterprise/types.gen'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import Link from '@/next/link'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { DeploymentStatusBadge } from '../../../shared/ui/deployment-status-badge'
-
-type AccessStatusSectionProps = {
- accessChannels?: AccessChannels
-}
-
-type ApiTokenSummarySectionProps = {
- accessChannels?: AccessChannels
- apiKeySummary?: ApiKeySummary
- deployedEnvironmentCount: number
-}
-
-type AccessStatusItem = {
- key: 'webapp' | 'cli'
- href: string
- icon: string
- label: string
- enabled: boolean
- meta: string
-}
-
-const ACCESS_STATUS_SKELETON_KEYS = ['webapp', 'cli']
-const OVERVIEW_CARD_CLASS_NAME =
- 'rounded-xl border border-components-panel-border bg-components-panel-bg p-4'
-const OVERVIEW_INTERACTIVE_CARD_CLASS_NAME = cn(
- OVERVIEW_CARD_CLASS_NAME,
- 'transition-colors hover:border-components-panel-border-subtle hover:bg-components-panel-on-panel-item-bg-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-components-button-primary-bg',
-)
-const OVERVIEW_ICON_CLASS_NAME =
- 'flex size-8 shrink-0 items-center justify-center rounded-lg bg-background-section-burn text-text-tertiary'
-
-export function AccessStatusSection({ accessChannels }: AccessStatusSectionProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
-
- if (!appInstanceId) return null
-
- const items: AccessStatusItem[] = [
- {
- key: 'webapp',
- href: `/deployments/${appInstanceId}/access`,
- icon: 'i-ri-global-line',
- label: t(($) => $['card.access.webApp']),
- enabled: Boolean(accessChannels?.webAppEnabled),
- meta: t(($) => $['overview.accessMeta.webApp']),
- },
- {
- key: 'cli',
- href: `/deployments/${appInstanceId}/access`,
- icon: 'i-ri-terminal-box-line',
- label: t(($) => $['card.access.cli']),
- enabled: Boolean(accessChannels?.webAppEnabled),
- meta: t(($) => $['overview.accessMeta.cli']),
- },
- ]
-
- return (
-
-
- {t(($) => $['overview.accessStatus'])}
-
-
-
- {items.map((item) => (
-
-
-
-
-
-
- {item.label}
-
-
-
-
-
- {item.meta}
-
-
- ))}
-
-
- )
-}
-
-export function ApiTokenSummarySection({
- accessChannels,
- apiKeySummary,
- deployedEnvironmentCount,
-}: ApiTokenSummarySectionProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const apiEnabled = Boolean(accessChannels?.developerApiEnabled)
- const apiKeyCount = apiKeySummary?.apiKeyCount ?? 0
-
- if (!appInstanceId) return null
-
- return (
-
- {t(($) => $['overview.api'])}
-
-
-
-
-
-
-
-
- {t(($) => $['card.access.api'])}
-
-
-
-
-
-
- {apiEnabled ? (
-
-
- {t(($) => $['overview.apiKeysCount'], { count: apiKeyCount })}
-
- {/* "deployed environments" = envs with a runtime deployment, not envs-with-keys */}
-
- {t(($) => $['overview.apiTokenSummary.environments'], {
- count: deployedEnvironmentCount,
- })}
-
-
- ) : (
-
- {t(($) => $['overview.accessMeta.apiTokens'])}
-
- )}
-
-
-
- )
-}
-
-function StatusBadge({ enabled }: { enabled: boolean }) {
- const { t } = useTranslation('deployments')
-
- return (
- $['overview.enabled']) : t(($) => $['overview.disabled'])}
- />
- )
-}
-
-export function ApiTokenSummarySectionSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
-
- {t(($) => $['overview.api'])}
-
-
- )
-}
-
-function ApiTokenSummaryCardSkeleton() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-export function AccessStatusSectionSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['overview.accessStatus'])}
-
-
-
- {ACCESS_STATUS_SKELETON_KEYS.map((key) => (
-
-
-
-
-
-
-
-
-
-
- ))}
-
-
- )
-}
diff --git a/web/features/deployments/detail/overview/environment-status/README.md b/web/features/deployments/detail/overview/environment-status/README.md
deleted file mode 100644
index a00b4814cb6..00000000000
--- a/web/features/deployments/detail/overview/environment-status/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Deployment Overview Environment Status
-
-Environment status section for previewing runtime deployments and opening deployment actions from the overview route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ----------------- | ------------------------------------------------------------------------------ |
-| `deploy-drawer` | Opens the deploy drawer from overview environment actions. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for environment links and actions. |
-| `detail/overview` | Reuses overview card and icon styling shared by overview sections. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/overview/environment-status/__tests__/environment-tile-utils.spec.ts b/web/features/deployments/detail/overview/environment-status/__tests__/environment-tile-utils.spec.ts
deleted file mode 100644
index 92303105e9b..00000000000
--- a/web/features/deployments/detail/overview/environment-status/__tests__/environment-tile-utils.spec.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import type { TFunction } from 'i18next'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { describe, expect, it } from 'vitest'
-import { withSelectorKey } from '@/test/i18n-mock'
-import {
- renderActionLabel,
- renderDriftTitle,
- renderStatus,
- resolveConfig,
-} from '../environment-tile-utils'
-
-const t = withSelectorKey((key: string, options?: Record) => {
- return options ? `${key}:${JSON.stringify(options)}` : key
-}, 'deployments') as unknown as TFunction<'deployments'>
-
-describe('resolveConfig', () => {
- it('treats undeploying environments as in progress', () => {
- const config = resolveConfig({
- drift: { kind: 'up-to-date' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING,
- hasAnyRelease: true,
- latestId: 'release-2',
- currentReleaseId: 'release-1',
- })
-
- expect(config.kind).toBe('deploying')
- expect(config.status).toBe(RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING)
- expect(config.intent).toBe('navigate')
- })
-
- it('disables empty environments when no release exists', () => {
- const config = resolveConfig({
- drift: { kind: 'undeployed' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED,
- hasAnyRelease: false,
- latestId: undefined,
- currentReleaseId: undefined,
- })
-
- expect(config.kind).toBe('empty')
- expect(config.intent).toBe('disabled')
- expect(config.showRelease).toBe(false)
- expect(config.releaseId).toBeUndefined()
- })
-
- it('opens deploy drawer for undeployed environments when a release exists', () => {
- const config = resolveConfig({
- drift: { kind: 'undeployed' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED,
- hasAnyRelease: true,
- latestId: 'release-2',
- currentReleaseId: undefined,
- })
-
- expect(config.kind).toBe('empty')
- expect(config.intent).toBe('drawer')
- expect(config.releaseId).toBe('release-2')
- })
-
- it('resolves failed environments to the current release first', () => {
- const config = resolveConfig({
- drift: { kind: 'behind', steps: 1 },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED,
- hasAnyRelease: true,
- latestId: 'release-2',
- currentReleaseId: 'release-1',
- })
-
- expect(config.kind).toBe('failed')
- expect(config.intent).toBe('drawer')
- expect(config.releaseId).toBe('release-1')
- })
-
- it('resolves up-to-date and behind environments to drawer actions', () => {
- expect(
- resolveConfig({
- drift: { kind: 'up-to-date' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- hasAnyRelease: true,
- latestId: 'release-2',
- currentReleaseId: 'release-2',
- }),
- ).toMatchObject({
- kind: 'latest',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- intent: 'drawer',
- releaseId: 'release-2',
- })
-
- expect(
- resolveConfig({
- drift: { kind: 'behind', steps: 2 },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- hasAnyRelease: true,
- latestId: 'release-3',
- currentReleaseId: 'release-1',
- }),
- ).toMatchObject({
- kind: 'behind',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DRIFTED,
- intent: 'drawer',
- releaseId: 'release-3',
- })
- })
-
- it('treats unknown drift as an older release state', () => {
- const config = resolveConfig({
- drift: { kind: 'unknown' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- hasAnyRelease: true,
- latestId: 'release-3',
- currentReleaseId: 'release-1',
- })
-
- expect(config.kind).toBe('older')
- expect(config.status).toBe(RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED)
- expect(config.intent).toBe('drawer')
- expect(config.releaseId).toBe('release-3')
- })
-})
-
-describe('environment tile copy helpers', () => {
- it('renders action labels for deployment states', () => {
- expect(renderActionLabel('empty', false, t)).toBe('overview.cardAction.deployLatest')
- expect(renderActionLabel('older', true, t)).toBe('overview.cardAction.deployLatest')
- expect(renderActionLabel('behind', true, t)).toBe('overview.cardAction.deployLatest')
- expect(renderActionLabel('latest', true, t)).toBe('overview.cardAction.redeploy')
- expect(renderActionLabel('deploying', true, t)).toBe('overview.cardAction.viewProgress')
- expect(renderActionLabel('failed', true, t)).toBe('overview.cardAction.redeploy')
- expect(renderActionLabel('failed', false, t)).toBe('overview.cardAction.deployLatest')
- })
-
- it('renders status labels and drift titles with counts when needed', () => {
- expect(renderStatus('empty', { kind: 'undeployed' }, t)).toBe('overview.chip.empty')
- expect(renderStatus('latest', { kind: 'up-to-date' }, t)).toBe('overview.chip.latest')
- expect(renderStatus('older', { kind: 'unknown' }, t)).toBe('overview.chip.olderRelease')
- expect(renderStatus('deploying', { kind: 'unknown' }, t)).toBe('overview.chip.deploying')
- expect(renderStatus('failed', { kind: 'unknown' }, t)).toBe('overview.chip.failed')
- expect(renderStatus('behind', { kind: 'behind', steps: 3 }, t)).toBe(
- 'overview.chip.behind:{"count":3}',
- )
-
- expect(renderDriftTitle('latest', { kind: 'up-to-date' }, t)).toBe(
- 'overview.chip.latestTooltip',
- )
- expect(renderDriftTitle('behind', { kind: 'behind', steps: 2 }, t)).toBe(
- 'overview.chip.behindTooltip:{"count":2}',
- )
- expect(renderDriftTitle('older', { kind: 'unknown' }, t)).toBe(
- 'overview.chip.olderReleaseTooltip',
- )
- expect(renderDriftTitle('empty', { kind: 'undeployed' }, t)).toBe('overview.chip.emptyTooltip')
- expect(renderDriftTitle('deploying', { kind: 'unknown' }, t)).toBe(
- 'overview.chip.deployingTooltip',
- )
- expect(renderDriftTitle('failed', { kind: 'unknown' }, t)).toBe('overview.chip.failedTooltip')
- })
-})
diff --git a/web/features/deployments/detail/overview/environment-status/environment-strip.tsx b/web/features/deployments/detail/overview/environment-status/environment-strip.tsx
deleted file mode 100644
index 7b97b0b141e..00000000000
--- a/web/features/deployments/detail/overview/environment-status/environment-strip.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-'use client'
-
-import type { EnvironmentDeployment, Release } from '@dify/contracts/enterprise/types.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import Link from '@/next/link'
-import { openDeployDrawerAtom } from '../../../deploy-drawer/state'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { DeploymentEmptyState } from '../../../shared/components/empty-state'
-import { hasRuntimeInstanceDeployment } from '../../../shared/domain/runtime-status'
-import { EnvironmentTile } from './environment-tile'
-
-const OVERVIEW_RUNTIME_INSTANCE_LIMIT = 4
-const OVERVIEW_CARD_CLASS_NAME =
- 'rounded-xl border border-components-panel-border bg-components-panel-bg p-4'
-
-type EnvironmentStripProps = {
- rows: EnvironmentDeployment[]
- releaseRows: Release[]
-}
-
-export function EnvironmentStrip({ rows, releaseRows }: EnvironmentStripProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const runtimeRows = rows.filter(hasRuntimeInstanceDeployment)
- const previewRows = runtimeRows.slice(0, OVERVIEW_RUNTIME_INSTANCE_LIMIT)
- const hasRuntimeRows = runtimeRows.length > 0
- const hasRelease = releaseRows.length > 0
-
- return (
-
-
-
- {t(($) => $['overview.strip.title'])}
-
- {hasRuntimeRows && appInstanceId && (
-
- {t(($) => $['overview.previousReleases.viewAll'])}
-
-
- )}
-
-
- {!hasRuntimeRows ? (
-
- ) : (
-
- {previewRows.map((row) => (
-
- ))}
-
- )}
-
- )
-}
-
-function EnvironmentEmptyState({ canDeploy }: { canDeploy: boolean }) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
-
- return (
- $['overview.strip.emptyTitle'])}
- description={
- canDeploy
- ? t(($) => $['overview.strip.emptyDeployableDescription'])
- : t(($) => $['overview.strip.emptyDescription'])
- }
- className="min-h-44"
- action={
- canDeploy && appInstanceId ? (
-
- ) : undefined
- }
- />
- )
-}
-
-const SKELETON_KEYS = ['a', 'b', 'c']
-
-function CardSkeletons() {
- return (
-
- {SKELETON_KEYS.map((key) => (
-
- ))}
-
- )
-}
-
-function EnvironmentTileSkeleton() {
- return (
-
-
-
-
-
- )
-}
-
-export function EnvironmentStripSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['overview.strip.title'])}
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/overview/environment-status/environment-tile-utils.ts b/web/features/deployments/detail/overview/environment-status/environment-tile-utils.ts
deleted file mode 100644
index 8ba0e33d2a3..00000000000
--- a/web/features/deployments/detail/overview/environment-status/environment-tile-utils.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-import type { RuntimeInstanceStatus as RuntimeInstanceStatusValue } from '@dify/contracts/enterprise/types.gen'
-import type { TFunction } from 'i18next'
-import type { computeDrift } from './overview-drift'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { isRuntimeDeploymentInProgress } from '../../../shared/domain/runtime-status'
-
-export type TileKind = 'empty' | 'latest' | 'behind' | 'older' | 'deploying' | 'failed'
-
-export type TileConfig = {
- kind: TileKind
- status: RuntimeInstanceStatusValue
- actionClass: string
- showRelease: boolean
- intent: 'drawer' | 'navigate' | 'disabled'
- releaseId?: string
-}
-
-export function resolveConfig({
- drift,
- status,
- hasAnyRelease,
- latestId,
- currentReleaseId,
-}: {
- drift: ReturnType
- status: RuntimeInstanceStatusValue
- hasAnyRelease: boolean
- latestId: string | undefined
- currentReleaseId: string | undefined
-}): TileConfig {
- if (isRuntimeDeploymentInProgress(status)) {
- return {
- kind: 'deploying',
- status,
- actionClass: 'text-text-secondary hover:bg-state-base-hover hover:text-text-primary',
- showRelease: true,
- intent: 'navigate',
- }
- }
-
- if (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED) {
- return {
- kind: 'failed',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED,
- actionClass: 'text-primary-600 hover:bg-state-accent-hover',
- showRelease: true,
- intent: 'drawer',
- releaseId: currentReleaseId ?? latestId,
- }
- }
-
- if (drift.kind === 'undeployed') {
- return {
- kind: 'empty',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED,
- actionClass: hasAnyRelease
- ? 'text-primary-600 hover:bg-state-accent-hover'
- : 'text-text-tertiary',
- showRelease: false,
- intent: hasAnyRelease ? 'drawer' : 'disabled',
- releaseId: latestId,
- }
- }
-
- if (drift.kind === 'up-to-date') {
- return {
- kind: 'latest',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- actionClass: 'text-text-secondary hover:bg-state-base-hover hover:text-text-primary',
- showRelease: true,
- intent: 'drawer',
- releaseId: currentReleaseId,
- }
- }
-
- if (drift.kind === 'behind') {
- return {
- kind: 'behind',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DRIFTED,
- actionClass: 'text-primary-600 hover:bg-state-accent-hover',
- showRelease: true,
- intent: 'drawer',
- releaseId: latestId,
- }
- }
-
- return {
- kind: 'older',
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED,
- actionClass: 'text-primary-600 hover:bg-state-accent-hover',
- showRelease: true,
- intent: 'drawer',
- releaseId: latestId,
- }
-}
-
-export function renderActionLabel(
- kind: TileKind,
- hasCurrentRelease: boolean,
- t: TFunction<'deployments'>,
-): string {
- switch (kind) {
- case 'empty':
- case 'older':
- case 'behind':
- return t(($) => $['overview.cardAction.deployLatest'])
- case 'latest':
- return t(($) => $['overview.cardAction.redeploy'])
- case 'deploying':
- return t(($) => $['overview.cardAction.viewProgress'])
- case 'failed':
- return hasCurrentRelease
- ? t(($) => $['overview.cardAction.redeploy'])
- : t(($) => $['overview.cardAction.deployLatest'])
- }
-}
-
-export function renderStatus(
- kind: TileKind,
- drift: ReturnType,
- t: TFunction<'deployments'>,
-): string {
- switch (kind) {
- case 'empty':
- return t(($) => $['overview.chip.empty'])
- case 'latest':
- return t(($) => $['overview.chip.latest'])
- case 'behind':
- return t(($) => $['overview.chip.behind'], {
- count: drift.kind === 'behind' ? drift.steps : 0,
- })
- case 'older':
- return t(($) => $['overview.chip.olderRelease'])
- case 'deploying':
- return t(($) => $['overview.chip.deploying'])
- case 'failed':
- return t(($) => $['overview.chip.failed'])
- }
-}
-
-export function renderDriftTitle(
- kind: TileKind,
- drift: ReturnType,
- t: TFunction<'deployments'>,
-): string {
- switch (kind) {
- case 'latest':
- return t(($) => $['overview.chip.latestTooltip'])
- case 'behind':
- return t(($) => $['overview.chip.behindTooltip'], {
- count: drift.kind === 'behind' ? drift.steps : 0,
- })
- case 'older':
- return t(($) => $['overview.chip.olderReleaseTooltip'])
- case 'empty':
- return t(($) => $['overview.chip.emptyTooltip'])
- case 'deploying':
- return t(($) => $['overview.chip.deployingTooltip'])
- case 'failed':
- return t(($) => $['overview.chip.failedTooltip'])
- }
-}
diff --git a/web/features/deployments/detail/overview/environment-status/environment-tile.tsx b/web/features/deployments/detail/overview/environment-status/environment-tile.tsx
deleted file mode 100644
index ec45f3b4eb0..00000000000
--- a/web/features/deployments/detail/overview/environment-status/environment-tile.tsx
+++ /dev/null
@@ -1,181 +0,0 @@
-'use client'
-
-import type {
- EnvironmentDeployment,
- Release,
- RuntimeInstanceStatus as RuntimeInstanceStatusValue,
-} from '@dify/contracts/enterprise/types.gen'
-import type { TileConfig } from './environment-tile-utils'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import Link from '@/next/link'
-import { openDeployDrawerAtom } from '../../../deploy-drawer/state'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { TitleTooltip } from '../../../shared/components/title-tooltip'
-import { releaseCommit } from '../../../shared/domain/release'
-import { DeploymentStatusBadge } from '../../../shared/ui/deployment-status-badge'
-import { deploymentStatusLabelKey } from '../../../shared/ui/deployment-status-style'
-import {
- renderActionLabel,
- renderDriftTitle,
- renderStatus,
- resolveConfig,
-} from './environment-tile-utils'
-import { computeDrift, latestReleaseId } from './overview-drift'
-
-const OVERVIEW_CARD_CLASS_NAME =
- 'rounded-xl border border-components-panel-border bg-components-panel-bg p-4'
-const OVERVIEW_INTERACTIVE_CARD_CLASS_NAME = cn(
- OVERVIEW_CARD_CLASS_NAME,
- 'transition-colors hover:border-components-panel-border-subtle hover:bg-components-panel-on-panel-item-bg-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-components-button-primary-bg',
-)
-const OVERVIEW_ICON_CLASS_NAME =
- 'flex size-8 shrink-0 items-center justify-center rounded-lg bg-background-section-burn text-text-tertiary'
-
-type EnvironmentTileProps = {
- row: EnvironmentDeployment
- releaseRows: Release[]
-}
-
-export function EnvironmentTile({ row, releaseRows }: EnvironmentTileProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
-
- const envId = row.environment.id
- const drift = computeDrift(row)
- const status = row.status
- const latestId = latestReleaseId(releaseRows)
- const hasAnyRelease = releaseRows.length > 0
- const currentReleaseId = row.currentRelease?.id
- const config = resolveConfig({ drift, status, hasAnyRelease, latestId, currentReleaseId })
- const isDisabled = config.intent === 'disabled'
- const showStatusSignal = config.kind !== 'deploying'
- const release = row.currentRelease
- const showRelease = config.showRelease && release
- const commit = releaseCommit(release)
- const tooltip = isDisabled
- ? t(($) => $['overview.chip.needsReleaseFirst'])
- : config.intent === 'navigate'
- ? t(($) => $['overview.chip.openInDeployTab'])
- : undefined
-
- function handleDrawerAction() {
- if (config.intent === 'disabled' || !appInstanceId) return
- openDeployDrawer({ appInstanceId, environmentId: envId, releaseId: config.releaseId })
- }
-
- const actionClassName = cn(
- 'inline-flex h-8 max-w-full min-w-0 shrink-0 items-center justify-center rounded-md px-2.5 system-xs-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-components-button-primary-bg',
- config.actionClass,
- isDisabled && 'cursor-not-allowed opacity-60',
- )
- const actionLabel = renderActionLabel(config.kind, Boolean(currentReleaseId), t)
- const actionControl =
- config.intent === 'navigate' && appInstanceId ? (
-
- {actionLabel}
-
- ) : (
-
- )
-
- return (
-
-
-
-
-
-
-
- {row.environment.displayName}
-
-
-
-
- {showStatusSignal && }
-
-
-
-
-
-
- {t(($) => $['deployTab.col.currentRelease'])}
-
-
-
- {showRelease ? showRelease.displayName : '—'}
-
- {showRelease && commit !== '—' && (
-
- {commit}
-
- )}
-
-
-
- {tooltip ? (
-
- {actionControl}
-
- ) : (
- actionControl
- )}
-
-
- )
-}
-
-function RuntimeStatusSignal({
- status,
- t,
-}: {
- status: RuntimeInstanceStatusValue
- t: ReturnType>['t']
-}) {
- const label = t(($) => $[deploymentStatusLabelKey(status)])
-
- return (
-
-
-
- )
-}
-
-function StatusSignal({
- className,
- config,
- drift,
- t,
-}: {
- className?: string
- config: TileConfig
- drift: ReturnType
- t: ReturnType>['t']
-}) {
- const title = renderDriftTitle(config.kind, drift, t)
-
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/overview/environment-status/overview-drift.ts b/web/features/deployments/detail/overview/environment-status/overview-drift.ts
deleted file mode 100644
index 78b988c8254..00000000000
--- a/web/features/deployments/detail/overview/environment-status/overview-drift.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { EnvironmentDeployment, Release } from '@dify/contracts/enterprise/types.gen'
-import { isUndeployedDeploymentRow } from '../../../shared/domain/runtime-status'
-
-export type Drift =
- | { kind: 'undeployed' }
- | { kind: 'unknown' }
- | { kind: 'up-to-date' }
- | { kind: 'behind'; steps: number }
-
-export function computeDrift(row: EnvironmentDeployment): Drift {
- if (isUndeployedDeploymentRow(row)) return { kind: 'undeployed' }
-
- if (!row.currentRelease) return { kind: 'unknown' }
-
- // releasesBehind is server-computed against the full release history (0 == up
- // to date). It is absent only when undetermined, which renders as unknown.
- const behind = row.releasesBehind
- if (behind == null) return { kind: 'unknown' }
- if (behind === 0) return { kind: 'up-to-date' }
- return { kind: 'behind', steps: behind }
-}
-
-export function latestReleaseId(releaseRows: Release[]): string | undefined {
- return releaseRows[0]?.id
-}
diff --git a/web/features/deployments/detail/overview/index.tsx b/web/features/deployments/detail/overview/index.tsx
deleted file mode 100644
index 61dc5c9ed64..00000000000
--- a/web/features/deployments/detail/overview/index.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-'use client'
-
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import Link from '@/next/link'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-import { DeploymentStateMessage } from '../../shared/components/empty-state'
-import { hasRuntimeInstanceDeployment } from '../../shared/domain/runtime-status'
-import {
- AccessStatusSection,
- AccessStatusSectionSkeleton,
- ApiTokenSummarySection,
- ApiTokenSummarySectionSkeleton,
-} from './access-summary/access-status-section'
-import { EnvironmentStrip, EnvironmentStripSkeleton } from './environment-status/environment-strip'
-import { ReleaseHero, ReleaseHeroSkeleton } from './release-summary/release-hero'
-import {
- deploymentOverviewAtom,
- deploymentOverviewIsErrorAtom,
- deploymentOverviewIsLoadingAtom,
-} from './state'
-
-function OverviewLayout({ children }: { children: React.ReactNode }) {
- return {children}
-}
-
-function LatestReleaseSection({ children }: { children: React.ReactNode }) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
-
- return (
-
-
-
- {t(($) => $['overview.latestReleaseTitle'])}
-
- {appInstanceId && (
-
- {t(($) => $['overview.previousReleases.viewAll'])}
-
-
- )}
-
- {children}
-
- )
-}
-
-function OverviewLoadingSkeleton() {
- return (
-
-
-
-
-
-
-
-
- )
-}
-
-export function DeploymentOverview() {
- const { t } = useTranslation('deployments')
- const overview = useAtomValue(deploymentOverviewAtom)
- const isLoading = useAtomValue(deploymentOverviewIsLoadingAtom)
- const isError = useAtomValue(deploymentOverviewIsErrorAtom)
-
- if (isLoading) return
-
- if (isError) {
- return (
-
-
- {t(($) => $['common.loadFailed'])}
-
-
- )
- }
-
- if (!overview) {
- return (
-
-
- {t(($) => $['detail.notFound'])}
-
-
- )
- }
-
- const releaseRows = overview.recentReleases
- // recentReleases is a capped preview; totalReleaseCount is the true total.
- const releaseCount = overview.totalReleaseCount
- const runtimeRows = overview.environmentDeployments
- const deployedEnvironmentCount = runtimeRows.filter(hasRuntimeInstanceDeployment).length
- const latestRelease = releaseRows[0]
- const accessChannels = overview.accessChannels
- const apiKeySummary = overview.apiKeySummary
-
- return (
-
-
-
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/overview/release-summary/README.md b/web/features/deployments/detail/overview/release-summary/README.md
deleted file mode 100644
index 10ca6d364d1..00000000000
--- a/web/features/deployments/detail/overview/release-summary/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Deployment Overview Release Summary
-
-Release summary section for showing the latest release and release creation entry point on the overview route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ----------------- | ------------------------------------------------------------------------------ |
-| `create-release` | Opens release creation from the release summary card. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for release creation. |
-| `detail/overview` | Reuses overview card and icon styling shared by overview sections. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/overview/release-summary/release-hero.tsx b/web/features/deployments/detail/overview/release-summary/release-hero.tsx
deleted file mode 100644
index c669cf01455..00000000000
--- a/web/features/deployments/detail/overview/release-summary/release-hero.tsx
+++ /dev/null
@@ -1,188 +0,0 @@
-'use client'
-
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import type { ReactNode } from 'react'
-import { ReleaseSource } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useQuery } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
-import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
-import { CreateReleaseControl } from '../../../create-release'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { DeploymentEmptyState } from '../../../shared/components/empty-state'
-import { TitleTooltip } from '../../../shared/components/title-tooltip'
-import { formatDate, releaseCommit } from '../../../shared/domain/release'
-
-type ReleaseHeroProps = {
- latestRelease?: Release
- releaseCount: number
-}
-
-type ReleaseMetaItemProps = {
- label?: string
- showSeparator?: boolean
- children: ReactNode
-}
-
-const OVERVIEW_CARD_CLASS_NAME =
- 'rounded-xl border border-components-panel-border bg-components-panel-bg p-4'
-const OVERVIEW_ICON_CLASS_NAME =
- 'flex size-8 shrink-0 items-center justify-center rounded-lg bg-background-section-burn text-text-tertiary'
-
-export function ReleaseHero({ latestRelease, releaseCount }: ReleaseHeroProps) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const { formatTimeFromNow } = useFormatTimeFromNow()
-
- if (!latestRelease) {
- return (
- $['overview.hero.empty'])}
- description={t(($) => $['overview.hero.emptyDescription'])}
- action={
- appInstanceId ? (
-
- ) : undefined
- }
- className="min-h-44"
- />
- )
- }
-
- const author = latestRelease.createdBy.displayName
- const ago = formatTimeFromNow(new Date(latestRelease.createdAt).getTime())
- const createdAtTitle = formatDate(latestRelease.createdAt)
- const commit = releaseCommit(latestRelease)
-
- return (
-
-
-
-
-
-
-
-
- {latestRelease.displayName}
-
- {commit !== '—' && (
- $['versions.commitTooltip'], { commit })}>
-
- {commit}
-
-
- )}
-
-
- $['versions.col.sourceApp'])} showSeparator={false}>
-
-
- {author && (
-
- {t(($) => $['overview.hero.byName'], { name: author })}
-
- )}
- {ago && (
-
-
- {ago}
-
-
- )}
-
- {t(($) => $['overview.latestRelease.releaseCount'], { count: releaseCount })}
-
-
-
-
-
- )
-}
-
-function ReleaseMetaItem({ label, showSeparator = true, children }: ReleaseMetaItemProps) {
- return (
-
- {showSeparator && (
-
- ·
-
- )}
- {label && {label}}
- {children}
-
- )
-}
-
-function LatestReleaseSource({ release }: { release: Release }) {
- const { t } = useTranslation('deployments')
- const sourceAppId = release.sourceAppId
-
- if (!sourceAppId) {
- return (
-
- {release.source === ReleaseSource.RELEASE_SOURCE_UPLOAD
- ? t(($) => $['versions.manualDslOption'])
- : '—'}
-
- )
- }
-
- return
-}
-
-function LatestReleaseSourceLink({ sourceAppId }: { sourceAppId: string }) {
- const sourceAppQuery = useQuery(
- consoleQuery.apps.byAppId.get.queryOptions({
- input: {
- params: { app_id: sourceAppId },
- },
- }),
- )
- const sourceAppName = sourceAppQuery.data?.name
- const label = sourceAppName || sourceAppId
- const title = sourceAppName ? `${sourceAppName} (${sourceAppId})` : sourceAppId
-
- return (
-
-
- {label}
-
-
-
- )
-}
-
-export function ReleaseHeroSkeleton() {
- return (
-
- )
-}
diff --git a/web/features/deployments/detail/overview/state.ts b/web/features/deployments/detail/overview/state.ts
deleted file mode 100644
index 33b14907e55..00000000000
--- a/web/features/deployments/detail/overview/state.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-'use client'
-
-import { skipToken } from '@tanstack/react-query'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-
-export const deploymentOverviewQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
-
- return consoleQuery.enterprise.appInstanceService.getAppInstanceOverview.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- })
-})
-
-export const deploymentOverviewAtom = selectAtom(deploymentOverviewQueryAtom, (query) => query.data)
-export const deploymentOverviewIsLoadingAtom = selectAtom(
- deploymentOverviewQueryAtom,
- (query) => query.isLoading,
-)
-export const deploymentOverviewIsErrorAtom = selectAtom(
- deploymentOverviewQueryAtom,
- (query) => query.isError,
-)
diff --git a/web/features/deployments/detail/releases/README.md b/web/features/deployments/detail/releases/README.md
deleted file mode 100644
index 72d05992f78..00000000000
--- a/web/features/deployments/detail/releases/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Deployment Releases
-
-Releases route for release history, release actions, deployment summaries, and release DSL export.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------------------- | ---------------------------------------------------------- |
-| `route-state` | Reads the route app instance identity for release queries. |
-| `detail/releases/release-history` | Renders release history rows and pagination. |
-
-## External Modules
-
-None.
diff --git a/web/features/deployments/detail/releases/__tests__/state.spec.ts b/web/features/deployments/detail/releases/__tests__/state.spec.ts
deleted file mode 100644
index 0cfb0fc8e72..00000000000
--- a/web/features/deployments/detail/releases/__tests__/state.spec.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- placeholderData?: unknown
- queryKey?: readonly unknown[]
-}
-
-const mockReleaseSummariesQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- releaseService: {
- listReleaseSummaries: {
- queryOptions: (options: QueryOptions) => {
- mockReleaseSummariesQueryOptions(options)
- return {
- ...options,
- queryKey: ['listReleaseSummaries', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/overview`,
- params: { appInstanceId },
- })
-}
-
-describe('deployment releases state', () => {
- beforeEach(() => {
- mockReleaseSummariesQueryOptions.mockClear()
- })
-
- it('should gate release history query until route state is ready', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.releaseHistoryQueryAtom)
- expect(mockReleaseSummariesQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: false,
- input: skipToken,
- }),
- )
- })
-
- it('should build release history input from the current page', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
- setDeploymentRoute(store)
-
- store.set(state.setReleaseHistoryCurrentPageAtom, -1)
- expect(store.get(state.releaseHistoryCurrentPageAtom)).toBe(0)
-
- store.set(state.setReleaseHistoryCurrentPageAtom, 2)
- store.get(state.releaseHistoryQueryAtom)
- expect(mockReleaseSummariesQueryOptions).toHaveBeenLastCalledWith(
- expect.objectContaining({
- enabled: true,
- input: expect.objectContaining({
- params: { appInstanceId: 'app-instance-1' },
- query: expect.objectContaining({
- pageNumber: 3,
- }),
- }),
- }),
- )
- })
-
- it('should adjust the release page only when deleting the last row on a later page', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.set(state.setReleaseHistoryCurrentPageAtom, 2)
- store.set(state.adjustReleaseHistoryPageAfterDeleteAtom, 2)
- expect(store.get(state.releaseHistoryCurrentPageAtom)).toBe(2)
-
- store.set(state.adjustReleaseHistoryPageAfterDeleteAtom, 1)
- expect(store.get(state.releaseHistoryCurrentPageAtom)).toBe(1)
- })
-})
diff --git a/web/features/deployments/detail/releases/index.tsx b/web/features/deployments/detail/releases/index.tsx
deleted file mode 100644
index 55e44b84eef..00000000000
--- a/web/features/deployments/detail/releases/index.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-'use client'
-
-import { useAtomValue } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-import { ReleaseHistoryTable } from './release-history/release-history-table'
-import { releasesLocalAtoms } from './state'
-
-export function DeploymentReleases() {
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
-
- return (
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-actions/README.md b/web/features/deployments/detail/releases/release-actions/README.md
deleted file mode 100644
index 1c82270dbed..00000000000
--- a/web/features/deployments/detail/releases/release-actions/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment Releases Actions
-
-Release action menu and dialogs for deploying, editing, deleting, and exporting releases.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------- | ------------------------------------------------------------------------------ |
-| `deploy-drawer` | Opens the deploy drawer from release actions. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `route-state` | Reads the route app instance identity for action queries and mutations. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ---------------- | --------------------------------------- |
-| `utils/download` | Downloads exported release DSL content. |
diff --git a/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu-utils.spec.ts b/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu-utils.spec.ts
deleted file mode 100644
index 7f6ad260452..00000000000
--- a/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu-utils.spec.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import type {
- Environment,
- EnvironmentDeployment,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import { ReleaseSource, RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-import { describe, expect, it } from 'vitest'
-import { withSelectorKey } from '@/test/i18n-mock'
-import { buildDeployMenuSections } from '../deploy-release-menu-utils'
-
-const t = withSelectorKey((key: string, options?: { name?: string }) => {
- return options?.name ? `${key}:${options.name}` : key
-}, 'deployments')
-
-function createRelease(id: string): Release {
- return {
- id,
- appInstanceId: 'app-instance-1',
- displayName: id,
- description: '',
- source: ReleaseSource.RELEASE_SOURCE_SOURCE_APP,
- gateCommitId: id,
- requiredSlots: [],
- createdBy: {
- id: 'account-1',
- displayName: 'Dify Admin',
- },
- createdAt: '2026-01-01T00:00:00.000Z',
- }
-}
-
-describe('buildDeployMenuSections', () => {
- it('disables deploy actions while an environment is undeploying', () => {
- const env = {
- id: 'env-1',
- displayName: 'Production',
- } as Environment
- const targetRelease = createRelease('release-1')
- const deployment = {
- appInstanceId: 'app-instance-1',
- environment: env,
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING,
- currentRelease: createRelease('release-0'),
- updatedAt: '2026-01-01T00:00:00.000Z',
- } as EnvironmentDeployment
-
- const sections = buildDeployMenuSections({
- environments: [env],
- environmentDeployments: [deployment],
- releaseRows: [targetRelease],
- releaseId: targetRelease.id,
- targetRelease,
- t,
- })
-
- expect(sections).toHaveLength(1)
- expect(sections[0]?.group).toBe('unavailable')
- expect(sections[0]?.rows[0]).toMatchObject({
- environmentId: env.id,
- state: 'deploying',
- label: 'versions.deployingTo:Production',
- disabledReason: 'versions.disabledReason.deploying',
- })
- })
-})
diff --git a/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu.spec.tsx b/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu.spec.tsx
deleted file mode 100644
index e087dc05a3f..00000000000
--- a/web/features/deployments/detail/releases/release-actions/__tests__/deploy-release-menu.spec.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-import type { EnvironmentDeployment, Release } from '@dify/contracts/enterprise/types.gen'
-import { ReleaseSource } from '@dify/contracts/enterprise/types.gen'
-import { fireEvent, render, screen } from '@testing-library/react'
-import { describe, expect, it, vi } from 'vitest'
-import { DeployReleaseMenu } from '../deploy-release-menu'
-
-const mockDeleteRelease = vi.hoisted(() => vi.fn())
-const mockExportReleaseDsl = vi.hoisted(() => vi.fn())
-const mockMutationState = vi.hoisted(() => ({ exportPending: false }))
-
-vi.mock('@tanstack/react-query', async (importOriginal) => {
- const actual = await importOriginal()
-
- return {
- ...actual,
- useMutation: (options: { mutationKey?: readonly unknown[] }) => {
- if (options.mutationKey?.[0] === 'deployments')
- return { isPending: mockMutationState.exportPending, mutate: mockExportReleaseDsl }
-
- return { isPending: false, mutate: mockDeleteRelease }
- },
- }
-})
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- releaseService: {
- deleteRelease: {
- mutationOptions: () => ({ mutationKey: ['deleteRelease'] }),
- },
- },
- },
- },
-}))
-
-vi.mock('../state', async (importOriginal) => {
- const actual = await importOriginal()
- const { RuntimeInstanceStatus } = await import('@dify/contracts/enterprise/types.gen')
- const { atom } = await import('jotai')
- const currentRelease = {
- id: 'release-1',
- createdAt: '2026-01-01T00:00:00.000Z',
- } as Release
- const previousRelease = {
- id: 'release-0',
- createdAt: '2025-12-01T00:00:00.000Z',
- } as Release
- const environmentDeployments = {
- environmentDeployments: [
- {
- environment: { id: 'env-current', displayName: 'Current' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- currentRelease,
- },
- {
- environment: { id: 'env-available', displayName: 'Available' },
- status: RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY,
- currentRelease: previousRelease,
- },
- ] as EnvironmentDeployment[],
- }
-
- return {
- ...actual,
- deployReleaseMenuEnvironmentDeploymentsAtom: atom(environmentDeployments),
- deployReleaseMenuEnvironmentDeploymentsIsErrorAtom: atom(true),
- deployReleaseMenuEnvironmentDeploymentsIsLoadingAtom: atom(false),
- deployReleaseMenuAppInstanceNameAtom: atom('Deployment 1'),
- }
-})
-
-vi.mock('../edit-release-dialog', () => ({
- EditReleaseDialog: () => null,
-}))
-
-vi.mock('../delete-release-dialog', async () => {
- const { useAtomValue } = await import('jotai')
- const { deleteReleaseDialogOpenAtom } = await import('../state')
-
- return {
- DeleteReleaseDialog: () =>
- useAtomValue(deleteReleaseDialogOpenAtom) ? delete confirm
: null,
- }
-})
-
-vi.mock('../release-dsl-export', () => ({
- exportReleaseDsl: vi.fn(),
-}))
-
-function createRelease(): Release {
- return {
- id: 'release-1',
- appInstanceId: 'app-instance-1',
- displayName: 'Release 1',
- description: '',
- source: ReleaseSource.RELEASE_SOURCE_UPLOAD,
- gateCommitId: 'commit-1',
- requiredSlots: [],
- createdBy: {
- id: 'account-1',
- displayName: 'Dify Admin',
- },
- createdAt: '2026-01-01T00:00:00.000Z',
- }
-}
-
-describe('DeployReleaseMenu', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- mockMutationState.exportPending = false
- })
-
- it('should disable release deletion when deployment usage cannot be checked', () => {
- const release = createRelease()
-
- render()
-
- fireEvent.click(screen.getByLabelText('deployments.versions.moreActions'))
- const deleteItem = screen.getByRole('menuitem', { name: 'deployments.versions.deleteRelease' })
-
- expect(deleteItem).toHaveAttribute('aria-disabled', 'true')
- expect(deleteItem).toHaveAttribute('data-disabled')
- expect(deleteItem).toHaveClass('data-disabled:cursor-not-allowed', 'data-disabled:opacity-60')
-
- fireEvent.click(deleteItem)
-
- expect(screen.queryByText('delete confirm')).not.toBeInTheDocument()
- expect(mockDeleteRelease).not.toHaveBeenCalled()
- })
-
- it('should expose disabled state for exporting and unavailable environment actions', () => {
- mockMutationState.exportPending = true
- const release = createRelease()
-
- render()
-
- fireEvent.click(screen.getByLabelText('deployments.versions.moreActions'))
-
- const exportItem = screen.getByRole('menuitem', { name: 'deployments.versions.exportingDsl' })
- const currentEnvironmentItem = screen.getByRole('menuitem', {
- name: /deployments\.versions\.currentOn/,
- })
- const availableEnvironmentItem = screen.getByRole('menuitem', {
- name: /deployments\.versions\.(deployTo|rollbackTo)/,
- })
- expect(exportItem).toHaveAttribute('data-disabled')
- expect(currentEnvironmentItem).toHaveAttribute('data-disabled')
- expect(availableEnvironmentItem).not.toHaveAttribute('data-disabled')
-
- fireEvent.click(exportItem)
- expect(mockExportReleaseDsl).not.toHaveBeenCalled()
- })
-})
diff --git a/web/features/deployments/detail/releases/release-actions/__tests__/state.spec.ts b/web/features/deployments/detail/releases/release-actions/__tests__/state.spec.ts
deleted file mode 100644
index 57c7ea7c9d6..00000000000
--- a/web/features/deployments/detail/releases/release-actions/__tests__/state.spec.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { skipToken } from '@tanstack/react-query'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { setNextRouteStateAtom } from '@/app/components/next-route-state/atoms'
-import { createQueryAtomTestStore } from '@/test/query-atom'
-
-type QueryOptions = {
- enabled?: boolean
- input?: unknown
- queryKey?: readonly unknown[]
-}
-
-const mockGetAppInstanceQueryOptions = vi.hoisted(() => vi.fn())
-const mockListEnvironmentDeploymentsQueryOptions = vi.hoisted(() => vi.fn())
-
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appInstanceService: {
- getAppInstance: {
- queryOptions: (options: QueryOptions) => {
- mockGetAppInstanceQueryOptions(options)
- return {
- ...options,
- queryKey: ['getAppInstance', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- deploymentService: {
- listEnvironmentDeployments: {
- queryOptions: (options: QueryOptions) => {
- mockListEnvironmentDeploymentsQueryOptions(options)
- return {
- ...options,
- queryKey: ['listEnvironmentDeployments', options.input],
- queryFn: async () => undefined,
- }
- },
- },
- },
- },
- },
-}))
-
-async function loadState() {
- return await import('../state')
-}
-
-function setDeploymentRoute(
- store: ReturnType['store'],
- appInstanceId = 'app-instance-1',
-) {
- store.set(setNextRouteStateAtom, {
- pathname: `/deployments/${appInstanceId}/releases`,
- params: { appInstanceId },
- })
-}
-
-describe('deployment release actions state', () => {
- beforeEach(() => {
- mockGetAppInstanceQueryOptions.mockClear()
- mockListEnvironmentDeploymentsQueryOptions.mockClear()
- })
-
- it('should gate action queries until route and menu state are ready', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.get(state.deployReleaseMenuEnvironmentDeploymentsQueryAtom)
- expect(mockListEnvironmentDeploymentsQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
- store.get(state.deployReleaseMenuAppInstanceQueryAtom)
- expect(mockGetAppInstanceQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: skipToken,
- })
-
- setDeploymentRoute(store)
-
- store.get(state.deployReleaseMenuEnvironmentDeploymentsQueryAtom)
- expect(mockListEnvironmentDeploymentsQueryOptions).toHaveBeenLastCalledWith({
- enabled: false,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
-
- store.set(state.deployReleaseMenuOpenAtom, true)
-
- store.get(state.deployReleaseMenuEnvironmentDeploymentsQueryAtom)
- expect(mockListEnvironmentDeploymentsQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- store.get(state.deployReleaseMenuAppInstanceQueryAtom)
- expect(mockGetAppInstanceQueryOptions).toHaveBeenLastCalledWith({
- enabled: true,
- input: { params: { appInstanceId: 'app-instance-1' } },
- })
- })
-
- it('should open one secondary dialog at a time and close the menu', async () => {
- const state = await loadState()
- const { store } = createQueryAtomTestStore()
-
- store.set(state.deployReleaseMenuOpenAtom, true)
- store.set(state.openDeleteReleaseDialogAtom)
-
- expect(store.get(state.deployReleaseMenuOpenAtom)).toBe(false)
- expect(store.get(state.editReleaseDialogOpenAtom)).toBe(false)
- expect(store.get(state.deleteReleaseDialogOpenAtom)).toBe(true)
-
- store.set(state.deployReleaseMenuOpenAtom, true)
- store.set(state.openEditReleaseDialogAtom)
-
- expect(store.get(state.deployReleaseMenuOpenAtom)).toBe(false)
- expect(store.get(state.editReleaseDialogOpenAtom)).toBe(true)
- expect(store.get(state.deleteReleaseDialogOpenAtom)).toBe(false)
- })
-})
diff --git a/web/features/deployments/detail/releases/release-actions/delete-release-dialog.tsx b/web/features/deployments/detail/releases/release-actions/delete-release-dialog.tsx
deleted file mode 100644
index b43a1e258e5..00000000000
--- a/web/features/deployments/detail/releases/release-actions/delete-release-dialog.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-'use client'
-
-import {
- AlertDialog,
- AlertDialogActions,
- AlertDialogCancelButton,
- AlertDialogConfirmButton,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogTitle,
-} from '@langgenius/dify-ui/alert-dialog'
-import { useAtom, useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { deleteReleaseDialogOpenAtom, releaseActionItemAtom } from './state'
-
-export function DeleteReleaseDialog({
- isDeleting,
- onConfirm,
-}: {
- isDeleting: boolean
- onConfirm: () => void
-}) {
- const { t } = useTranslation('deployments')
- const { releaseId, releaseRows } = useAtomValue(releaseActionItemAtom)
- const [open, setOpen] = useAtom(deleteReleaseDialogOpenAtom)
- const release = releaseRows.find((release) => release.id === releaseId)
- if (!release) return null
-
- return (
- {
- if (isDeleting) return
- setOpen(nextOpen)
- }}
- >
-
-
-
- {t(($) => $['versions.deleteConfirmTitle'])}
-
-
- {t(($) => $['versions.deleteConfirmDesc'], { name: release.displayName })}
-
-
-
-
- {t(($) => $['versions.cancelDelete'])}
-
-
- {t(($) => $['versions.deleteRelease'])}
-
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-actions/deploy-release-menu-utils.ts b/web/features/deployments/detail/releases/release-actions/deploy-release-menu-utils.ts
deleted file mode 100644
index e74f658f3ff..00000000000
--- a/web/features/deployments/detail/releases/release-actions/deploy-release-menu-utils.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import type {
- Environment,
- EnvironmentDeployment,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import type { SelectorParam } from 'i18next'
-import { releaseDeploymentAction } from '../../../shared/domain/release-action'
-import {
- isRuntimeDeploymentInProgress,
- isUndeployedDeploymentRow,
-} from '../../../shared/domain/runtime-status'
-
-export type DeployMenuRowState = 'deploy' | 'rollback' | 'current' | 'deploying'
-
-export type DeployMenuRow = {
- env?: Environment
- environmentId: string
- state: DeployMenuRowState
- label: string
- disabledReason?: string
-}
-
-export type DeployMenuGroup = 'deploy' | 'rollback' | 'unavailable'
-
-export type DeployMenuSection = {
- group: DeployMenuGroup
- rows: DeployMenuRow[]
-}
-
-type DeploymentTranslator = (
- selector: SelectorParam<'deployments'>,
- options?: Record,
-) => string
-
-const GROUP_ORDER: DeployMenuGroup[] = ['deploy', 'rollback', 'unavailable']
-
-function stateToGroup(state: DeployMenuRowState): DeployMenuGroup {
- if (state === 'rollback') return 'rollback'
- if (state === 'deploy') return 'deploy'
- return 'unavailable'
-}
-
-export function releaseUsageCount(releaseId: string, deploymentRows: EnvironmentDeployment[]) {
- const environmentIds = new Set()
-
- deploymentRows.forEach((row) => {
- const usesRelease = row.currentRelease?.id === releaseId || row.desiredRelease?.id === releaseId
- if (usesRelease) environmentIds.add(row.environment.id)
- })
-
- return environmentIds.size
-}
-
-function buildDeployMenuRow({
- env,
- deploymentRows,
- releaseRows,
- releaseId,
- targetRelease,
- t,
-}: {
- env: Environment
- deploymentRows: EnvironmentDeployment[]
- releaseRows: Release[]
- releaseId: string
- targetRelease: Release
- t: DeploymentTranslator
-}): DeployMenuRow {
- const envId = env.id
- const envName = env.displayName
- const row = deploymentRows.find((item) => item.environment.id === envId)
- const currentRelease = row?.currentRelease
- const isCurrent = currentRelease?.id === releaseId
- const isEnvironmentInProgress = isRuntimeDeploymentInProgress(row?.status)
-
- if (isEnvironmentInProgress) {
- return {
- env,
- environmentId: envId,
- state: 'deploying',
- label: t(($) => $['versions.deployingTo'], { name: envName }),
- disabledReason: t(($) => $['versions.disabledReason.deploying']),
- }
- }
- if (isCurrent) {
- return {
- env,
- environmentId: envId,
- state: 'current',
- label: t(($) => $['versions.currentOn'], { name: envName }),
- disabledReason: t(($) => $['versions.disabledReason.current'], { name: envName }),
- }
- }
-
- const action = releaseDeploymentAction({
- targetRelease,
- currentRelease,
- releaseRows,
- isExistingRelease: true,
- })
-
- if (!row) {
- return {
- env,
- environmentId: envId,
- state: 'deploy',
- label: t(($) => $['versions.deployTo'], { name: envName }),
- }
- }
- if (action === 'rollback') {
- return {
- env,
- environmentId: envId,
- state: 'rollback',
- label: t(($) => $['versions.rollbackTo'], { name: envName }),
- }
- }
- return {
- env,
- environmentId: envId,
- state: 'deploy',
- label: t(($) => $['versions.deployTo'], { name: envName }),
- }
-}
-
-export function buildDeployMenuSections({
- environments,
- environmentDeployments,
- releaseRows,
- releaseId,
- targetRelease,
- t,
-}: {
- environments: Environment[]
- environmentDeployments: EnvironmentDeployment[]
- releaseRows: Release[]
- releaseId: string
- targetRelease: Release
- t: DeploymentTranslator
-}) {
- const deploymentRows = environmentDeployments.filter((row) => !isUndeployedDeploymentRow(row))
- const menuRows = environments.map((env) =>
- buildDeployMenuRow({
- env,
- deploymentRows,
- releaseRows,
- releaseId,
- targetRelease,
- t,
- }),
- )
-
- return GROUP_ORDER.map((group) => ({
- group,
- rows: menuRows.filter((row) => stateToGroup(row.state) === group),
- })).filter((section): section is DeployMenuSection => section.rows.length > 0)
-}
diff --git a/web/features/deployments/detail/releases/release-actions/deploy-release-menu.tsx b/web/features/deployments/detail/releases/release-actions/deploy-release-menu.tsx
deleted file mode 100644
index bf8883977ee..00000000000
--- a/web/features/deployments/detail/releases/release-actions/deploy-release-menu.tsx
+++ /dev/null
@@ -1,260 +0,0 @@
-'use client'
-
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from '@langgenius/dify-ui/dropdown-menu'
-import { toast } from '@langgenius/dify-ui/toast'
-import { mutationOptions, useMutation } from '@tanstack/react-query'
-import { useAtom, useAtomValue, useSetAtom } from 'jotai'
-import { ScopeProvider } from 'jotai-scope'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { openDeployDrawerAtom } from '../../../deploy-drawer/state'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-import { DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME } from '../../../shared/components/detail-table-styles'
-import { TitleTooltip } from '../../../shared/components/title-tooltip'
-import { isUndeployedDeploymentRow } from '../../../shared/domain/runtime-status'
-import { DeleteReleaseDialog } from './delete-release-dialog'
-import { buildDeployMenuSections, releaseUsageCount } from './deploy-release-menu-utils'
-import { EditReleaseDialog } from './edit-release-dialog'
-import { exportReleaseDsl } from './release-dsl-export'
-import {
- deleteReleaseDialogOpenAtom,
- deployReleaseMenuAppInstanceNameAtom,
- deployReleaseMenuEnvironmentDeploymentsAtom,
- deployReleaseMenuEnvironmentDeploymentsIsErrorAtom,
- deployReleaseMenuEnvironmentDeploymentsIsLoadingAtom,
- deployReleaseMenuOpenAtom,
- openDeleteReleaseDialogAtom,
- openEditReleaseDialogAtom,
- releaseActionItemAtom,
- releaseActionLocalAtoms,
-} from './state'
-
-type ExportReleaseDslInput = {
- release: Release
- releaseId: string
- appInstanceName?: string
-}
-
-function DeployReleaseMenuContent({ onDeleted }: { onDeleted?: () => void }) {
- const { t } = useTranslation('deployments')
- const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom)
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
- const { releaseId, releaseRows } = useAtomValue(releaseActionItemAtom)
- const [open, setOpen] = useAtom(deployReleaseMenuOpenAtom)
- const setDeleteReleaseDialogOpen = useSetAtom(deleteReleaseDialogOpenAtom)
- const openEditReleaseDialog = useSetAtom(openEditReleaseDialogAtom)
- const openDeleteReleaseDialog = useSetAtom(openDeleteReleaseDialogAtom)
- const environmentDeployments = useAtomValue(deployReleaseMenuEnvironmentDeploymentsAtom)
- const environmentDeploymentsIsLoading = useAtomValue(
- deployReleaseMenuEnvironmentDeploymentsIsLoadingAtom,
- )
- const environmentDeploymentsIsError = useAtomValue(
- deployReleaseMenuEnvironmentDeploymentsIsErrorAtom,
- )
- const appInstanceName = useAtomValue(deployReleaseMenuAppInstanceNameAtom)
- const deleteRelease = useMutation(
- consoleQuery.enterprise.releaseService.deleteRelease.mutationOptions(),
- )
- const exportReleaseDslMutation = useMutation(
- mutationOptions({
- mutationKey: ['deployments', 'release-dsl-export'],
- mutationFn: (input: ExportReleaseDslInput) => exportReleaseDsl(input),
- }),
- )
-
- const deploymentEnvironmentRows = environmentDeployments?.environmentDeployments ?? []
- const environments = deploymentEnvironmentRows.map((row) => row.environment)
- const deploymentRows = deploymentEnvironmentRows.filter((row) => !isUndeployedDeploymentRow(row))
- const targetRelease = releaseRows.find((release) => release.id === releaseId)
-
- if (!targetRelease) return null
-
- const release = targetRelease
- const targetReleaseName = release.displayName
- const deleteUsageCount = releaseUsageCount(releaseId, deploymentRows)
- const isCheckingDeleteUsage = open && environmentDeploymentsIsLoading
- const hasDeleteUsageCheckFailed = open && environmentDeploymentsIsError
- const isReleaseInUse = deleteUsageCount > 0
- const isDeletingRelease = deleteRelease.isPending
- const isExportingDsl = exportReleaseDslMutation.isPending
- const deleteDisabledReason = isCheckingDeleteUsage
- ? t(($) => $['versions.disabledReason.checkingDeployments'])
- : hasDeleteUsageCheckFailed
- ? t(($) => $['versions.disabledReason.checkDeploymentsFailed'])
- : isReleaseInUse
- ? t(($) => $['versions.disabledReason.releaseInUse'], { count: deleteUsageCount })
- : undefined
- const deleteActionDisabled =
- isDeletingRelease || isCheckingDeleteUsage || hasDeleteUsageCheckFailed || isReleaseInUse
-
- function handleExportDsl() {
- if (isExportingDsl) return
-
- exportReleaseDslMutation.mutate(
- { release, releaseId, appInstanceName },
- {
- onSuccess: () => {
- setOpen(false)
- },
- onError: () => {
- toast.error(t(($) => $['versions.exportDslFailed']))
- },
- },
- )
- }
-
- function handleDeleteRelease() {
- if (deleteActionDisabled) return
-
- deleteRelease.mutate(
- {
- params: {
- releaseId,
- },
- },
- {
- onSuccess: () => {
- setDeleteReleaseDialogOpen(false)
- toast.success(t(($) => $['versions.deleteSuccess'], { name: targetReleaseName }))
- onDeleted?.()
- },
- onError: () => {
- toast.error(t(($) => $['versions.deleteFailed']))
- },
- },
- )
- }
-
- const groupedRows = buildDeployMenuSections({
- environments,
- environmentDeployments: deploymentEnvironmentRows,
- releaseRows,
- releaseId,
- targetRelease: release,
- t: (selector, options) => t(selector, options),
- })
-
- return (
- <>
-
- $['versions.moreActions'])}
- className={DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME}
- >
-
-
- {open && (
-
-
-
-
- {t(($) => $['versions.editRelease'])}
-
-
-
-
-
- {isExportingDsl
- ? t(($) => $['versions.exportingDsl'])
- : t(($) => $['versions.exportDsl'])}
-
-
- {groupedRows.length > 0 && (
-
- )}
- {groupedRows.map((section, sectionIndex) => (
-
- {sectionIndex > 0 && (
-
- )}
-
- {t(($) => $[`versions.groupHeader.${section.group}`])}
-
- {section.rows.map((row) => {
- const isDisabled = row.state === 'current' || row.state === 'deploying'
- return (
-
- {
- if (isDisabled || !appInstanceId) return
- setOpen(false)
- openDeployDrawer({
- appInstanceId,
- environmentId: row.environmentId,
- releaseId,
- })
- }}
- >
- {row.label}
-
-
- )
- })}
-
- ))}
-
-
- {
- if (deleteActionDisabled) return
- openDeleteReleaseDialog()
- }}
- >
-
- {t(($) => $['versions.deleteRelease'])}
-
-
-
- )}
-
-
-
-
-
- >
- )
-}
-
-export function DeployReleaseMenu({
- releaseId,
- releaseRows,
- onDeleted,
-}: {
- releaseId: string
- releaseRows: Release[]
- onDeleted?: () => void
-}) {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-actions/edit-release-dialog.tsx b/web/features/deployments/detail/releases/release-actions/edit-release-dialog.tsx
deleted file mode 100644
index b5292ce5a9c..00000000000
--- a/web/features/deployments/detail/releases/release-actions/edit-release-dialog.tsx
+++ /dev/null
@@ -1,180 +0,0 @@
-'use client'
-
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import {
- Dialog,
- DialogCloseButton,
- DialogContent,
- DialogDescription,
- DialogTitle,
-} from '@langgenius/dify-ui/dialog'
-import { Field, FieldControl, FieldError, FieldLabel } from '@langgenius/dify-ui/field'
-import { Form } from '@langgenius/dify-ui/form'
-import { Textarea } from '@langgenius/dify-ui/textarea'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useMutation } from '@tanstack/react-query'
-import { useAtom, useAtomValue } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
-import { editReleaseDialogOpenAtom, releaseActionItemAtom } from './state'
-
-type EditReleaseFormValues = {
- name: string
- description: string
-}
-
-function normalizedEditReleaseFormValues(value: EditReleaseFormValues) {
- return {
- name: value.name.trim(),
- description: value.description.trim(),
- }
-}
-
-function canSubmitEditReleaseForm(
- initialValues: EditReleaseFormValues,
- value: EditReleaseFormValues,
-) {
- const normalizedValues = normalizedEditReleaseFormValues(value)
-
- return Boolean(
- normalizedValues.name &&
- (normalizedValues.name !== initialValues.name ||
- normalizedValues.description !== initialValues.description),
- )
-}
-
-function EditReleaseForm({
- release,
- isSaving,
- onClose,
- onSubmit,
-}: {
- release: Release
- isSaving: boolean
- onClose: () => void
- onSubmit: (values: EditReleaseFormValues) => void
-}) {
- const { t } = useTranslation('deployments')
- const nameLabel = t(($) => $['versions.releaseNameLabel'])
- const initialValues = {
- name: release.displayName,
- description: release.description,
- }
-
- function handleSubmit(values: EditReleaseFormValues) {
- if (!canSubmitEditReleaseForm(initialValues, values)) return
-
- onSubmit(normalizedEditReleaseFormValues(values))
- }
-
- return (
-
- )
-}
-
-export function EditReleaseDialog() {
- const { t } = useTranslation('deployments')
- const { releaseId, releaseRows } = useAtomValue(releaseActionItemAtom)
- const [open, setOpen] = useAtom(editReleaseDialogOpenAtom)
- const updateRelease = useMutation(
- consoleQuery.enterprise.releaseService.updateRelease.mutationOptions(),
- )
- const targetRelease = releaseRows.find((release) => release.id === releaseId)
- if (!targetRelease) return null
-
- const release = targetRelease
- const formKey = `${release.id}-${release.displayName}-${release.description}`
-
- function handleOpenChange(nextOpen: boolean) {
- if (!nextOpen && updateRelease.isPending) return
- setOpen(nextOpen)
- }
-
- function handleSubmit(values: EditReleaseFormValues) {
- updateRelease.mutate(
- {
- params: {
- releaseId: release.id,
- },
- body: {
- releaseId: release.id,
- displayName: values.name,
- description: values.description,
- },
- },
- {
- onSuccess: (data) => {
- const updatedName = data.release.displayName
- toast.success(t(($) => $['versions.editSuccess'], { name: updatedName }))
- handleOpenChange(false)
- },
- onError: () => {
- toast.error(t(($) => $['versions.editFailed']))
- },
- },
- )
- }
-
- return (
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-actions/release-dsl-export.ts b/web/features/deployments/detail/releases/release-actions/release-dsl-export.ts
deleted file mode 100644
index 2f8a7dd14b6..00000000000
--- a/web/features/deployments/detail/releases/release-actions/release-dsl-export.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import { downloadBlob } from '@/utils/download'
-import { fetchReleaseDsl } from './release-dsl'
-
-const YAML_EXTENSION_PATTERN = /\.ya?ml$/i
-const INVALID_FILENAME_CHARS_PATTERN = /[\\/:*?"<>|]+/g
-const FILENAME_SEPARATOR_PATTERN = /[\s-]+/g
-
-function sanitizeFileNamePart(value?: string) {
- if (!value) return ''
-
- return value
- .trim()
- .replace(YAML_EXTENSION_PATTERN, '')
- .replace(INVALID_FILENAME_CHARS_PATTERN, '-')
- .replace(FILENAME_SEPARATOR_PATTERN, '-')
- .replace(/^-+|-+$/g, '')
-}
-
-function releaseDslFileName({
- release,
- appInstanceName,
-}: {
- release: Release
- appInstanceName?: string
-}) {
- const projectName = sanitizeFileNamePart(appInstanceName)
- const releaseName = sanitizeFileNamePart(release.displayName) || 'release'
- const baseName = [projectName, releaseName].filter(Boolean).join('-')
-
- return `${baseName}.yaml`
-}
-
-export async function exportReleaseDsl({
- release,
- releaseId,
- appInstanceName,
-}: {
- release: Release
- releaseId: string
- appInstanceName?: string
-}) {
- const data = new Blob([await fetchReleaseDsl(releaseId)], {
- type: 'application/x-yaml;charset=utf-8',
- })
- downloadBlob({
- data,
- fileName: releaseDslFileName({ release, appInstanceName }),
- })
-}
diff --git a/web/features/deployments/detail/releases/release-actions/release-dsl.ts b/web/features/deployments/detail/releases/release-actions/release-dsl.ts
deleted file mode 100644
index 17bd90f25a3..00000000000
--- a/web/features/deployments/detail/releases/release-actions/release-dsl.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { consoleClient } from '@/service/client'
-
-export async function fetchReleaseDsl(releaseId: string) {
- const response = await consoleClient.enterprise.releaseService.exportReleaseDsl({
- params: { releaseId },
- })
-
- if (!response.dsl) throw new Error('Invalid release DSL response')
-
- return response.dsl
-}
diff --git a/web/features/deployments/detail/releases/release-actions/state.ts b/web/features/deployments/detail/releases/release-actions/state.ts
deleted file mode 100644
index 9d45811deb9..00000000000
--- a/web/features/deployments/detail/releases/release-actions/state.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-'use client'
-
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import { skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { atomWithLazy, selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../../route-state'
-
-export type ReleaseActionItem = {
- releaseId: string
- releaseRows: Release[]
-}
-
-export const releaseActionItemAtom = atomWithLazy(() => {
- throw new Error('Missing release action item.')
-})
-
-export const deployReleaseMenuOpenAtom = atom(false)
-export const editReleaseDialogOpenAtom = atom(false)
-export const deleteReleaseDialogOpenAtom = atom(false)
-
-export const deployReleaseMenuEnvironmentDeploymentsQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
- const menuOpen = get(deployReleaseMenuOpenAtom)
-
- return consoleQuery.enterprise.deploymentService.listEnvironmentDeployments.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId && menuOpen),
- })
-})
-
-export const deployReleaseMenuEnvironmentDeploymentsAtom = selectAtom(
- deployReleaseMenuEnvironmentDeploymentsQueryAtom,
- (query) => query.data,
-)
-export const deployReleaseMenuEnvironmentDeploymentsIsLoadingAtom = selectAtom(
- deployReleaseMenuEnvironmentDeploymentsQueryAtom,
- (query) => query.isLoading,
-)
-export const deployReleaseMenuEnvironmentDeploymentsIsErrorAtom = selectAtom(
- deployReleaseMenuEnvironmentDeploymentsQueryAtom,
- (query) => query.isError,
-)
-
-export const deployReleaseMenuAppInstanceQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
- const menuOpen = get(deployReleaseMenuOpenAtom)
-
- return consoleQuery.enterprise.appInstanceService.getAppInstance.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId && menuOpen),
- })
-})
-
-export const deployReleaseMenuAppInstanceNameAtom = selectAtom(
- deployReleaseMenuAppInstanceQueryAtom,
- (query) => query.data?.appInstance.displayName,
-)
-
-export const openEditReleaseDialogAtom = atom(null, (_get, set) => {
- set(deployReleaseMenuOpenAtom, false)
- set(deleteReleaseDialogOpenAtom, false)
- set(editReleaseDialogOpenAtom, true)
-})
-
-export const openDeleteReleaseDialogAtom = atom(null, (_get, set) => {
- set(deployReleaseMenuOpenAtom, false)
- set(editReleaseDialogOpenAtom, false)
- set(deleteReleaseDialogOpenAtom, true)
-})
-
-export const releaseActionLocalAtoms = [
- deployReleaseMenuOpenAtom,
- editReleaseDialogOpenAtom,
- deleteReleaseDialogOpenAtom,
-] as const
diff --git a/web/features/deployments/detail/releases/release-history/README.md b/web/features/deployments/detail/releases/release-history/README.md
deleted file mode 100644
index c89dbf53472..00000000000
--- a/web/features/deployments/detail/releases/release-history/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Deployment Releases History
-
-Release history section for rendering release rows, deployment summaries, and pagination on the releases route.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------------------- | ------------------------------------------------------------------------------ |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `detail/releases` | Reads releases route query and pagination state. |
-| `detail/releases/release-actions` | Renders release action menus inside release history rows. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| -------------------------------- | ------------------------------------------------------------ |
-| `hooks/use-format-time-from-now` | Formats relative release timestamps in release history rows. |
diff --git a/web/features/deployments/detail/releases/release-history/deployed-to-badge.tsx b/web/features/deployments/detail/releases/release-history/deployed-to-badge.tsx
deleted file mode 100644
index cc289605777..00000000000
--- a/web/features/deployments/detail/releases/release-history/deployed-to-badge.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-'use client'
-
-import type { ReleaseDeployment } from './release-deployments'
-import { cn } from '@langgenius/dify-ui/cn'
-import { StatusDot } from '@langgenius/dify-ui/status-dot'
-import { useTranslation } from 'react-i18next'
-import { isRuntimeDeploymentInProgress } from '../../../shared/domain/runtime-status'
-import {
- deploymentStatusDotStatus,
- deploymentStatusDotTextClassName,
-} from '../../../shared/ui/deployment-status-style'
-
-export function DeployedToBadge({ item }: { item: ReleaseDeployment }) {
- const { t } = useTranslation('deployments')
- const status = item.status
- const statusLabel = t(($) => $[`versions.deployedStatus.${status}`])
- const dotStatus = deploymentStatusDotStatus(status)
- const isInProgress = isRuntimeDeploymentInProgress(status)
- const textClassName = deploymentStatusDotTextClassName(status)
-
- return (
-
-
-
- {item.environmentName}
- {' · '}
- {statusLabel}
-
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-deployments.ts b/web/features/deployments/detail/releases/release-history/release-deployments.ts
deleted file mode 100644
index 01b12a091f2..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-deployments.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import type {
- Environment,
- Release,
- ReleaseSummary,
- RuntimeInstanceStatus as RuntimeInstanceStatusValue,
-} from '@dify/contracts/enterprise/types.gen'
-import {
- ReleaseEnvironmentActionKind,
- RuntimeInstanceStatus,
-} from '@dify/contracts/enterprise/types.gen'
-
-export type ReleaseDeployment = {
- environmentId: string
- environmentName: string
- status: RuntimeInstanceStatusValue
-}
-
-export type ReleaseWithSummaryDeployments = Release & {
- summaryDeployments: ReleaseDeployment[]
-}
-
-function dedupeReleaseDeployments(items: ReleaseDeployment[]) {
- return items.filter((item, index) => {
- return items.findIndex((candidate) => candidate.environmentId === item.environmentId) === index
- })
-}
-
-function releaseSummaryEnvironmentDeployment(
- environment: Environment,
- status: RuntimeInstanceStatusValue,
-): ReleaseDeployment {
- return {
- environmentId: environment.id,
- environmentName: environment.displayName,
- status,
- }
-}
-
-export function getReleaseSummaryDeployments(summary: ReleaseSummary) {
- // Each deployed environment carries its runtime status so a failed deployment
- // surfaces as failed instead of being assumed healthy.
- const deployedItems = summary.deployedEnvironments.map((deployment) =>
- releaseSummaryEnvironmentDeployment(deployment.environment, deployment.status),
- )
- const actionItems = summary.environmentActions
- .filter(
- (action) =>
- action.kind === ReleaseEnvironmentActionKind.RELEASE_ENVIRONMENT_ACTION_KIND_DEPLOYING,
- )
- .map((action) =>
- releaseSummaryEnvironmentDeployment(
- action.environment,
- RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING,
- ),
- )
-
- return dedupeReleaseDeployments([...deployedItems, ...actionItems])
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-history-deployments.tsx b/web/features/deployments/detail/releases/release-history/release-history-deployments.tsx
deleted file mode 100644
index fc5fa1e1f0c..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-history-deployments.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-'use client'
-
-import type { ReleaseDeployment } from './release-deployments'
-import { DeployedToBadge } from './deployed-to-badge'
-
-export function ReleaseDeploymentsContent({ items }: { items: ReleaseDeployment[] }) {
- if (items.length === 0) return —
-
- return items.map((item) => (
-
- ))
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-history-rows.tsx b/web/features/deployments/detail/releases/release-history/release-history-rows.tsx
deleted file mode 100644
index 245328f948e..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-history-rows.tsx
+++ /dev/null
@@ -1,245 +0,0 @@
-'use client'
-
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import type { ReleaseWithSummaryDeployments } from './release-deployments'
-import { ReleaseSource } from '@dify/contracts/enterprise/types.gen'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
-import { useQuery } from '@tanstack/react-query'
-import { useTranslation } from 'react-i18next'
-import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
-import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../../shared/components/detail-table'
-import { TitleTooltip } from '../../../shared/components/title-tooltip'
-import { formatDate, releaseCommit } from '../../../shared/domain/release'
-import { DeployReleaseMenu } from '../release-actions/deploy-release-menu'
-import { ReleaseDeploymentsContent } from './release-history-deployments'
-import { RELEASE_DETAIL_TABLE_COLUMN_CLASS_NAMES } from './table-styles'
-
-function ReleaseTitleTooltip({ release }: { release: Release }) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {release.displayName}
-
- }
- />
-
- {t(($) => $['versions.commitTooltip'], { commit: releaseCommit(release) })}
-
-
- )
-}
-
-function CreatedAtCell({ createdAt }: { createdAt: string }) {
- const { formatTimeFromNow } = useFormatTimeFromNow()
- const ms = Date.parse(createdAt)
- if (Number.isNaN(ms)) return <>{formatDate(createdAt)}>
- return (
-
- {formatTimeFromNow(ms)}} />
- {formatDate(createdAt)}
-
- )
-}
-
-function ReleaseSourceCell({ release }: { release: Release }) {
- const { t } = useTranslation('deployments')
- const sourceAppId = release.sourceAppId
-
- if (!sourceAppId) {
- return (
-
- {release.source === ReleaseSource.RELEASE_SOURCE_UPLOAD
- ? t(($) => $['versions.manualDslOption'])
- : '—'}
-
- )
- }
-
- return
-}
-
-function ReleaseSourceLink({ sourceAppId }: { sourceAppId: string }) {
- const sourceAppQuery = useQuery(
- consoleQuery.apps.byAppId.get.queryOptions({
- input: {
- params: { app_id: sourceAppId },
- },
- }),
- )
- const sourceAppName = sourceAppQuery.data?.name
- const label = sourceAppName || sourceAppId
- const title = sourceAppName ? `${sourceAppName} (${sourceAppId})` : sourceAppId
-
- return (
-
-
- {label}
-
-
-
- )
-}
-
-function ReleaseHistoryMobileRows({
- releaseRows,
- onReleaseDeleted,
-}: {
- releaseRows: ReleaseWithSummaryDeployments[]
- onReleaseDeleted?: () => void
-}) {
- const { t } = useTranslation('deployments')
-
- return (
-
- {releaseRows.map((row) => {
- const release = row
- const releaseId = release.id
- const hasDeployments = row.summaryDeployments.length > 0
-
- return (
-
-
-
-
-
-
-
- ·
- {row.createdBy.displayName}
- {(release.sourceAppId ||
- release.source === ReleaseSource.RELEASE_SOURCE_UPLOAD) && (
- <>
- ·
-
- {t(($) => $['versions.col.sourceApp'])}
-
-
- >
- )}
-
-
-
-
-
-
- {hasDeployments && (
-
-
-
- )}
-
-
- )
- })}
-
- )
-}
-
-export function ReleaseHistoryRows({
- releaseRows,
- onReleaseDeleted,
-}: {
- releaseRows: ReleaseWithSummaryDeployments[]
- onReleaseDeleted?: () => void
-}) {
- const { t } = useTranslation('deployments')
-
- return (
- <>
-
-
-
-
-
-
- {t(($) => $['versions.col.release'])}
-
-
- {t(($) => $['versions.col.sourceApp'])}
-
-
- {t(($) => $['versions.col.createdAt'])}
-
-
- {t(($) => $['versions.col.author'])}
-
-
- {t(($) => $['versions.col.deployedTo'])}
-
-
- {t(($) => $['versions.col.action'])}
-
-
-
-
- {releaseRows.map((row) => {
- const release = row
- const releaseId = release.id
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- {row.createdBy.displayName}
-
-
-
-
-
-
-
-
-
-
-
-
- )
- })}
-
-
-
- >
- )
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-history-table-skeleton.tsx b/web/features/deployments/detail/releases/release-history/release-history-table-skeleton.tsx
deleted file mode 100644
index dcf98ca02a6..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-history-table-skeleton.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-'use client'
-
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
-import {
- DetailTable,
- DetailTableBody,
- DetailTableCard,
- DetailTableCardList,
- DetailTableCell,
- DetailTableHead,
- DetailTableHeader,
- DetailTableRow,
-} from '../../../shared/components/detail-table'
-import { RELEASE_DETAIL_TABLE_COLUMN_CLASS_NAMES } from './table-styles'
-
-const RELEASE_TABLE_ROW_SKELETON_KEYS = ['latest', 'previous', 'older', 'archived', 'initial']
-
-function ReleaseDeploymentsSkeleton() {
- return (
-
-
-
-
- )
-}
-
-export function ReleaseHistoryTableSkeleton() {
- const { t } = useTranslation('deployments')
-
- return (
- <>
-
- {RELEASE_TABLE_ROW_SKELETON_KEYS.map((key) => (
-
-
-
- ))}
-
-
-
-
-
-
- {t(($) => $['versions.col.release'])}
-
-
- {t(($) => $['versions.col.sourceApp'])}
-
-
- {t(($) => $['versions.col.createdAt'])}
-
-
- {t(($) => $['versions.col.author'])}
-
-
- {t(($) => $['versions.col.deployedTo'])}
-
-
- {t(($) => $['versions.col.action'])}
-
-
-
-
- {RELEASE_TABLE_ROW_SKELETON_KEYS.map((key) => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ))}
-
-
-
- >
- )
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-history-table.tsx b/web/features/deployments/detail/releases/release-history/release-history-table.tsx
deleted file mode 100644
index 5af2834c53b..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-history-table.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-'use client'
-
-import { Pagination } from '@langgenius/dify-ui/pagination'
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import {
- DeploymentEmptyState,
- DeploymentStateMessage,
-} from '../../../shared/components/empty-state'
-import {
- adjustReleaseHistoryPageAfterDeleteAtom,
- RELEASE_HISTORY_PAGE_SIZE,
- releaseHistoryAtom,
- releaseHistoryCurrentPageAtom,
- releaseHistoryIsErrorAtom,
- releaseHistoryIsLoadingAtom,
- setReleaseHistoryCurrentPageAtom,
-} from '../state'
-import { ReleaseHistoryRows } from './release-history-rows'
-import { ReleaseHistoryTableSkeleton } from './release-history-table-skeleton'
-import { releaseRowFromSummary } from './release-history-types'
-
-export function ReleaseHistoryTable() {
- const { t } = useTranslation('deployments')
- const currentPage = useAtomValue(releaseHistoryCurrentPageAtom)
- const setCurrentPage = useSetAtom(setReleaseHistoryCurrentPageAtom)
- const adjustPageAfterDelete = useSetAtom(adjustReleaseHistoryPageAfterDeleteAtom)
- const releaseHistory = useAtomValue(releaseHistoryAtom)
- const isLoading = useAtomValue(releaseHistoryIsLoadingAtom)
- const hasError = useAtomValue(releaseHistoryIsErrorAtom)
-
- if (isLoading) return
-
- if (hasError) {
- return (
-
- {t(($) => $['common.loadFailed'])}
-
- )
- }
-
- if (!releaseHistory) {
- return (
-
- {t(($) => $['common.loadFailed'])}
-
- )
- }
-
- const releaseRows = releaseHistory.releaseSummaries.map(releaseRowFromSummary)
- const totalReleases = releaseHistory.pagination.totalCount ?? releaseRows.length
- const totalReleasePages = Math.ceil(totalReleases / RELEASE_HISTORY_PAGE_SIZE)
-
- function handleReleaseDeleted() {
- adjustPageAfterDelete(releaseRows.length)
- }
-
- if (releaseRows.length === 0) {
- return (
- $['versions.emptyTitle'])}
- description={t(($) => $['versions.emptyDescription'])}
- />
- )
- }
-
- return (
-
-
- {totalReleases > RELEASE_HISTORY_PAGE_SIZE && (
-
setCurrentPage(page - 1)}
- />
- )}
-
- )
-}
diff --git a/web/features/deployments/detail/releases/release-history/release-history-types.ts b/web/features/deployments/detail/releases/release-history/release-history-types.ts
deleted file mode 100644
index 72399a67e04..00000000000
--- a/web/features/deployments/detail/releases/release-history/release-history-types.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { ReleaseSummary } from '@dify/contracts/enterprise/types.gen'
-import type { ReleaseWithSummaryDeployments } from './release-deployments'
-import { getReleaseSummaryDeployments } from './release-deployments'
-
-export function releaseRowFromSummary(summary: ReleaseSummary): ReleaseWithSummaryDeployments {
- return {
- ...summary.release,
- summaryDeployments: getReleaseSummaryDeployments(summary),
- }
-}
diff --git a/web/features/deployments/detail/releases/release-history/table-styles.ts b/web/features/deployments/detail/releases/release-history/table-styles.ts
deleted file mode 100644
index 8ad11298a1e..00000000000
--- a/web/features/deployments/detail/releases/release-history/table-styles.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export const RELEASE_DETAIL_TABLE_COLUMN_CLASS_NAMES = {
- action: 'w-14 py-1.5 whitespace-nowrap',
- author: 'whitespace-nowrap',
- createdAt: 'whitespace-nowrap',
- deployedTo: '',
- release: 'whitespace-nowrap',
- sourceApp: 'whitespace-nowrap',
-}
diff --git a/web/features/deployments/detail/releases/state.ts b/web/features/deployments/detail/releases/state.ts
deleted file mode 100644
index 3e29dd7c217..00000000000
--- a/web/features/deployments/detail/releases/state.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-'use client'
-
-import { keepPreviousData, skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../../route-state'
-
-export const RELEASE_HISTORY_PAGE_SIZE = 20
-
-export const releaseHistoryCurrentPageAtom = atom(0)
-
-export const releaseHistoryQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
- const currentPage = get(releaseHistoryCurrentPageAtom)
-
- return consoleQuery.enterprise.releaseService.listReleaseSummaries.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- query: {
- pageNumber: currentPage + 1,
- resultsPerPage: RELEASE_HISTORY_PAGE_SIZE,
- },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- placeholderData: keepPreviousData,
- })
-})
-
-export const releaseHistoryAtom = selectAtom(releaseHistoryQueryAtom, (query) => query.data)
-export const releaseHistoryIsLoadingAtom = selectAtom(
- releaseHistoryQueryAtom,
- (query) => query.isLoading,
-)
-export const releaseHistoryIsErrorAtom = selectAtom(
- releaseHistoryQueryAtom,
- (query) => query.isError,
-)
-
-export const setReleaseHistoryCurrentPageAtom = atom(null, (_get, set, page: number) => {
- set(releaseHistoryCurrentPageAtom, Math.max(page, 0))
-})
-
-export const adjustReleaseHistoryPageAfterDeleteAtom = atom(
- null,
- (get, set, remainingRowsOnPage: number) => {
- const currentPage = get(releaseHistoryCurrentPageAtom)
- if (remainingRowsOnPage === 1 && currentPage > 0)
- set(releaseHistoryCurrentPageAtom, currentPage - 1)
- },
-)
-
-export const releasesLocalAtoms = [releaseHistoryCurrentPageAtom] as const
diff --git a/web/features/deployments/detail/state.ts b/web/features/deployments/detail/state.ts
deleted file mode 100644
index 6add1bcdd7c..00000000000
--- a/web/features/deployments/detail/state.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-'use client'
-
-import { skipToken } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom } from 'jotai/utils'
-import { nextPathnameAtom } from '@/app/components/next-route-state/atoms'
-import { consoleQuery } from '@/service/client'
-import { deploymentRouteAppInstanceIdAtom } from '../route-state'
-import {
- deploymentStatusPollingInterval,
- hasRuntimeInstanceDeployment,
-} from '../shared/domain/runtime-status'
-import { isInstanceDetailTabKey } from './tabs'
-
-export const deploymentDetailActiveTabAtom = atom((get) => {
- const pathnameSegments = get(nextPathnameAtom).split('/').filter(Boolean)
- const deploymentsSegmentIndex = pathnameSegments.indexOf('deployments')
- const selectedSegment =
- deploymentsSegmentIndex >= 0 ? pathnameSegments[deploymentsSegmentIndex + 2] : undefined
-
- return isInstanceDetailTabKey(selectedSegment) ? selectedSegment : 'overview'
-})
-
-export const deploymentDetailAppInstanceQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
-
- return consoleQuery.enterprise.appInstanceService.getAppInstance.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- })
-})
-
-export const deploymentDetailAppInstanceAtom = selectAtom(
- deploymentDetailAppInstanceQueryAtom,
- (query) => query.data,
-)
-export const deploymentDetailAppInstanceIsLoadingAtom = selectAtom(
- deploymentDetailAppInstanceQueryAtom,
- (query) => query.isLoading,
-)
-export const deploymentDetailAppInstanceIsErrorAtom = selectAtom(
- deploymentDetailAppInstanceQueryAtom,
- (query) => query.isError,
-)
-
-export const deploymentEnvironmentDeploymentsQueryAtom = atomWithQuery((get) => {
- const appInstanceId = get(deploymentRouteAppInstanceIdAtom)
-
- return consoleQuery.enterprise.deploymentService.listEnvironmentDeployments.queryOptions({
- input: appInstanceId
- ? {
- params: { appInstanceId },
- }
- : skipToken,
- enabled: Boolean(appInstanceId),
- refetchInterval: (query) =>
- deploymentStatusPollingInterval(query.state.data?.environmentDeployments),
- })
-})
-
-export const deploymentEnvironmentDeploymentsAtom = selectAtom(
- deploymentEnvironmentDeploymentsQueryAtom,
- (query) => query.data,
-)
-export const deploymentEnvironmentDeploymentsIsLoadingAtom = selectAtom(
- deploymentEnvironmentDeploymentsQueryAtom,
- (query) => query.isLoading,
-)
-export const deploymentEnvironmentDeploymentsIsErrorAtom = selectAtom(
- deploymentEnvironmentDeploymentsQueryAtom,
- (query) => query.isError,
-)
-
-export const deploymentRuntimeInstanceRowsAtom = atom((get) => {
- return (
- get(deploymentEnvironmentDeploymentsAtom)?.environmentDeployments.filter(
- hasRuntimeInstanceDeployment,
- ) ?? []
- )
-})
diff --git a/web/features/deployments/detail/tabs.ts b/web/features/deployments/detail/tabs.ts
deleted file mode 100644
index 0d6e1fa8bf7..00000000000
--- a/web/features/deployments/detail/tabs.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export const INSTANCE_DETAIL_TAB_KEYS = [
- 'overview',
- 'instances',
- 'releases',
- 'access',
- 'api-tokens',
-] as const
-
-export type InstanceDetailTabKey = (typeof INSTANCE_DETAIL_TAB_KEYS)[number]
-
-const INSTANCE_DETAIL_TAB_KEY_SET = new Set(INSTANCE_DETAIL_TAB_KEYS)
-
-export function isInstanceDetailTabKey(value?: string): value is InstanceDetailTabKey {
- return value != null && INSTANCE_DETAIL_TAB_KEY_SET.has(value)
-}
diff --git a/web/features/deployments/list/README.md b/web/features/deployments/list/README.md
deleted file mode 100644
index ec04502db93..00000000000
--- a/web/features/deployments/list/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Deployments List
-
-Deployment list page for browsing app instances, filtering by keyword or environment, and rendering deployment status cards.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------- |
-| `create-guide/link` | Links the create deployment CTA to the create-guide workflow while keeping list-owned button styling local. |
-| `deployment-actions` | Reuses the deployment action menu for each card. The list supplies the app instance identity and placement only. |
-| `create-release` | Reuses release creation entry points from card footer actions. |
-| `deploy-drawer/state` | Opens the deploy drawer from a card action without making the list own deploy form state. |
-| `shared` | Reuses shared deployment domain rules, UI primitives, hooks, or local helpers. |
-| `detail/tabs` | Uses the detail tab key type when building card navigation URLs. The list must not depend on detail tab components. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ---------------------------------------- | ----------------------------------------------------------------------------------------- |
-| `app/components/apps/studio-list-header` | Reuses the app studio list header layout instead of defining a list-specific page chrome. |
-| `app/components/base/skeleton` | Reuses the existing skeleton primitive for list and card loading states. |
diff --git a/web/features/deployments/list/index.tsx b/web/features/deployments/list/index.tsx
deleted file mode 100644
index 05eef13a39c..00000000000
--- a/web/features/deployments/list/index.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-'use client'
-
-import { DeploymentsListStateBoundary } from './state'
-import { DeploymentsListShell } from './ui/shell'
-
-export function DeploymentsList() {
- return (
-
-
-
- )
-}
diff --git a/web/features/deployments/list/state/index.ts b/web/features/deployments/list/state/index.ts
deleted file mode 100644
index c13fb36897c..00000000000
--- a/web/features/deployments/list/state/index.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { keepPreviousData } from '@tanstack/react-query'
-import { atom } from 'jotai'
-import { atomWithInfiniteQuery, atomWithQuery } from 'jotai-tanstack-query'
-import { selectAtom, useHydrateAtoms } from 'jotai/utils'
-import { parseAsString, useQueryState } from 'nuqs'
-import { consoleQuery } from '@/service/client'
-import { deploymentStatusPollingInterval } from '../../shared/domain/runtime-status'
-
-const DEPLOYMENTS_LIST_PAGE_SIZE = 100
-
-export const envFilterQueryState = parseAsString.withOptions({ history: 'push' })
-export const keywordsQueryState = parseAsString.withDefault('').withOptions({ history: 'push' })
-
-// Mirrors nuqs URL state. DeploymentsListStateBoundary force-hydrates these
-// atoms on render so query atoms can read URL filters through Jotai.
-const deploymentsListKeywordsAtom = atom('')
-const deploymentsListEnvironmentIdAtom = atom(null)
-
-export type DeploymentsListEnvironmentFilterOption = {
- kind: 'all' | 'environment'
- value: string | null
- displayName?: string
-}
-
-export function DeploymentsListStateBoundary({ children }: { children: ReactNode }) {
- const [envFilter] = useQueryState('env', envFilterQueryState)
- const [keywords] = useQueryState('keywords', keywordsQueryState)
-
- useHydrateAtoms(
- [
- [deploymentsListEnvironmentIdAtom, envFilter],
- [deploymentsListKeywordsAtom, keywords],
- ] as const,
- { dangerouslyForceHydrate: true },
- )
-
- return children
-}
-
-const deploymentsListEnvironmentsQueryAtom = atomWithQuery(() => {
- return consoleQuery.enterprise.environmentService.listEnvironments.queryOptions({
- input: {
- query: {
- // The filter lists every deployable environment; environment count is
- // capped well below the 100-per-page maximum.
- pageNumber: 1,
- resultsPerPage: 100,
- },
- },
- })
-})
-
-const deploymentsListEnvironmentsDataAtom = selectAtom(
- deploymentsListEnvironmentsQueryAtom,
- (query) => query.data,
-)
-
-export const deploymentsListEnvironmentFilterOptionsAtom = atom(
- (get): DeploymentsListEnvironmentFilterOption[] => {
- const environments = get(deploymentsListEnvironmentsDataAtom)?.environments ?? []
-
- return [
- {
- kind: 'all',
- value: null,
- },
- ...environments.map((environment) => ({
- kind: 'environment' as const,
- value: environment.id,
- displayName: environment.displayName,
- })),
- ]
- },
-)
-
-export const deploymentsListSelectedEnvironmentFilterOptionAtom = atom(
- (get): DeploymentsListEnvironmentFilterOption => {
- const envFilter = get(deploymentsListEnvironmentIdAtom)
- const options = get(deploymentsListEnvironmentFilterOptionsAtom)
- const allOption = options[0] ?? { kind: 'all' as const, value: null }
-
- return (
- options.find((option) => option.value === envFilter) ??
- (envFilter
- ? {
- kind: 'environment',
- value: envFilter,
- displayName: envFilter,
- }
- : allOption)
- )
- },
-)
-
-const deploymentsListQueryAtom = atomWithInfiniteQuery((get) => {
- const queryKeywords = get(deploymentsListKeywordsAtom).trim()
- const queryEnvironmentId = get(deploymentsListEnvironmentIdAtom) ?? undefined
-
- return consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.infiniteOptions({
- input: (pageParam) => ({
- query: {
- pageNumber: Number(pageParam),
- resultsPerPage: DEPLOYMENTS_LIST_PAGE_SIZE,
- ...(queryEnvironmentId ? { environmentId: queryEnvironmentId } : {}),
- ...(queryKeywords ? { displayName: queryKeywords } : {}),
- },
- }),
- getNextPageParam: (lastPage) => {
- const currentPage = lastPage.pagination?.currentPage ?? 1
- const totalPages = lastPage.pagination?.totalPages ?? 1
-
- return currentPage < totalPages ? currentPage + 1 : undefined
- },
- initialPageParam: 1,
- placeholderData: keepPreviousData,
- refetchInterval: (query) => {
- const rows =
- query.state.data?.pages.flatMap((page) =>
- page.appInstanceSummaries.flatMap((summary) => summary.environmentDeployments),
- ) ?? []
-
- return deploymentStatusPollingInterval(rows)
- },
- })
-})
-
-const deploymentsListDataAtom = selectAtom(deploymentsListQueryAtom, (query) => query.data)
-export const deploymentsListErrorAtom = selectAtom(deploymentsListQueryAtom, (query) => query.error)
-export const deploymentsListFetchNextPageAtom = selectAtom(
- deploymentsListQueryAtom,
- (query) => query.fetchNextPage,
-)
-export const deploymentsListHasNextPageAtom = selectAtom(
- deploymentsListQueryAtom,
- (query) => query.hasNextPage,
-)
-export const deploymentsListIsFetchingAtom = selectAtom(
- deploymentsListQueryAtom,
- (query) => query.isFetching,
-)
-export const deploymentsListIsFetchingNextPageAtom = selectAtom(
- deploymentsListQueryAtom,
- (query) => query.isFetchingNextPage,
-)
-const deploymentsListIsErrorAtom = selectAtom(deploymentsListQueryAtom, (query) => query.isError)
-
-export const deploymentsListRowsAtom = atom((get) => {
- return get(deploymentsListDataAtom)?.pages.flatMap((page) => page.appInstanceSummaries) ?? []
-})
-
-export const deploymentsListShowSkeletonAtom = atom((get) => {
- const pages = get(deploymentsListDataAtom)?.pages ?? []
-
- return get(deploymentsListIsFetchingAtom) && pages.length === 0
-})
-
-export const deploymentsListShowEmptyStateAtom = atom((get) => {
- return (
- !get(deploymentsListShowSkeletonAtom) &&
- !get(deploymentsListIsErrorAtom) &&
- get(deploymentsListRowsAtom).length === 0
- )
-})
-
-export const deploymentsListShowErrorStateAtom = atom((get) => {
- return !get(deploymentsListShowSkeletonAtom) && get(deploymentsListIsErrorAtom)
-})
-
-export const deploymentsListHasFilterAtom = atom((get) => {
- return Boolean(get(deploymentsListKeywordsAtom).trim() || get(deploymentsListEnvironmentIdAtom))
-})
diff --git a/web/features/deployments/list/ui/__tests__/environment-filter.spec.tsx b/web/features/deployments/list/ui/__tests__/environment-filter.spec.tsx
deleted file mode 100644
index c4ef207c78c..00000000000
--- a/web/features/deployments/list/ui/__tests__/environment-filter.spec.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { screen } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { renderWithNuqs } from '@/test/nuqs-testing'
-import { EnvironmentFilter } from '../environment-filter'
-
-vi.mock('../../state', async () => {
- const { atom } = await import('jotai')
- const { parseAsString } = await import('nuqs')
- const allOption = { kind: 'all' as const, value: null }
-
- return {
- deploymentsListEnvironmentFilterOptionsAtom: atom([allOption]),
- deploymentsListSelectedEnvironmentFilterOptionAtom: atom(allOption),
- envFilterQueryState: parseAsString.withOptions({ history: 'push' }),
- }
-})
-
-describe('EnvironmentFilter', () => {
- it('should keep trigger open state, shadow variant, and arrow DOM in sync', async () => {
- const user = userEvent.setup()
- renderWithNuqs()
-
- const trigger = screen.getByRole('button', { name: 'deployments.filter.allEnvs' })
- const arrow = trigger.querySelector('.i-ri-arrow-down-s-line')
- expect(trigger).not.toHaveAttribute('data-popup-open')
- expect(trigger).toHaveClass('data-popup-open:shadow-xs')
- expect(arrow).not.toHaveClass('rotate-180')
-
- await user.click(trigger)
-
- expect(trigger).toHaveAttribute('data-popup-open')
- expect(arrow).toHaveClass('rotate-180')
-
- await user.click(trigger)
-
- expect(trigger).not.toHaveAttribute('data-popup-open')
- expect(arrow).not.toHaveClass('rotate-180')
- })
-})
diff --git a/web/features/deployments/list/ui/create-deployment-button.tsx b/web/features/deployments/list/ui/create-deployment-button.tsx
deleted file mode 100644
index 7aa11459285..00000000000
--- a/web/features/deployments/list/ui/create-deployment-button.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-'use client'
-
-import { cn } from '@langgenius/dify-ui/cn'
-import { useTranslation } from 'react-i18next'
-import { CreateDeploymentGuideLink } from '../../create-guide/link'
-
-export function CreateDeploymentButton({ className }: { className?: string }) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['list.createDeployment'])}
-
- )
-}
diff --git a/web/features/deployments/list/ui/environment-filter.tsx b/web/features/deployments/list/ui/environment-filter.tsx
deleted file mode 100644
index ed15fec9ecd..00000000000
--- a/web/features/deployments/list/ui/environment-filter.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-'use client'
-
-import type { DeploymentsListEnvironmentFilterOption } from '../state'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from '@langgenius/dify-ui/dropdown-menu'
-import { useAtomValue } from 'jotai'
-import { useQueryState } from 'nuqs'
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import {
- deploymentsListEnvironmentFilterOptionsAtom,
- deploymentsListSelectedEnvironmentFilterOptionAtom,
- envFilterQueryState,
-} from '../state'
-
-function EnvironmentOptionIcon() {
- return
-}
-
-function EnvironmentFilterOptionIcon({
- option,
-}: {
- option: DeploymentsListEnvironmentFilterOption
-}) {
- return option.kind === 'all' ? (
-
- ) : (
-
- )
-}
-
-export function EnvironmentFilter({ className }: { className?: string }) {
- const { t } = useTranslation('deployments')
- const [open, setOpen] = useState(false)
- const [_envFilter, setEnvFilter] = useQueryState('env', envFilterQueryState)
- const filterOptions = useAtomValue(deploymentsListEnvironmentFilterOptionsAtom)
- const selectedOption = useAtomValue(deploymentsListSelectedEnvironmentFilterOptionAtom)
- const activeFilter = selectedOption.value
-
- function optionText(option: DeploymentsListEnvironmentFilterOption) {
- return option.kind === 'all'
- ? t(($) => $['filter.allEnvs'])
- : (option.displayName ?? option.value ?? '')
- }
-
- return (
-
-
-
-
-
-
- {optionText(selectedOption)}
-
-
-
-
-
- {open && (
-
-
- {filterOptions.map((option) => (
- {
- void setEnvFilter(option.value)
- setOpen(false)
- }}
- className={cn(
- 'flex items-center gap-2 rounded-lg py-1.5 pr-2 pl-3 select-none',
- 'cursor-pointer hover:bg-state-base-hover',
- )}
- >
-
-
-
-
- {optionText(option)}
-
- {option.value === activeFilter && (
-
- )}
-
- ))}
-
-
- )}
-
- )
-}
diff --git a/web/features/deployments/list/ui/instance-card-sections.tsx b/web/features/deployments/list/ui/instance-card-sections.tsx
deleted file mode 100644
index 43c336b27a3..00000000000
--- a/web/features/deployments/list/ui/instance-card-sections.tsx
+++ /dev/null
@@ -1,274 +0,0 @@
-'use client'
-
-import type {
- AccessChannels,
- EnvironmentDeployment,
- Release,
-} from '@dify/contracts/enterprise/types.gen'
-import type { ReactElement } from 'react'
-import { ReleaseSource } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
-import {
- PreviewCard,
- PreviewCardContent,
- PreviewCardTrigger,
-} from '@langgenius/dify-ui/preview-card'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
-import { useTranslation } from 'react-i18next'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import Link from '@/next/link'
-import { formatDate } from '../../shared/domain/release'
-import { EnvironmentDeploymentBadge } from '../../shared/ui/deployment-status-badge'
-import { deploymentStatusLabelKey } from '../../shared/ui/deployment-status-style'
-import { getInstanceTabHref } from './instance-card-utils'
-
-const VISIBLE_ENVIRONMENT_COUNT = 3
-
-function releaseSourceLabel(
- release: Release | undefined,
- t: ReturnType>['t'],
-) {
- if (release?.source === ReleaseSource.RELEASE_SOURCE_SOURCE_APP || release?.sourceAppId)
- return t(($) => $['versions.sourceAppOption'])
- if (release?.source === ReleaseSource.RELEASE_SOURCE_UPLOAD)
- return t(($) => $['versions.manualDslOption'])
- return '—'
-}
-
-export function ReleaseMetaTooltip({
- release,
- deployed,
- children,
-}: {
- release?: Release
- deployed: boolean
- children: ReactElement
-}) {
- const { t } = useTranslation('deployments')
-
- if (!release) return children
-
- const rows = [
- { label: t(($) => $['card.tooltip.releaseName']), value: release.displayName },
- {
- label: t(($) => $['card.tooltip.deploymentStatus']),
- value: deployed
- ? t(($) => $['card.tooltip.deployed'])
- : t(($) => $['card.tooltip.notDeployedShort']),
- },
- { label: t(($) => $['card.tooltip.source']), value: releaseSourceLabel(release, t) },
- { label: t(($) => $['card.tooltip.createdAt']), value: formatDate(release.createdAt) },
- ]
-
- return (
-
-
-
-
- {rows.map((row) => (
-
- {row.label}
- {row.value}
-
- ))}
-
-
-
- )
-}
-
-function EnvironmentChip({ row }: { row: EnvironmentDeployment }) {
- const { t } = useTranslation('deployments')
- const name = row.environment.displayName
- const status = row.status
- const statusLabel = t(($) => $[deploymentStatusLabelKey(status)])
- const tooltipSummary = [
- name,
- row.currentRelease ? row.currentRelease.displayName : undefined,
- statusLabel,
- ]
- .filter(Boolean)
- .join(' · ')
-
- return (
-
-
- }
- />
-
- {tooltipSummary}
-
-
- )
-}
-
-function EnvironmentOverflow({ rows }: { rows: EnvironmentDeployment[] }) {
- const { t } = useTranslation('deployments')
-
- return (
-
-
- {t(($) => $['card.envOverflow'], { count: rows.length })}
-
- }
- />
-
-
- {rows.map((row) => {
- const status = row.status
- const summary = [
- row.environment.displayName,
- row.currentRelease ? row.currentRelease.displayName : undefined,
- t(($) => $[deploymentStatusLabelKey(status)]),
- ]
- .filter(Boolean)
- .join(' · ')
-
- return (
-
- {summary}
-
- )
- })}
-
-
-
- )
-}
-
-export function DeploymentStatusContent({
- rows,
- emptyAction,
-}: {
- rows: EnvironmentDeployment[]
- emptyAction?: ReactElement
-}) {
- const visibleRows = rows.slice(0, VISIBLE_ENVIRONMENT_COUNT)
- const overflowRows = rows.slice(VISIBLE_ENVIRONMENT_COUNT)
-
- if (rows.length > 0) {
- return (
-
- {visibleRows.map((row) => (
-
- ))}
- {overflowRows.length > 0 && }
-
- )
- }
-
- if (emptyAction) return {emptyAction}
-
- return null
-}
-
-export function DeploymentAccessLinks({
- appInstanceId,
- access,
- isLoading,
-}: {
- appInstanceId: string
- access?: AccessChannels
- isLoading?: boolean
-}) {
- const { t } = useTranslation('deployments')
-
- if (isLoading) {
- return (
- $['overview.accessStatus'])}
- className="flex min-w-0 grow items-center gap-2"
- >
-
-
-
- )
- }
-
- const links = [
- ...(access?.webAppEnabled
- ? [
- {
- key: 'webapp',
- href: getInstanceTabHref(appInstanceId, 'access'),
- label: t(($) => $['card.access.webApp']),
- icon: 'i-ri-global-line',
- },
- ]
- : []),
- ...(access?.webAppEnabled
- ? [
- {
- key: 'cli',
- href: getInstanceTabHref(appInstanceId, 'access'),
- label: t(($) => $['card.access.cli']),
- icon: 'i-ri-terminal-box-line',
- },
- ]
- : []),
- ...(access?.developerApiEnabled
- ? [
- {
- key: 'api-tokens',
- href: getInstanceTabHref(appInstanceId, 'api-tokens'),
- label: t(($) => $['card.access.api']),
- icon: 'i-ri-code-s-slash-line',
- },
- ]
- : []),
- ]
-
- if (links.length === 0) {
- return (
- $['overview.accessStatus'])}
- className="flex min-w-0 grow items-center gap-1.5 text-text-quaternary"
- >
-
- {t(($) => $['card.access.none'])}
-
- )
- }
-
- return (
- $['overview.accessStatus'])}
- className="flex min-w-0 grow items-center gap-2"
- >
- {links.map((link) => (
-
-
-
-
- }
- />
- {link.label}
-
- ))}
-
- )
-}
diff --git a/web/features/deployments/list/ui/instance-card-utils.ts b/web/features/deployments/list/ui/instance-card-utils.ts
deleted file mode 100644
index 9fc43487c66..00000000000
--- a/web/features/deployments/list/ui/instance-card-utils.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { EnvironmentDeployment, Release } from '@dify/contracts/enterprise/types.gen'
-import type { InstanceDetailTabKey } from '../../detail/tabs'
-import { isUndeployedDeploymentRow } from '../../shared/domain/runtime-status'
-
-export function getInstanceTabHref(appInstanceId: string, tabKey: InstanceDetailTabKey) {
- return `/deployments/${appInstanceId}/${tabKey}`
-}
-
-export function isActiveDeployment(row: EnvironmentDeployment) {
- return !isUndeployedDeploymentRow(row)
-}
-
-export function isReleaseDeployed(release: Release | undefined, rows: EnvironmentDeployment[]) {
- if (!release) return false
-
- return rows.some((row) => row.currentRelease?.id === release.id)
-}
diff --git a/web/features/deployments/list/ui/instance-card.tsx b/web/features/deployments/list/ui/instance-card.tsx
deleted file mode 100644
index c942cbfd724..00000000000
--- a/web/features/deployments/list/ui/instance-card.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-'use client'
-
-import type { AppInstanceSummary } from '@dify/contracts/enterprise/types.gen'
-import { Button } from '@langgenius/dify-ui/button'
-import { useSetAtom } from 'jotai'
-import { useTranslation } from 'react-i18next'
-import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
-import Link from '@/next/link'
-import { CreateReleaseControl } from '../../create-release'
-import { openDeployDrawerAtom } from '../../deploy-drawer/state'
-import { DeploymentActionsMenu } from '../../deployment-actions'
-import {
- DeploymentAccessLinks,
- DeploymentStatusContent,
- ReleaseMetaTooltip,
-} from './instance-card-sections'
-import { getInstanceTabHref, isActiveDeployment, isReleaseDeployed } from './instance-card-utils'
-
-export function InstanceCard({ summary }: { summary: AppInstanceSummary }) {
- const { t } = useTranslation('deployments')
- const { formatTimeFromNow } = useFormatTimeFromNow()
- const openDeployDrawer = useSetAtom(openDeployDrawerAtom)
- const appInstance = summary.appInstance
- const appInstanceId = appInstance.id
- const appName = appInstance.displayName
- const detailHref = getInstanceTabHref(appInstanceId, 'overview')
- const description = appInstance.description.trim()
- const access = summary.accessChannels
- const releaseRows = summary.latestRelease ? [summary.latestRelease] : []
- const hasRelease = releaseRows.length > 0
- const activeDeploymentRows = summary.environmentDeployments.filter(isActiveDeployment)
- const latestRelease = releaseRows[0]
- const latestReleaseTime = latestRelease?.createdAt
- const latestReleaseTimeMs = latestReleaseTime ? Date.parse(latestReleaseTime) : Number.NaN
- const latestReleaseDeployed = isReleaseDeployed(latestRelease, activeDeploymentRows)
- const releaseMeta = latestRelease
- ? [
- latestRelease.displayName,
- Number.isNaN(latestReleaseTimeMs) ? undefined : formatTimeFromNow(latestReleaseTimeMs),
- ]
- .filter(Boolean)
- .join(' · ')
- : t(($) => $['card.notDeployed'])
- const showDeployAction = hasRelease && activeDeploymentRows.length === 0
- const showFooterCreateReleaseAction = !hasRelease
-
- return (
-
-
-
-
-
{appName}
- {description ? (
-
{description}
- ) : (
-
- {t(($) => $['card.noDescription'])}
-
- )}
-
-
-
$['card.tooltip.deploymentStatus'])}
- className="min-h-8 px-4 pt-4 pb-3"
- >
- openDeployDrawer({ appInstanceId })}
- >
- {t(($) => $['card.menu.deploy'])}
-
- ) : undefined
- }
- />
-
-
-
- {showFooterCreateReleaseAction ? (
-
- $['card.createFirstRelease'])}
- className="max-w-full"
- />
-
- ) : (
-
- )}
-
-
- {releaseMeta}
-
-
-
-
-
- )
-}
diff --git a/web/features/deployments/list/ui/shell.tsx b/web/features/deployments/list/ui/shell.tsx
deleted file mode 100644
index 8b4e32616d4..00000000000
--- a/web/features/deployments/list/ui/shell.tsx
+++ /dev/null
@@ -1,219 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { Button } from '@langgenius/dify-ui/button'
-import { cn } from '@langgenius/dify-ui/cn'
-import { Input } from '@langgenius/dify-ui/input'
-import { useAtomValue } from 'jotai'
-import { debounce, useQueryState } from 'nuqs'
-import { useRef } from 'react'
-import { useTranslation } from 'react-i18next'
-import { StudioListHeader } from '@/app/components/apps/studio-list-header'
-import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-sentinel'
-import { SkeletonRectangle } from '@/app/components/base/skeleton'
-import { DeploymentEmptyState, DeploymentStateMessage } from '../../shared/components/empty-state'
-import {
- deploymentsListErrorAtom,
- deploymentsListFetchNextPageAtom,
- deploymentsListHasFilterAtom,
- deploymentsListHasNextPageAtom,
- deploymentsListIsFetchingAtom,
- deploymentsListIsFetchingNextPageAtom,
- deploymentsListRowsAtom,
- deploymentsListShowEmptyStateAtom,
- deploymentsListShowErrorStateAtom,
- deploymentsListShowSkeletonAtom,
- envFilterQueryState,
- keywordsQueryState,
-} from '../state'
-import { CreateDeploymentButton } from './create-deployment-button'
-import { EnvironmentFilter } from './environment-filter'
-import { InstanceCard } from './instance-card'
-
-const INSTANCE_CARD_SKELETON_KEYS = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
-
-function DeploymentsListState({ children }: { children: ReactNode }) {
- return {children}
-}
-
-function DeploymentsListEmpty() {
- const { t } = useTranslation('deployments')
- const hasFilter = useAtomValue(deploymentsListHasFilterAtom)
- const [_keywords, setKeywords] = useQueryState('keywords', keywordsQueryState)
- const [_envFilter, setEnvFilter] = useQueryState('env', envFilterQueryState)
-
- function clearFilters() {
- void setKeywords(null)
- void setEnvFilter(null)
- }
-
- return (
- $['list.emptyFilteredTitle']) : t(($) => $['list.emptyTitle'])}
- description={
- hasFilter
- ? t(($) => $['list.emptyFilteredDescription'])
- : t(($) => $['list.emptyDescription'])
- }
- action={
- hasFilter ? (
-
- ) : (
-
- )
- }
- />
- )
-}
-
-function InstanceCardSkeleton() {
- return (
-
- )
-}
-
-function DeploymentsListSkeleton() {
- return INSTANCE_CARD_SKELETON_KEYS.map((key) => )
-}
-
-function DeploymentsSearchInput({ className }: { className?: string }) {
- const { t } = useTranslation('deployments')
- const [keywords, setKeywords] = useQueryState('keywords', keywordsQueryState)
-
- function handleKeywordsChange(next: string) {
- void setKeywords(next.trim() ? next : null, {
- limitUrlUpdates: next.trim() ? debounce(300) : undefined,
- shallow: false,
- })
- }
-
- return (
-
-
- $['filter.searchPlaceholder'])}
- placeholder={t(($) => $['filter.searchPlaceholder'])}
- value={keywords}
- onChange={(e) => handleKeywordsChange(e.target.value)}
- />
- {keywords && (
-
- )}
-
- )
-}
-
-function DeploymentsListControls() {
- const { t } = useTranslation()
-
- return (
-
-
- {t(($) => $['menus.deployments'], { ns: 'common' })}
-
-
- }
- >
-
-
- )
-}
-
-export function DeploymentsListShell() {
- const { t } = useTranslation('deployments')
- const deploymentsListError = useAtomValue(deploymentsListErrorAtom)
- const deploymentsListFetchNextPage = useAtomValue(deploymentsListFetchNextPageAtom)
- const deploymentsListHasNextPage = useAtomValue(deploymentsListHasNextPageAtom)
- const deploymentsListIsFetching = useAtomValue(deploymentsListIsFetchingAtom)
- const deploymentsListIsFetchingNextPage = useAtomValue(deploymentsListIsFetchingNextPageAtom)
- const appInstanceSummaries = useAtomValue(deploymentsListRowsAtom)
- const showSkeleton = useAtomValue(deploymentsListShowSkeletonAtom)
- const showErrorState = useAtomValue(deploymentsListShowErrorStateAtom)
- const showEmptyState = useAtomValue(deploymentsListShowEmptyStateAtom)
- const scrollContainerRef = useRef(null)
- const canLoadMore =
- deploymentsListHasNextPage && !deploymentsListIsFetching && !deploymentsListError
-
- return (
-
-
-
- {showSkeleton ? (
-
- ) : showErrorState ? (
- {t(($) => $['common.loadFailed'])}
- ) : showEmptyState ? (
-
- ) : (
- appInstanceSummaries.map((summary) => (
-
- ))
- )}
- {deploymentsListIsFetchingNextPage && }
- {
- void deploymentsListFetchNextPage({ cancelRefetch: false })
- }}
- preloadDistance={300}
- scrollContainerRef={scrollContainerRef}
- />
-
-
- )
-}
diff --git a/web/features/deployments/route-state.ts b/web/features/deployments/route-state.ts
deleted file mode 100644
index 72463fa0fed..00000000000
--- a/web/features/deployments/route-state.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-'use client'
-
-import { atom } from 'jotai'
-import { nextParamsAtom } from '@/app/components/next-route-state/atoms'
-
-export const deploymentRouteAppInstanceIdAtom = atom((get) => {
- const appInstanceId = get(nextParamsAtom).appInstanceId
-
- return typeof appInstanceId === 'string' ? appInstanceId : undefined
-})
diff --git a/web/features/deployments/shared/README.md b/web/features/deployments/shared/README.md
deleted file mode 100644
index 6e2819a00eb..00000000000
--- a/web/features/deployments/shared/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Deployment Shared
-
-Shared deployment domain rules, UI primitives, hooks, and local helpers used by multiple deployment modules.
-
-## Internal Modules
-
-| Module | Why this module uses it |
-| ------------------- | ------------------------------------------------------------------------- |
-| `shared/components` | Provides reusable deployment section, table, endpoint, and binding UI. |
-| `shared/domain` | Provides reusable deployment DSL, release, runtime, and error rules. |
-| `shared/hooks` | Provides reusable hooks for deployment module workflows. |
-| `shared/ui` | Provides reusable deployment status presentation primitives and mappings. |
-
-## External Modules
-
-| Module | Why this module uses it |
-| ------------ | ----------------------------------------------------------------- |
-| `types/app` | Uses app mode enums when parsing deployment DSL content. |
-| `utils/time` | Formats release timestamps for deployment release metadata views. |
diff --git a/web/features/deployments/shared/components/__tests__/env-var-bindings-utils.spec.ts b/web/features/deployments/shared/components/__tests__/env-var-bindings-utils.spec.ts
deleted file mode 100644
index ab177b3b355..00000000000
--- a/web/features/deployments/shared/components/__tests__/env-var-bindings-utils.spec.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import type { EnvVarSlot } from '@dify/contracts/enterprise/types.gen'
-import { EnvVarValueType } from '@dify/contracts/enterprise/types.gen'
-import { describe, expect, it } from 'vitest'
-import { envVarBindingSlotFromContract, envVarBindingValueType } from '../env-var-bindings-utils'
-
-function slot(overrides: Partial): EnvVarSlot {
- return {
- key: 'API_KEY',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_STRING,
- description: '',
- ...overrides,
- }
-}
-
-describe('env var binding value type normalization', () => {
- it('should normalize generated and DSL value types', () => {
- expect(envVarBindingValueType(EnvVarValueType.ENV_VAR_VALUE_TYPE_NUMBER)).toBe('number')
- expect(envVarBindingValueType('number')).toBe('number')
- expect(envVarBindingValueType(EnvVarValueType.ENV_VAR_VALUE_TYPE_SECRET)).toBe('secret')
- expect(envVarBindingValueType('secret')).toBe('secret')
- expect(envVarBindingValueType(EnvVarValueType.ENV_VAR_VALUE_TYPE_STRING)).toBe('string')
- expect(envVarBindingValueType()).toBe('string')
- })
-})
-
-describe('env var contract slot conversion', () => {
- it('should trim keys and preserve default and last value availability', () => {
- expect(
- envVarBindingSlotFromContract(
- slot({
- key: ' API_TOKEN ',
- valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_SECRET,
- defaultValue: '',
- lastValue: 'previous',
- }),
- ),
- ).toMatchObject({
- key: 'API_TOKEN',
- valueType: 'secret',
- hasDefaultValue: true,
- hasLastValue: true,
- })
- })
-
- it('should ignore blank keys and mark absent values as unavailable', () => {
- expect(envVarBindingSlotFromContract(slot({ key: ' ' }))).toBeUndefined()
- expect(
- envVarBindingSlotFromContract(
- slot({ key: 'PORT', valueType: EnvVarValueType.ENV_VAR_VALUE_TYPE_NUMBER }),
- ),
- ).toMatchObject({
- key: 'PORT',
- valueType: 'number',
- hasDefaultValue: false,
- hasLastValue: false,
- })
- })
-})
diff --git a/web/features/deployments/shared/components/__tests__/runtime-credential-bindings-utils.spec.ts b/web/features/deployments/shared/components/__tests__/runtime-credential-bindings-utils.spec.ts
deleted file mode 100644
index 70513a638cd..00000000000
--- a/web/features/deployments/shared/components/__tests__/runtime-credential-bindings-utils.spec.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import type { CredentialCandidate, CredentialSlot } from '@dify/contracts/enterprise/types.gen'
-import { PluginCategory } from '@dify/contracts/enterprise/types.gen'
-import { describe, expect, it } from 'vitest'
-import {
- hasMissingRequiredRuntimeCredentialBinding,
- runtimeCredentialCandidateOptions,
- runtimeCredentialProviderName,
- runtimeCredentialSlotKey,
- selectedDeploymentRuntimeCredentials,
- selectedRuntimeCredentialSelections,
-} from '../runtime-credential-bindings-utils'
-
-function candidate(overrides: Partial): CredentialCandidate {
- return {
- credentialId: 'credential-1',
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- displayName: 'OpenAI key',
- fromEnterprise: false,
- ...overrides,
- }
-}
-
-function slot(overrides: Partial): CredentialSlot {
- return {
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- candidates: [
- candidate({ credentialId: 'credential-1', displayName: 'Primary key' }),
- candidate({ credentialId: 'credential-2', displayName: 'Backup key' }),
- ],
- lastCredentialId: '',
- ...overrides,
- }
-}
-
-describe('runtime credential provider names', () => {
- it('should resolve known provider slugs and title-case custom slugs', () => {
- expect(runtimeCredentialProviderName('langgenius/openai')).toBe('OpenAI')
- expect(runtimeCredentialProviderName('langgenius/azure_openai')).toBe('Azure OpenAI')
- expect(runtimeCredentialProviderName('custom/my-provider')).toBe('My Provider')
- expect(runtimeCredentialProviderName('/')).toBeUndefined()
- })
-})
-
-describe('runtime credential selection helpers', () => {
- it('should build stable slot keys and candidate labels', () => {
- const credentialSlot = slot({
- candidates: [
- candidate({
- credentialId: 'credential-1',
- providerId: 'langgenius/openai',
- displayName: 'Production key · langgenius/openai',
- }),
- candidate({
- credentialId: 'credential-2',
- providerId: 'langgenius/openai',
- displayName: 'Backup key (langgenius/openai)',
- }),
- candidate({
- credentialId: 'credential-3',
- providerId: 'langgenius/openai',
- displayName: '',
- }),
- ],
- })
-
- expect(runtimeCredentialSlotKey(credentialSlot)).toBe('langgenius/openai:PLUGIN_CATEGORY_MODEL')
- expect(runtimeCredentialCandidateOptions(credentialSlot)).toEqual([
- { value: 'credential-1', label: 'Production key' },
- { value: 'credential-2', label: 'Backup key' },
- { value: 'credential-3', label: 'credential-3' },
- ])
- })
-
- it('should prefer valid manual selections before last or only candidates', () => {
- const firstSlot = slot({
- providerId: 'langgenius/openai',
- lastCredentialId: 'credential-2',
- })
- const secondSlot = slot({
- providerId: 'langgenius/bedrock',
- candidates: [candidate({ credentialId: 'bedrock-1', providerId: 'langgenius/bedrock' })],
- lastCredentialId: '',
- })
- const thirdSlot = slot({
- providerId: 'custom/empty',
- candidates: [
- candidate({ credentialId: 'empty-1', providerId: 'custom/empty' }),
- candidate({ credentialId: 'empty-2', providerId: 'custom/empty' }),
- ],
- lastCredentialId: 'stale',
- })
-
- expect(
- selectedRuntimeCredentialSelections([firstSlot, secondSlot, thirdSlot], {
- [runtimeCredentialSlotKey(firstSlot)]: 'credential-1',
- [runtimeCredentialSlotKey(secondSlot)]: 'stale',
- }),
- ).toEqual({
- [runtimeCredentialSlotKey(firstSlot)]: 'credential-1',
- [runtimeCredentialSlotKey(secondSlot)]: 'bedrock-1',
- })
- })
-
- it('should convert selected credentials into deployment payload inputs', () => {
- const firstSlot = slot({ providerId: 'langgenius/openai' })
- const secondSlot = slot({ providerId: 'langgenius/bedrock' })
-
- expect(hasMissingRequiredRuntimeCredentialBinding(firstSlot)).toBe(true)
- expect(hasMissingRequiredRuntimeCredentialBinding(firstSlot, 'credential-1')).toBe(false)
- expect(
- selectedDeploymentRuntimeCredentials([firstSlot, secondSlot], {
- [runtimeCredentialSlotKey(firstSlot)]: 'credential-1',
- }),
- ).toEqual([
- {
- providerId: 'langgenius/openai',
- category: PluginCategory.PLUGIN_CATEGORY_MODEL,
- credentialId: 'credential-1',
- },
- ])
- })
-})
diff --git a/web/features/deployments/shared/components/__tests__/title-tooltip.spec.tsx b/web/features/deployments/shared/components/__tests__/title-tooltip.spec.tsx
deleted file mode 100644
index 6f9abf66b68..00000000000
--- a/web/features/deployments/shared/components/__tests__/title-tooltip.spec.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { fireEvent, render, screen, waitFor } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { describe, expect, it } from 'vitest'
-import { TitleTooltip } from '../title-tooltip'
-
-function setElementSize(
- element: HTMLElement,
- {
- clientWidth,
- scrollWidth,
- }: {
- clientWidth: number
- scrollWidth: number
- },
-) {
- Object.defineProperties(element, {
- clientWidth: { configurable: true, value: clientWidth },
- scrollWidth: { configurable: true, value: scrollWidth },
- })
-}
-
-describe('TitleTooltip', () => {
- it('does not show duplicate content when the trigger is not truncated', () => {
- render(
-
- 11
- ,
- )
-
- fireEvent.pointerOver(screen.getByText('11'))
-
- expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
- })
-
- it('shows duplicate content when the trigger is truncated', async () => {
- const user = userEvent.setup()
- render(
-
- Long deployment name
- ,
- )
-
- const trigger = screen.getByText('Long deployment name')
- setElementSize(trigger, { clientWidth: 80, scrollWidth: 160 })
- await user.hover(trigger)
-
- await waitFor(() => {
- expect(screen.getAllByText('Long deployment name')).toHaveLength(2)
- })
- })
-
- it('shows content that adds information beyond the trigger text', async () => {
- const user = userEvent.setup()
- render(
-
-
- ,
- )
-
- await user.hover(screen.getByRole('button', { name: 'Deploy' }))
-
- expect(await screen.findByText('Disabled until an initial release exists')).toBeInTheDocument()
- })
-})
diff --git a/web/features/deployments/shared/components/detail-table-styles.ts b/web/features/deployments/shared/components/detail-table-styles.ts
deleted file mode 100644
index 5a975b8d2e0..00000000000
--- a/web/features/deployments/shared/components/detail-table-styles.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { cn } from '@langgenius/dify-ui/cn'
-
-export const DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME = cn(
- 'inline-flex size-8 items-center justify-center rounded-md text-text-tertiary outline-hidden',
- 'hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid',
- 'data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary',
- 'disabled:cursor-not-allowed disabled:opacity-50',
-)
diff --git a/web/features/deployments/shared/components/detail-table.tsx b/web/features/deployments/shared/components/detail-table.tsx
deleted file mode 100644
index 22918d3ea77..00000000000
--- a/web/features/deployments/shared/components/detail-table.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import type { ComponentProps } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-
-type DetailTableProps = ComponentProps<'table'> & {
- containerClassName?: string
-}
-
-export function DetailTable({ className, containerClassName, ...props }: DetailTableProps) {
- return (
-
- )
-}
-
-export function DetailTableHeader({ className, ...props }: ComponentProps<'thead'>) {
- return (
-
- )
-}
-
-export function DetailTableBody({ className, ...props }: ComponentProps<'tbody'>) {
- return (
-
- )
-}
-
-export function DetailTableRow({ className, ...props }: ComponentProps<'tr'>) {
- return (
-
- )
-}
-
-export function DetailTableHead({ className, ...props }: ComponentProps<'th'>) {
- return (
- |
- )
-}
-
-export function DetailTableCell({ className, ...props }: ComponentProps<'td'>) {
- return (
- |
- )
-}
-
-export function DetailTableCardList({ className, ...props }: ComponentProps<'div'>) {
- return (
-
- )
-}
-
-export function DetailTableCard({ className, ...props }: ComponentProps<'div'>) {
- return (
-
- )
-}
diff --git a/web/features/deployments/shared/components/empty-state.tsx b/web/features/deployments/shared/components/empty-state.tsx
deleted file mode 100644
index 3cbcd7bd2c0..00000000000
--- a/web/features/deployments/shared/components/empty-state.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-
-type DeploymentEmptyStateVariant = 'page' | 'list' | 'section' | 'compact'
-type DeploymentStateMessageVariant = 'page' | 'list' | 'section' | 'compact' | 'embedded'
-type DeploymentEmptyStateAlign = 'center' | 'start'
-
-type DeploymentEmptyStateProps = {
- icon?: string
- title: ReactNode
- description?: ReactNode
- action?: ReactNode
- variant?: DeploymentEmptyStateVariant
- align?: DeploymentEmptyStateAlign
- className?: string
-}
-
-type DeploymentStateMessageProps = {
- children: ReactNode
- variant?: DeploymentStateMessageVariant
- className?: string
-}
-
-type DeploymentNoticeStateProps = {
- children: ReactNode
- icon?: string
- className?: string
-}
-
-const emptyStateContainerClassNames: Record = {
- page: 'col-span-full min-h-80 rounded-xl border border-divider-subtle bg-background-default-subtle px-6 py-12',
- list: 'min-h-60 rounded-lg border border-divider-subtle bg-background-default-subtle px-6 py-12',
- section:
- 'min-h-36 rounded-lg border border-divider-subtle bg-background-default-subtle px-6 py-8',
- compact:
- 'min-h-14 rounded-lg border border-divider-subtle bg-background-default-subtle px-3 py-3',
-}
-
-const stateMessageClassNames: Record = {
- page: 'col-span-full flex min-h-80 items-center justify-center rounded-xl border border-dashed border-divider-subtle bg-background-default-subtle px-6 py-12 text-center system-sm-regular text-text-tertiary',
- list: 'flex min-h-36 items-center justify-center rounded-lg border border-dashed border-divider-subtle bg-background-default-subtle px-6 py-12 text-center system-sm-regular text-text-tertiary',
- section:
- 'flex min-h-24 items-center justify-center rounded-lg border border-dashed border-divider-subtle bg-background-default-subtle px-4 py-6 text-center system-sm-regular text-text-tertiary',
- compact:
- 'rounded-lg border border-dashed border-divider-subtle bg-background-default-subtle px-3 py-3 system-sm-regular text-text-tertiary',
- embedded: 'px-4 py-10 text-center system-sm-regular text-text-tertiary',
-}
-
-export function DeploymentEmptyState({
- icon,
- title,
- description,
- action,
- variant = 'list',
- align,
- className,
-}: DeploymentEmptyStateProps) {
- const effectiveAlign = align ?? (variant === 'compact' ? 'start' : 'center')
- const isLarge = variant === 'page' || variant === 'list'
- const hasDescription = Boolean(description)
- const hasAction = Boolean(action)
- const hasIcon = Boolean(icon)
-
- return (
-
- {hasIcon && (
-
-
-
- )}
-
- {title}
-
- {hasDescription && (
-
- {description}
-
- )}
- {hasAction && (
-
{action}
- )}
-
- )
-}
-
-export function DeploymentStateMessage({
- children,
- variant = 'list',
- className,
-}: DeploymentStateMessageProps) {
- return {children}
-}
-
-export function DeploymentNoticeState({
- children,
- icon = 'i-ri-information-line',
- className,
-}: DeploymentNoticeStateProps) {
- return (
-
-
- {children}
-
- )
-}
diff --git a/web/features/deployments/shared/components/endpoint.tsx b/web/features/deployments/shared/components/endpoint.tsx
deleted file mode 100644
index e4f7233e0fe..00000000000
--- a/web/features/deployments/shared/components/endpoint.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-import { toast } from '@langgenius/dify-ui/toast'
-import { useClipboard } from 'foxact/use-clipboard'
-import { useTranslation } from 'react-i18next'
-
-type CopyPillProps = {
- label: string
- value: string
- prefix?: ReactNode
- className?: string
-}
-
-export function CopyPill({ label, value, prefix, className }: CopyPillProps) {
- const { t } = useTranslation('deployments')
- const { copied, copy } = useClipboard({
- onCopyError: () => {
- toast.error(t(($) => $['access.copyFailed']))
- },
- })
-
- return (
-
-
- {label}
-
- {prefix}
-
- {value}
-
-
-
-
- )
-}
-
-type EndpointRowProps = {
- envName: string
- label: string
- value: string
- openLabel?: string
-}
-
-export function EndpointRow({ envName, label, value, openLabel }: EndpointRowProps) {
- return (
-
- )
-}
diff --git a/web/features/deployments/shared/components/env-var-bindings-utils.ts b/web/features/deployments/shared/components/env-var-bindings-utils.ts
deleted file mode 100644
index 5007bfe3dcd..00000000000
--- a/web/features/deployments/shared/components/env-var-bindings-utils.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type { EnvVarSlot } from '@dify/contracts/enterprise/types.gen'
-import type { EnvVarBindingSlot } from './env-var-bindings'
-
-export function envVarBindingValueType(
- valueType?: EnvVarSlot['valueType'] | string,
-): EnvVarBindingSlot['valueType'] {
- switch (valueType) {
- case 'ENV_VAR_VALUE_TYPE_NUMBER':
- case 'number':
- return 'number'
- case 'ENV_VAR_VALUE_TYPE_SECRET':
- case 'secret':
- return 'secret'
- default:
- return 'string'
- }
-}
-
-export function envVarBindingSlotFromContract(slot: EnvVarSlot): EnvVarBindingSlot | undefined {
- const key = slot.key.trim()
- if (!key) return undefined
-
- return {
- ...slot,
- key,
- valueType: envVarBindingValueType(slot.valueType),
- hasDefaultValue: slot.defaultValue !== undefined,
- hasLastValue: slot.lastValue !== undefined,
- }
-}
diff --git a/web/features/deployments/shared/components/env-var-bindings.tsx b/web/features/deployments/shared/components/env-var-bindings.tsx
deleted file mode 100644
index 396514fca85..00000000000
--- a/web/features/deployments/shared/components/env-var-bindings.tsx
+++ /dev/null
@@ -1,268 +0,0 @@
-'use client'
-
-import type { EnvVarInput, EnvVarSlot } from '@dify/contracts/enterprise/types.gen'
-import type { InputHTMLAttributes } from 'react'
-import { EnvVarValueSource as ApiEnvVarValueSource } from '@dify/contracts/enterprise/types.gen'
-import { cn } from '@langgenius/dify-ui/cn'
-import { Input } from '@langgenius/dify-ui/input'
-import { SegmentedControl, SegmentedControlItem } from '@langgenius/dify-ui/segmented-control'
-import { TitleTooltip } from './title-tooltip'
-
-export type EnvVarValueSource = NonNullable
-type EnvVarValueType = 'string' | 'number' | 'secret'
-// Contract EnvVarSlot carries an EnvVarValueType enum and signals default/last
-// presence via optional fields; binding slots keep the legacy lowercase value
-// type plus explicit has* flags because DSL-metadata slots share this shape.
-// Adapters live in env-var-bindings-utils.ts.
-export type EnvVarBindingSlot = Omit & {
- key: string
- valueType: EnvVarValueType
- hasDefaultValue?: boolean
- hasLastValue?: boolean
-}
-export type EnvVarValueSelection = {
- valueSource: EnvVarValueSource
- value?: string
-}
-export type EnvVarValues = Record
-type EnvVarDefaultSourcePriority = 'dslDefault' | 'lastDeployment'
-
-type EnvVarValueSourceOption = {
- value: EnvVarValueSource
- label: string
-}
-
-type EnvVarBindingsPanelProps = {
- slots: EnvVarBindingSlot[]
- values: EnvVarValues
- title: string
- hint: string
- envVarPlaceholder: string
- literalSourceLabel: string
- defaultSourceLabel: string
- lastDeploymentSourceLabel: string
- valueTypeLabels: Record
- sourceAriaLabel: (key: string) => string
- defaultSourcePriority?: EnvVarDefaultSourcePriority
- envVarCountLabel?: string
- missingRequiredLabel?: string
- showMissingRequired?: boolean
- listScrollable?: boolean
- onChange: (key: string, value: EnvVarValueSelection) => void
- className?: string
- listClassName?: string
-}
-
-const ENV_VAR_INPUT_TYPES = {
- string: 'text',
- number: 'number',
- secret: 'password',
-} satisfies Record['type']>
-
-function envVarInputId(index: number, key: string) {
- const safeKey = key.replace(/[^\w-]/g, '-')
-
- return `env-var-binding-${index}-${safeKey}`
-}
-
-function envVarValueSourceOptions(
- slot: EnvVarBindingSlot,
- labels: {
- literal: string
- defaultValue: string
- lastDeployment: string
- },
-): EnvVarValueSourceOption[] {
- const options: EnvVarValueSourceOption[] = [
- {
- value: ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- label: labels.literal,
- },
- ]
-
- if (slot.hasDefaultValue) {
- options.push({
- value: ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT,
- label: labels.defaultValue,
- })
- }
-
- if (slot.hasLastValue) {
- options.push({
- value: ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT,
- label: labels.lastDeployment,
- })
- }
-
- return options
-}
-
-export function EnvVarBindingsPanel({
- slots,
- values,
- title,
- hint,
- envVarPlaceholder,
- literalSourceLabel,
- defaultSourceLabel,
- lastDeploymentSourceLabel,
- valueTypeLabels,
- sourceAriaLabel,
- defaultSourcePriority,
- envVarCountLabel,
- missingRequiredLabel,
- showMissingRequired = false,
- listScrollable = true,
- onChange,
- className,
- listClassName,
-}: EnvVarBindingsPanelProps) {
- if (slots.length === 0) return null
-
- return (
-
-
-
-
{title}
-
- {envVarCountLabel ?? slots.length}
-
-
-
{hint}
-
-
- {slots.map((slot, index) => {
- const description = slot.description
- const inputId = envVarInputId(index, slot.key)
- const selection = values[slot.key]
- const defaultValueSource =
- defaultSourcePriority === 'lastDeployment' && slot.hasLastValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT
- : slot.hasDefaultValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT
- : slot.hasLastValue
- ? ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT
- : ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL
- const valueSource = selection?.valueSource ?? defaultValueSource
- const invalidLiteralNumber =
- slot.valueType === 'number' && Number.isNaN(Number(selection?.value))
- const missing =
- showMissingRequired &&
- valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL &&
- (!selection?.value || invalidLiteralNumber)
- const sourceOptions = envVarValueSourceOptions(slot, {
- literal: literalSourceLabel,
- defaultValue: defaultSourceLabel,
- lastDeployment: lastDeploymentSourceLabel,
- })
- const isLiteralValue = valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL
- const displayValue =
- valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_DSL_DEFAULT
- ? slot.defaultValue
- : valueSource === ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LAST_DEPLOYMENT
- ? slot.lastValue
- : selection?.value
-
- return (
-
-
-
-
-
-
-
-
-
- {valueTypeLabels[slot.valueType]}
-
- {slot.valueType === 'secret' && (
-
- )}
-
- {sourceOptions.length > 1 && (
-
- aria-label={sourceAriaLabel(slot.key)}
- value={[valueSource]}
- onValueChange={(value) => {
- const nextSource = value[0]
- if (!nextSource) return
- onChange(slot.key, {
- value: selection?.value,
- valueSource: nextSource,
- })
- }}
- className="shrink-0"
- >
- {sourceOptions.map((option) => (
-
- {option.label}
-
- ))}
-
- )}
-
- {description && (
-
-
- {description}
-
-
- )}
-
- onChange(slot.key, {
- value: event.target.value,
- valueSource: ApiEnvVarValueSource.ENV_VAR_VALUE_SOURCE_LITERAL,
- })
- }
- placeholder={envVarPlaceholder}
- autoComplete="off"
- disabled={!isLiteralValue}
- required
- className="h-8"
- />
-
- {missing && missingRequiredLabel && (
-
- {missingRequiredLabel}
-
- )}
-
- )
- })}
-
-
- )
-}
diff --git a/web/features/deployments/shared/components/runtime-credential-bindings-utils.ts b/web/features/deployments/shared/components/runtime-credential-bindings-utils.ts
deleted file mode 100644
index bccc4946145..00000000000
--- a/web/features/deployments/shared/components/runtime-credential-bindings-utils.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import type {
- CredentialCandidate,
- CredentialSelectionInput,
- CredentialSlot,
-} from '@dify/contracts/enterprise/types.gen'
-
-export type RuntimeCredentialBindingSelections = Record
-
-export type RuntimeCredentialSelectOption = {
- value: string
- label: string
-}
-
-const PROVIDER_DISPLAY_NAMES: Record = {
- azure_openai: 'Azure OpenAI',
- bedrock: 'Amazon Bedrock',
- gemini: 'Gemini',
- google: 'Google',
- openai: 'OpenAI',
- vertex_ai: 'Vertex AI',
- volcengine_maas: 'Volcengine',
-}
-
-function providerSlug(providerId: string) {
- const parts = providerId.split('/').filter(Boolean)
- return parts[parts.length - 1]
-}
-
-function titleCaseProviderName(value: string) {
- return value
- .split(/[-_]/)
- .filter(Boolean)
- .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
- .join(' ')
-}
-
-export function runtimeCredentialSlotKey(slot: CredentialSlot) {
- return [slot.providerId, slot.category].join(':')
-}
-
-export function runtimeCredentialProviderName(providerId: string) {
- const slug = providerSlug(providerId)
- if (!slug) return undefined
-
- return PROVIDER_DISPLAY_NAMES[slug.toLowerCase()] ?? titleCaseProviderName(slug)
-}
-
-function runtimeCredentialCandidateLabel(candidate: CredentialCandidate) {
- const fallback = candidate.credentialId
- const rawLabel = candidate.displayName.trim() || fallback
- const providerId = candidate.providerId.trim()
-
- const providerSuffixes = [` · ${providerId}`, ` - ${providerId}`, ` (${providerId})`]
- const label = providerSuffixes.reduce((nextLabel, suffix) => {
- return nextLabel.endsWith(suffix) ? nextLabel.slice(0, -suffix.length).trim() : nextLabel
- }, rawLabel)
-
- return label || fallback
-}
-
-export function runtimeCredentialCandidateOptions(
- slot: CredentialSlot,
-): RuntimeCredentialSelectOption[] {
- return slot.candidates.map((candidate) => ({
- value: candidate.credentialId,
- label: runtimeCredentialCandidateLabel(candidate),
- }))
-}
-
-export function hasMissingRequiredRuntimeCredentialBinding(
- _slot: CredentialSlot,
- selectedValue?: string,
-) {
- return !selectedValue
-}
-
-export function selectedRuntimeCredentialSelections(
- slots: CredentialSlot[],
- manualBindings: RuntimeCredentialBindingSelections,
-): RuntimeCredentialBindingSelections {
- const next: RuntimeCredentialBindingSelections = {}
- for (const slot of slots) {
- const slotKey = runtimeCredentialSlotKey(slot)
- const candidates = runtimeCredentialCandidateOptions(slot)
- const existing = manualBindings[slotKey]
- if (existing && candidates.some((candidate) => candidate.value === existing))
- next[slotKey] = existing
- else if (
- slot.lastCredentialId &&
- candidates.some((candidate) => candidate.value === slot.lastCredentialId)
- )
- next[slotKey] = slot.lastCredentialId
- else if (candidates.length === 1 && candidates[0]) next[slotKey] = candidates[0].value
- }
- return next
-}
-
-export function selectedDeploymentRuntimeCredentials(
- slots: CredentialSlot[],
- selections: RuntimeCredentialBindingSelections,
-): CredentialSelectionInput[] {
- return slots.flatMap((slot): CredentialSelectionInput[] => {
- const slotKey = runtimeCredentialSlotKey(slot)
- const selectedValue = selections[slotKey]
- if (!selectedValue) return []
-
- return [
- {
- providerId: slot.providerId,
- category: slot.category,
- credentialId: selectedValue,
- },
- ]
- })
-}
diff --git a/web/features/deployments/shared/components/runtime-credential-bindings.tsx b/web/features/deployments/shared/components/runtime-credential-bindings.tsx
deleted file mode 100644
index d6e9103b1c4..00000000000
--- a/web/features/deployments/shared/components/runtime-credential-bindings.tsx
+++ /dev/null
@@ -1,200 +0,0 @@
-'use client'
-
-import type { CredentialSlot } from '@dify/contracts/enterprise/types.gen'
-import type {
- RuntimeCredentialBindingSelections,
- RuntimeCredentialSelectOption,
-} from './runtime-credential-bindings-utils'
-import { cn } from '@langgenius/dify-ui/cn'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectItemIndicator,
- SelectItemText,
- SelectTrigger,
-} from '@langgenius/dify-ui/select'
-import { useTranslation } from 'react-i18next'
-import {
- hasMissingRequiredRuntimeCredentialBinding,
- runtimeCredentialCandidateOptions,
- runtimeCredentialProviderName,
- runtimeCredentialSlotKey,
-} from './runtime-credential-bindings-utils'
-import { TitleTooltip } from './title-tooltip'
-
-type RuntimeCredentialBindingsPanelProps = {
- slots: CredentialSlot[]
- selections: RuntimeCredentialBindingSelections
- title: string
- hint: string
- noBindingRequiredLabel: string
- noCredentialCandidatesLabel: string
- selectCredentialLabel: string
- missingRequiredLabel: string
- bindingCountLabel?: string
- showMissingRequired?: boolean
- listScrollable?: boolean
- onChange: (slotKey: string, value: string) => void
- className?: string
- listClassName?: string
-}
-
-function RuntimeCredentialSelect({
- ariaLabel,
- value,
- options,
- placeholder,
- onChange,
-}: {
- ariaLabel: string
- value?: string
- options: RuntimeCredentialSelectOption[]
- placeholder: string
- onChange: (value: string) => void
-}) {
- const selectedOption = options.find((option) => option.value === value)
-
- return (
-
- )
-}
-
-export function RuntimeCredentialBindingsPanel({
- slots,
- selections,
- title,
- hint,
- noBindingRequiredLabel,
- noCredentialCandidatesLabel,
- selectCredentialLabel,
- missingRequiredLabel,
- bindingCountLabel,
- showMissingRequired = false,
- listScrollable = true,
- onChange,
- className,
- listClassName,
-}: RuntimeCredentialBindingsPanelProps) {
- const { t } = useTranslation('plugin')
-
- return (
-
-
-
-
{title}
- {slots.length > 0 && (
-
- {bindingCountLabel ?? slots.length}
-
- )}
-
-
{hint}
-
- {slots.length === 0 ? (
-
- {noBindingRequiredLabel}
-
- ) : (
-
- {slots.map((slot) => {
- const slotKey = runtimeCredentialSlotKey(slot)
- const candidates = runtimeCredentialCandidateOptions(slot)
- const selectedValue = selections[slotKey]
- const missing =
- showMissingRequired && hasMissingRequiredRuntimeCredentialBinding(slot, selectedValue)
- const slotName = runtimeCredentialProviderName(slot.providerId) ?? slotKey
- const categoryLabel =
- slot.category === 'PLUGIN_CATEGORY_MODEL'
- ? t(($) => $['categorySingle.model'])
- : slot.category === 'PLUGIN_CATEGORY_TOOL'
- ? t(($) => $['categorySingle.tool'])
- : undefined
-
- return (
-
-
-
-
-
-
- {slotName}
-
-
-
-
- {categoryLabel && (
-
- {categoryLabel}
-
- )}
-
-
- {candidates.length === 0 ? (
-
- {noCredentialCandidatesLabel}
-
- ) : (
-
onChange(slotKey, value)}
- options={candidates}
- placeholder={selectCredentialLabel}
- />
- )}
-
- {missing && (
-
- {missingRequiredLabel}
-
- )}
-
- )
- })}
-
- )}
-
- )
-}
diff --git a/web/features/deployments/shared/components/section.tsx b/web/features/deployments/shared/components/section.tsx
deleted file mode 100644
index 94c67b434e2..00000000000
--- a/web/features/deployments/shared/components/section.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-
-type SectionProps = {
- title: string
- description?: string
- action?: ReactNode
- children: ReactNode
- layout?: 'block' | 'row'
- tone?: 'default' | 'destructive'
- showDivider?: boolean
-}
-
-export function Section({
- title,
- description,
- action,
- children,
- layout = 'block',
- tone = 'default',
- showDivider = true,
-}: SectionProps) {
- const hasAction = Boolean(action)
- const titleClassName = cn(
- 'system-sm-semibold',
- tone === 'destructive'
- ? 'text-util-colors-red-red-700'
- : layout === 'row'
- ? 'text-text-secondary'
- : 'text-text-primary',
- )
- const descriptionClassName = cn(
- 'mt-1 body-xs-regular',
- tone === 'destructive' ? 'text-util-colors-red-red-600' : 'text-text-tertiary',
- )
-
- if (layout === 'row') {
- return (
-
-
-
-
{title}
- {description &&
{description}
}
-
-
- {hasAction ? (
-
-
{children}
-
{action}
-
- ) : (
- children
- )}
-
-
-
- )
- }
-
- return (
-
-
-
-
{title}
- {hasAction &&
{action}
}
-
- {description &&
{description}
}
-
- {children}
-
- )
-}
diff --git a/web/features/deployments/shared/components/title-tooltip.tsx b/web/features/deployments/shared/components/title-tooltip.tsx
deleted file mode 100644
index 80a8caab043..00000000000
--- a/web/features/deployments/shared/components/title-tooltip.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-'use client'
-
-import type { FocusEvent, PointerEvent, ReactElement, ReactNode } from 'react'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
-import { cloneElement, useState } from 'react'
-
-type TriggerProps = {
- onFocusCapture?: (event: FocusEvent) => void
- onPointerOverCapture?: (event: PointerEvent) => void
-}
-
-function normalizeText(value: string) {
- return value.replace(/\s+/g, ' ').trim()
-}
-
-function contentText(content: ReactNode) {
- if (typeof content === 'string' || typeof content === 'number') return String(content)
-}
-
-function isOverflowing(element: HTMLElement) {
- return element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight
-}
-
-function shouldShowTooltipContent(element: HTMLElement, content: ReactNode) {
- const text = contentText(content)
- if (text === undefined) return true
-
- if (normalizeText(text) !== normalizeText(element.textContent ?? '')) return true
-
- return isOverflowing(element)
-}
-
-export function TitleTooltip({
- children,
- content,
-}: {
- children: ReactElement
- content?: ReactNode
-}) {
- const [shouldShowContent, setShouldShowContent] = useState(false)
-
- if (!content) return children
-
- const childProps = children.props as TriggerProps
-
- function updateShouldShowContent(element: HTMLElement) {
- setShouldShowContent(shouldShowTooltipContent(element, content))
- }
-
- // oxlint-disable-next-line react/no-clone-element -- Preserve the trigger element while adding overflow checks.
- const trigger = cloneElement(children as ReactElement, {
- onFocusCapture: (event) => {
- childProps.onFocusCapture?.(event)
- updateShouldShowContent(event.currentTarget)
- },
- onPointerOverCapture: (event) => {
- childProps.onPointerOverCapture?.(event)
- updateShouldShowContent(event.currentTarget)
- },
- })
-
- return (
-
-
- {shouldShowContent && {content}}
-
- )
-}
diff --git a/web/features/deployments/shared/components/unsupported-dsl-nodes-alert.tsx b/web/features/deployments/shared/components/unsupported-dsl-nodes-alert.tsx
deleted file mode 100644
index f694d4122f3..00000000000
--- a/web/features/deployments/shared/components/unsupported-dsl-nodes-alert.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-'use client'
-
-import type { SelectorParam, TFunction } from 'i18next'
-import type { UnsupportedDslNode } from '../domain/error'
-import { cn } from '@langgenius/dify-ui/cn'
-import { useTranslation } from 'react-i18next'
-import { BlockEnum } from '@/app/components/workflow/types'
-
-const workflowBlockTypeSelectors: Record> = {
- [BlockEnum.Start]: ($) => $['blocks.start'],
- [BlockEnum.StartPlaceholder]: ($) => $['blocks.start-placeholder'],
- [BlockEnum.End]: ($) => $['blocks.end'],
- [BlockEnum.Answer]: ($) => $['blocks.answer'],
- [BlockEnum.LLM]: ($) => $['blocks.llm'],
- [BlockEnum.KnowledgeRetrieval]: ($) => $['blocks.knowledge-retrieval'],
- [BlockEnum.QuestionClassifier]: ($) => $['blocks.question-classifier'],
- [BlockEnum.IfElse]: ($) => $['blocks.if-else'],
- [BlockEnum.Code]: ($) => $['blocks.code'],
- [BlockEnum.TemplateTransform]: ($) => $['blocks.template-transform'],
- [BlockEnum.HttpRequest]: ($) => $['blocks.http-request'],
- [BlockEnum.VariableAssigner]: ($) => $['blocks.variable-assigner'],
- [BlockEnum.VariableAggregator]: ($) => $['blocks.variable-aggregator'],
- [BlockEnum.Tool]: ($) => $['blocks.tool'],
- [BlockEnum.ParameterExtractor]: ($) => $['blocks.parameter-extractor'],
- [BlockEnum.Iteration]: ($) => $['blocks.iteration'],
- [BlockEnum.DocExtractor]: ($) => $['blocks.document-extractor'],
- [BlockEnum.ListFilter]: ($) => $['blocks.list-operator'],
- [BlockEnum.IterationStart]: ($) => $['blocks.iteration-start'],
- [BlockEnum.Assigner]: ($) => $['blocks.assigner'],
- [BlockEnum.Agent]: ($) => $['blocks.agent'],
- [BlockEnum.AgentV2]: ($) => $['blocks.agent-v2'],
- [BlockEnum.Loop]: ($) => $['blocks.loop'],
- [BlockEnum.LoopStart]: ($) => $['blocks.loop-start'],
- [BlockEnum.LoopEnd]: ($) => $['blocks.loop-end'],
- [BlockEnum.HumanInput]: ($) => $['blocks.human-input'],
- [BlockEnum.DataSource]: ($) => $['blocks.datasource'],
- [BlockEnum.DataSourceEmpty]: ($) => $['blocks.datasource-empty'],
- [BlockEnum.KnowledgeBase]: ($) => $['blocks.knowledge-index'],
- [BlockEnum.TriggerSchedule]: ($) => $['blocks.trigger-schedule'],
- [BlockEnum.TriggerWebhook]: ($) => $['blocks.trigger-webhook'],
- [BlockEnum.TriggerPlugin]: ($) => $['blocks.trigger-plugin'],
-}
-
-function isWorkflowBlockType(type: string): type is BlockEnum {
- return Object.hasOwn(workflowBlockTypeSelectors, type)
-}
-
-function translatedNodeType(
- type: string | undefined,
- tDeployments: TFunction<'deployments'>,
- tWorkflow: TFunction<'workflow'>,
-) {
- if (!type) return tDeployments(($) => $['unsupportedDslNodes.unknownType'])
-
- if (!isWorkflowBlockType(type)) return type
-
- return tWorkflow(workflowBlockTypeSelectors[type])
-}
-
-function unsupportedNodeTypeLabels(
- nodes: UnsupportedDslNode[],
- tDeployments: TFunction<'deployments'>,
- tWorkflow: TFunction<'workflow'>,
-) {
- return Array.from(
- new Set(nodes.map((node) => translatedNodeType(node.type, tDeployments, tWorkflow))),
- )
-}
-
-function formattedNodeTypeList(labels: string[], language: string) {
- if (labels.length === 0) return ''
-
- try {
- return new Intl.ListFormat(language, { type: 'conjunction' }).format(labels)
- } catch {
- return labels.join(', ')
- }
-}
-
-export function UnsupportedDslNodesAlert({
- nodes,
- className,
-}: {
- nodes: UnsupportedDslNode[]
- className?: string
-}) {
- const { i18n, t } = useTranslation('deployments')
- const { t: tWorkflow } = useTranslation('workflow')
-
- if (nodes.length === 0) return null
-
- const nodeTypeLabels = unsupportedNodeTypeLabels(nodes, t, tWorkflow)
- const nodeTypes = formattedNodeTypeList(nodeTypeLabels, i18n.language)
- const description = nodeTypes
- ? t(($) => $['unsupportedDslNodes.descriptionWithTypes'], { nodeTypes })
- : t(($) => $['unsupportedDslNodes.description'])
-
- return (
-
-
-
-
-
- {t(($) => $['unsupportedDslNodes.title'])}
-
-
{description}
-
-
-
- )
-}
diff --git a/web/features/deployments/shared/domain/__tests__/dsl.spec.ts b/web/features/deployments/shared/domain/__tests__/dsl.spec.ts
deleted file mode 100644
index 4c0f48ef6fa..00000000000
--- a/web/features/deployments/shared/domain/__tests__/dsl.spec.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import { dslAppName, dslEnvVarSlots, encodeDslContent, isWorkflowDsl } from '../dsl'
-
-describe('deployment DSL domain', () => {
- describe('content encoding', () => {
- it('should preserve Unicode content through base64 encoding', () => {
- const content = 'app:\n name: 部署 🚀'
-
- const decoded = new TextDecoder().decode(
- Uint8Array.from(atob(encodeDslContent(content)), (character) => character.charCodeAt(0)),
- )
-
- expect(decoded).toBe(content)
- })
- })
-
- describe('app metadata', () => {
- it('should trim the app name', () => {
- expect(dslAppName('app:\n name: " Deployment app "')).toBe('Deployment app')
- })
-
- it('should return an empty app name for malformed content', () => {
- expect(dslAppName('app: [')).toBe('')
- })
-
- it('should identify workflow apps', () => {
- expect(isWorkflowDsl('app:\n mode: workflow')).toBe(true)
- })
-
- it('should reject non-workflow apps', () => {
- expect(isWorkflowDsl('app:\n mode: advanced-chat')).toBe(false)
- })
- })
-
- describe('environment variable slots', () => {
- it('should return no slots for malformed content', () => {
- expect(dslEnvVarSlots('workflow: [')).toEqual([])
- })
-
- it('should keep the first slot when names are duplicated', () => {
- const content = `
-workflow:
- environment_variables:
- - name: REGION
- value: first
- - name: " REGION "
- value: second
-`
-
- expect(dslEnvVarSlots(content)).toEqual([
- {
- key: 'REGION',
- defaultValue: 'first',
- hasDefaultValue: true,
- },
- ])
- })
-
- it('should omit masked secret defaults', () => {
- const content = `
-workflow:
- environment_variables:
- - name: API_KEY
- value: '[__HIDDEN__]'
- value_type: secret
-`
-
- expect(dslEnvVarSlots(content)).toEqual([
- {
- key: 'API_KEY',
- valueType: 'secret',
- },
- ])
- })
-
- it('should normalize unquoted timestamp defaults', () => {
- const content = `
-workflow:
- environment_variables:
- - name: START_AT
- value: 2026-07-10T12:34:56Z
-`
-
- expect(dslEnvVarSlots(content)).toEqual([
- {
- key: 'START_AT',
- defaultValue: '"2026-07-10T12:34:56.000Z"',
- hasDefaultValue: true,
- },
- ])
- })
-
- it('should apply values inherited through YAML merge keys', () => {
- const content = `
-defaults: &defaults
- description: Deployment region
- value: ap-southeast-1
- value_type: string
-workflow:
- environment_variables:
- - <<: *defaults
- name: REGION
-`
-
- expect(dslEnvVarSlots(content)).toEqual([
- {
- key: 'REGION',
- description: 'Deployment region',
- defaultValue: 'ap-southeast-1',
- hasDefaultValue: true,
- valueType: 'string',
- },
- ])
- })
- })
-})
diff --git a/web/features/deployments/shared/domain/dsl.ts b/web/features/deployments/shared/domain/dsl.ts
deleted file mode 100644
index 0da9fafeb07..00000000000
--- a/web/features/deployments/shared/domain/dsl.ts
+++ /dev/null
@@ -1,140 +0,0 @@
-import { AppModeEnum } from '@/types/app'
-import { loadYaml } from '@/utils/yaml'
-
-export type DslEnvVarSlot = {
- key: string
- description?: string
- defaultValue?: string
- hasDefaultValue?: boolean
- valueType?: string
-}
-
-type DslMetadata = {
- app?: {
- mode?: unknown
- name?: unknown
- }
- workflow?: {
- environment_variables?: unknown
- }
-}
-
-type DslEnvVarRecord = Record
-
-const ENV_VAR_DEFAULT_VALUE_FIELDS = ['value', 'default_value', 'defaultValue', 'default'] as const
-const ENV_VAR_VALUE_TYPE_FIELDS = ['value_type', 'valueType', 'type'] as const
-const MASKED_SECRET_PLACEHOLDERS = new Set(['[__HIDDEN__]'])
-
-export function encodeDslContent(value: string) {
- const bytes = new TextEncoder().encode(value)
- const chunkSize = 0x8000
- const chunks: string[] = []
-
- for (let offset = 0; offset < bytes.length; offset += chunkSize)
- chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + chunkSize)))
-
- return btoa(chunks.join(''))
-}
-
-function parseDsl(content: string) {
- try {
- return loadYaml(content) as DslMetadata | undefined
- } catch {
- return undefined
- }
-}
-
-function isRecord(value: unknown): value is DslEnvVarRecord {
- return Boolean(value && typeof value === 'object' && !Array.isArray(value))
-}
-
-function stringValue(value: unknown) {
- return typeof value === 'string' ? value.trim() : ''
-}
-
-function normalizeEnvVarDefaultValue(value: unknown) {
- if (value === undefined || value === null) return undefined
-
- let normalizedValue: string | undefined
- if (typeof value === 'string') {
- normalizedValue = value
- } else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {
- normalizedValue = String(value)
- } else {
- try {
- normalizedValue = JSON.stringify(value)
- } catch {
- normalizedValue = undefined
- }
- }
-
- if (!normalizedValue?.trim()) return undefined
- if (MASKED_SECRET_PLACEHOLDERS.has(normalizedValue)) return undefined
-
- return normalizedValue
-}
-
-function envVarDefaultValue(record: DslEnvVarRecord) {
- for (const field of ENV_VAR_DEFAULT_VALUE_FIELDS) {
- if (Object.prototype.hasOwnProperty.call(record, field))
- return normalizeEnvVarDefaultValue(record[field])
- }
-
- return undefined
-}
-
-function envVarValueType(record: DslEnvVarRecord) {
- for (const field of ENV_VAR_VALUE_TYPE_FIELDS) {
- const valueType = stringValue(record[field])
- if (valueType) return valueType
- }
-
- return undefined
-}
-
-export function dslAppName(content: string) {
- const name = parseDsl(content)?.app?.name
-
- return typeof name === 'string' ? name.trim() : ''
-}
-
-function dslAppMode(content: string) {
- return stringValue(parseDsl(content)?.app?.mode)
-}
-
-export function isWorkflowDsl(content: string) {
- return dslAppMode(content) === AppModeEnum.WORKFLOW
-}
-
-export function dslEnvVarSlots(content: string): DslEnvVarSlot[] {
- const environmentVariables = parseDsl(content)?.workflow?.environment_variables
- if (!Array.isArray(environmentVariables)) return []
-
- const seenKeys = new Set()
-
- return environmentVariables.flatMap((envVar): DslEnvVarSlot[] => {
- if (!isRecord(envVar)) return []
-
- const key = stringValue(envVar.name ?? envVar.key ?? envVar.variable)
- if (!key || seenKeys.has(key)) return []
-
- seenKeys.add(key)
- const description = stringValue(envVar.description)
- const defaultValue = envVarDefaultValue(envVar)
- const valueType = envVarValueType(envVar)
-
- return [
- {
- key,
- ...(description ? { description } : {}),
- ...(valueType ? { valueType } : {}),
- ...(defaultValue !== undefined
- ? {
- defaultValue,
- hasDefaultValue: true,
- }
- : {}),
- },
- ]
- })
-}
diff --git a/web/features/deployments/shared/domain/error.ts b/web/features/deployments/shared/domain/error.ts
deleted file mode 100644
index 7240ee9f5d6..00000000000
--- a/web/features/deployments/shared/domain/error.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-type DeploymentErrorPayload = {
- message?: unknown
- error?: unknown
- reason?: unknown
- code?: unknown
- metadata?: unknown
- unsupported_nodes?: unknown
-}
-
-const APP_DEPLOY_UNSUPPORTED_DSL_NODE_TYPE = 'APPDEPLOY_UNSUPPORTED_DSL_NODE_TYPE'
-
-export type UnsupportedDslNode = {
- id?: string
- type?: string
-}
-
-export type UnsupportedDslNodeError = {
- message?: string
- nodes: UnsupportedDslNode[]
-}
-
-function nonEmptyString(value: unknown) {
- if (typeof value !== 'string') return undefined
-
- const trimmedValue = value.trim()
- return trimmedValue || undefined
-}
-
-function isRecord(value: unknown): value is Record {
- return typeof value === 'object' && value !== null && !Array.isArray(value)
-}
-
-function formatDeploymentError(data: DeploymentErrorPayload) {
- const message = nonEmptyString(data.message) ?? nonEmptyString(data.error)
- const reason = nonEmptyString(data.reason) ?? nonEmptyString(data.code)
-
- if (message && reason) return `${message} (${reason})`
-
- return message ?? reason
-}
-
-async function deploymentErrorData(error: unknown) {
- if (error instanceof Response && !error.bodyUsed) {
- try {
- return (await error.clone().json()) as DeploymentErrorPayload
- } catch {}
- }
-
- return undefined
-}
-
-function deploymentErrorReason(data: DeploymentErrorPayload) {
- return nonEmptyString(data.reason) ?? nonEmptyString(data.code)
-}
-
-function unsupportedNodesPayload(data: DeploymentErrorPayload) {
- if (isRecord(data.metadata)) return data.metadata.unsupported_nodes
-
- return data.unsupported_nodes
-}
-
-function parsedJsonValue(value: string) {
- try {
- return JSON.parse(value) as unknown
- } catch {
- return undefined
- }
-}
-
-function unsupportedDslNode(value: unknown) {
- if (!isRecord(value)) return undefined
-
- const id = nonEmptyString(value.id)
- const type = nonEmptyString(value.type)
- if (!id && !type) return undefined
-
- return {
- ...(id ? { id } : {}),
- ...(type ? { type } : {}),
- } satisfies UnsupportedDslNode
-}
-
-function unsupportedDslNodes(value: unknown) {
- const nodeList = typeof value === 'string' ? parsedJsonValue(value) : value
- if (!Array.isArray(nodeList)) return []
-
- const seen = new Set()
- const nodes: UnsupportedDslNode[] = []
-
- nodeList.forEach((item) => {
- const node = unsupportedDslNode(item)
- if (!node) return
-
- const key = `${node.id}\u0000${node.type}`
- if (seen.has(key)) return
-
- seen.add(key)
- nodes.push(node)
- })
-
- return nodes
-}
-
-export async function unsupportedDslNodeError(
- error: unknown,
-): Promise {
- const errorData = await deploymentErrorData(error)
- if (!errorData) return undefined
-
- if (deploymentErrorReason(errorData) !== APP_DEPLOY_UNSUPPORTED_DSL_NODE_TYPE) return undefined
-
- return {
- message: formatDeploymentError(errorData),
- nodes: unsupportedDslNodes(unsupportedNodesPayload(errorData)),
- }
-}
-
-export async function deploymentErrorMessage(error: unknown) {
- const errorData = await deploymentErrorData(error)
- if (errorData) return formatDeploymentError(errorData)
-
- if (error instanceof Error) return nonEmptyString(error.message)
-
- return undefined
-}
diff --git a/web/features/deployments/shared/domain/feature-flags.ts b/web/features/deployments/shared/domain/feature-flags.ts
deleted file mode 100644
index 791ca6cdd73..00000000000
--- a/web/features/deployments/shared/domain/feature-flags.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Temporary kill switch for deployment DSL import flows. Flip to true to restore them.
-export const isDeploymentDslImportEnabled = false
diff --git a/web/features/deployments/shared/domain/idempotency.ts b/web/features/deployments/shared/domain/idempotency.ts
deleted file mode 100644
index be9cff693d9..00000000000
--- a/web/features/deployments/shared/domain/idempotency.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export function createDeploymentIdempotencyKey() {
- if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID()
-
- return `deployment-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`
-}
diff --git a/web/features/deployments/shared/domain/release-action.ts b/web/features/deployments/shared/domain/release-action.ts
deleted file mode 100644
index cb93a5abc6e..00000000000
--- a/web/features/deployments/shared/domain/release-action.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-
-export type ReleaseDeploymentAction = 'deploy' | 'deployExistingRelease' | 'promote' | 'rollback'
-
-function releaseCreatedAt(release: Release) {
- const time = Date.parse(release.createdAt)
- return Number.isFinite(time) ? time : undefined
-}
-
-function releaseById(releaseRows: Release[], releaseId?: string) {
- return releaseRows.find((release) => release.id === releaseId)
-}
-
-function releaseOrderIndex(releaseRows: Release[], releaseId?: string) {
- return releaseRows.findIndex((release) => release.id === releaseId)
-}
-
-function compareReleaseOrder(
- targetRelease: Release | undefined,
- currentRelease: Release,
- releaseRows: Release[],
-) {
- if (!targetRelease) return undefined
- if (targetRelease.id === currentRelease.id) return 0
-
- const normalizedTargetRelease = releaseById(releaseRows, targetRelease.id) ?? targetRelease
- const normalizedCurrentRelease = releaseById(releaseRows, currentRelease.id) ?? currentRelease
- const targetCreatedAt = releaseCreatedAt(normalizedTargetRelease)
- const currentCreatedAt = releaseCreatedAt(normalizedCurrentRelease)
-
- if (
- targetCreatedAt !== undefined &&
- currentCreatedAt !== undefined &&
- targetCreatedAt !== currentCreatedAt
- )
- return targetCreatedAt > currentCreatedAt ? 1 : -1
-
- const targetIndex = releaseOrderIndex(releaseRows, targetRelease.id)
- const currentIndex = releaseOrderIndex(releaseRows, currentRelease.id)
- if (targetIndex >= 0 && currentIndex >= 0 && targetIndex !== currentIndex)
- return targetIndex < currentIndex ? 1 : -1
-
- return undefined
-}
-
-export function releaseDeploymentAction({
- targetRelease,
- currentRelease,
- releaseRows,
- isExistingRelease,
-}: {
- targetRelease?: Release
- currentRelease?: Release
- releaseRows: Release[]
- isExistingRelease?: boolean
-}): ReleaseDeploymentAction {
- if (!currentRelease) return isExistingRelease ? 'deployExistingRelease' : 'deploy'
-
- const order = compareReleaseOrder(targetRelease, currentRelease, releaseRows)
- if (order === -1) return 'rollback'
- if (order === 1) return 'promote'
-
- return targetRelease && targetRelease.id !== currentRelease.id
- ? 'promote'
- : isExistingRelease
- ? 'deployExistingRelease'
- : 'deploy'
-}
diff --git a/web/features/deployments/shared/domain/release.ts b/web/features/deployments/shared/domain/release.ts
deleted file mode 100644
index dda5a652b21..00000000000
--- a/web/features/deployments/shared/domain/release.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { Release } from '@dify/contracts/enterprise/types.gen'
-import { formatTime } from '@/utils/time'
-
-export function formatDate(value?: string) {
- if (!value) return '—'
-
- const date = new Date(value)
- if (Number.isNaN(date.getTime()))
- return value
- .replace('T', ' ')
- .replace(/\.\d+Z?$/, '')
- .replace(/Z$/, '')
- .slice(0, 16)
-
- return formatTime({ date, dateFormat: 'YYYY-MM-DD HH:mm' })
-}
-
-export function releaseCommit(release?: Release) {
- return release?.gateCommitId ? release.gateCommitId.slice(0, 8) : '—'
-}
diff --git a/web/features/deployments/shared/domain/runtime-status.ts b/web/features/deployments/shared/domain/runtime-status.ts
deleted file mode 100644
index 8313b83718a..00000000000
--- a/web/features/deployments/shared/domain/runtime-status.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import type {
- EnvironmentDeployment,
- RuntimeInstanceStatus as RuntimeInstanceStatusValue,
-} from '@dify/contracts/enterprise/types.gen'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-
-const DEPLOYMENT_STATUS_POLLING_INTERVAL = 3000
-
-export function isUndeployedDeploymentRow(row: EnvironmentDeployment) {
- const status = row.status
- return (
- status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED ||
- (status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED &&
- !row.currentRelease &&
- !row.desiredRelease &&
- !row.currentDeployment)
- )
-}
-
-export function hasRuntimeInstanceDeployment(row: EnvironmentDeployment) {
- return !isUndeployedDeploymentRow(row)
-}
-
-export function isAvailableDeploymentTarget(row: EnvironmentDeployment) {
- return isUndeployedDeploymentRow(row)
-}
-
-export function isRuntimeDeploymentInProgress(status?: RuntimeInstanceStatusValue) {
- return (
- status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING ||
- status === RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING
- )
-}
-
-export function deploymentStatusPollingInterval(rows?: EnvironmentDeployment[]) {
- return rows?.some((row) => isRuntimeDeploymentInProgress(row.status))
- ? DEPLOYMENT_STATUS_POLLING_INTERVAL
- : false
-}
diff --git a/web/features/deployments/shared/ui/deployment-status-badge.tsx b/web/features/deployments/shared/ui/deployment-status-badge.tsx
deleted file mode 100644
index e26298f259f..00000000000
--- a/web/features/deployments/shared/ui/deployment-status-badge.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-'use client'
-
-import type {
- EnvironmentDeployment,
- RuntimeInstanceStatus as RuntimeInstanceStatusValue,
-} from '@dify/contracts/enterprise/types.gen'
-import type { ComponentPropsWithRef } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-import { StatusDot } from '@langgenius/dify-ui/status-dot'
-import { useTranslation } from 'react-i18next'
-import { isRuntimeDeploymentInProgress } from '../domain/runtime-status'
-import {
- deploymentStatusDotStatus,
- deploymentStatusDotTextClassName,
- deploymentStatusLabelKey,
- deploymentStatusToneClassNames,
-} from './deployment-status-style'
-
-type DeploymentStatusBadgeProps = Omit, 'children'> & {
- status: RuntimeInstanceStatusValue
- label: string
- variant?: 'badge' | 'status-dot'
-}
-
-export function DeploymentStatusBadge({
- status,
- label,
- className,
- variant = 'badge',
- ref,
- ...props
-}: DeploymentStatusBadgeProps) {
- const isInProgress = isRuntimeDeploymentInProgress(status)
-
- if (variant === 'status-dot') {
- const dotStatus = deploymentStatusDotStatus(status)
-
- return (
-
-
- {label}
-
- )
- }
-
- const toneClassNames = deploymentStatusToneClassNames(status)
- const dotStatus = deploymentStatusDotStatus(status)
-
- return (
-
-
- {label}
-
- )
-}
-
-type EnvironmentDeploymentBadgeProps = Omit, 'children' | 'title'> & {
- row: EnvironmentDeployment
- showStatus?: boolean
- summaryLabel?: string
-}
-
-export function EnvironmentDeploymentBadge({
- row,
- className,
- showStatus = true,
- summaryLabel,
- 'aria-label': ariaLabel,
- ref,
- ...props
-}: EnvironmentDeploymentBadgeProps) {
- const { t } = useTranslation('deployments')
- const name = row.environment.displayName
- const status = row.status
- const toneClassNames = deploymentStatusToneClassNames(status)
- const dotStatus = deploymentStatusDotStatus(status)
- const isInProgress = isRuntimeDeploymentInProgress(status)
- const statusLabel = t(($) => $[deploymentStatusLabelKey(status)])
- const label = summaryLabel ?? `${name} · ${statusLabel}`
- const visibleLabel = showStatus ? `${name} · ${statusLabel}` : name
-
- return (
-
-
- {visibleLabel}
-
- )
-}
diff --git a/web/features/deployments/shared/ui/deployment-status-style.ts b/web/features/deployments/shared/ui/deployment-status-style.ts
deleted file mode 100644
index d234348310d..00000000000
--- a/web/features/deployments/shared/ui/deployment-status-style.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import type { RuntimeInstanceStatus as RuntimeInstanceStatusValue } from '@dify/contracts/enterprise/types.gen'
-import type { StatusDotStatus } from '@langgenius/dify-ui/status-dot'
-import { RuntimeInstanceStatus } from '@dify/contracts/enterprise/types.gen'
-
-type DeploymentStatusTone = 'neutral' | 'success' | 'warning' | 'danger' | 'info'
-type DeploymentStatusLabelKey = `status.${RuntimeInstanceStatusValue}`
-
-const STATUS_TONE: Record = {
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED]: 'neutral',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED]: 'neutral',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING]: 'info',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY]: 'success',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED]: 'danger',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DRIFTED]: 'warning',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_INVALID]: 'danger',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING]: 'info',
-}
-
-const STATUS_DOT_STATUS: Record = {
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED]: 'disabled',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED]: 'disabled',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING]: 'normal',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_READY]: 'success',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_FAILED]: 'error',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_DRIFTED]: 'warning',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_INVALID]: 'error',
- [RuntimeInstanceStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING]: 'normal',
-}
-
-const STATUS_DOT_TEXT_CLASS_NAMES: Record = {
- disabled: 'text-text-tertiary',
- error: 'text-util-colors-red-red-600',
- normal: 'text-util-colors-blue-light-blue-light-600',
- success: 'text-util-colors-green-green-600',
- warning: 'text-util-colors-warning-warning-600',
-}
-
-const TONE_CLASS_NAMES: Record = {
- danger: {
- badge: 'border-util-colors-red-red-200 bg-util-colors-red-red-50 text-util-colors-red-red-700',
- dot: 'bg-util-colors-red-red-500',
- },
- info: {
- badge:
- 'border-util-colors-blue-blue-200 bg-util-colors-blue-blue-50 text-util-colors-blue-blue-700',
- dot: 'bg-util-colors-blue-blue-500',
- },
- neutral: {
- badge: 'border-divider-subtle bg-background-section-burn text-text-tertiary',
- dot: 'bg-text-quaternary',
- },
- success: {
- badge:
- 'border-util-colors-green-green-200 bg-util-colors-green-green-50 text-util-colors-green-green-700',
- dot: 'bg-util-colors-green-green-500',
- },
- warning: {
- badge:
- 'border-util-colors-warning-warning-200 bg-util-colors-warning-warning-50 text-util-colors-warning-warning-700',
- dot: 'bg-util-colors-warning-warning-500',
- },
-}
-
-export function deploymentStatusLabelKey(
- status: RuntimeInstanceStatusValue,
-): DeploymentStatusLabelKey {
- return `status.${status}`
-}
-
-function deploymentStatusTone(status: RuntimeInstanceStatusValue) {
- return STATUS_TONE[status]
-}
-
-export function deploymentStatusToneClassNames(status: RuntimeInstanceStatusValue) {
- return TONE_CLASS_NAMES[deploymentStatusTone(status)]
-}
-
-export function deploymentStatusDotStatus(status: RuntimeInstanceStatusValue) {
- return STATUS_DOT_STATUS[status]
-}
-
-export function deploymentStatusDotTextClassName(status: RuntimeInstanceStatusValue) {
- return STATUS_DOT_TEXT_CLASS_NAMES[deploymentStatusDotStatus(status)]
-}
diff --git a/web/i18n/ar-TN/common.json b/web/i18n/ar-TN/common.json
index f0717eaa232..f85bb549b73 100644
--- a/web/i18n/ar-TN/common.json
+++ b/web/i18n/ar-TN/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "تفاصيل التطبيق",
"menus.apps": "الاستوديو",
"menus.datasets": "المعرفة",
- "menus.deployments": "عمليات النشر",
"menus.exploreMarketplace": "استكشاف السوق",
"menus.plugins": "الإضافات",
"menus.status": "بيتا",
diff --git a/web/i18n/ar-TN/deployments.json b/web/i18n/ar-TN/deployments.json
index ba01ce8b511..cd5004dc8ed 100644
--- a/web/i18n/ar-TN/deployments.json
+++ b/web/i18n/ar-TN/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "نسخ مثال cURL",
- "access.api.createFailed": "فشل في إنشاء رمز API.",
- "access.api.createKey": "إنشاء رمز API",
- "access.api.createKeyTitle": "إنشاء رمز API جديد",
- "access.api.curlExampleTitle": "مثال cURL",
- "access.api.description": "الوصول إلى هذا النشر عبر HTTP. كل رمز API مخصص لبيئة واحدة.",
- "access.api.developerTitle": "واجهة API للمطورين",
- "access.api.disabled": "الوصول إلى API معطل لهذا النشر.",
- "access.api.disabledHint": "قم بتمكين الوصول إلى API لإنشاء رموز مخصصة للبيئة.",
- "access.api.docs": "وثائق API",
- "access.api.docsClose": "إغلاق وثائق API",
- "access.api.docsDescription": "عرض مرجع Workflow API لهذا النشر.",
- "access.api.docsTitle": "وثائق Workflow API",
- "access.api.empty": "قم بالنشر إلى بيئة أولاً لبدء إصدار رموز API.",
- "access.api.emptyTitle": "لا توجد بيئات منشورة",
- "access.api.endpoint": "عنوان URL للطلب",
- "access.api.keyList": "قائمة رموز API",
- "access.api.nameLabel": "اسم رمز API",
- "access.api.namePlaceholder": "أدخل اسم رمز API",
- "access.api.nameRequired": "اسم رمز API مطلوب.",
- "access.api.newKey": "إنشاء رمز API جديد",
- "access.api.newTokenDescription": "يتم عرض رمز API هذا مرة واحدة فقط. انسخه قبل مغادرة هذه الصفحة.",
- "access.api.newTokenLabel": "رمز API",
- "access.api.newTokenTitle": "تم إنشاء رمز API",
- "access.api.noKeys": "لا توجد رموز API بعد. أنشئ واحدًا لبدء استدعاء API.",
- "access.api.noKeysTitle": "لا توجد رموز API بعد",
- "access.api.revokeConfirmDescription": "سيتوقف رمز API \"{{name}}\" عن العمل فورًا. لا يمكن التراجع عن هذا الإجراء.",
- "access.api.revokeConfirmTitle": "هل تريد إبطال رمز API؟",
- "access.api.revokeFailed": "فشل في إبطال رمز API.",
- "access.api.revokeSuccess": "تم إبطال رمز API",
- "access.api.table.action": "الإجراء",
- "access.api.table.environment": "البيئة",
- "access.api.table.key": "رمز API",
- "access.api.table.name": "الاسم",
- "access.channels.disabled": "قنوات الوصول معطلة لهذا النشر.",
- "access.channels.disabledHint": "قم بتمكين قنوات الوصول لعرض نقاط دخول WebApp وCLI.",
- "access.channels.title": "قنوات الوصول",
- "access.cli.description": "استدعِ من الطرفية باستخدام difyctl، مناسب للسكربتات أو سير العمل الآلي أو تكاملات الوكلاء.",
- "access.cli.docs": "دليل الاستخدام",
- "access.cli.domain": "النطاق",
- "access.cli.empty": "لم يتم تكوين نقطة نهاية CLI.",
- "access.cli.install": "تثبيت CLI",
- "access.cli.title": "CLI",
- "access.copy": "نسخ",
- "access.copyFailed": "فشل النسخ",
- "access.members.groupCount_one": "{{count}} مجموعة",
- "access.members.groupCount_other": "{{count}} مجموعات",
- "access.members.memberCount_one": "{{count}} عضو",
- "access.members.memberCount_other": "{{count}} أعضاء",
- "access.permission.anyone": "أي شخص لديه الرابط",
- "access.permission.organization": "جميع الأعضاء في المنصة",
- "access.permission.specific": "أعضاء محددون في المنصة",
- "access.permission.specificDesc": "اختر مجموعات أو أعضاء محددين",
- "access.permission.updateFailed": "فشل في تحديث سياسة الوصول.",
- "access.permissions.editAriaLabel": "تكوين الوصول لـ {{environment}}",
- "access.permissions.editDescription": "اضبط أذونات الوصول لنقاط دخول WebApp وCLI.",
- "access.permissions.editTitle": "أذونات الوصول",
- "access.permissions.title": "أذونات الوصول",
- "access.revoke": "إبطال",
- "access.runAccess.noEnvs": "قم بالنشر إلى بيئة لتكوين أذونات الوصول.",
- "access.runAccess.noEnvsTitle": "لا توجد بيئات منشورة",
- "access.runAccess.openWebapp": "فتح WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "صفحة ويب مستضافة للمستخدمين النهائيين.",
- "access.runAccess.webappEmpty": "قريبًا.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "خارجي",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "غير معروف",
- "card.access.api": "رموز API",
- "card.access.cli": "CLI",
- "card.access.none": "لا يوجد وصول",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "إنشاء أول إصدار",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "حذف النشر",
- "card.menu.deploy": "النشر إلى البيئة",
- "card.menu.editInfo": "تعديل المعلومات",
- "card.moreActions": "المزيد من الإجراءات",
- "card.noDescription": "لم يتم تقديم وصف.",
"card.notDeployed": "غير منشور",
- "card.tooltip.createdAt": "تم الإنشاء",
- "card.tooltip.deployed": "تم النشر",
- "card.tooltip.deploymentStatus": "النشر",
- "card.tooltip.notDeployedShort": "غير منشور",
- "card.tooltip.releaseName": "اسم الإصدار",
- "card.tooltip.source": "المصدر",
"common.loadFailed": "فشل التحميل. حاول مرة أخرى لاحقًا.",
- "createGuide.actions.back": "رجوع",
- "createGuide.actions.createAndDeploy": "إنشاء ونشر",
- "createGuide.actions.creating": "جاري الإنشاء...",
- "createGuide.actions.deploying": "جاري الإنشاء والنشر...",
- "createGuide.actions.next": "التالي",
- "createGuide.actions.skipDeploy": "تخطي، النشر لاحقًا",
- "createGuide.dsl.defaultAppName": "تطبيق DSL المستورد",
- "createGuide.dsl.description": "قم بتحميل حزمة Workflow DSL لإنشاء النشر والإصدار الأول ونشر البيئة الاختياري.",
- "createGuide.dsl.dropDescription": "قم بتحميل حزمة Workflow YAML DSL. يتم تحديد خيارات النشر من هذا الملف قبل النشر.",
- "createGuide.dsl.dropTitle": "تحميل حزمة Workflow DSL",
- "createGuide.dsl.readFailed": "فشل في قراءة ملف DSL. اختر ملفًا آخر وحاول مرة أخرى.",
- "createGuide.dsl.reading": "جاري قراءة ملف DSL...",
- "createGuide.dsl.title": "استيراد DSL",
- "createGuide.dsl.unsupportedMode": "يمكن استخدام ملفات Workflow DSL فقط لعمليات النشر.",
- "createGuide.errors.createReleaseFailed": "فشل في إنشاء النشر أو الإصدار.",
- "createGuide.errors.deployFailed": "فشل في النشر إلى البيئة.",
- "createGuide.method.description": "اختر المصدر المستخدم لإنشاء الإصدار الأول.",
- "createGuide.methods.bindApp.description": "استخدم تطبيق Workflow موجود في Studio كمصدر للإصدار.",
- "createGuide.methods.bindApp.title": "ربط تطبيق Workflow موجود",
- "createGuide.methods.importDsl.description": "قم بتحميل حزمة Workflow YAML DSL ومتابعة عبر واجهة النشر.",
- "createGuide.methods.importDsl.title": "استيراد DSL",
- "createGuide.nav.back": "عمليات النشر",
- "createGuide.release.defaultName": "الإصدار الأولي",
- "createGuide.release.deployInfo": "معلومات النشر",
- "createGuide.release.description": "املأ معلومات النشر وتفاصيل الإصدار الأول.",
- "createGuide.release.firstVersion": "الإصدار الأول",
- "createGuide.release.instanceDescription": "وصف النشر",
- "createGuide.release.instanceDescriptionPlaceholder": "صف الغرض من استخدام هذا النشر",
- "createGuide.release.instanceName": "اسم النشر",
- "createGuide.release.instanceNameConflict": "يوجد بالفعل نشر بهذا الاسم. اختر اسمًا آخر.",
- "createGuide.release.releaseDescription": "وصف الإصدار",
- "createGuide.release.releaseDescriptionPlaceholder": "صف هذا الإصدار",
- "createGuide.release.releaseName": "اسم الإصدار",
- "createGuide.release.title": "المعلومات الأساسية",
- "createGuide.source.clearSearch": "مسح بحث التطبيقات",
- "createGuide.source.description": "اختر المصدر المستخدم لإنشاء الإصدار الأول.",
- "createGuide.source.empty": "لم يتم العثور على تطبيقات Workflow.",
- "createGuide.source.searchPlaceholder": "بحث عن التطبيقات",
- "createGuide.source.sourceApp": "تطبيق Workflow",
- "createGuide.source.title": "مصدر الإصدار",
- "createGuide.steps.method": "مصدر الإصدار",
- "createGuide.steps.release": "المعلومات الأساسية",
- "createGuide.steps.source": "مصدر الإصدار",
- "createGuide.steps.target": "النشر إلى البيئة",
- "createGuide.target.bindingCount_one": "{{count}} ربط",
- "createGuide.target.bindingCount_other": "{{count}} روابط",
- "createGuide.target.bindingHint": "اختر بيانات الاعتماد التي يستخدمها هذا الإصدار.",
- "createGuide.target.bindings": "بيانات الاعتماد",
- "createGuide.target.description": "اختر بيئة مستهدفة وقدم إعدادات وقت التشغيل التي يحتاجها هذا الإصدار هناك. يمكن تخطي هذه الخطوة.",
- "createGuide.target.envVarCount_one": "{{count}} متغير",
- "createGuide.target.envVarCount_other": "{{count}} متغيرات",
- "createGuide.target.envVarHint": "لكل متغير بيئة يحتاجه هذا الإصدار، أدخل قيمة مخصصة أو استخدم القيمة المحددة في التطبيق.",
- "createGuide.target.envVarPlaceholder": "أدخل القيمة",
- "createGuide.target.envVarSource.ariaLabel": "اختر مصدر قيمة المتغير لـ {{key}}",
- "createGuide.target.envVarSource.default": "قيمة التطبيق",
- "createGuide.target.envVarSource.lastDeployment": "آخر قيمة منشورة",
- "createGuide.target.envVarSource.literal": "قيمة مخصصة",
- "createGuide.target.envVarType.number": "رقم",
- "createGuide.target.envVarType.secret": "سر",
- "createGuide.target.envVarType.string": "نص",
- "createGuide.target.envVars": "متغيرات البيئة",
- "createGuide.target.environment": "البيئة المستهدفة",
- "createGuide.target.loadBindingsFailed": "فشل في تحميل بيانات الاعتماد.",
- "createGuide.target.loadEnvironmentsFailed": "فشل في تحميل بيئات النشر.",
- "createGuide.target.missingRequiredBinding": "اختر بيانات اعتماد لهذا الربط المطلوب.",
- "createGuide.target.noBindingRequired": "لا يلزم بيانات اعتماد.",
- "createGuide.target.noCredentialCandidates": "لا توجد بيانات اعتماد متاحة.",
- "createGuide.target.noEnvironmentOptions": "لا توجد بيئات نشر متاحة.",
- "createGuide.target.selectCredential": "اختر بيانات اعتماد",
- "createGuide.target.title": "النشر إلى البيئة",
- "createGuide.title": "نشر جديد",
- "createModal.appPickerPlaceholder": "اختر تطبيق Workflow",
- "createModal.appSearchEmpty": "لا توجد تطبيقات Workflow مطابقة",
- "createModal.appSearchPlaceholder": "بحث عن تطبيقات Workflow…",
- "createModal.cancel": "إلغاء",
- "createModal.loadingApps": "جاري تحميل التطبيقات…",
- "deployDrawer.bindingCount_one": "{{count}} ربط",
- "deployDrawer.bindingCount_other": "{{count}} روابط",
"deployDrawer.bindingOptionsFailed": "فشل في تحميل خيارات بيانات الاعتماد.",
"deployDrawer.bindingSelectionHint": "اختر بيانات الاعتماد التي يستخدمها هذا النشر.",
- "deployDrawer.cancel": "إلغاء",
- "deployDrawer.close": "إغلاق درج النشر",
- "deployDrawer.defaultSelect": "اختر...",
- "deployDrawer.deploy": "النشر إلى البيئة",
- "deployDrawer.deployFailed": "فشل في بدء النشر.",
"deployDrawer.deploying": "جاري النشر...",
- "deployDrawer.description": "اختر إصدارًا وبيئة مستهدفة للنشر.",
- "deployDrawer.envVarCount_one": "{{count}} متغير",
- "deployDrawer.envVarCount_other": "{{count}} متغيرات",
- "deployDrawer.envVarHint": "لكل متغير بيئة يحتاجه هذا الإصدار، أدخل قيمة مخصصة أو استخدم القيمة المحددة في التطبيق.",
- "deployDrawer.envVarPlaceholder": "أدخل القيمة",
"deployDrawer.envVarSource.ariaLabel": "اختر مصدر قيمة المتغير لـ {{key}}",
- "deployDrawer.envVarSource.default": "قيمة التطبيق",
"deployDrawer.envVarSource.lastDeployment": "آخر قيمة منشورة",
"deployDrawer.envVarSource.literal": "قيمة مخصصة",
"deployDrawer.envVarType.number": "رقم",
"deployDrawer.envVarType.secret": "سر",
"deployDrawer.envVarType.string": "نص",
"deployDrawer.envVars": "متغيرات البيئة",
- "deployDrawer.existingReleaseHint": "سيتم نشر هذا الإصدار كما هو. لن يتم إنشاء إصدار جديد.",
- "deployDrawer.lockedHint": "مقفل على البيئة الحالية",
- "deployDrawer.missingRequiredBinding": "اختر بيانات اعتماد لهذا الربط المطلوب.",
- "deployDrawer.missingRequiredEnvVar": "أدخل قيمة لمتغير البيئة المطلوب هذا.",
- "deployDrawer.noBindingRequired": "غير مطلوب",
"deployDrawer.noCredentialCandidates": "لا توجد بيانات اعتماد متاحة.",
"deployDrawer.noNewEnvironmentAvailable": "جميع البيئات المتاحة لديها بالفعل نشر.",
- "deployDrawer.noOtherReleaseAvailable": "لا توجد إصدارات أخرى متاحة لهذه البيئة.",
- "deployDrawer.noReleaseAvailable": "أنشئ إصدارًا قبل النشر إلى بيئة.",
- "deployDrawer.notFound": "لم يتم العثور على النشر.",
- "deployDrawer.releaseLabel": "الإصدار",
"deployDrawer.runtimeCredentials": "بيانات الاعتماد",
"deployDrawer.selectCredential": "اختر بيانات اعتماد",
- "deployDrawer.selectEnv": "اختر بيئة",
- "deployDrawer.selectRelease": "اختر إصدارًا",
- "deployDrawer.targetEnv": "البيئة المستهدفة",
- "deployDrawer.title": "النشر إلى البيئة",
- "deployTab.closeError": "إغلاق",
"deployTab.col.actions": "الإجراءات",
- "deployTab.col.currentRelease": "الإصدار الحالي",
"deployTab.col.environment": "البيئة",
"deployTab.col.status": "الحالة",
"deployTab.confirmUndeploy": "إلغاء النشر",
- "deployTab.deployOtherVersion": "نشر إصدار آخر",
- "deployTab.emptyDescription": "اختر إصدارًا وبيئة مستهدفة لجعل هذا النشر متاحًا للمستخدمين.",
- "deployTab.emptyTitle": "لا توجد بيئات قيد التشغيل بعد",
- "deployTab.errorCode": "الكود",
- "deployTab.errorDialogDesc": "راجع آخر نشر فاشل قبل إعادة المحاولة أو نشر إصدار آخر.",
- "deployTab.errorDialogTitle": "خطأ في النشر في {{name}}",
- "deployTab.errorMessage": "الرسالة",
- "deployTab.errorPhase": "المرحلة",
"deployTab.moreActions": "المزيد من الإجراءات",
- "deployTab.newDeployment": "النشر إلى بيئة جديدة",
- "deployTab.panel.unknownError": "فشل النشر.",
"deployTab.redeploy": "إعادة النشر",
- "deployTab.retry": "إعادة المحاولة",
- "deployTab.status.deployFailed": "فشل النشر",
- "deployTab.status.deployingRelease": "جاري النشر ({{release}})",
- "deployTab.status.runningOutOfSync": "قيد التشغيل (المزامنة معلقة)",
- "deployTab.status.runningWithFailed": "قيد التشغيل (فشل آخر نشر)",
"deployTab.undeploy": "إلغاء النشر",
- "deployTab.undeployConfirmDesc": "ستصبح نقطة نهاية البيئة غير متاحة، لكن لن يتم حذف الإصدار.",
- "deployTab.undeployConfirmTitle": "إلغاء نشر {{name}}؟",
"deployTab.undeployConfirmWarning": "بعد التأكيد، ستدخل هذه البيئة حالة إلغاء النشر وسيتم تعطيل الإجراءات مؤقتًا.",
- "deployTab.viewError": "عرض الخطأ",
- "detail.mobileTabs": "أقسام النشر",
- "detail.notFound": "لم يتم العثور على النشر",
- "documentTitle.create": "نشر جديد · عمليات النشر",
- "documentTitle.detail": "النشر · عمليات النشر",
- "documentTitle.list": "عمليات النشر",
- "filter.allEnvs": "جميع البيئات",
- "filter.searchPlaceholder": "بحث عن عمليات النشر",
- "health.ENVIRONMENT_STATUS_ADMISSION": "القبول",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "التمهيد",
- "health.ENVIRONMENT_STATUS_DELETING": "جاري الحذف",
"health.ENVIRONMENT_STATUS_FAILED": "غير متاح",
- "health.ENVIRONMENT_STATUS_READY": "متاح",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "غير معروف",
- "list.clearFilters": "مسح الفلاتر",
- "list.clearSearch": "مسح بحث النشر",
- "list.createDeployment": "جديد",
- "list.emptyDescription": "أنشئ نشرًا من تطبيق Workflow أو حزمة Workflow DSL لإدارة الإصدارات والبيئات والوصول.",
- "list.emptyFilteredDescription": "لا يوجد نشر يطابق البحث الحالي أو فلتر البيئة.",
- "list.emptyFilteredTitle": "لا توجد عمليات نشر مطابقة",
"list.emptyTitle": "لا توجد عمليات نشر بعد",
- "mode.ENVIRONMENT_MODE_ISOLATED": "معزول",
- "mode.ENVIRONMENT_MODE_SHARED": "مشترك",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "غير معروف",
- "overview.accessMeta.apiTokens": "إدارة رموز API",
- "overview.accessMeta.cli": "عرض وصول CLI",
- "overview.accessMeta.webApp": "إدارة وصول WebApp",
- "overview.accessStatus": "الوصول",
- "overview.api": "رموز API",
- "overview.apiKeysCount_one": "{{count}} رمز API",
- "overview.apiKeysCount_other": "{{count}} رموز API",
- "overview.apiTokenSummary.environments_one": "{{count}} بيئة منشورة",
- "overview.apiTokenSummary.environments_other": "{{count}} بيئات منشورة",
- "overview.cardAction.deployLatest": "نشر أحدث إصدار",
- "overview.cardAction.redeploy": "إعادة النشر",
- "overview.cardAction.viewProgress": "عرض النشر",
- "overview.chip.behindTooltip_one": "إصدار واحد متأخر عن الأحدث. قم بنشر أحدث إصدار للتحديث.",
- "overview.chip.behindTooltip_other": "{{count}} إصدارات متأخرة عن الأحدث. قم بنشر أحدث إصدار للتحديث.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "قيد النشر",
- "overview.chip.deployingTooltip": "النشر قيد التقدم.",
- "overview.chip.empty": "فارغ",
- "overview.chip.emptyTooltip": "لم يتم نشر أي إصدار إلى هذه البيئة.",
- "overview.chip.failed": "فشل",
- "overview.chip.failedTooltip": "فشلت محاولة النشر الأخيرة.",
"overview.chip.latest": "الأحدث",
- "overview.chip.latestTooltip": "هذه البيئة تشغل أحدث إصدار.",
- "overview.chip.needsReleaseFirst": "أنشئ إصدارًا أولاً",
- "overview.chip.olderRelease": "أقدم",
- "overview.chip.olderReleaseTooltip": "هذه البيئة تشغل إصدارًا أقدم.",
- "overview.chip.openInDeployTab": "عرض تقدم النشر",
- "overview.disabled": "معطل",
- "overview.enabled": "ممكّن",
- "overview.hero.byName": "بواسطة {{name}}",
- "overview.hero.empty": "لا توجد إصدارات بعد",
- "overview.hero.emptyDescription": "أنشئ إصدارًا من المصدر الحالي قبل النشر.",
- "overview.latestRelease.releaseCount_one": "{{count}} إصدار",
- "overview.latestRelease.releaseCount_other": "{{count}} إصدارات",
- "overview.latestReleaseTitle": "أحدث إصدار",
- "overview.previousReleases.viewAll": "عرض الكل",
- "overview.strip.deployToNewEnvironment": "النشر إلى بيئة جديدة",
- "overview.strip.emptyDeployableDescription": "انشر أحدث إصدار إلى بيئة عندما تكون جاهزًا.",
- "overview.strip.emptyDescription": "أنشئ إصدارًا قبل النشر إلى بيئة.",
- "overview.strip.emptyTitle": "لا توجد مثيلات بعد",
- "overview.strip.title": "المثيلات",
- "settings.delete": "حذف النشر",
- "settings.deleteConfirmDesc": "هل تريد حذف {{name}}؟ سيتوقف كل مثيل عن العمل وستتم إزالته من جميع البيئات. لا يمكن التراجع عن ذلك.",
- "settings.deleteConfirmTitle": "حذف النشر",
- "settings.deleteFailed": "فشل في حذف النشر.",
- "settings.deleted": "تم حذف النشر",
- "settings.description": "الوصف",
- "settings.name": "اسم النشر",
- "settings.save": "حفظ التغييرات",
- "settings.updateFailed": "فشل في تحديث النشر.",
- "settings.updated": "تم تحديث النشر",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "جاري النشر",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "المزامنة معلقة",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "فشل النشر",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "غير صالح",
"status.RUNTIME_INSTANCE_STATUS_READY": "قيد التشغيل",
@@ -370,87 +89,6 @@
"studio.versionValue": "قيمة الإصدار",
"studio.versionsBehind_one": "متأخر بـ {{count}} إصدار",
"studio.versionsBehind_other": "متأخر بـ {{count}} إصدارات",
- "tabs.access.description": "إدارة قنوات الوصول وأذونات الوصول.",
- "tabs.access.name": "الوصول",
- "tabs.api-tokens.description": "إدارة رموز API واستدعاء المثيلات عبر HTTP.",
- "tabs.api-tokens.name": "رموز API",
- "tabs.instances.description": "عرض وإدارة المثيلات في البيئات المنشورة.",
- "tabs.instances.name": "المثيلات",
- "tabs.overview.description": "اطلع على حالة النشر عبر البيئات.",
- "tabs.overview.name": "نظرة عامة",
- "tabs.releases.description": "إنشاء ونشر وإدارة الإصدارات.",
- "tabs.releases.name": "الإصدارات",
- "unsupportedDslNodes.description": "يحتوي هذا الإصدار على عقد لا يدعمها وقت تشغيل النشر بعد. قم بإزالتها أو استبدالها في Studio، ثم حاول مرة أخرى.",
- "unsupportedDslNodes.descriptionWithTypes": "يحتوي هذا الإصدار على عقد لا يدعمها وقت تشغيل النشر بعد: {{nodeTypes}}. قم بإزالتها أو استبدالها في Studio، ثم حاول مرة أخرى.",
- "unsupportedDslNodes.title": "عقد غير مدعومة",
- "unsupportedDslNodes.unknownType": "نوع غير معروف",
- "versions.cancelCreate": "إلغاء",
- "versions.cancelDelete": "إلغاء",
- "versions.cancelEdit": "إلغاء",
"versions.checkingReleaseContent": "جاري التحقق من محتوى الإصدار...",
- "versions.col.action": "الإجراء",
- "versions.col.author": "أنشئ بواسطة",
- "versions.col.createdAt": "تم الإنشاء في",
- "versions.col.deployedTo": "تم النشر إلى",
- "versions.col.release": "الإصدار",
- "versions.col.sourceApp": "المصدر",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "إنشاء",
- "versions.createFailed": "فشل في إنشاء الإصدار.",
- "versions.createRelease": "إنشاء إصدار",
- "versions.createReleaseDescription": "أنشئ إصدارًا قابلاً للنشر من تطبيق Workflow أو ملف Workflow DSL.",
- "versions.createSuccess": "تم إنشاء الإصدار \"{{name}}\".",
- "versions.creating": "جاري الإنشاء...",
- "versions.currentOn": "الإصدار الحالي على {{name}}",
- "versions.deleteConfirmDesc": "سيتم حذف الإصدار \"{{name}}\" نهائيًا. لا يمكن التراجع عن ذلك.",
- "versions.deleteConfirmTitle": "حذف الإصدار؟",
- "versions.deleteFailed": "فشل في حذف الإصدار.",
- "versions.deleteRelease": "حذف الإصدار",
- "versions.deleteSuccess": "تم حذف الإصدار \"{{name}}\".",
- "versions.deployTo": "النشر إلى {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "جاري النشر",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "المزامنة معلقة",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "فشل",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "غير صالح",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "قيد التشغيل",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "غير منشور",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "جاري إلغاء النشر",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "غير معروف",
- "versions.deployingTo": "{{name}} قيد النشر",
- "versions.disabledReason.checkDeploymentsFailed": "تعذر التحقق من استخدام النشر. حاول مرة أخرى لاحقًا.",
- "versions.disabledReason.checkingDeployments": "جاري التحقق من استخدام النشر",
- "versions.disabledReason.current": "هذا الإصدار يعمل بالفعل على {{name}}",
- "versions.disabledReason.deploying": "انتظر حتى ينتهي النشر النشط",
- "versions.disabledReason.releaseInUse_one": "ألغِ نشر هذا الإصدار من {{count}} بيئة قبل حذفه",
- "versions.disabledReason.releaseInUse_other": "ألغِ نشر هذا الإصدار من {{count}} بيئات قبل حذفه",
- "versions.dslReadFailed": "فشل في قراءة ملف DSL. اختر ملفًا آخر وحاول مرة أخرى.",
- "versions.dslReading": "جاري قراءة ملف DSL...",
- "versions.dslUnsupportedMode": "يمكن استخدام ملفات Workflow DSL فقط لعمليات النشر.",
- "versions.editFailed": "فشل في تحديث الإصدار.",
- "versions.editRelease": "تعديل الإصدار",
- "versions.editReleaseDescription": "تحديث اسم ووصف هذا الإصدار.",
- "versions.editSuccess": "تم تحديث الإصدار \"{{name}}\".",
- "versions.emptyDescription": "أنشئ الإصدار الأول قبل النشر إلى بيئة.",
- "versions.emptyTitle": "لا توجد إصدارات بعد",
- "versions.exportDsl": "تصدير DSL",
- "versions.exportDslFailed": "فشل في تصدير DSL.",
- "versions.exportingDsl": "جاري التصدير...",
- "versions.groupHeader.deploy": "نشر",
- "versions.groupHeader.rollback": "نشر الإصدار السابق",
- "versions.groupHeader.unavailable": "غير متاح",
- "versions.manualDslOption": "تحميل DSL",
- "versions.moreActions": "المزيد من الإجراءات",
- "versions.optional": "اختياري",
- "versions.releaseAlreadyExists": "يوجد بالفعل إصدار بنفس المحتوى: {{name}}.",
- "versions.releaseContentCheckFailed": "فشل في التحقق من محتوى الإصدار.",
- "versions.releaseDescriptionLabel": "الوصف",
- "versions.releaseDescriptionPlaceholder": "صف هذا الإصدار",
- "versions.releaseNameConflict": "يوجد بالفعل إصدار بهذا الاسم. اختر اسمًا آخر.",
- "versions.releaseNameLabel": "اسم الإصدار",
- "versions.releaseNamePlaceholder": "اسم الإصدار",
- "versions.releaseNameRequired": "أدخل اسم الإصدار.",
- "versions.releaseSourceLabel": "مصدر الإصدار",
- "versions.rollbackTo": "النشر إلى {{name}}",
- "versions.saveEdit": "حفظ",
- "versions.sourceAppOption": "تطبيق Workflow"
+ "versions.deployTo": "النشر إلى {{name}}"
}
diff --git a/web/i18n/de-DE/common.json b/web/i18n/de-DE/common.json
index 6f970d9f9b4..237f1360fd3 100644
--- a/web/i18n/de-DE/common.json
+++ b/web/i18n/de-DE/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "App-Details",
"menus.apps": "Studio",
"menus.datasets": "Wissen",
- "menus.deployments": "Bereitstellungen",
"menus.exploreMarketplace": "Marketplace erkunden",
"menus.plugins": "Integrationen",
"menus.status": "Beta",
diff --git a/web/i18n/de-DE/deployments.json b/web/i18n/de-DE/deployments.json
index 508e597d60a..8b62c2e8af1 100644
--- a/web/i18n/de-DE/deployments.json
+++ b/web/i18n/de-DE/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "cURL-Beispiel kopieren",
- "access.api.createFailed": "API-Token konnte nicht generiert werden.",
- "access.api.createKey": "API-Token generieren",
- "access.api.createKeyTitle": "Neuen API-Token generieren",
- "access.api.curlExampleTitle": "cURL-Beispiel",
- "access.api.description": "Zugriff auf diese Bereitstellung über HTTP. Jeder API-Token gilt für eine Umgebung.",
- "access.api.developerTitle": "Entwickler-API",
- "access.api.disabled": "Der API-Zugriff ist für diese Bereitstellung deaktiviert.",
- "access.api.disabledHint": "Aktivieren Sie den API-Zugriff, um umgebungsspezifische Token zu generieren.",
- "access.api.docs": "API-Dokumentation",
- "access.api.docsClose": "API-Dokumentation schließen",
- "access.api.docsDescription": "Workflow-API-Referenz für diese Bereitstellung anzeigen.",
- "access.api.docsTitle": "Workflow-API-Dokumentation",
- "access.api.empty": "Stellen Sie zuerst in einer Umgebung bereit, um API-Token auszustellen.",
- "access.api.emptyTitle": "Keine bereitgestellten Umgebungen",
- "access.api.endpoint": "Anforderungs-URL",
- "access.api.keyList": "API-Token-Liste",
- "access.api.nameLabel": "Name des API-Tokens",
- "access.api.namePlaceholder": "Geben Sie einen Namen für den API-Token ein",
- "access.api.nameRequired": "Der Name des API-Tokens ist erforderlich.",
- "access.api.newKey": "Neuen API-Token generieren",
- "access.api.newTokenDescription": "Dieser API-Token wird nur einmal angezeigt. Kopieren Sie ihn, bevor Sie diese Seite verlassen.",
- "access.api.newTokenLabel": "API-Token",
- "access.api.newTokenTitle": "API-Token generiert",
- "access.api.noKeys": "Noch keine API-Token. Generieren Sie einen, um die API aufzurufen.",
- "access.api.noKeysTitle": "Noch keine API-Token",
- "access.api.revokeConfirmDescription": "Der API-Token \"{{name}}\" funktioniert sofort nicht mehr. Diese Aktion kann nicht rückgängig gemacht werden.",
- "access.api.revokeConfirmTitle": "API-Token widerrufen?",
- "access.api.revokeFailed": "API-Token konnte nicht widerrufen werden.",
- "access.api.revokeSuccess": "API-Token widerrufen",
- "access.api.table.action": "Aktion",
- "access.api.table.environment": "Umgebung",
- "access.api.table.key": "API-Token",
- "access.api.table.name": "Name",
- "access.channels.disabled": "Zugriffskanäle sind für diese Bereitstellung deaktiviert.",
- "access.channels.disabledHint": "Aktivieren Sie Zugriffskanäle, um WebApp- und CLI-Einstiegspunkte verfügbar zu machen.",
- "access.channels.title": "Zugriffskanäle",
- "access.cli.description": "Über das Terminal mit difyctl aufrufen, geeignet für Skripte, automatisierte Workflows oder Agent-Integrationen.",
- "access.cli.docs": "Anwendungsleitfaden",
- "access.cli.domain": "Domain",
- "access.cli.empty": "CLI-Endpunkt nicht konfiguriert.",
- "access.cli.install": "CLI installieren",
- "access.cli.title": "CLI",
- "access.copy": "Kopieren",
- "access.copyFailed": "Kopieren fehlgeschlagen",
- "access.members.groupCount_one": "{{count}} Gruppe",
- "access.members.groupCount_other": "{{count}} Gruppen",
- "access.members.memberCount_one": "{{count}} Mitglied",
- "access.members.memberCount_other": "{{count}} Mitglieder",
- "access.permission.anyone": "Jeder mit dem Link",
- "access.permission.organization": "Alle Mitglieder innerhalb der Plattform",
- "access.permission.specific": "Bestimmte Mitglieder innerhalb der Plattform",
- "access.permission.specificDesc": "Bestimmte Gruppen oder Mitglieder auswählen",
- "access.permission.updateFailed": "Zugriffsrichtlinie konnte nicht aktualisiert werden.",
- "access.permissions.editAriaLabel": "Zugriff für {{environment}} konfigurieren",
- "access.permissions.editDescription": "Legen Sie Zugriffsberechtigungen für WebApp- und CLI-Einstiegspunkte fest.",
- "access.permissions.editTitle": "Zugriffsberechtigungen",
- "access.permissions.title": "Zugriffsberechtigungen",
- "access.revoke": "Widerrufen",
- "access.runAccess.noEnvs": "Stellen Sie in einer Umgebung bereit, um Zugriffsberechtigungen zu konfigurieren.",
- "access.runAccess.noEnvsTitle": "Keine bereitgestellten Umgebungen",
- "access.runAccess.openWebapp": "WebApp öffnen",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Gehostete Webseite für Endbenutzer.",
- "access.runAccess.webappEmpty": "Demnächst verfügbar.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Extern",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Unbekannt",
- "card.access.api": "API-Token",
- "card.access.cli": "CLI",
- "card.access.none": "Kein Zugriff",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Erstes Release erstellen",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Bereitstellung löschen",
- "card.menu.deploy": "In Umgebung bereitstellen",
- "card.menu.editInfo": "Informationen bearbeiten",
- "card.moreActions": "Weitere Aktionen",
- "card.noDescription": "Keine Beschreibung angegeben.",
"card.notDeployed": "Nicht bereitgestellt",
- "card.tooltip.createdAt": "Erstellt",
- "card.tooltip.deployed": "Bereitgestellt",
- "card.tooltip.deploymentStatus": "Bereitstellung",
- "card.tooltip.notDeployedShort": "Nicht bereitgestellt",
- "card.tooltip.releaseName": "Release-Name",
- "card.tooltip.source": "Quelle",
"common.loadFailed": "Laden fehlgeschlagen. Versuchen Sie es später erneut.",
- "createGuide.actions.back": "Zurück",
- "createGuide.actions.createAndDeploy": "Erstellen und bereitstellen",
- "createGuide.actions.creating": "Wird erstellt...",
- "createGuide.actions.deploying": "Wird erstellt und bereitgestellt...",
- "createGuide.actions.next": "Weiter",
- "createGuide.actions.skipDeploy": "Überspringen, später bereitstellen",
- "createGuide.dsl.defaultAppName": "Importierte DSL-App",
- "createGuide.dsl.description": "Laden Sie ein Workflow-DSL-Paket hoch, um die Bereitstellung, das erste Release und die optionale Umgebungsbereitstellung zu erstellen.",
- "createGuide.dsl.dropDescription": "Laden Sie ein Workflow-YAML-DSL-Paket hoch. Die Bereitstellungsoptionen werden vor der Bereitstellung aus dieser Datei aufgelöst.",
- "createGuide.dsl.dropTitle": "Workflow-DSL-Paket hochladen",
- "createGuide.dsl.readFailed": "Die DSL-Datei konnte nicht gelesen werden. Wählen Sie eine andere Datei und versuchen Sie es erneut.",
- "createGuide.dsl.reading": "DSL-Datei wird gelesen...",
- "createGuide.dsl.title": "DSL importieren",
- "createGuide.dsl.unsupportedMode": "Nur Workflow-DSL-Dateien können für Bereitstellungen verwendet werden.",
- "createGuide.errors.createReleaseFailed": "Bereitstellung oder Release konnte nicht erstellt werden.",
- "createGuide.errors.deployFailed": "Bereitstellung in der Umgebung fehlgeschlagen.",
- "createGuide.method.description": "Wählen Sie die Quelle, die zum Erstellen des ersten Releases verwendet wird.",
- "createGuide.methods.bindApp.description": "Verwenden Sie eine bestehende Workflow-App in Studio als Release-Quelle.",
- "createGuide.methods.bindApp.title": "Bestehende Workflow-App binden",
- "createGuide.methods.importDsl.description": "Laden Sie ein Workflow-YAML-DSL-Paket hoch und fahren Sie über die Bereitstellungs-UI fort.",
- "createGuide.methods.importDsl.title": "DSL importieren",
- "createGuide.nav.back": "Bereitstellungen",
- "createGuide.release.defaultName": "initiales Release",
- "createGuide.release.deployInfo": "Bereitstellungsinformationen",
- "createGuide.release.description": "Geben Sie Bereitstellungsinformationen und Details zum ersten Release ein.",
- "createGuide.release.firstVersion": "Erstes Release",
- "createGuide.release.instanceDescription": "Bereitstellungsbeschreibung",
- "createGuide.release.instanceDescriptionPlaceholder": "Beschreiben Sie, wofür diese Bereitstellung verwendet wird",
- "createGuide.release.instanceName": "Bereitstellungsname",
- "createGuide.release.instanceNameConflict": "Eine Bereitstellung mit diesem Namen existiert bereits. Wählen Sie einen anderen Namen.",
- "createGuide.release.releaseDescription": "Release-Beschreibung",
- "createGuide.release.releaseDescriptionPlaceholder": "Beschreiben Sie dieses Release",
- "createGuide.release.releaseName": "Release-Name",
- "createGuide.release.title": "Basisinformationen",
- "createGuide.source.clearSearch": "App-Suche löschen",
- "createGuide.source.description": "Wählen Sie die Quelle, die zum Erstellen des ersten Releases verwendet wird.",
- "createGuide.source.empty": "Keine Workflow-Apps gefunden.",
- "createGuide.source.searchPlaceholder": "Apps suchen",
- "createGuide.source.sourceApp": "Workflow-App",
- "createGuide.source.title": "Release-Quelle",
- "createGuide.steps.method": "Release-Quelle",
- "createGuide.steps.release": "Basisinformationen",
- "createGuide.steps.source": "Release-Quelle",
- "createGuide.steps.target": "In Umgebung bereitstellen",
- "createGuide.target.bindingCount_one": "{{count}} Anmeldedaten",
- "createGuide.target.bindingCount_other": "{{count}} Anmeldedaten",
- "createGuide.target.bindingHint": "Wählen Sie die Anmeldedaten aus, die von diesem Release verwendet werden.",
- "createGuide.target.bindings": "Anmeldedaten",
- "createGuide.target.description": "Wählen Sie eine Zielumgebung und geben Sie die Laufzeiteinstellungen an, die dieses Release dort benötigt. Dieser Schritt kann übersprungen werden.",
- "createGuide.target.envVarCount_one": "{{count}} Variable",
- "createGuide.target.envVarCount_other": "{{count}} Variablen",
- "createGuide.target.envVarHint": "Geben Sie für jede Umgebungsvariable, die dieses Release benötigt, einen benutzerdefinierten Wert ein oder verwenden Sie den in der App definierten Wert.",
- "createGuide.target.envVarPlaceholder": "Wert eingeben",
- "createGuide.target.envVarSource.ariaLabel": "Wertquelle für die Variable {{key}} auswählen",
- "createGuide.target.envVarSource.default": "App-Wert",
- "createGuide.target.envVarSource.lastDeployment": "Zuletzt bereitgestellter Wert",
- "createGuide.target.envVarSource.literal": "Benutzerdefinierter Wert",
- "createGuide.target.envVarType.number": "Zahl",
- "createGuide.target.envVarType.secret": "Geheimnis",
- "createGuide.target.envVarType.string": "Zeichenkette",
- "createGuide.target.envVars": "Umgebungsvariablen",
- "createGuide.target.environment": "Zielumgebung",
- "createGuide.target.loadBindingsFailed": "Anmeldedaten konnten nicht geladen werden.",
- "createGuide.target.loadEnvironmentsFailed": "Bereitstellungsumgebungen konnten nicht geladen werden.",
- "createGuide.target.missingRequiredBinding": "Wählen Sie Anmeldedaten für diese erforderliche Bindung aus.",
- "createGuide.target.noBindingRequired": "Keine Anmeldedaten erforderlich.",
- "createGuide.target.noCredentialCandidates": "Keine verfügbaren Anmeldedaten.",
- "createGuide.target.noEnvironmentOptions": "Keine Bereitstellungsumgebungen verfügbar.",
- "createGuide.target.selectCredential": "Anmeldedaten auswählen",
- "createGuide.target.title": "In Umgebung bereitstellen",
- "createGuide.title": "Neue Bereitstellung",
- "createModal.appPickerPlaceholder": "Workflow-App auswählen",
- "createModal.appSearchEmpty": "Keine passenden Workflow-Apps",
- "createModal.appSearchPlaceholder": "Workflow-Apps suchen…",
- "createModal.cancel": "Abbrechen",
- "createModal.loadingApps": "Apps werden geladen…",
- "deployDrawer.bindingCount_one": "{{count}} Anmeldedaten",
- "deployDrawer.bindingCount_other": "{{count}} Anmeldedaten",
"deployDrawer.bindingOptionsFailed": "Anmeldedaten-Optionen konnten nicht geladen werden.",
"deployDrawer.bindingSelectionHint": "Wählen Sie die Anmeldedaten aus, die von dieser Bereitstellung verwendet werden.",
- "deployDrawer.cancel": "Abbrechen",
- "deployDrawer.close": "Bereitstellungs-Drawer schließen",
- "deployDrawer.defaultSelect": "Auswählen...",
- "deployDrawer.deploy": "In Umgebung bereitstellen",
- "deployDrawer.deployFailed": "Bereitstellung konnte nicht gestartet werden.",
"deployDrawer.deploying": "Wird bereitgestellt...",
- "deployDrawer.description": "Wählen Sie ein Release und eine Zielumgebung zur Bereitstellung aus.",
- "deployDrawer.envVarCount_one": "{{count}} Variable",
- "deployDrawer.envVarCount_other": "{{count}} Variablen",
- "deployDrawer.envVarHint": "Geben Sie für jede Umgebungsvariable, die dieses Release benötigt, einen benutzerdefinierten Wert ein oder verwenden Sie den in der App definierten Wert.",
- "deployDrawer.envVarPlaceholder": "Wert eingeben",
"deployDrawer.envVarSource.ariaLabel": "Wertquelle für die Variable {{key}} auswählen",
- "deployDrawer.envVarSource.default": "App-Wert",
"deployDrawer.envVarSource.lastDeployment": "Zuletzt bereitgestellter Wert",
"deployDrawer.envVarSource.literal": "Benutzerdefinierter Wert",
"deployDrawer.envVarType.number": "Zahl",
"deployDrawer.envVarType.secret": "Geheimnis",
"deployDrawer.envVarType.string": "Zeichenkette",
"deployDrawer.envVars": "Umgebungsvariablen",
- "deployDrawer.existingReleaseHint": "Dieses Release wird unverändert bereitgestellt. Es wird kein neues Release erstellt.",
- "deployDrawer.lockedHint": "An aktuelle Umgebung gebunden",
- "deployDrawer.missingRequiredBinding": "Wählen Sie Anmeldedaten für diese erforderliche Bindung aus.",
- "deployDrawer.missingRequiredEnvVar": "Geben Sie einen Wert für diese erforderliche Umgebungsvariable ein.",
- "deployDrawer.noBindingRequired": "Nicht erforderlich",
"deployDrawer.noCredentialCandidates": "Keine verfügbaren Anmeldedaten.",
"deployDrawer.noNewEnvironmentAvailable": "Alle verfügbaren Umgebungen haben bereits eine Bereitstellung.",
- "deployDrawer.noOtherReleaseAvailable": "Es sind keine weiteren Releases für diese Umgebung verfügbar.",
- "deployDrawer.noReleaseAvailable": "Erstellen Sie ein Release, bevor Sie in einer Umgebung bereitstellen.",
- "deployDrawer.notFound": "Bereitstellung nicht gefunden.",
- "deployDrawer.releaseLabel": "Release",
"deployDrawer.runtimeCredentials": "Anmeldedaten",
"deployDrawer.selectCredential": "Anmeldedaten auswählen",
- "deployDrawer.selectEnv": "Eine Umgebung auswählen",
- "deployDrawer.selectRelease": "Ein Release auswählen",
- "deployDrawer.targetEnv": "Zielumgebung",
- "deployDrawer.title": "In Umgebung bereitstellen",
- "deployTab.closeError": "Schließen",
"deployTab.col.actions": "Aktionen",
- "deployTab.col.currentRelease": "Aktuelles Release",
"deployTab.col.environment": "Umgebung",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Bereitstellung aufheben",
- "deployTab.deployOtherVersion": "Anderes Release bereitstellen",
- "deployTab.emptyDescription": "Wählen Sie ein Release und eine Zielumgebung aus, um diese Bereitstellung Benutzern zur Verfügung zu stellen.",
- "deployTab.emptyTitle": "Es werden noch keine Umgebungen ausgeführt",
- "deployTab.errorCode": "Code",
- "deployTab.errorDialogDesc": "Überprüfen Sie die letzte fehlgeschlagene Bereitstellung, bevor Sie es erneut versuchen oder ein anderes Release bereitstellen.",
- "deployTab.errorDialogTitle": "Bereitstellungsfehler in {{name}}",
- "deployTab.errorMessage": "Meldung",
- "deployTab.errorPhase": "Phase",
"deployTab.moreActions": "Weitere Aktionen",
- "deployTab.newDeployment": "In neuer Umgebung bereitstellen",
- "deployTab.panel.unknownError": "Bereitstellung fehlgeschlagen.",
"deployTab.redeploy": "Erneut bereitstellen",
- "deployTab.retry": "Erneut versuchen",
- "deployTab.status.deployFailed": "Bereitstellung fehlgeschlagen",
- "deployTab.status.deployingRelease": "Wird bereitgestellt ({{release}})",
- "deployTab.status.runningOutOfSync": "Läuft (Synchronisierung ausstehend)",
- "deployTab.status.runningWithFailed": "Läuft (letzte Bereitstellung fehlgeschlagen)",
"deployTab.undeploy": "Bereitstellung aufheben",
- "deployTab.undeployConfirmDesc": "Der Endpunkt der Umgebung ist danach nicht mehr verfügbar, die Version wird jedoch nicht gelöscht.",
- "deployTab.undeployConfirmTitle": "Bereitstellung von {{name}} aufheben?",
"deployTab.undeployConfirmWarning": "Nach der Bestätigung wechselt diese Umgebung in den Status „Bereitstellung wird aufgehoben“ und Aktionen werden vorübergehend deaktiviert.",
- "deployTab.viewError": "Fehler anzeigen",
- "detail.mobileTabs": "Bereitstellungsbereiche",
- "detail.notFound": "Bereitstellung nicht gefunden",
- "documentTitle.create": "Neue Bereitstellung · Bereitstellungen",
- "documentTitle.detail": "Bereitstellung · Bereitstellungen",
- "documentTitle.list": "Bereitstellungen",
- "filter.allEnvs": "Alle Umgebungen",
- "filter.searchPlaceholder": "Bereitstellungen suchen",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Zulassung",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Wird initialisiert",
- "health.ENVIRONMENT_STATUS_DELETING": "Wird gelöscht",
"health.ENVIRONMENT_STATUS_FAILED": "Nicht verfügbar",
- "health.ENVIRONMENT_STATUS_READY": "Verfügbar",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Unbekannt",
- "list.clearFilters": "Filter löschen",
- "list.clearSearch": "Bereitstellungssuche löschen",
- "list.createDeployment": "Neu",
- "list.emptyDescription": "Erstellen Sie eine Bereitstellung aus einer Workflow-App oder einem Workflow-DSL-Paket, um Releases, Umgebungen und Zugriff zu verwalten.",
- "list.emptyFilteredDescription": "Keine Bereitstellung entspricht der aktuellen Suche oder dem Umgebungsfilter.",
- "list.emptyFilteredTitle": "Keine passenden Bereitstellungen",
"list.emptyTitle": "Noch keine Bereitstellungen",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Isoliert",
- "mode.ENVIRONMENT_MODE_SHARED": "Geteilt",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Unbekannt",
- "overview.accessMeta.apiTokens": "API-Token verwalten",
- "overview.accessMeta.cli": "CLI-Zugriff anzeigen",
- "overview.accessMeta.webApp": "WebApp-Zugriff verwalten",
- "overview.accessStatus": "Zugriff",
- "overview.api": "API-Token",
- "overview.apiKeysCount_one": "{{count}} API-Token",
- "overview.apiKeysCount_other": "{{count}} API-Token",
- "overview.apiTokenSummary.environments_one": "{{count}} bereitgestellte Umgebung",
- "overview.apiTokenSummary.environments_other": "{{count}} bereitgestellte Umgebungen",
- "overview.cardAction.deployLatest": "Neuestes Release bereitstellen",
- "overview.cardAction.redeploy": "Erneut bereitstellen",
- "overview.cardAction.viewProgress": "Bereitstellung anzeigen",
- "overview.chip.behindTooltip_one": "1 Release hinter dem neuesten. Stellen Sie das neueste Release bereit, um zu aktualisieren.",
- "overview.chip.behindTooltip_other": "{{count}} Releases hinter dem neuesten. Stellen Sie das neueste Release bereit, um zu aktualisieren.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "wird bereitgestellt",
- "overview.chip.deployingTooltip": "Die Bereitstellung läuft.",
- "overview.chip.empty": "leer",
- "overview.chip.emptyTooltip": "In dieser Umgebung ist kein Release bereitgestellt.",
- "overview.chip.failed": "fehlgeschlagen",
- "overview.chip.failedTooltip": "Der letzte Bereitstellungsversuch ist fehlgeschlagen.",
"overview.chip.latest": "neueste",
- "overview.chip.latestTooltip": "In dieser Umgebung läuft das neueste Release.",
- "overview.chip.needsReleaseFirst": "Zuerst ein Release erstellen",
- "overview.chip.olderRelease": "älter",
- "overview.chip.olderReleaseTooltip": "In dieser Umgebung läuft ein älteres Release.",
- "overview.chip.openInDeployTab": "Bereitstellungsfortschritt anzeigen",
- "overview.disabled": "Deaktiviert",
- "overview.enabled": "Aktiviert",
- "overview.hero.byName": "von {{name}}",
- "overview.hero.empty": "Noch keine Releases",
- "overview.hero.emptyDescription": "Erstellen Sie ein Release aus der aktuellen Quelle, bevor Sie bereitstellen.",
- "overview.latestRelease.releaseCount_one": "{{count}} Release",
- "overview.latestRelease.releaseCount_other": "{{count}} Releases",
- "overview.latestReleaseTitle": "Neuestes Release",
- "overview.previousReleases.viewAll": "Alle anzeigen",
- "overview.strip.deployToNewEnvironment": "In neuer Umgebung bereitstellen",
- "overview.strip.emptyDeployableDescription": "Stellen Sie das neueste Release in einer Umgebung bereit, sobald Sie bereit sind.",
- "overview.strip.emptyDescription": "Erstellen Sie ein Release, bevor Sie in einer Umgebung bereitstellen.",
- "overview.strip.emptyTitle": "Noch keine Instanzen",
- "overview.strip.title": "Instanzen",
- "settings.delete": "Bereitstellung löschen",
- "settings.deleteConfirmDesc": "{{name}} löschen? Jede Instanz wird gestoppt und in allen Umgebungen entfernt. Dies kann nicht rückgängig gemacht werden.",
- "settings.deleteConfirmTitle": "Bereitstellung löschen",
- "settings.deleteFailed": "Bereitstellung konnte nicht gelöscht werden.",
- "settings.deleted": "Bereitstellung gelöscht",
- "settings.description": "Beschreibung",
- "settings.name": "Bereitstellungsname",
- "settings.save": "Änderungen speichern",
- "settings.updateFailed": "Bereitstellung konnte nicht aktualisiert werden.",
- "settings.updated": "Bereitstellung aktualisiert",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Wird bereitgestellt",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisierung ausstehend",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Bereitstellung fehlgeschlagen",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Ungültig",
"status.RUNTIME_INSTANCE_STATUS_READY": "Läuft",
@@ -370,87 +89,6 @@
"studio.versionValue": "Versionswert",
"studio.versionsBehind_one": "{{count}} Version zurück",
"studio.versionsBehind_other": "{{count}} Versionen zurück",
- "tabs.access.description": "Verwalten Sie Zugriffskanäle und Zugriffsberechtigungen.",
- "tabs.access.name": "Zugriff",
- "tabs.api-tokens.description": "Verwalten Sie API-Token und rufen Sie Instanzen über HTTP auf.",
- "tabs.api-tokens.name": "API-Token",
- "tabs.instances.description": "Anzeigen und Verwalten von Instanzen in bereitgestellten Umgebungen.",
- "tabs.instances.name": "Instanzen",
- "tabs.overview.description": "Sehen Sie den Status der Bereitstellung über die Umgebungen hinweg.",
- "tabs.overview.name": "Übersicht",
- "tabs.releases.description": "Releases erstellen, bereitstellen und verwalten.",
- "tabs.releases.name": "Releases",
- "unsupportedDslNodes.description": "Dieses Release enthält Knoten, die die Bereitstellungslaufzeit noch nicht unterstützt. Entfernen oder ersetzen Sie sie in Studio und versuchen Sie es erneut.",
- "unsupportedDslNodes.descriptionWithTypes": "Dieses Release enthält Knoten, die die Bereitstellungslaufzeit noch nicht unterstützt: {{nodeTypes}}. Entfernen oder ersetzen Sie sie in Studio und versuchen Sie es erneut.",
- "unsupportedDslNodes.title": "Nicht unterstützte Knoten",
- "unsupportedDslNodes.unknownType": "Unbekannter Typ",
- "versions.cancelCreate": "Abbrechen",
- "versions.cancelDelete": "Abbrechen",
- "versions.cancelEdit": "Abbrechen",
"versions.checkingReleaseContent": "Release-Inhalt wird überprüft...",
- "versions.col.action": "Aktion",
- "versions.col.author": "Erstellt von",
- "versions.col.createdAt": "Erstellt am",
- "versions.col.deployedTo": "Bereitgestellt in",
- "versions.col.release": "Release",
- "versions.col.sourceApp": "Quelle",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Erstellen",
- "versions.createFailed": "Release konnte nicht erstellt werden.",
- "versions.createRelease": "Release erstellen",
- "versions.createReleaseDescription": "Erstellen Sie ein bereitstellbares Release aus einer Workflow-App oder einer Workflow-DSL-Datei.",
- "versions.createSuccess": "Release \"{{name}}\" erstellt.",
- "versions.creating": "Wird erstellt...",
- "versions.currentOn": "Aktuelles Release in {{name}}",
- "versions.deleteConfirmDesc": "Release \"{{name}}\" wird dauerhaft gelöscht. Dies kann nicht rückgängig gemacht werden.",
- "versions.deleteConfirmTitle": "Release löschen?",
- "versions.deleteFailed": "Release konnte nicht gelöscht werden.",
- "versions.deleteRelease": "Release löschen",
- "versions.deleteSuccess": "Release \"{{name}}\" gelöscht.",
- "versions.deployTo": "In {{name}} bereitstellen",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Wird bereitgestellt",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisierung ausstehend",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Fehlgeschlagen",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Ungültig",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Läuft",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Nicht bereitgestellt",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Bereitstellung wird aufgehoben",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Unbekannt",
- "versions.deployingTo": "{{name}} wird bereitgestellt",
- "versions.disabledReason.checkDeploymentsFailed": "Bereitstellungsnutzung konnte nicht überprüft werden. Versuchen Sie es später erneut.",
- "versions.disabledReason.checkingDeployments": "Bereitstellungsnutzung wird überprüft",
- "versions.disabledReason.current": "Dieses Release läuft bereits in {{name}}",
- "versions.disabledReason.deploying": "Warten Sie, bis die aktive Bereitstellung abgeschlossen ist",
- "versions.disabledReason.releaseInUse_one": "Heben Sie die Bereitstellung dieses Releases aus {{count}} Umgebung auf, bevor Sie es löschen",
- "versions.disabledReason.releaseInUse_other": "Heben Sie die Bereitstellung dieses Releases aus {{count}} Umgebungen auf, bevor Sie es löschen",
- "versions.dslReadFailed": "Die DSL-Datei konnte nicht gelesen werden. Wählen Sie eine andere Datei und versuchen Sie es erneut.",
- "versions.dslReading": "DSL-Datei wird gelesen...",
- "versions.dslUnsupportedMode": "Nur Workflow-DSL-Dateien können für Bereitstellungen verwendet werden.",
- "versions.editFailed": "Release konnte nicht aktualisiert werden.",
- "versions.editRelease": "Release bearbeiten",
- "versions.editReleaseDescription": "Aktualisieren Sie den Namen und die Beschreibung dieses Releases.",
- "versions.editSuccess": "Release \"{{name}}\" aktualisiert.",
- "versions.emptyDescription": "Erstellen Sie das erste Release, bevor Sie in einer Umgebung bereitstellen.",
- "versions.emptyTitle": "Noch keine Releases",
- "versions.exportDsl": "DSL exportieren",
- "versions.exportDslFailed": "DSL konnte nicht exportiert werden.",
- "versions.exportingDsl": "Wird exportiert...",
- "versions.groupHeader.deploy": "Bereitstellen",
- "versions.groupHeader.rollback": "Vorherige Version bereitstellen",
- "versions.groupHeader.unavailable": "Nicht verfügbar",
- "versions.manualDslOption": "DSL hochladen",
- "versions.moreActions": "Weitere Aktionen",
- "versions.optional": "Optional",
- "versions.releaseAlreadyExists": "Ein Release mit demselben Inhalt existiert bereits: {{name}}.",
- "versions.releaseContentCheckFailed": "Release-Inhalt konnte nicht überprüft werden.",
- "versions.releaseDescriptionLabel": "Beschreibung",
- "versions.releaseDescriptionPlaceholder": "Beschreiben Sie dieses Release",
- "versions.releaseNameConflict": "Ein Release mit diesem Namen existiert bereits. Wählen Sie einen anderen Namen.",
- "versions.releaseNameLabel": "Release-Name",
- "versions.releaseNamePlaceholder": "Release-Name",
- "versions.releaseNameRequired": "Geben Sie einen Release-Namen ein.",
- "versions.releaseSourceLabel": "Release-Quelle",
- "versions.rollbackTo": "In {{name}} bereitstellen",
- "versions.saveEdit": "Speichern",
- "versions.sourceAppOption": "Workflow-App"
+ "versions.deployTo": "In {{name}} bereitstellen"
}
diff --git a/web/i18n/en-US/common.json b/web/i18n/en-US/common.json
index 77b5e37dd28..21147db1868 100644
--- a/web/i18n/en-US/common.json
+++ b/web/i18n/en-US/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "App Detail",
"menus.apps": "Studio",
"menus.datasets": "Knowledge",
- "menus.deployments": "Deployments",
"menus.exploreMarketplace": "Explore Marketplace",
"menus.plugins": "Integrations",
"menus.status": "beta",
diff --git a/web/i18n/en-US/deployments.json b/web/i18n/en-US/deployments.json
index 30478b1d8db..9c9a5335956 100644
--- a/web/i18n/en-US/deployments.json
+++ b/web/i18n/en-US/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copy cURL example",
- "access.api.createFailed": "Failed to generate API Token.",
- "access.api.createKey": "Generate API Token",
- "access.api.createKeyTitle": "Generate new API Token",
- "access.api.curlExampleTitle": "cURL example",
- "access.api.description": "Access this deployment over HTTP. Each API Token is scoped to one environment.",
- "access.api.developerTitle": "Developer API",
- "access.api.disabled": "API access is turned off for this deployment.",
- "access.api.disabledHint": "Enable API access to generate environment-scoped tokens.",
- "access.api.docs": "API Docs",
- "access.api.docsClose": "Close API docs",
- "access.api.docsDescription": "View the Workflow API reference for this deployment.",
- "access.api.docsTitle": "Workflow API documentation",
- "access.api.empty": "Deploy to an environment first to start issuing API Tokens.",
- "access.api.emptyTitle": "No deployed environments",
- "access.api.endpoint": "Request URL",
- "access.api.keyList": "API Token list",
- "access.api.nameLabel": "API Token name",
- "access.api.namePlaceholder": "Enter an API Token name",
- "access.api.nameRequired": "API Token name is required.",
- "access.api.newKey": "Generate New API Token",
- "access.api.newTokenDescription": "This API Token is shown only once. Copy it before leaving this page.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token generated",
- "access.api.noKeys": "No API Tokens yet. Generate one to start calling the API.",
- "access.api.noKeysTitle": "No API Tokens yet",
- "access.api.revokeConfirmDescription": "The API Token \"{{name}}\" will stop working immediately. This action cannot be undone.",
- "access.api.revokeConfirmTitle": "Revoke API Token?",
- "access.api.revokeFailed": "Failed to revoke API Token.",
- "access.api.revokeSuccess": "API Token revoked",
- "access.api.table.action": "Action",
- "access.api.table.environment": "Environment",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Name",
- "access.channels.disabled": "Access channels are turned off for this deployment.",
- "access.channels.disabledHint": "Enable access channels to expose WebApp and CLI entry points.",
- "access.channels.title": "Access channels",
- "access.cli.description": "Invoke from the terminal with difyctl, suitable for scripts, automated workflows, or Agent integrations.",
- "access.cli.docs": "Usage guide",
- "access.cli.domain": "Domain",
- "access.cli.empty": "CLI endpoint not configured.",
- "access.cli.install": "Install CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copy",
- "access.copyFailed": "Copy failed",
- "access.members.groupCount_one": "{{count}} group",
- "access.members.groupCount_other": "{{count}} groups",
- "access.members.memberCount_one": "{{count}} member",
- "access.members.memberCount_other": "{{count}} members",
- "access.permission.anyone": "Anyone with the link",
- "access.permission.organization": "All members within the platform",
- "access.permission.specific": "Specific members within the platform",
- "access.permission.specificDesc": "Select specific groups or members",
- "access.permission.updateFailed": "Failed to update access policy.",
- "access.permissions.editAriaLabel": "Configure access for {{environment}}",
- "access.permissions.editDescription": "Set access permissions for WebApp and CLI entry points.",
- "access.permissions.editTitle": "Access permissions",
- "access.permissions.title": "Access permissions",
- "access.revoke": "Revoke",
- "access.runAccess.noEnvs": "Deploy to an environment to configure access permissions.",
- "access.runAccess.noEnvsTitle": "No deployed environments",
- "access.runAccess.openWebapp": "Open WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Hosted web page for end users.",
- "access.runAccess.webappEmpty": "Coming soon.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "External",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Unknown",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "No access",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Create First Release",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Delete deployment",
- "card.menu.deploy": "Deploy to Environment",
- "card.menu.editInfo": "Edit Info",
- "card.moreActions": "More actions",
- "card.noDescription": "No description provided.",
"card.notDeployed": "Not deployed",
- "card.tooltip.createdAt": "Created",
- "card.tooltip.deployed": "Deployed",
- "card.tooltip.deploymentStatus": "Deployment",
- "card.tooltip.notDeployedShort": "Not deployed",
- "card.tooltip.releaseName": "Release Name",
- "card.tooltip.source": "Source",
"common.loadFailed": "Failed to load. Try again later.",
- "createGuide.actions.back": "Back",
- "createGuide.actions.createAndDeploy": "Create & Deploy",
- "createGuide.actions.creating": "Creating...",
- "createGuide.actions.deploying": "Creating & deploying...",
- "createGuide.actions.next": "Next",
- "createGuide.actions.skipDeploy": "Skip, deploy later",
- "createGuide.dsl.defaultAppName": "Imported DSL app",
- "createGuide.dsl.description": "Upload a Workflow DSL package to create the deployment, first release, and optional environment deployment.",
- "createGuide.dsl.dropDescription": "Upload a Workflow YAML DSL package. Deployment options are resolved from this file before deploy.",
- "createGuide.dsl.dropTitle": "Upload Workflow DSL package",
- "createGuide.dsl.readFailed": "Failed to read the DSL file. Choose another file and try again.",
- "createGuide.dsl.reading": "Reading DSL file...",
- "createGuide.dsl.title": "Import DSL",
- "createGuide.dsl.unsupportedMode": "Only Workflow DSL files can be used for deployments.",
- "createGuide.errors.createReleaseFailed": "Failed to create the deployment or release.",
- "createGuide.errors.deployFailed": "Failed to deploy to the environment.",
- "createGuide.method.description": "Choose the source used to create the first release.",
- "createGuide.methods.bindApp.description": "Use an existing Workflow App in Studio as the release source.",
- "createGuide.methods.bindApp.title": "Bind existing Workflow App",
- "createGuide.methods.importDsl.description": "Upload a Workflow YAML DSL package and continue through the deployment UI.",
- "createGuide.methods.importDsl.title": "Import DSL",
- "createGuide.nav.back": "Deployments",
- "createGuide.release.defaultName": "initial release",
- "createGuide.release.deployInfo": "Deployment Info",
- "createGuide.release.description": "Fill in deployment info and first release details.",
- "createGuide.release.firstVersion": "First Release",
- "createGuide.release.instanceDescription": "Deployment Description",
- "createGuide.release.instanceDescriptionPlaceholder": "Describe what this deployment is used for",
- "createGuide.release.instanceName": "Deployment Name",
- "createGuide.release.instanceNameConflict": "A deployment with this name already exists. Choose another name.",
- "createGuide.release.releaseDescription": "Release Description",
- "createGuide.release.releaseDescriptionPlaceholder": "Describe this release",
- "createGuide.release.releaseName": "Release Name",
- "createGuide.release.title": "Basic Info",
- "createGuide.source.clearSearch": "Clear app search",
- "createGuide.source.description": "Choose the source used to create the first release.",
- "createGuide.source.empty": "No Workflow Apps found.",
- "createGuide.source.searchPlaceholder": "Search apps",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Release Source",
- "createGuide.steps.method": "Release Source",
- "createGuide.steps.release": "Basic Info",
- "createGuide.steps.source": "Release Source",
- "createGuide.steps.target": "Deploy to Environment",
- "createGuide.target.bindingCount_one": "{{count}} binding",
- "createGuide.target.bindingCount_other": "{{count}} bindings",
- "createGuide.target.bindingHint": "Pick the credentials used by this release.",
- "createGuide.target.bindings": "Credentials",
- "createGuide.target.description": "Choose a target environment and provide the runtime settings this release needs there. This step can be skipped.",
- "createGuide.target.envVarCount_one": "{{count}} variable",
- "createGuide.target.envVarCount_other": "{{count}} variables",
- "createGuide.target.envVarHint": "For each environment variable this release needs, enter a custom value or use the value defined in the app.",
- "createGuide.target.envVarPlaceholder": "Enter value",
- "createGuide.target.envVarSource.ariaLabel": "Select the variable value source for {{key}}",
- "createGuide.target.envVarSource.default": "App value",
- "createGuide.target.envVarSource.lastDeployment": "Last deployed value",
- "createGuide.target.envVarSource.literal": "Custom value",
- "createGuide.target.envVarType.number": "Number",
- "createGuide.target.envVarType.secret": "Secret",
- "createGuide.target.envVarType.string": "String",
- "createGuide.target.envVars": "Environment Variables",
- "createGuide.target.environment": "Target Environment",
- "createGuide.target.loadBindingsFailed": "Failed to load credentials.",
- "createGuide.target.loadEnvironmentsFailed": "Failed to load deploy environments.",
- "createGuide.target.missingRequiredBinding": "Select a credential for this required binding.",
- "createGuide.target.noBindingRequired": "No credentials required.",
- "createGuide.target.noCredentialCandidates": "No available credentials.",
- "createGuide.target.noEnvironmentOptions": "No deploy environments available.",
- "createGuide.target.selectCredential": "Select a credential",
- "createGuide.target.title": "Deploy to Environment",
- "createGuide.title": "New Deployment",
- "createModal.appPickerPlaceholder": "Select a Workflow App",
- "createModal.appSearchEmpty": "No matching Workflow Apps",
- "createModal.appSearchPlaceholder": "Search Workflow Apps…",
- "createModal.cancel": "Cancel",
- "createModal.loadingApps": "Loading apps…",
- "deployDrawer.bindingCount_one": "{{count}} binding",
- "deployDrawer.bindingCount_other": "{{count}} bindings",
"deployDrawer.bindingOptionsFailed": "Failed to load credential options.",
"deployDrawer.bindingSelectionHint": "Choose the credentials used by this deployment.",
- "deployDrawer.cancel": "Cancel",
- "deployDrawer.close": "Close deployment drawer",
- "deployDrawer.defaultSelect": "Select...",
- "deployDrawer.deploy": "Deploy to Environment",
- "deployDrawer.deployFailed": "Failed to start deployment.",
"deployDrawer.deploying": "Deploying...",
- "deployDrawer.description": "Select a release and target environment to deploy.",
- "deployDrawer.envVarCount_one": "{{count}} variable",
- "deployDrawer.envVarCount_other": "{{count}} variables",
- "deployDrawer.envVarHint": "For each environment variable this release needs, enter a custom value or use the value defined in the app.",
- "deployDrawer.envVarPlaceholder": "Enter value",
"deployDrawer.envVarSource.ariaLabel": "Select the variable value source for {{key}}",
- "deployDrawer.envVarSource.default": "App value",
"deployDrawer.envVarSource.lastDeployment": "Last deployed value",
"deployDrawer.envVarSource.literal": "Custom value",
"deployDrawer.envVarType.number": "Number",
"deployDrawer.envVarType.secret": "Secret",
"deployDrawer.envVarType.string": "String",
"deployDrawer.envVars": "Environment Variables",
- "deployDrawer.existingReleaseHint": "This release will be deployed as-is. No new release will be created.",
- "deployDrawer.lockedHint": "Locked to current environment",
- "deployDrawer.missingRequiredBinding": "Select a credential for this required binding.",
- "deployDrawer.missingRequiredEnvVar": "Enter a value for this required environment variable.",
- "deployDrawer.noBindingRequired": "Not required",
"deployDrawer.noCredentialCandidates": "No available credentials.",
"deployDrawer.noNewEnvironmentAvailable": "All available environments already have a deployment.",
- "deployDrawer.noOtherReleaseAvailable": "No other releases are available for this environment.",
- "deployDrawer.noReleaseAvailable": "Create a release before deploying to an environment.",
- "deployDrawer.notFound": "Deployment not found.",
- "deployDrawer.releaseLabel": "Release",
"deployDrawer.runtimeCredentials": "Credentials",
"deployDrawer.selectCredential": "Select a credential",
- "deployDrawer.selectEnv": "Select an environment",
- "deployDrawer.selectRelease": "Select a release",
- "deployDrawer.targetEnv": "Target Environment",
- "deployDrawer.title": "Deploy to Environment",
- "deployTab.closeError": "Close",
"deployTab.col.actions": "Actions",
- "deployTab.col.currentRelease": "Current Release",
"deployTab.col.environment": "Environment",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Undeploy",
- "deployTab.deployOtherVersion": "Deploy Another Release",
- "deployTab.emptyDescription": "Choose a release and target environment to make this deployment available to users.",
- "deployTab.emptyTitle": "No environments are running yet",
- "deployTab.errorCode": "Code",
- "deployTab.errorDialogDesc": "Review the last failed deployment before retrying or deploying another release.",
- "deployTab.errorDialogTitle": "Deployment error in {{name}}",
- "deployTab.errorMessage": "Message",
- "deployTab.errorPhase": "Phase",
"deployTab.moreActions": "More actions",
- "deployTab.newDeployment": "Deploy to New Environment",
- "deployTab.panel.unknownError": "Deployment failed.",
"deployTab.redeploy": "Redeploy",
- "deployTab.retry": "Retry",
- "deployTab.status.deployFailed": "Deploy failed",
- "deployTab.status.deployingRelease": "Deploying ({{release}})",
- "deployTab.status.runningOutOfSync": "Running (sync pending)",
- "deployTab.status.runningWithFailed": "Running (last deployment failed)",
"deployTab.undeploy": "Undeploy",
- "deployTab.undeployConfirmDesc": "The environment endpoint will become unavailable, but the version will not be deleted.",
- "deployTab.undeployConfirmTitle": "Undeploy {{name}}?",
"deployTab.undeployConfirmWarning": "After confirmation, this environment will enter the undeploying state and actions will be temporarily disabled.",
- "deployTab.viewError": "View error",
- "detail.mobileTabs": "Deployment sections",
- "detail.notFound": "Deployment not found",
- "documentTitle.create": "New deployment · Deployments",
- "documentTitle.detail": "Deployment · Deployments",
- "documentTitle.list": "Deployments",
- "filter.allEnvs": "All environments",
- "filter.searchPlaceholder": "Search deployments",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Admission",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Bootstrapping",
- "health.ENVIRONMENT_STATUS_DELETING": "Deleting",
"health.ENVIRONMENT_STATUS_FAILED": "Unavailable",
- "health.ENVIRONMENT_STATUS_READY": "Available",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Unknown",
- "list.clearFilters": "Clear filters",
- "list.clearSearch": "Clear deployment search",
- "list.createDeployment": "New",
- "list.emptyDescription": "Create a deployment from a Workflow App or Workflow DSL package to manage releases, environments, and access.",
- "list.emptyFilteredDescription": "No deployment matches the current search or environment filter.",
- "list.emptyFilteredTitle": "No matching deployments",
"list.emptyTitle": "No deployments yet",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Isolated",
- "mode.ENVIRONMENT_MODE_SHARED": "Shared",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Unknown",
- "overview.accessMeta.apiTokens": "Manage API Tokens",
- "overview.accessMeta.cli": "View CLI access",
- "overview.accessMeta.webApp": "Manage WebApp access",
- "overview.accessStatus": "Access",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} deployed environment",
- "overview.apiTokenSummary.environments_other": "{{count}} deployed environments",
- "overview.cardAction.deployLatest": "Deploy Latest Release",
- "overview.cardAction.redeploy": "Redeploy",
- "overview.cardAction.viewProgress": "View deployment",
- "overview.chip.behindTooltip_one": "1 release behind latest. Deploy the latest release to update.",
- "overview.chip.behindTooltip_other": "{{count}} releases behind latest. Deploy the latest release to update.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "deploying",
- "overview.chip.deployingTooltip": "Deployment is in progress.",
- "overview.chip.empty": "empty",
- "overview.chip.emptyTooltip": "No release is deployed to this environment.",
- "overview.chip.failed": "failed",
- "overview.chip.failedTooltip": "The latest deployment attempt failed.",
"overview.chip.latest": "latest",
- "overview.chip.latestTooltip": "This environment is running the latest release.",
- "overview.chip.needsReleaseFirst": "Create a Release first",
- "overview.chip.olderRelease": "older",
- "overview.chip.olderReleaseTooltip": "This environment is running an older release.",
- "overview.chip.openInDeployTab": "View deployment progress",
- "overview.disabled": "Disabled",
- "overview.enabled": "Enabled",
- "overview.hero.byName": "by {{name}}",
- "overview.hero.empty": "No releases yet",
- "overview.hero.emptyDescription": "Create a release from the current source before deploying.",
- "overview.latestRelease.releaseCount_one": "{{count}} release",
- "overview.latestRelease.releaseCount_other": "{{count}} releases",
- "overview.latestReleaseTitle": "Latest Release",
- "overview.previousReleases.viewAll": "View All",
- "overview.strip.deployToNewEnvironment": "Deploy to new environment",
- "overview.strip.emptyDeployableDescription": "Deploy the latest release to an environment when you're ready.",
- "overview.strip.emptyDescription": "Create a release before deploying to an environment.",
- "overview.strip.emptyTitle": "No instances yet",
- "overview.strip.title": "Instances",
- "settings.delete": "Delete Deployment",
- "settings.deleteConfirmDesc": "Delete {{name}}? Every instance will stop running and be removed across all environments. This can't be undone.",
- "settings.deleteConfirmTitle": "Delete deployment",
- "settings.deleteFailed": "Failed to delete deployment.",
- "settings.deleted": "Deployment deleted",
- "settings.description": "Description",
- "settings.name": "Deployment name",
- "settings.save": "Save Changes",
- "settings.updateFailed": "Failed to update deployment.",
- "settings.updated": "Deployment updated",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Deploying",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sync pending",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Deploy failed",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Invalid",
"status.RUNTIME_INSTANCE_STATUS_READY": "Running",
@@ -370,87 +89,6 @@
"studio.versionValue": "Version value",
"studio.versionsBehind_one": "{{count}} version behind",
"studio.versionsBehind_other": "{{count}} versions behind",
- "tabs.access.description": "Manage access channels and access permissions.",
- "tabs.access.name": "Access",
- "tabs.api-tokens.description": "Manage API Tokens and invoke instances over HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "View and manage instances in deployed environments.",
- "tabs.instances.name": "Instances",
- "tabs.overview.description": "See the deployment's status across environments.",
- "tabs.overview.name": "Overview",
- "tabs.releases.description": "Create, deploy, and manage releases.",
- "tabs.releases.name": "Releases",
- "unsupportedDslNodes.description": "This release contains nodes that the deployment runtime does not support yet. Remove or replace them in Studio, then try again.",
- "unsupportedDslNodes.descriptionWithTypes": "This release contains nodes that the deployment runtime does not support yet: {{nodeTypes}}. Remove or replace them in Studio, then try again.",
- "unsupportedDslNodes.title": "Unsupported nodes",
- "unsupportedDslNodes.unknownType": "Unknown type",
- "versions.cancelCreate": "Cancel",
- "versions.cancelDelete": "Cancel",
- "versions.cancelEdit": "Cancel",
"versions.checkingReleaseContent": "Checking release content...",
- "versions.col.action": "Action",
- "versions.col.author": "Created by",
- "versions.col.createdAt": "Created at",
- "versions.col.deployedTo": "Deployed to",
- "versions.col.release": "Release",
- "versions.col.sourceApp": "Source",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Create",
- "versions.createFailed": "Failed to create release.",
- "versions.createRelease": "Create Release",
- "versions.createReleaseDescription": "Create a deployable release from a Workflow App or Workflow DSL file.",
- "versions.createSuccess": "Release \"{{name}}\" created.",
- "versions.creating": "Creating...",
- "versions.currentOn": "Current Release on {{name}}",
- "versions.deleteConfirmDesc": "Release \"{{name}}\" will be permanently deleted. This can't be undone.",
- "versions.deleteConfirmTitle": "Delete release?",
- "versions.deleteFailed": "Failed to delete release.",
- "versions.deleteRelease": "Delete Release",
- "versions.deleteSuccess": "Release \"{{name}}\" deleted.",
- "versions.deployTo": "Deploy to {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Deploying",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sync pending",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Failed",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Invalid",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Running",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Not deployed",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Undeploying",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Unknown",
- "versions.deployingTo": "{{name}} is deploying",
- "versions.disabledReason.checkDeploymentsFailed": "Could not verify deployment usage. Try again later.",
- "versions.disabledReason.checkingDeployments": "Checking deployment usage",
- "versions.disabledReason.current": "This release is already running on {{name}}",
- "versions.disabledReason.deploying": "Wait for the active deployment to finish",
- "versions.disabledReason.releaseInUse_one": "Undeploy this release from {{count}} environment before deleting it",
- "versions.disabledReason.releaseInUse_other": "Undeploy this release from {{count}} environments before deleting it",
- "versions.dslReadFailed": "Failed to read the DSL file. Choose another file and try again.",
- "versions.dslReading": "Reading DSL file...",
- "versions.dslUnsupportedMode": "Only Workflow DSL files can be used for deployments.",
- "versions.editFailed": "Failed to update release.",
- "versions.editRelease": "Edit Release",
- "versions.editReleaseDescription": "Update this release's name and description.",
- "versions.editSuccess": "Release \"{{name}}\" updated.",
- "versions.emptyDescription": "Create the first release before deploying to an environment.",
- "versions.emptyTitle": "No releases yet",
- "versions.exportDsl": "Export DSL",
- "versions.exportDslFailed": "Failed to export DSL.",
- "versions.exportingDsl": "Exporting...",
- "versions.groupHeader.deploy": "Deploy",
- "versions.groupHeader.rollback": "Deploy previous version",
- "versions.groupHeader.unavailable": "Unavailable",
- "versions.manualDslOption": "Upload DSL",
- "versions.moreActions": "More actions",
- "versions.optional": "Optional",
- "versions.releaseAlreadyExists": "A release with the same content already exists: {{name}}.",
- "versions.releaseContentCheckFailed": "Failed to check release content.",
- "versions.releaseDescriptionLabel": "Description",
- "versions.releaseDescriptionPlaceholder": "Describe this release",
- "versions.releaseNameConflict": "A release with this name already exists. Choose another name.",
- "versions.releaseNameLabel": "Release Name",
- "versions.releaseNamePlaceholder": "Release Name",
- "versions.releaseNameRequired": "Enter a release name.",
- "versions.releaseSourceLabel": "Release Source",
- "versions.rollbackTo": "Deploy to {{name}}",
- "versions.saveEdit": "Save",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "Deploy to {{name}}"
}
diff --git a/web/i18n/es-ES/common.json b/web/i18n/es-ES/common.json
index 5a51f7c4158..c3fdf9fca81 100644
--- a/web/i18n/es-ES/common.json
+++ b/web/i18n/es-ES/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Detalles de la aplicación",
"menus.apps": "Estudio",
"menus.datasets": "Conocimiento",
- "menus.deployments": "Despliegues",
"menus.exploreMarketplace": "Explora el mercado",
"menus.plugins": "Integraciones",
"menus.status": "beta",
diff --git a/web/i18n/es-ES/deployments.json b/web/i18n/es-ES/deployments.json
index 01a2c2f815d..1bf59d5544d 100644
--- a/web/i18n/es-ES/deployments.json
+++ b/web/i18n/es-ES/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copiar ejemplo cURL",
- "access.api.createFailed": "Error al generar el API Token.",
- "access.api.createKey": "Generar API Token",
- "access.api.createKeyTitle": "Generar nuevo API Token",
- "access.api.curlExampleTitle": "Ejemplo cURL",
- "access.api.description": "Accede a este despliegue mediante HTTP. Cada API Token está limitado a un único entorno.",
- "access.api.developerTitle": "API de desarrollador",
- "access.api.disabled": "El acceso a la API está desactivado para este despliegue.",
- "access.api.disabledHint": "Activa el acceso a la API para generar tokens limitados a un entorno.",
- "access.api.docs": "Documentación de la API",
- "access.api.docsClose": "Cerrar documentación de la API",
- "access.api.docsDescription": "Consulta la referencia de la API de Workflow para este despliegue.",
- "access.api.docsTitle": "Documentación de la API de Workflow",
- "access.api.empty": "Despliega primero a un entorno para empezar a emitir API Tokens.",
- "access.api.emptyTitle": "No hay entornos desplegados",
- "access.api.endpoint": "URL de la solicitud",
- "access.api.keyList": "Lista de API Tokens",
- "access.api.nameLabel": "Nombre del API Token",
- "access.api.namePlaceholder": "Introduce un nombre para el API Token",
- "access.api.nameRequired": "El nombre del API Token es obligatorio.",
- "access.api.newKey": "Generar nuevo API Token",
- "access.api.newTokenDescription": "Este API Token se muestra solo una vez. Cópialo antes de salir de esta página.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token generado",
- "access.api.noKeys": "Aún no hay API Tokens. Genera uno para empezar a llamar a la API.",
- "access.api.noKeysTitle": "Aún no hay API Tokens",
- "access.api.revokeConfirmDescription": "El API Token \"{{name}}\" dejará de funcionar inmediatamente. Esta acción no se puede deshacer.",
- "access.api.revokeConfirmTitle": "¿Revocar API Token?",
- "access.api.revokeFailed": "Error al revocar el API Token.",
- "access.api.revokeSuccess": "API Token revocado",
- "access.api.table.action": "Acción",
- "access.api.table.environment": "Entorno",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Nombre",
- "access.channels.disabled": "Los canales de acceso están desactivados para este despliegue.",
- "access.channels.disabledHint": "Activa los canales de acceso para exponer los puntos de entrada de WebApp y CLI.",
- "access.channels.title": "Canales de acceso",
- "access.cli.description": "Invócalo desde la terminal con difyctl, adecuado para scripts, flujos automatizados o integraciones con Agentes.",
- "access.cli.docs": "Guía de uso",
- "access.cli.domain": "Dominio",
- "access.cli.empty": "Endpoint de CLI no configurado.",
- "access.cli.install": "Instalar CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copiar",
- "access.copyFailed": "Error al copiar",
- "access.members.groupCount_one": "{{count}} grupo",
- "access.members.groupCount_other": "{{count}} grupos",
- "access.members.memberCount_one": "{{count}} miembro",
- "access.members.memberCount_other": "{{count}} miembros",
- "access.permission.anyone": "Cualquiera con el enlace",
- "access.permission.organization": "Todos los miembros de la plataforma",
- "access.permission.specific": "Miembros específicos de la plataforma",
- "access.permission.specificDesc": "Selecciona grupos o miembros específicos",
- "access.permission.updateFailed": "Error al actualizar la política de acceso.",
- "access.permissions.editAriaLabel": "Configurar acceso para {{environment}}",
- "access.permissions.editDescription": "Define los permisos de acceso para los puntos de entrada de WebApp y CLI.",
- "access.permissions.editTitle": "Permisos de acceso",
- "access.permissions.title": "Permisos de acceso",
- "access.revoke": "Revocar",
- "access.runAccess.noEnvs": "Despliega a un entorno para configurar los permisos de acceso.",
- "access.runAccess.noEnvsTitle": "No hay entornos desplegados",
- "access.runAccess.openWebapp": "Abrir WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Página web alojada para usuarios finales.",
- "access.runAccess.webappEmpty": "Próximamente.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Externo",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Desconocido",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Sin acceso",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Crear primera versión",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Eliminar despliegue",
- "card.menu.deploy": "Desplegar a un entorno",
- "card.menu.editInfo": "Editar información",
- "card.moreActions": "Más acciones",
- "card.noDescription": "Sin descripción.",
"card.notDeployed": "No desplegado",
- "card.tooltip.createdAt": "Creado",
- "card.tooltip.deployed": "Desplegado",
- "card.tooltip.deploymentStatus": "Despliegue",
- "card.tooltip.notDeployedShort": "No desplegado",
- "card.tooltip.releaseName": "Nombre de la versión",
- "card.tooltip.source": "Origen",
"common.loadFailed": "Error al cargar. Inténtalo de nuevo más tarde.",
- "createGuide.actions.back": "Atrás",
- "createGuide.actions.createAndDeploy": "Crear y desplegar",
- "createGuide.actions.creating": "Creando...",
- "createGuide.actions.deploying": "Creando y desplegando...",
- "createGuide.actions.next": "Siguiente",
- "createGuide.actions.skipDeploy": "Omitir, desplegar después",
- "createGuide.dsl.defaultAppName": "App DSL importada",
- "createGuide.dsl.description": "Sube un paquete DSL de Workflow para crear el despliegue, la primera versión y, opcionalmente, el despliegue al entorno.",
- "createGuide.dsl.dropDescription": "Sube un paquete DSL YAML de Workflow. Las opciones de despliegue se resuelven a partir de este archivo antes de desplegar.",
- "createGuide.dsl.dropTitle": "Subir paquete DSL de Workflow",
- "createGuide.dsl.readFailed": "Error al leer el archivo DSL. Elige otro archivo e inténtalo de nuevo.",
- "createGuide.dsl.reading": "Leyendo el archivo DSL...",
- "createGuide.dsl.title": "Importar DSL",
- "createGuide.dsl.unsupportedMode": "Solo se pueden usar archivos DSL de Workflow para los despliegues.",
- "createGuide.errors.createReleaseFailed": "Error al crear el despliegue o la versión.",
- "createGuide.errors.deployFailed": "Error al desplegar al entorno.",
- "createGuide.method.description": "Elige el origen utilizado para crear la primera versión.",
- "createGuide.methods.bindApp.description": "Usa una Workflow App existente en Studio como origen de la versión.",
- "createGuide.methods.bindApp.title": "Vincular una Workflow App existente",
- "createGuide.methods.importDsl.description": "Sube un paquete DSL YAML de Workflow y continúa por la interfaz de despliegue.",
- "createGuide.methods.importDsl.title": "Importar DSL",
- "createGuide.nav.back": "Despliegues",
- "createGuide.release.defaultName": "versión inicial",
- "createGuide.release.deployInfo": "Información del despliegue",
- "createGuide.release.description": "Completa la información del despliegue y los detalles de la primera versión.",
- "createGuide.release.firstVersion": "Primera versión",
- "createGuide.release.instanceDescription": "Descripción del despliegue",
- "createGuide.release.instanceDescriptionPlaceholder": "Describe para qué se usa este despliegue",
- "createGuide.release.instanceName": "Nombre del despliegue",
- "createGuide.release.instanceNameConflict": "Ya existe un despliegue con este nombre. Elige otro nombre.",
- "createGuide.release.releaseDescription": "Descripción de la versión",
- "createGuide.release.releaseDescriptionPlaceholder": "Describe esta versión",
- "createGuide.release.releaseName": "Nombre de la versión",
- "createGuide.release.title": "Información básica",
- "createGuide.source.clearSearch": "Borrar búsqueda de apps",
- "createGuide.source.description": "Elige el origen utilizado para crear la primera versión.",
- "createGuide.source.empty": "No se encontraron Workflow Apps.",
- "createGuide.source.searchPlaceholder": "Buscar apps",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Origen de la versión",
- "createGuide.steps.method": "Origen de la versión",
- "createGuide.steps.release": "Información básica",
- "createGuide.steps.source": "Origen de la versión",
- "createGuide.steps.target": "Desplegar a un entorno",
- "createGuide.target.bindingCount_one": "{{count}} credencial",
- "createGuide.target.bindingCount_other": "{{count}} credenciales",
- "createGuide.target.bindingHint": "Elige las credenciales que usará esta versión.",
- "createGuide.target.bindings": "Credenciales",
- "createGuide.target.description": "Elige un entorno de destino y proporciona los ajustes de ejecución que esta versión necesita allí. Este paso se puede omitir.",
- "createGuide.target.envVarCount_one": "{{count}} variable",
- "createGuide.target.envVarCount_other": "{{count}} variables",
- "createGuide.target.envVarHint": "Para cada variable de entorno que necesite esta versión, introduce un valor personalizado o usa el valor definido en la app.",
- "createGuide.target.envVarPlaceholder": "Introduce un valor",
- "createGuide.target.envVarSource.ariaLabel": "Selecciona el origen del valor de la variable para {{key}}",
- "createGuide.target.envVarSource.default": "Valor de la app",
- "createGuide.target.envVarSource.lastDeployment": "Último valor desplegado",
- "createGuide.target.envVarSource.literal": "Valor personalizado",
- "createGuide.target.envVarType.number": "Número",
- "createGuide.target.envVarType.secret": "Secreto",
- "createGuide.target.envVarType.string": "Cadena",
- "createGuide.target.envVars": "Variables de entorno",
- "createGuide.target.environment": "Entorno de destino",
- "createGuide.target.loadBindingsFailed": "Error al cargar las credenciales.",
- "createGuide.target.loadEnvironmentsFailed": "Error al cargar los entornos de despliegue.",
- "createGuide.target.missingRequiredBinding": "Selecciona una credencial para esta vinculación obligatoria.",
- "createGuide.target.noBindingRequired": "No se requieren credenciales.",
- "createGuide.target.noCredentialCandidates": "No hay credenciales disponibles.",
- "createGuide.target.noEnvironmentOptions": "No hay entornos de despliegue disponibles.",
- "createGuide.target.selectCredential": "Selecciona una credencial",
- "createGuide.target.title": "Desplegar a un entorno",
- "createGuide.title": "Nuevo despliegue",
- "createModal.appPickerPlaceholder": "Selecciona una Workflow App",
- "createModal.appSearchEmpty": "No hay Workflow Apps coincidentes",
- "createModal.appSearchPlaceholder": "Buscar Workflow Apps…",
- "createModal.cancel": "Cancelar",
- "createModal.loadingApps": "Cargando apps…",
- "deployDrawer.bindingCount_one": "{{count}} credencial",
- "deployDrawer.bindingCount_other": "{{count}} credenciales",
"deployDrawer.bindingOptionsFailed": "Error al cargar las opciones de credenciales.",
"deployDrawer.bindingSelectionHint": "Elige las credenciales utilizadas por este despliegue.",
- "deployDrawer.cancel": "Cancelar",
- "deployDrawer.close": "Cerrar panel de despliegue",
- "deployDrawer.defaultSelect": "Seleccionar...",
- "deployDrawer.deploy": "Desplegar a un entorno",
- "deployDrawer.deployFailed": "Error al iniciar el despliegue.",
"deployDrawer.deploying": "Desplegando...",
- "deployDrawer.description": "Selecciona una versión y un entorno de destino para desplegar.",
- "deployDrawer.envVarCount_one": "{{count}} variable",
- "deployDrawer.envVarCount_other": "{{count}} variables",
- "deployDrawer.envVarHint": "Para cada variable de entorno que necesite esta versión, introduce un valor personalizado o usa el valor definido en la app.",
- "deployDrawer.envVarPlaceholder": "Introduce un valor",
"deployDrawer.envVarSource.ariaLabel": "Selecciona el origen del valor de la variable para {{key}}",
- "deployDrawer.envVarSource.default": "Valor de la app",
"deployDrawer.envVarSource.lastDeployment": "Último valor desplegado",
"deployDrawer.envVarSource.literal": "Valor personalizado",
"deployDrawer.envVarType.number": "Número",
"deployDrawer.envVarType.secret": "Secreto",
"deployDrawer.envVarType.string": "Cadena",
"deployDrawer.envVars": "Variables de entorno",
- "deployDrawer.existingReleaseHint": "Esta versión se desplegará tal cual. No se creará una nueva versión.",
- "deployDrawer.lockedHint": "Bloqueado al entorno actual",
- "deployDrawer.missingRequiredBinding": "Selecciona una credencial para esta vinculación obligatoria.",
- "deployDrawer.missingRequiredEnvVar": "Introduce un valor para esta variable de entorno obligatoria.",
- "deployDrawer.noBindingRequired": "No obligatorio",
"deployDrawer.noCredentialCandidates": "No hay credenciales disponibles.",
"deployDrawer.noNewEnvironmentAvailable": "Todos los entornos disponibles ya tienen un despliegue.",
- "deployDrawer.noOtherReleaseAvailable": "No hay otras versiones disponibles para este entorno.",
- "deployDrawer.noReleaseAvailable": "Crea una versión antes de desplegar a un entorno.",
- "deployDrawer.notFound": "Despliegue no encontrado.",
- "deployDrawer.releaseLabel": "Versión",
"deployDrawer.runtimeCredentials": "Credenciales",
"deployDrawer.selectCredential": "Selecciona una credencial",
- "deployDrawer.selectEnv": "Selecciona un entorno",
- "deployDrawer.selectRelease": "Selecciona una versión",
- "deployDrawer.targetEnv": "Entorno de destino",
- "deployDrawer.title": "Desplegar a un entorno",
- "deployTab.closeError": "Cerrar",
"deployTab.col.actions": "Acciones",
- "deployTab.col.currentRelease": "Versión actual",
"deployTab.col.environment": "Entorno",
"deployTab.col.status": "Estado",
"deployTab.confirmUndeploy": "Retirar despliegue",
- "deployTab.deployOtherVersion": "Desplegar otra versión",
- "deployTab.emptyDescription": "Elige una versión y un entorno de destino para poner este despliegue a disposición de los usuarios.",
- "deployTab.emptyTitle": "Aún no hay entornos en ejecución",
- "deployTab.errorCode": "Código",
- "deployTab.errorDialogDesc": "Revisa el último despliegue fallido antes de reintentar o desplegar otra versión.",
- "deployTab.errorDialogTitle": "Error de despliegue en {{name}}",
- "deployTab.errorMessage": "Mensaje",
- "deployTab.errorPhase": "Fase",
"deployTab.moreActions": "Más acciones",
- "deployTab.newDeployment": "Desplegar a nuevo entorno",
- "deployTab.panel.unknownError": "El despliegue ha fallado.",
"deployTab.redeploy": "Volver a desplegar",
- "deployTab.retry": "Reintentar",
- "deployTab.status.deployFailed": "Despliegue fallido",
- "deployTab.status.deployingRelease": "Desplegando ({{release}})",
- "deployTab.status.runningOutOfSync": "En ejecución (sincronización pendiente)",
- "deployTab.status.runningWithFailed": "En ejecución (último despliegue fallido)",
"deployTab.undeploy": "Retirar despliegue",
- "deployTab.undeployConfirmDesc": "El endpoint del entorno dejará de estar disponible, pero la versión no se eliminará.",
- "deployTab.undeployConfirmTitle": "¿Retirar el despliegue de {{name}}?",
"deployTab.undeployConfirmWarning": "Después de confirmar, este entorno pasará al estado de retirada y las acciones se deshabilitarán temporalmente.",
- "deployTab.viewError": "Ver error",
- "detail.mobileTabs": "Secciones del despliegue",
- "detail.notFound": "Despliegue no encontrado",
- "documentTitle.create": "Nuevo despliegue · Despliegues",
- "documentTitle.detail": "Despliegue · Despliegues",
- "documentTitle.list": "Despliegues",
- "filter.allEnvs": "Todos los entornos",
- "filter.searchPlaceholder": "Buscar despliegues",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Admisión",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Inicializando",
- "health.ENVIRONMENT_STATUS_DELETING": "Eliminando",
"health.ENVIRONMENT_STATUS_FAILED": "No disponible",
- "health.ENVIRONMENT_STATUS_READY": "Disponible",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Desconocido",
- "list.clearFilters": "Borrar filtros",
- "list.clearSearch": "Borrar búsqueda de despliegues",
- "list.createDeployment": "Nuevo",
- "list.emptyDescription": "Crea un despliegue a partir de una Workflow App o un paquete DSL de Workflow para gestionar versiones, entornos y acceso.",
- "list.emptyFilteredDescription": "Ningún despliegue coincide con la búsqueda o el filtro de entorno actuales.",
- "list.emptyFilteredTitle": "No hay despliegues coincidentes",
"list.emptyTitle": "Aún no hay despliegues",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Aislado",
- "mode.ENVIRONMENT_MODE_SHARED": "Compartido",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Desconocido",
- "overview.accessMeta.apiTokens": "Gestionar API Tokens",
- "overview.accessMeta.cli": "Ver acceso CLI",
- "overview.accessMeta.webApp": "Gestionar acceso WebApp",
- "overview.accessStatus": "Acceso",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} entorno desplegado",
- "overview.apiTokenSummary.environments_other": "{{count}} entornos desplegados",
- "overview.cardAction.deployLatest": "Desplegar última versión",
- "overview.cardAction.redeploy": "Volver a desplegar",
- "overview.cardAction.viewProgress": "Ver despliegue",
- "overview.chip.behindTooltip_one": "1 versión por detrás de la última. Despliega la última versión para actualizar.",
- "overview.chip.behindTooltip_other": "{{count}} versiones por detrás de la última. Despliega la última versión para actualizar.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "desplegándose",
- "overview.chip.deployingTooltip": "El despliegue está en curso.",
- "overview.chip.empty": "vacío",
- "overview.chip.emptyTooltip": "No hay ninguna versión desplegada en este entorno.",
- "overview.chip.failed": "fallido",
- "overview.chip.failedTooltip": "El último intento de despliegue ha fallado.",
"overview.chip.latest": "última",
- "overview.chip.latestTooltip": "Este entorno está ejecutando la última versión.",
- "overview.chip.needsReleaseFirst": "Crea primero una versión",
- "overview.chip.olderRelease": "anterior",
- "overview.chip.olderReleaseTooltip": "Este entorno está ejecutando una versión anterior.",
- "overview.chip.openInDeployTab": "Ver progreso del despliegue",
- "overview.disabled": "Desactivado",
- "overview.enabled": "Activado",
- "overview.hero.byName": "por {{name}}",
- "overview.hero.empty": "Aún no hay versiones",
- "overview.hero.emptyDescription": "Crea una versión a partir del origen actual antes de desplegar.",
- "overview.latestRelease.releaseCount_one": "{{count}} versión",
- "overview.latestRelease.releaseCount_other": "{{count}} versiones",
- "overview.latestReleaseTitle": "Última versión",
- "overview.previousReleases.viewAll": "Ver todas",
- "overview.strip.deployToNewEnvironment": "Desplegar a nuevo entorno",
- "overview.strip.emptyDeployableDescription": "Despliega la última versión a un entorno cuando estés listo.",
- "overview.strip.emptyDescription": "Crea una versión antes de desplegar a un entorno.",
- "overview.strip.emptyTitle": "Aún no hay instancias",
- "overview.strip.title": "Instancias",
- "settings.delete": "Eliminar despliegue",
- "settings.deleteConfirmDesc": "¿Eliminar {{name}}? Todas las instancias dejarán de ejecutarse y se eliminarán de todos los entornos. Esta acción no se puede deshacer.",
- "settings.deleteConfirmTitle": "Eliminar despliegue",
- "settings.deleteFailed": "Error al eliminar el despliegue.",
- "settings.deleted": "Despliegue eliminado",
- "settings.description": "Descripción",
- "settings.name": "Nombre del despliegue",
- "settings.save": "Guardar cambios",
- "settings.updateFailed": "Error al actualizar el despliegue.",
- "settings.updated": "Despliegue actualizado",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Desplegando",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronización pendiente",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Despliegue fallido",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "No válido",
"status.RUNTIME_INSTANCE_STATUS_READY": "En ejecución",
@@ -370,87 +89,6 @@
"studio.versionValue": "Valor de la versión",
"studio.versionsBehind_one": "{{count}} versión por detrás",
"studio.versionsBehind_other": "{{count}} versiones por detrás",
- "tabs.access.description": "Gestiona los canales y permisos de acceso.",
- "tabs.access.name": "Acceso",
- "tabs.api-tokens.description": "Gestiona los API Tokens e invoca instancias mediante HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "Visualiza y gestiona las instancias en los entornos desplegados.",
- "tabs.instances.name": "Instancias",
- "tabs.overview.description": "Consulta el estado del despliegue en los distintos entornos.",
- "tabs.overview.name": "Resumen",
- "tabs.releases.description": "Crea, despliega y gestiona versiones.",
- "tabs.releases.name": "Versiones",
- "unsupportedDslNodes.description": "Esta versión contiene nodos que el entorno de ejecución del despliegue aún no admite. Quítalos o reemplázalos en Studio y vuelve a intentarlo.",
- "unsupportedDslNodes.descriptionWithTypes": "Esta versión contiene nodos que el entorno de ejecución del despliegue aún no admite: {{nodeTypes}}. Quítalos o reemplázalos en Studio y vuelve a intentarlo.",
- "unsupportedDslNodes.title": "Nodos no admitidos",
- "unsupportedDslNodes.unknownType": "Tipo desconocido",
- "versions.cancelCreate": "Cancelar",
- "versions.cancelDelete": "Cancelar",
- "versions.cancelEdit": "Cancelar",
"versions.checkingReleaseContent": "Comprobando el contenido de la versión...",
- "versions.col.action": "Acción",
- "versions.col.author": "Creado por",
- "versions.col.createdAt": "Creado el",
- "versions.col.deployedTo": "Desplegado en",
- "versions.col.release": "Versión",
- "versions.col.sourceApp": "Origen",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Crear",
- "versions.createFailed": "Error al crear la versión.",
- "versions.createRelease": "Crear versión",
- "versions.createReleaseDescription": "Crea una versión desplegable a partir de una Workflow App o un archivo DSL de Workflow.",
- "versions.createSuccess": "Versión \"{{name}}\" creada.",
- "versions.creating": "Creando...",
- "versions.currentOn": "Versión actual en {{name}}",
- "versions.deleteConfirmDesc": "La versión \"{{name}}\" se eliminará permanentemente. Esta acción no se puede deshacer.",
- "versions.deleteConfirmTitle": "¿Eliminar versión?",
- "versions.deleteFailed": "Error al eliminar la versión.",
- "versions.deleteRelease": "Eliminar versión",
- "versions.deleteSuccess": "Versión \"{{name}}\" eliminada.",
- "versions.deployTo": "Desplegar a {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Desplegando",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronización pendiente",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Fallido",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "No válido",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "En ejecución",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "No desplegado",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Retirando despliegue",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Desconocido",
- "versions.deployingTo": "{{name}} se está desplegando",
- "versions.disabledReason.checkDeploymentsFailed": "No se pudo verificar el uso del despliegue. Inténtalo de nuevo más tarde.",
- "versions.disabledReason.checkingDeployments": "Comprobando el uso del despliegue",
- "versions.disabledReason.current": "Esta versión ya se está ejecutando en {{name}}",
- "versions.disabledReason.deploying": "Espera a que finalice el despliegue activo",
- "versions.disabledReason.releaseInUse_one": "Retira el despliegue de esta versión de {{count}} entorno antes de eliminarla",
- "versions.disabledReason.releaseInUse_other": "Retira el despliegue de esta versión de {{count}} entornos antes de eliminarla",
- "versions.dslReadFailed": "Error al leer el archivo DSL. Elige otro archivo e inténtalo de nuevo.",
- "versions.dslReading": "Leyendo el archivo DSL...",
- "versions.dslUnsupportedMode": "Solo se pueden usar archivos DSL de Workflow para los despliegues.",
- "versions.editFailed": "Error al actualizar la versión.",
- "versions.editRelease": "Editar versión",
- "versions.editReleaseDescription": "Actualiza el nombre y la descripción de esta versión.",
- "versions.editSuccess": "Versión \"{{name}}\" actualizada.",
- "versions.emptyDescription": "Crea la primera versión antes de desplegar a un entorno.",
- "versions.emptyTitle": "Aún no hay versiones",
- "versions.exportDsl": "Exportar DSL",
- "versions.exportDslFailed": "Error al exportar el DSL.",
- "versions.exportingDsl": "Exportando...",
- "versions.groupHeader.deploy": "Desplegar",
- "versions.groupHeader.rollback": "Desplegar versión anterior",
- "versions.groupHeader.unavailable": "No disponible",
- "versions.manualDslOption": "Subir DSL",
- "versions.moreActions": "Más acciones",
- "versions.optional": "Opcional",
- "versions.releaseAlreadyExists": "Ya existe una versión con el mismo contenido: {{name}}.",
- "versions.releaseContentCheckFailed": "Error al comprobar el contenido de la versión.",
- "versions.releaseDescriptionLabel": "Descripción",
- "versions.releaseDescriptionPlaceholder": "Describe esta versión",
- "versions.releaseNameConflict": "Ya existe una versión con este nombre. Elige otro nombre.",
- "versions.releaseNameLabel": "Nombre de la versión",
- "versions.releaseNamePlaceholder": "Nombre de la versión",
- "versions.releaseNameRequired": "Introduce un nombre de versión.",
- "versions.releaseSourceLabel": "Origen de la versión",
- "versions.rollbackTo": "Desplegar a {{name}}",
- "versions.saveEdit": "Guardar",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "Desplegar a {{name}}"
}
diff --git a/web/i18n/fa-IR/common.json b/web/i18n/fa-IR/common.json
index 608402d41f1..774a3cec197 100644
--- a/web/i18n/fa-IR/common.json
+++ b/web/i18n/fa-IR/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "جزئیات برنامه",
"menus.apps": "استودیو",
"menus.datasets": "دانش",
- "menus.deployments": "استقرارها",
"menus.exploreMarketplace": "بازار را کاوش کنید",
"menus.plugins": "یکپارچهسازیها",
"menus.status": "بتا",
diff --git a/web/i18n/fa-IR/deployments.json b/web/i18n/fa-IR/deployments.json
index ca59205e42b..44b32f95387 100644
--- a/web/i18n/fa-IR/deployments.json
+++ b/web/i18n/fa-IR/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "کپی نمونه cURL",
- "access.api.createFailed": "تولید API Token ناموفق بود.",
- "access.api.createKey": "تولید API Token",
- "access.api.createKeyTitle": "تولید API Token جدید",
- "access.api.curlExampleTitle": "نمونه cURL",
- "access.api.description": "دسترسی به این استقرار از طریق HTTP. هر API Token محدود به یک محیط است.",
- "access.api.developerTitle": "API توسعهدهنده",
- "access.api.disabled": "دسترسی API برای این استقرار خاموش است.",
- "access.api.disabledHint": "دسترسی API را فعال کنید تا توکنهای محدود به محیط تولید شود.",
- "access.api.docs": "مستندات API",
- "access.api.docsClose": "بستن مستندات API",
- "access.api.docsDescription": "مرجع Workflow API را برای این استقرار مشاهده کنید.",
- "access.api.docsTitle": "مستندات Workflow API",
- "access.api.empty": "ابتدا در یک محیط مستقر شوید تا شروع به صدور API Token کنید.",
- "access.api.emptyTitle": "هیچ محیط مستقر شدهای وجود ندارد",
- "access.api.endpoint": "URL درخواست",
- "access.api.keyList": "فهرست API Token",
- "access.api.nameLabel": "نام API Token",
- "access.api.namePlaceholder": "نام یک API Token را وارد کنید",
- "access.api.nameRequired": "نام API Token الزامی است.",
- "access.api.newKey": "تولید API Token جدید",
- "access.api.newTokenDescription": "این API Token فقط یک بار نمایش داده میشود. قبل از ترک این صفحه آن را کپی کنید.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token تولید شد",
- "access.api.noKeys": "هنوز API Tokenای وجود ندارد. یکی تولید کنید تا شروع به فراخوانی API کنید.",
- "access.api.noKeysTitle": "هنوز API Tokenای وجود ندارد",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" بلافاصله از کار میافتد. این عمل قابل بازگشت نیست.",
- "access.api.revokeConfirmTitle": "لغو API Token؟",
- "access.api.revokeFailed": "لغو API Token ناموفق بود.",
- "access.api.revokeSuccess": "API Token لغو شد",
- "access.api.table.action": "عملیات",
- "access.api.table.environment": "محیط",
- "access.api.table.key": "API Token",
- "access.api.table.name": "نام",
- "access.channels.disabled": "کانالهای دسترسی برای این استقرار خاموش هستند.",
- "access.channels.disabledHint": "کانالهای دسترسی را فعال کنید تا نقاط ورود WebApp و CLI را در دسترس قرار دهید.",
- "access.channels.title": "کانالهای دسترسی",
- "access.cli.description": "از ترمینال با difyctl فراخوانی کنید، مناسب برای اسکریپتها، Workflowهای خودکار یا یکپارچهسازیهای Agent.",
- "access.cli.docs": "راهنمای استفاده",
- "access.cli.domain": "دامنه",
- "access.cli.empty": "نقطه پایانی CLI پیکربندی نشده است.",
- "access.cli.install": "نصب CLI",
- "access.cli.title": "CLI",
- "access.copy": "کپی",
- "access.copyFailed": "کپی ناموفق بود",
- "access.members.groupCount_one": "{{count}} گروه",
- "access.members.groupCount_other": "{{count}} گروه",
- "access.members.memberCount_one": "{{count}} عضو",
- "access.members.memberCount_other": "{{count}} عضو",
- "access.permission.anyone": "هر کسی که لینک را داشته باشد",
- "access.permission.organization": "همه اعضای داخل پلتفرم",
- "access.permission.specific": "اعضای مشخص داخل پلتفرم",
- "access.permission.specificDesc": "گروهها یا اعضای مشخصی را انتخاب کنید",
- "access.permission.updateFailed": "بهروزرسانی سیاست دسترسی ناموفق بود.",
- "access.permissions.editAriaLabel": "پیکربندی دسترسی برای {{environment}}",
- "access.permissions.editDescription": "مجوزهای دسترسی را برای نقاط ورود WebApp و CLI تنظیم کنید.",
- "access.permissions.editTitle": "مجوزهای دسترسی",
- "access.permissions.title": "مجوزهای دسترسی",
- "access.revoke": "لغو",
- "access.runAccess.noEnvs": "برای پیکربندی مجوزهای دسترسی، در یک محیط مستقر شوید.",
- "access.runAccess.noEnvsTitle": "هیچ محیط مستقر شدهای وجود ندارد",
- "access.runAccess.openWebapp": "باز کردن WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "صفحه وب میزبانی شده برای کاربران نهایی.",
- "access.runAccess.webappEmpty": "به زودی.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "خارجی",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "ناشناخته",
- "card.access.api": "API Tokenها",
- "card.access.cli": "CLI",
- "card.access.none": "بدون دسترسی",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "ایجاد اولین نسخه",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "حذف استقرار",
- "card.menu.deploy": "استقرار به محیط",
- "card.menu.editInfo": "ویرایش اطلاعات",
- "card.moreActions": "اقدامات بیشتر",
- "card.noDescription": "توضیحاتی ارائه نشده است.",
"card.notDeployed": "مستقر نشده",
- "card.tooltip.createdAt": "ایجاد شده",
- "card.tooltip.deployed": "مستقر شده",
- "card.tooltip.deploymentStatus": "استقرار",
- "card.tooltip.notDeployedShort": "مستقر نشده",
- "card.tooltip.releaseName": "نام نسخه",
- "card.tooltip.source": "منبع",
"common.loadFailed": "بارگذاری ناموفق بود. بعداً دوباره تلاش کنید.",
- "createGuide.actions.back": "بازگشت",
- "createGuide.actions.createAndDeploy": "ایجاد و استقرار",
- "createGuide.actions.creating": "در حال ایجاد...",
- "createGuide.actions.deploying": "در حال ایجاد و استقرار...",
- "createGuide.actions.next": "بعدی",
- "createGuide.actions.skipDeploy": "رد کردن، بعداً مستقر شود",
- "createGuide.dsl.defaultAppName": "برنامه DSL وارد شده",
- "createGuide.dsl.description": "یک بسته Workflow DSL را برای ایجاد استقرار، اولین نسخه و استقرار اختیاری محیط بارگذاری کنید.",
- "createGuide.dsl.dropDescription": "یک بسته Workflow YAML DSL را بارگذاری کنید. گزینههای استقرار قبل از استقرار از این فایل حل میشوند.",
- "createGuide.dsl.dropTitle": "بارگذاری بسته Workflow DSL",
- "createGuide.dsl.readFailed": "خواندن فایل DSL ناموفق بود. فایل دیگری را انتخاب کرده و دوباره تلاش کنید.",
- "createGuide.dsl.reading": "در حال خواندن فایل DSL...",
- "createGuide.dsl.title": "وارد کردن DSL",
- "createGuide.dsl.unsupportedMode": "فقط فایلهای Workflow DSL میتوانند برای استقرار استفاده شوند.",
- "createGuide.errors.createReleaseFailed": "ایجاد استقرار یا نسخه ناموفق بود.",
- "createGuide.errors.deployFailed": "استقرار در محیط ناموفق بود.",
- "createGuide.method.description": "منبع مورد استفاده برای ایجاد اولین نسخه را انتخاب کنید.",
- "createGuide.methods.bindApp.description": "از یک Workflow App موجود در Studio بهعنوان منبع نسخه استفاده کنید.",
- "createGuide.methods.bindApp.title": "اتصال Workflow App موجود",
- "createGuide.methods.importDsl.description": "یک بسته Workflow YAML DSL را بارگذاری کنید و از طریق رابط کاربری استقرار ادامه دهید.",
- "createGuide.methods.importDsl.title": "وارد کردن DSL",
- "createGuide.nav.back": "استقرارها",
- "createGuide.release.defaultName": "نسخه اولیه",
- "createGuide.release.deployInfo": "اطلاعات استقرار",
- "createGuide.release.description": "اطلاعات استقرار و جزئیات اولین نسخه را پر کنید.",
- "createGuide.release.firstVersion": "اولین نسخه",
- "createGuide.release.instanceDescription": "توضیحات استقرار",
- "createGuide.release.instanceDescriptionPlaceholder": "توضیح دهید این استقرار برای چه چیزی استفاده میشود",
- "createGuide.release.instanceName": "نام استقرار",
- "createGuide.release.instanceNameConflict": "یک استقرار با این نام در حال حاضر وجود دارد. نام دیگری انتخاب کنید.",
- "createGuide.release.releaseDescription": "توضیحات نسخه",
- "createGuide.release.releaseDescriptionPlaceholder": "این نسخه را توصیف کنید",
- "createGuide.release.releaseName": "نام نسخه",
- "createGuide.release.title": "اطلاعات اولیه",
- "createGuide.source.clearSearch": "پاک کردن جستجوی برنامه",
- "createGuide.source.description": "منبع مورد استفاده برای ایجاد اولین نسخه را انتخاب کنید.",
- "createGuide.source.empty": "هیچ Workflow App یافت نشد.",
- "createGuide.source.searchPlaceholder": "جستجوی برنامهها",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "منبع نسخه",
- "createGuide.steps.method": "منبع نسخه",
- "createGuide.steps.release": "اطلاعات اولیه",
- "createGuide.steps.source": "منبع نسخه",
- "createGuide.steps.target": "استقرار به محیط",
- "createGuide.target.bindingCount_one": "{{count}} اتصال",
- "createGuide.target.bindingCount_other": "{{count}} اتصال",
- "createGuide.target.bindingHint": "اعتبارنامههای مورد استفاده توسط این نسخه را انتخاب کنید.",
- "createGuide.target.bindings": "اعتبارنامهها",
- "createGuide.target.description": "یک محیط هدف را انتخاب کنید و تنظیمات زمان اجرایی که این نسخه در آنجا نیاز دارد را ارائه دهید. این مرحله میتواند رد شود.",
- "createGuide.target.envVarCount_one": "{{count}} متغیر",
- "createGuide.target.envVarCount_other": "{{count}} متغیر",
- "createGuide.target.envVarHint": "برای هر متغیر محیطی که این نسخه نیاز دارد، یک مقدار سفارشی وارد کنید یا از مقدار تعریف شده در برنامه استفاده کنید.",
- "createGuide.target.envVarPlaceholder": "مقدار را وارد کنید",
- "createGuide.target.envVarSource.ariaLabel": "منبع مقدار متغیر را برای {{key}} انتخاب کنید",
- "createGuide.target.envVarSource.default": "مقدار برنامه",
- "createGuide.target.envVarSource.lastDeployment": "آخرین مقدار مستقر شده",
- "createGuide.target.envVarSource.literal": "مقدار سفارشی",
- "createGuide.target.envVarType.number": "عدد",
- "createGuide.target.envVarType.secret": "محرمانه",
- "createGuide.target.envVarType.string": "رشته",
- "createGuide.target.envVars": "متغیرهای محیطی",
- "createGuide.target.environment": "محیط هدف",
- "createGuide.target.loadBindingsFailed": "بارگذاری اعتبارنامهها ناموفق بود.",
- "createGuide.target.loadEnvironmentsFailed": "بارگذاری محیطهای استقرار ناموفق بود.",
- "createGuide.target.missingRequiredBinding": "یک اعتبارنامه برای این اتصال الزامی انتخاب کنید.",
- "createGuide.target.noBindingRequired": "اعتبارنامهای لازم نیست.",
- "createGuide.target.noCredentialCandidates": "اعتبارنامهای در دسترس نیست.",
- "createGuide.target.noEnvironmentOptions": "هیچ محیط استقراری در دسترس نیست.",
- "createGuide.target.selectCredential": "یک اعتبارنامه انتخاب کنید",
- "createGuide.target.title": "استقرار به محیط",
- "createGuide.title": "استقرار جدید",
- "createModal.appPickerPlaceholder": "یک Workflow App انتخاب کنید",
- "createModal.appSearchEmpty": "هیچ Workflow App منطبقی یافت نشد",
- "createModal.appSearchPlaceholder": "جستجوی Workflow Appها…",
- "createModal.cancel": "لغو",
- "createModal.loadingApps": "در حال بارگذاری برنامهها…",
- "deployDrawer.bindingCount_one": "{{count}} اتصال",
- "deployDrawer.bindingCount_other": "{{count}} اتصال",
"deployDrawer.bindingOptionsFailed": "بارگذاری گزینههای اعتبارنامه ناموفق بود.",
"deployDrawer.bindingSelectionHint": "اعتبارنامههای مورد استفاده توسط این استقرار را انتخاب کنید.",
- "deployDrawer.cancel": "لغو",
- "deployDrawer.close": "بستن کشوی استقرار",
- "deployDrawer.defaultSelect": "انتخاب...",
- "deployDrawer.deploy": "استقرار به محیط",
- "deployDrawer.deployFailed": "شروع استقرار ناموفق بود.",
"deployDrawer.deploying": "در حال استقرار...",
- "deployDrawer.description": "یک نسخه و محیط هدف را برای استقرار انتخاب کنید.",
- "deployDrawer.envVarCount_one": "{{count}} متغیر",
- "deployDrawer.envVarCount_other": "{{count}} متغیر",
- "deployDrawer.envVarHint": "برای هر متغیر محیطی که این نسخه نیاز دارد، یک مقدار سفارشی وارد کنید یا از مقدار تعریف شده در برنامه استفاده کنید.",
- "deployDrawer.envVarPlaceholder": "مقدار را وارد کنید",
"deployDrawer.envVarSource.ariaLabel": "منبع مقدار متغیر را برای {{key}} انتخاب کنید",
- "deployDrawer.envVarSource.default": "مقدار برنامه",
"deployDrawer.envVarSource.lastDeployment": "آخرین مقدار مستقر شده",
"deployDrawer.envVarSource.literal": "مقدار سفارشی",
"deployDrawer.envVarType.number": "عدد",
"deployDrawer.envVarType.secret": "محرمانه",
"deployDrawer.envVarType.string": "رشته",
"deployDrawer.envVars": "متغیرهای محیطی",
- "deployDrawer.existingReleaseHint": "این نسخه به همان شکل مستقر خواهد شد. نسخه جدیدی ایجاد نخواهد شد.",
- "deployDrawer.lockedHint": "قفل شده به محیط فعلی",
- "deployDrawer.missingRequiredBinding": "یک اعتبارنامه برای این اتصال الزامی انتخاب کنید.",
- "deployDrawer.missingRequiredEnvVar": "یک مقدار برای این متغیر محیطی الزامی وارد کنید.",
- "deployDrawer.noBindingRequired": "الزامی نیست",
"deployDrawer.noCredentialCandidates": "اعتبارنامهای در دسترس نیست.",
"deployDrawer.noNewEnvironmentAvailable": "همه محیطهای در دسترس از قبل یک استقرار دارند.",
- "deployDrawer.noOtherReleaseAvailable": "نسخه دیگری برای این محیط در دسترس نیست.",
- "deployDrawer.noReleaseAvailable": "قبل از استقرار به یک محیط، یک نسخه ایجاد کنید.",
- "deployDrawer.notFound": "استقرار یافت نشد.",
- "deployDrawer.releaseLabel": "نسخه",
"deployDrawer.runtimeCredentials": "اعتبارنامهها",
"deployDrawer.selectCredential": "یک اعتبارنامه انتخاب کنید",
- "deployDrawer.selectEnv": "یک محیط انتخاب کنید",
- "deployDrawer.selectRelease": "یک نسخه انتخاب کنید",
- "deployDrawer.targetEnv": "محیط هدف",
- "deployDrawer.title": "استقرار به محیط",
- "deployTab.closeError": "بستن",
"deployTab.col.actions": "عملیات",
- "deployTab.col.currentRelease": "نسخه فعلی",
"deployTab.col.environment": "محیط",
"deployTab.col.status": "وضعیت",
"deployTab.confirmUndeploy": "لغو استقرار",
- "deployTab.deployOtherVersion": "استقرار نسخه دیگر",
- "deployTab.emptyDescription": "یک نسخه و محیط هدف انتخاب کنید تا این استقرار را در دسترس کاربران قرار دهید.",
- "deployTab.emptyTitle": "هیچ محیطی هنوز در حال اجرا نیست",
- "deployTab.errorCode": "کد",
- "deployTab.errorDialogDesc": "قبل از تلاش مجدد یا استقرار نسخه دیگر، آخرین استقرار ناموفق را بررسی کنید.",
- "deployTab.errorDialogTitle": "خطای استقرار در {{name}}",
- "deployTab.errorMessage": "پیام",
- "deployTab.errorPhase": "مرحله",
"deployTab.moreActions": "اقدامات بیشتر",
- "deployTab.newDeployment": "استقرار به محیط جدید",
- "deployTab.panel.unknownError": "استقرار ناموفق بود.",
"deployTab.redeploy": "استقرار مجدد",
- "deployTab.retry": "تلاش مجدد",
- "deployTab.status.deployFailed": "استقرار ناموفق",
- "deployTab.status.deployingRelease": "در حال استقرار ({{release}})",
- "deployTab.status.runningOutOfSync": "در حال اجرا (همگامسازی در انتظار)",
- "deployTab.status.runningWithFailed": "در حال اجرا (آخرین استقرار ناموفق بود)",
"deployTab.undeploy": "لغو استقرار",
- "deployTab.undeployConfirmDesc": "نقطه پایانی محیط از دسترس خارج میشود، اما نسخه حذف نخواهد شد.",
- "deployTab.undeployConfirmTitle": "استقرار {{name}} لغو شود؟",
"deployTab.undeployConfirmWarning": "پس از تأیید، این محیط وارد وضعیت لغو استقرار میشود و اقدامات بهطور موقت غیرفعال خواهند شد.",
- "deployTab.viewError": "مشاهده خطا",
- "detail.mobileTabs": "بخشهای استقرار",
- "detail.notFound": "استقرار یافت نشد",
- "documentTitle.create": "استقرار جدید · استقرارها",
- "documentTitle.detail": "استقرار · استقرارها",
- "documentTitle.list": "استقرارها",
- "filter.allEnvs": "همه محیطها",
- "filter.searchPlaceholder": "جستجوی استقرارها",
- "health.ENVIRONMENT_STATUS_ADMISSION": "پذیرش",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "در حال راهاندازی",
- "health.ENVIRONMENT_STATUS_DELETING": "در حال حذف",
"health.ENVIRONMENT_STATUS_FAILED": "در دسترس نیست",
- "health.ENVIRONMENT_STATUS_READY": "در دسترس",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "ناشناخته",
- "list.clearFilters": "پاک کردن فیلترها",
- "list.clearSearch": "پاک کردن جستجوی استقرار",
- "list.createDeployment": "جدید",
- "list.emptyDescription": "یک استقرار از Workflow App یا بسته Workflow DSL ایجاد کنید تا نسخهها، محیطها و دسترسی را مدیریت کنید.",
- "list.emptyFilteredDescription": "هیچ استقراری با جستجو یا فیلتر محیط فعلی مطابقت ندارد.",
- "list.emptyFilteredTitle": "هیچ استقرار منطبقی نیست",
"list.emptyTitle": "هنوز استقراری وجود ندارد",
- "mode.ENVIRONMENT_MODE_ISOLATED": "مجزا",
- "mode.ENVIRONMENT_MODE_SHARED": "اشتراکی",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "ناشناخته",
- "overview.accessMeta.apiTokens": "مدیریت API Tokenها",
- "overview.accessMeta.cli": "مشاهده دسترسی CLI",
- "overview.accessMeta.webApp": "مدیریت دسترسی WebApp",
- "overview.accessStatus": "دسترسی",
- "overview.api": "API Tokenها",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Token",
- "overview.apiTokenSummary.environments_one": "{{count}} محیط مستقر شده",
- "overview.apiTokenSummary.environments_other": "{{count}} محیط مستقر شده",
- "overview.cardAction.deployLatest": "استقرار آخرین نسخه",
- "overview.cardAction.redeploy": "استقرار مجدد",
- "overview.cardAction.viewProgress": "مشاهده استقرار",
- "overview.chip.behindTooltip_one": "۱ نسخه عقبتر از آخرین. آخرین نسخه را برای بهروزرسانی مستقر کنید.",
- "overview.chip.behindTooltip_other": "{{count}} نسخه عقبتر از آخرین. آخرین نسخه را برای بهروزرسانی مستقر کنید.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "در حال استقرار",
- "overview.chip.deployingTooltip": "استقرار در حال انجام است.",
- "overview.chip.empty": "خالی",
- "overview.chip.emptyTooltip": "نسخهای در این محیط مستقر نشده است.",
- "overview.chip.failed": "ناموفق",
- "overview.chip.failedTooltip": "آخرین تلاش استقرار ناموفق بود.",
"overview.chip.latest": "آخرین",
- "overview.chip.latestTooltip": "این محیط آخرین نسخه را اجرا میکند.",
- "overview.chip.needsReleaseFirst": "ابتدا یک نسخه ایجاد کنید",
- "overview.chip.olderRelease": "قدیمیتر",
- "overview.chip.olderReleaseTooltip": "این محیط نسخه قدیمیتری را اجرا میکند.",
- "overview.chip.openInDeployTab": "مشاهده پیشرفت استقرار",
- "overview.disabled": "غیرفعال",
- "overview.enabled": "فعال",
- "overview.hero.byName": "توسط {{name}}",
- "overview.hero.empty": "هنوز نسخهای وجود ندارد",
- "overview.hero.emptyDescription": "قبل از استقرار، یک نسخه از منبع فعلی ایجاد کنید.",
- "overview.latestRelease.releaseCount_one": "{{count}} نسخه",
- "overview.latestRelease.releaseCount_other": "{{count}} نسخه",
- "overview.latestReleaseTitle": "آخرین نسخه",
- "overview.previousReleases.viewAll": "مشاهده همه",
- "overview.strip.deployToNewEnvironment": "استقرار به محیط جدید",
- "overview.strip.emptyDeployableDescription": "هنگامی که آماده شدید، آخرین نسخه را در یک محیط مستقر کنید.",
- "overview.strip.emptyDescription": "قبل از استقرار به یک محیط، یک نسخه ایجاد کنید.",
- "overview.strip.emptyTitle": "هنوز نمونهای وجود ندارد",
- "overview.strip.title": "نمونهها",
- "settings.delete": "حذف استقرار",
- "settings.deleteConfirmDesc": "حذف {{name}}؟ هر نمونه در همه محیطها متوقف و حذف خواهد شد. این عمل قابل بازگشت نیست.",
- "settings.deleteConfirmTitle": "حذف استقرار",
- "settings.deleteFailed": "حذف استقرار ناموفق بود.",
- "settings.deleted": "استقرار حذف شد",
- "settings.description": "توضیحات",
- "settings.name": "نام استقرار",
- "settings.save": "ذخیره تغییرات",
- "settings.updateFailed": "بهروزرسانی استقرار ناموفق بود.",
- "settings.updated": "استقرار بهروزرسانی شد",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "در حال استقرار",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "همگامسازی در انتظار",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "استقرار ناموفق",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "نامعتبر",
"status.RUNTIME_INSTANCE_STATUS_READY": "در حال اجرا",
@@ -370,87 +89,6 @@
"studio.versionValue": "مقدار نسخه",
"studio.versionsBehind_one": "{{count}} نسخه عقبتر",
"studio.versionsBehind_other": "{{count}} نسخه عقبتر",
- "tabs.access.description": "مدیریت کانالهای دسترسی و مجوزهای دسترسی.",
- "tabs.access.name": "دسترسی",
- "tabs.api-tokens.description": "مدیریت API Tokenها و فراخوانی نمونهها از طریق HTTP.",
- "tabs.api-tokens.name": "API Tokenها",
- "tabs.instances.description": "مشاهده و مدیریت نمونهها در محیطهای مستقر شده.",
- "tabs.instances.name": "نمونهها",
- "tabs.overview.description": "وضعیت استقرار را در میان محیطها مشاهده کنید.",
- "tabs.overview.name": "نمای کلی",
- "tabs.releases.description": "نسخهها را ایجاد، مستقر و مدیریت کنید.",
- "tabs.releases.name": "نسخهها",
- "unsupportedDslNodes.description": "این نسخه شامل گرههایی است که زمان اجرای استقرار هنوز از آنها پشتیبانی نمیکند. آنها را در Studio حذف یا جایگزین کرده و دوباره تلاش کنید.",
- "unsupportedDslNodes.descriptionWithTypes": "این نسخه شامل گرههایی است که زمان اجرای استقرار هنوز از آنها پشتیبانی نمیکند: {{nodeTypes}}. آنها را در Studio حذف یا جایگزین کرده و دوباره تلاش کنید.",
- "unsupportedDslNodes.title": "گرههای پشتیبانی نشده",
- "unsupportedDslNodes.unknownType": "نوع ناشناخته",
- "versions.cancelCreate": "لغو",
- "versions.cancelDelete": "لغو",
- "versions.cancelEdit": "لغو",
"versions.checkingReleaseContent": "در حال بررسی محتوای نسخه...",
- "versions.col.action": "عملیات",
- "versions.col.author": "ایجاد شده توسط",
- "versions.col.createdAt": "ایجاد شده در",
- "versions.col.deployedTo": "مستقر شده در",
- "versions.col.release": "نسخه",
- "versions.col.sourceApp": "منبع",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "ایجاد",
- "versions.createFailed": "ایجاد نسخه ناموفق بود.",
- "versions.createRelease": "ایجاد نسخه",
- "versions.createReleaseDescription": "یک نسخه قابل استقرار از Workflow App یا فایل Workflow DSL ایجاد کنید.",
- "versions.createSuccess": "نسخه \"{{name}}\" ایجاد شد.",
- "versions.creating": "در حال ایجاد...",
- "versions.currentOn": "نسخه فعلی در {{name}}",
- "versions.deleteConfirmDesc": "نسخه \"{{name}}\" بهطور دائمی حذف خواهد شد. این عمل قابل بازگشت نیست.",
- "versions.deleteConfirmTitle": "حذف نسخه؟",
- "versions.deleteFailed": "حذف نسخه ناموفق بود.",
- "versions.deleteRelease": "حذف نسخه",
- "versions.deleteSuccess": "نسخه \"{{name}}\" حذف شد.",
- "versions.deployTo": "استقرار به {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "در حال استقرار",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "همگامسازی در انتظار",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "ناموفق",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "نامعتبر",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "در حال اجرا",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "مستقر نشده",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "در حال لغو استقرار",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "ناشناخته",
- "versions.deployingTo": "{{name}} در حال استقرار است",
- "versions.disabledReason.checkDeploymentsFailed": "بررسی استفاده از استقرار ممکن نشد. بعداً دوباره تلاش کنید.",
- "versions.disabledReason.checkingDeployments": "در حال بررسی استفاده از استقرار",
- "versions.disabledReason.current": "این نسخه از قبل در {{name}} در حال اجرا است",
- "versions.disabledReason.deploying": "منتظر بمانید تا استقرار فعال به پایان برسد",
- "versions.disabledReason.releaseInUse_one": "قبل از حذف، این نسخه را از {{count}} محیط لغو استقرار کنید",
- "versions.disabledReason.releaseInUse_other": "قبل از حذف، این نسخه را از {{count}} محیط لغو استقرار کنید",
- "versions.dslReadFailed": "خواندن فایل DSL ناموفق بود. فایل دیگری را انتخاب کرده و دوباره تلاش کنید.",
- "versions.dslReading": "در حال خواندن فایل DSL...",
- "versions.dslUnsupportedMode": "فقط فایلهای Workflow DSL میتوانند برای استقرار استفاده شوند.",
- "versions.editFailed": "بهروزرسانی نسخه ناموفق بود.",
- "versions.editRelease": "ویرایش نسخه",
- "versions.editReleaseDescription": "نام و توضیحات این نسخه را بهروزرسانی کنید.",
- "versions.editSuccess": "نسخه \"{{name}}\" بهروزرسانی شد.",
- "versions.emptyDescription": "قبل از استقرار به یک محیط، اولین نسخه را ایجاد کنید.",
- "versions.emptyTitle": "هنوز نسخهای وجود ندارد",
- "versions.exportDsl": "صادر کردن DSL",
- "versions.exportDslFailed": "صادر کردن DSL ناموفق بود.",
- "versions.exportingDsl": "در حال صادر کردن...",
- "versions.groupHeader.deploy": "استقرار",
- "versions.groupHeader.rollback": "استقرار نسخه قبلی",
- "versions.groupHeader.unavailable": "در دسترس نیست",
- "versions.manualDslOption": "بارگذاری DSL",
- "versions.moreActions": "اقدامات بیشتر",
- "versions.optional": "اختیاری",
- "versions.releaseAlreadyExists": "نسخهای با محتوای یکسان از قبل وجود دارد: {{name}}.",
- "versions.releaseContentCheckFailed": "بررسی محتوای نسخه ناموفق بود.",
- "versions.releaseDescriptionLabel": "توضیحات",
- "versions.releaseDescriptionPlaceholder": "این نسخه را توصیف کنید",
- "versions.releaseNameConflict": "نسخهای با این نام از قبل وجود دارد. نام دیگری انتخاب کنید.",
- "versions.releaseNameLabel": "نام نسخه",
- "versions.releaseNamePlaceholder": "نام نسخه",
- "versions.releaseNameRequired": "یک نام نسخه وارد کنید.",
- "versions.releaseSourceLabel": "منبع نسخه",
- "versions.rollbackTo": "استقرار به {{name}}",
- "versions.saveEdit": "ذخیره",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "استقرار به {{name}}"
}
diff --git a/web/i18n/fr-FR/common.json b/web/i18n/fr-FR/common.json
index 359be32b5dd..58b1ddd649c 100644
--- a/web/i18n/fr-FR/common.json
+++ b/web/i18n/fr-FR/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Détails de l'application",
"menus.apps": "Studio",
"menus.datasets": "Connaissance",
- "menus.deployments": "Déploiements",
"menus.exploreMarketplace": "Explorer Marketplace",
"menus.plugins": "Intégrations",
"menus.status": "bêta",
diff --git a/web/i18n/fr-FR/deployments.json b/web/i18n/fr-FR/deployments.json
index e77869103b3..fc83638fc2b 100644
--- a/web/i18n/fr-FR/deployments.json
+++ b/web/i18n/fr-FR/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copier l'exemple cURL",
- "access.api.createFailed": "Échec de la génération du Token API.",
- "access.api.createKey": "Générer un Token API",
- "access.api.createKeyTitle": "Générer un nouveau Token API",
- "access.api.curlExampleTitle": "Exemple cURL",
- "access.api.description": "Accédez à ce déploiement via HTTP. Chaque Token API est limité à un seul environnement.",
- "access.api.developerTitle": "API développeur",
- "access.api.disabled": "L'accès API est désactivé pour ce déploiement.",
- "access.api.disabledHint": "Activez l'accès API pour générer des tokens limités à un environnement.",
- "access.api.docs": "Documentation API",
- "access.api.docsClose": "Fermer la documentation API",
- "access.api.docsDescription": "Consultez la référence de l'API Workflow pour ce déploiement.",
- "access.api.docsTitle": "Documentation de l'API Workflow",
- "access.api.empty": "Déployez d'abord dans un environnement pour commencer à émettre des Tokens API.",
- "access.api.emptyTitle": "Aucun environnement déployé",
- "access.api.endpoint": "URL de requête",
- "access.api.keyList": "Liste des Tokens API",
- "access.api.nameLabel": "Nom du Token API",
- "access.api.namePlaceholder": "Entrez un nom de Token API",
- "access.api.nameRequired": "Le nom du Token API est requis.",
- "access.api.newKey": "Générer un nouveau Token API",
- "access.api.newTokenDescription": "Ce Token API n'est affiché qu'une seule fois. Copiez-le avant de quitter cette page.",
- "access.api.newTokenLabel": "Token API",
- "access.api.newTokenTitle": "Token API généré",
- "access.api.noKeys": "Aucun Token API pour le moment. Générez-en un pour commencer à appeler l'API.",
- "access.api.noKeysTitle": "Aucun Token API pour le moment",
- "access.api.revokeConfirmDescription": "Le Token API « {{name}} » cessera immédiatement de fonctionner. Cette action est irréversible.",
- "access.api.revokeConfirmTitle": "Révoquer le Token API ?",
- "access.api.revokeFailed": "Échec de la révocation du Token API.",
- "access.api.revokeSuccess": "Token API révoqué",
- "access.api.table.action": "Action",
- "access.api.table.environment": "Environnement",
- "access.api.table.key": "Token API",
- "access.api.table.name": "Nom",
- "access.channels.disabled": "Les canaux d'accès sont désactivés pour ce déploiement.",
- "access.channels.disabledHint": "Activez les canaux d'accès pour exposer les points d'entrée WebApp et CLI.",
- "access.channels.title": "Canaux d'accès",
- "access.cli.description": "Invoquez depuis le terminal avec difyctl, adapté aux scripts, aux workflows automatisés ou aux intégrations d'Agent.",
- "access.cli.docs": "Guide d'utilisation",
- "access.cli.domain": "Domaine",
- "access.cli.empty": "Point de terminaison CLI non configuré.",
- "access.cli.install": "Installer CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copier",
- "access.copyFailed": "Échec de la copie",
- "access.members.groupCount_one": "{{count}} groupe",
- "access.members.groupCount_other": "{{count}} groupes",
- "access.members.memberCount_one": "{{count}} membre",
- "access.members.memberCount_other": "{{count}} membres",
- "access.permission.anyone": "Toute personne disposant du lien",
- "access.permission.organization": "Tous les membres de la plateforme",
- "access.permission.specific": "Membres spécifiques de la plateforme",
- "access.permission.specificDesc": "Sélectionnez des groupes ou des membres spécifiques",
- "access.permission.updateFailed": "Échec de la mise à jour de la politique d'accès.",
- "access.permissions.editAriaLabel": "Configurer l'accès pour {{environment}}",
- "access.permissions.editDescription": "Définissez les autorisations d'accès pour les points d'entrée WebApp et CLI.",
- "access.permissions.editTitle": "Autorisations d'accès",
- "access.permissions.title": "Autorisations d'accès",
- "access.revoke": "Révoquer",
- "access.runAccess.noEnvs": "Déployez dans un environnement pour configurer les autorisations d'accès.",
- "access.runAccess.noEnvsTitle": "Aucun environnement déployé",
- "access.runAccess.openWebapp": "Ouvrir la WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Page web hébergée pour les utilisateurs finaux.",
- "access.runAccess.webappEmpty": "Bientôt disponible.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Externe",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Inconnu",
- "card.access.api": "Tokens API",
- "card.access.cli": "CLI",
- "card.access.none": "Aucun accès",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Créer la première version",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Supprimer le déploiement",
- "card.menu.deploy": "Déployer dans un environnement",
- "card.menu.editInfo": "Modifier les informations",
- "card.moreActions": "Plus d'actions",
- "card.noDescription": "Aucune description fournie.",
"card.notDeployed": "Non déployé",
- "card.tooltip.createdAt": "Créé",
- "card.tooltip.deployed": "Déployé",
- "card.tooltip.deploymentStatus": "Déploiement",
- "card.tooltip.notDeployedShort": "Non déployé",
- "card.tooltip.releaseName": "Nom de la version",
- "card.tooltip.source": "Source",
"common.loadFailed": "Échec du chargement. Réessayez plus tard.",
- "createGuide.actions.back": "Retour",
- "createGuide.actions.createAndDeploy": "Créer et déployer",
- "createGuide.actions.creating": "Création en cours...",
- "createGuide.actions.deploying": "Création et déploiement...",
- "createGuide.actions.next": "Suivant",
- "createGuide.actions.skipDeploy": "Ignorer, déployer plus tard",
- "createGuide.dsl.defaultAppName": "Application DSL importée",
- "createGuide.dsl.description": "Téléversez un package DSL Workflow pour créer le déploiement, la première version et le déploiement optionnel dans un environnement.",
- "createGuide.dsl.dropDescription": "Téléversez un package DSL YAML Workflow. Les options de déploiement sont résolues à partir de ce fichier avant le déploiement.",
- "createGuide.dsl.dropTitle": "Téléverser un package DSL Workflow",
- "createGuide.dsl.readFailed": "Échec de la lecture du fichier DSL. Choisissez un autre fichier et réessayez.",
- "createGuide.dsl.reading": "Lecture du fichier DSL...",
- "createGuide.dsl.title": "Importer un DSL",
- "createGuide.dsl.unsupportedMode": "Seuls les fichiers DSL Workflow peuvent être utilisés pour les déploiements.",
- "createGuide.errors.createReleaseFailed": "Échec de la création du déploiement ou de la version.",
- "createGuide.errors.deployFailed": "Échec du déploiement dans l'environnement.",
- "createGuide.method.description": "Choisissez la source utilisée pour créer la première version.",
- "createGuide.methods.bindApp.description": "Utilisez une application Workflow existante dans Studio comme source de version.",
- "createGuide.methods.bindApp.title": "Lier une application Workflow existante",
- "createGuide.methods.importDsl.description": "Téléversez un package DSL YAML Workflow et continuez dans l'interface de déploiement.",
- "createGuide.methods.importDsl.title": "Importer un DSL",
- "createGuide.nav.back": "Déploiements",
- "createGuide.release.defaultName": "version initiale",
- "createGuide.release.deployInfo": "Informations de déploiement",
- "createGuide.release.description": "Renseignez les informations du déploiement et les détails de la première version.",
- "createGuide.release.firstVersion": "Première version",
- "createGuide.release.instanceDescription": "Description du déploiement",
- "createGuide.release.instanceDescriptionPlaceholder": "Décrivez à quoi sert ce déploiement",
- "createGuide.release.instanceName": "Nom du déploiement",
- "createGuide.release.instanceNameConflict": "Un déploiement portant ce nom existe déjà. Choisissez un autre nom.",
- "createGuide.release.releaseDescription": "Description de la version",
- "createGuide.release.releaseDescriptionPlaceholder": "Décrivez cette version",
- "createGuide.release.releaseName": "Nom de la version",
- "createGuide.release.title": "Informations de base",
- "createGuide.source.clearSearch": "Effacer la recherche d'application",
- "createGuide.source.description": "Choisissez la source utilisée pour créer la première version.",
- "createGuide.source.empty": "Aucune application Workflow trouvée.",
- "createGuide.source.searchPlaceholder": "Rechercher des applications",
- "createGuide.source.sourceApp": "Application Workflow",
- "createGuide.source.title": "Source de la version",
- "createGuide.steps.method": "Source de la version",
- "createGuide.steps.release": "Informations de base",
- "createGuide.steps.source": "Source de la version",
- "createGuide.steps.target": "Déployer dans un environnement",
- "createGuide.target.bindingCount_one": "{{count}} liaison",
- "createGuide.target.bindingCount_other": "{{count}} liaisons",
- "createGuide.target.bindingHint": "Choisissez les identifiants utilisés par cette version.",
- "createGuide.target.bindings": "Identifiants",
- "createGuide.target.description": "Choisissez un environnement cible et fournissez les paramètres d'exécution dont cette version a besoin. Cette étape peut être ignorée.",
- "createGuide.target.envVarCount_one": "{{count}} variable",
- "createGuide.target.envVarCount_other": "{{count}} variables",
- "createGuide.target.envVarHint": "Pour chaque variable d'environnement requise par cette version, saisissez une valeur personnalisée ou utilisez la valeur définie dans l'application.",
- "createGuide.target.envVarPlaceholder": "Entrez une valeur",
- "createGuide.target.envVarSource.ariaLabel": "Sélectionnez la source de la valeur de la variable pour {{key}}",
- "createGuide.target.envVarSource.default": "Valeur de l'application",
- "createGuide.target.envVarSource.lastDeployment": "Valeur du dernier déploiement",
- "createGuide.target.envVarSource.literal": "Valeur personnalisée",
- "createGuide.target.envVarType.number": "Nombre",
- "createGuide.target.envVarType.secret": "Secret",
- "createGuide.target.envVarType.string": "Chaîne",
- "createGuide.target.envVars": "Variables d'environnement",
- "createGuide.target.environment": "Environnement cible",
- "createGuide.target.loadBindingsFailed": "Échec du chargement des identifiants.",
- "createGuide.target.loadEnvironmentsFailed": "Échec du chargement des environnements de déploiement.",
- "createGuide.target.missingRequiredBinding": "Sélectionnez un identifiant pour cette liaison requise.",
- "createGuide.target.noBindingRequired": "Aucun identifiant requis.",
- "createGuide.target.noCredentialCandidates": "Aucun identifiant disponible.",
- "createGuide.target.noEnvironmentOptions": "Aucun environnement de déploiement disponible.",
- "createGuide.target.selectCredential": "Sélectionnez un identifiant",
- "createGuide.target.title": "Déployer dans un environnement",
- "createGuide.title": "Nouveau déploiement",
- "createModal.appPickerPlaceholder": "Sélectionnez une application Workflow",
- "createModal.appSearchEmpty": "Aucune application Workflow correspondante",
- "createModal.appSearchPlaceholder": "Rechercher des applications Workflow…",
- "createModal.cancel": "Annuler",
- "createModal.loadingApps": "Chargement des applications…",
- "deployDrawer.bindingCount_one": "{{count}} liaison",
- "deployDrawer.bindingCount_other": "{{count}} liaisons",
"deployDrawer.bindingOptionsFailed": "Échec du chargement des options d'identifiants.",
"deployDrawer.bindingSelectionHint": "Choisissez les identifiants utilisés par ce déploiement.",
- "deployDrawer.cancel": "Annuler",
- "deployDrawer.close": "Fermer le panneau de déploiement",
- "deployDrawer.defaultSelect": "Sélectionner...",
- "deployDrawer.deploy": "Déployer dans un environnement",
- "deployDrawer.deployFailed": "Échec du démarrage du déploiement.",
"deployDrawer.deploying": "Déploiement en cours...",
- "deployDrawer.description": "Sélectionnez une version et un environnement cible à déployer.",
- "deployDrawer.envVarCount_one": "{{count}} variable",
- "deployDrawer.envVarCount_other": "{{count}} variables",
- "deployDrawer.envVarHint": "Pour chaque variable d'environnement requise par cette version, saisissez une valeur personnalisée ou utilisez la valeur définie dans l'application.",
- "deployDrawer.envVarPlaceholder": "Entrez une valeur",
"deployDrawer.envVarSource.ariaLabel": "Sélectionnez la source de la valeur de la variable pour {{key}}",
- "deployDrawer.envVarSource.default": "Valeur de l'application",
"deployDrawer.envVarSource.lastDeployment": "Valeur du dernier déploiement",
"deployDrawer.envVarSource.literal": "Valeur personnalisée",
"deployDrawer.envVarType.number": "Nombre",
"deployDrawer.envVarType.secret": "Secret",
"deployDrawer.envVarType.string": "Chaîne",
"deployDrawer.envVars": "Variables d'environnement",
- "deployDrawer.existingReleaseHint": "Cette version sera déployée telle quelle. Aucune nouvelle version ne sera créée.",
- "deployDrawer.lockedHint": "Verrouillé sur l'environnement actuel",
- "deployDrawer.missingRequiredBinding": "Sélectionnez un identifiant pour cette liaison requise.",
- "deployDrawer.missingRequiredEnvVar": "Entrez une valeur pour cette variable d'environnement requise.",
- "deployDrawer.noBindingRequired": "Non requis",
"deployDrawer.noCredentialCandidates": "Aucun identifiant disponible.",
"deployDrawer.noNewEnvironmentAvailable": "Tous les environnements disponibles ont déjà un déploiement.",
- "deployDrawer.noOtherReleaseAvailable": "Aucune autre version n'est disponible pour cet environnement.",
- "deployDrawer.noReleaseAvailable": "Créez une version avant de déployer dans un environnement.",
- "deployDrawer.notFound": "Déploiement introuvable.",
- "deployDrawer.releaseLabel": "Version",
"deployDrawer.runtimeCredentials": "Identifiants",
"deployDrawer.selectCredential": "Sélectionnez un identifiant",
- "deployDrawer.selectEnv": "Sélectionnez un environnement",
- "deployDrawer.selectRelease": "Sélectionnez une version",
- "deployDrawer.targetEnv": "Environnement cible",
- "deployDrawer.title": "Déployer dans un environnement",
- "deployTab.closeError": "Fermer",
"deployTab.col.actions": "Actions",
- "deployTab.col.currentRelease": "Version actuelle",
"deployTab.col.environment": "Environnement",
"deployTab.col.status": "Statut",
"deployTab.confirmUndeploy": "Annuler le déploiement",
- "deployTab.deployOtherVersion": "Déployer une autre version",
- "deployTab.emptyDescription": "Choisissez une version et un environnement cible pour mettre ce déploiement à la disposition des utilisateurs.",
- "deployTab.emptyTitle": "Aucun environnement en cours d'exécution",
- "deployTab.errorCode": "Code",
- "deployTab.errorDialogDesc": "Examinez le dernier déploiement en échec avant de réessayer ou de déployer une autre version.",
- "deployTab.errorDialogTitle": "Erreur de déploiement dans {{name}}",
- "deployTab.errorMessage": "Message",
- "deployTab.errorPhase": "Phase",
"deployTab.moreActions": "Plus d'actions",
- "deployTab.newDeployment": "Déployer dans un nouvel environnement",
- "deployTab.panel.unknownError": "Échec du déploiement.",
"deployTab.redeploy": "Redéployer",
- "deployTab.retry": "Réessayer",
- "deployTab.status.deployFailed": "Échec du déploiement",
- "deployTab.status.deployingRelease": "Déploiement en cours ({{release}})",
- "deployTab.status.runningOutOfSync": "En cours d'exécution (synchronisation en attente)",
- "deployTab.status.runningWithFailed": "En cours d'exécution (dernier déploiement en échec)",
"deployTab.undeploy": "Annuler le déploiement",
- "deployTab.undeployConfirmDesc": "Le point de terminaison de l’environnement ne sera plus disponible, mais la version ne sera pas supprimée.",
- "deployTab.undeployConfirmTitle": "Annuler le déploiement de {{name}} ?",
"deployTab.undeployConfirmWarning": "Après confirmation, cet environnement passera à l’état d’annulation du déploiement et les actions seront temporairement désactivées.",
- "deployTab.viewError": "Voir l'erreur",
- "detail.mobileTabs": "Sections du déploiement",
- "detail.notFound": "Déploiement introuvable",
- "documentTitle.create": "Nouveau déploiement · Déploiements",
- "documentTitle.detail": "Déploiement · Déploiements",
- "documentTitle.list": "Déploiements",
- "filter.allEnvs": "Tous les environnements",
- "filter.searchPlaceholder": "Rechercher des déploiements",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Admission",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Initialisation",
- "health.ENVIRONMENT_STATUS_DELETING": "Suppression",
"health.ENVIRONMENT_STATUS_FAILED": "Indisponible",
- "health.ENVIRONMENT_STATUS_READY": "Disponible",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Inconnu",
- "list.clearFilters": "Effacer les filtres",
- "list.clearSearch": "Effacer la recherche de déploiement",
- "list.createDeployment": "Nouveau",
- "list.emptyDescription": "Créez un déploiement à partir d'une application Workflow ou d'un package DSL Workflow pour gérer les versions, les environnements et l'accès.",
- "list.emptyFilteredDescription": "Aucun déploiement ne correspond à la recherche ou au filtre d'environnement actuel.",
- "list.emptyFilteredTitle": "Aucun déploiement correspondant",
"list.emptyTitle": "Aucun déploiement pour le moment",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Isolé",
- "mode.ENVIRONMENT_MODE_SHARED": "Partagé",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Inconnu",
- "overview.accessMeta.apiTokens": "Gérer les Tokens API",
- "overview.accessMeta.cli": "Voir l'accès CLI",
- "overview.accessMeta.webApp": "Gérer l'accès WebApp",
- "overview.accessStatus": "Accès",
- "overview.api": "Tokens API",
- "overview.apiKeysCount_one": "{{count}} Token API",
- "overview.apiKeysCount_other": "{{count}} Tokens API",
- "overview.apiTokenSummary.environments_one": "{{count}} environnement déployé",
- "overview.apiTokenSummary.environments_other": "{{count}} environnements déployés",
- "overview.cardAction.deployLatest": "Déployer la dernière version",
- "overview.cardAction.redeploy": "Redéployer",
- "overview.cardAction.viewProgress": "Voir le déploiement",
- "overview.chip.behindTooltip_one": "1 version en retard par rapport à la dernière. Déployez la dernière version pour mettre à jour.",
- "overview.chip.behindTooltip_other": "{{count}} versions en retard par rapport à la dernière. Déployez la dernière version pour mettre à jour.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "déploiement en cours",
- "overview.chip.deployingTooltip": "Un déploiement est en cours.",
- "overview.chip.empty": "vide",
- "overview.chip.emptyTooltip": "Aucune version n'est déployée dans cet environnement.",
- "overview.chip.failed": "en échec",
- "overview.chip.failedTooltip": "La dernière tentative de déploiement a échoué.",
"overview.chip.latest": "dernière",
- "overview.chip.latestTooltip": "Cet environnement exécute la dernière version.",
- "overview.chip.needsReleaseFirst": "Créez d'abord une version",
- "overview.chip.olderRelease": "ancienne",
- "overview.chip.olderReleaseTooltip": "Cet environnement exécute une version plus ancienne.",
- "overview.chip.openInDeployTab": "Voir la progression du déploiement",
- "overview.disabled": "Désactivé",
- "overview.enabled": "Activé",
- "overview.hero.byName": "par {{name}}",
- "overview.hero.empty": "Aucune version pour le moment",
- "overview.hero.emptyDescription": "Créez une version à partir de la source actuelle avant de déployer.",
- "overview.latestRelease.releaseCount_one": "{{count}} version",
- "overview.latestRelease.releaseCount_other": "{{count}} versions",
- "overview.latestReleaseTitle": "Dernière version",
- "overview.previousReleases.viewAll": "Tout voir",
- "overview.strip.deployToNewEnvironment": "Déployer dans un nouvel environnement",
- "overview.strip.emptyDeployableDescription": "Déployez la dernière version dans un environnement lorsque vous êtes prêt.",
- "overview.strip.emptyDescription": "Créez une version avant de déployer dans un environnement.",
- "overview.strip.emptyTitle": "Aucune instance pour le moment",
- "overview.strip.title": "Instances",
- "settings.delete": "Supprimer le déploiement",
- "settings.deleteConfirmDesc": "Supprimer {{name}} ? Chaque instance s'arrêtera et sera supprimée de tous les environnements. Cette action est irréversible.",
- "settings.deleteConfirmTitle": "Supprimer le déploiement",
- "settings.deleteFailed": "Échec de la suppression du déploiement.",
- "settings.deleted": "Déploiement supprimé",
- "settings.description": "Description",
- "settings.name": "Nom du déploiement",
- "settings.save": "Enregistrer les modifications",
- "settings.updateFailed": "Échec de la mise à jour du déploiement.",
- "settings.updated": "Déploiement mis à jour",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Déploiement en cours",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisation en attente",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Échec du déploiement",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Invalide",
"status.RUNTIME_INSTANCE_STATUS_READY": "En cours d'exécution",
@@ -370,87 +89,6 @@
"studio.versionValue": "Valeur de la version",
"studio.versionsBehind_one": "{{count}} version de retard",
"studio.versionsBehind_other": "{{count}} versions de retard",
- "tabs.access.description": "Gérez les canaux d'accès et les autorisations d'accès.",
- "tabs.access.name": "Accès",
- "tabs.api-tokens.description": "Gérez les Tokens API et invoquez les instances via HTTP.",
- "tabs.api-tokens.name": "Tokens API",
- "tabs.instances.description": "Visualisez et gérez les instances dans les environnements déployés.",
- "tabs.instances.name": "Instances",
- "tabs.overview.description": "Consultez le statut du déploiement dans tous les environnements.",
- "tabs.overview.name": "Aperçu",
- "tabs.releases.description": "Créez, déployez et gérez les versions.",
- "tabs.releases.name": "Versions",
- "unsupportedDslNodes.description": "Cette version contient des nœuds que le runtime de déploiement ne prend pas encore en charge. Supprimez-les ou remplacez-les dans Studio, puis réessayez.",
- "unsupportedDslNodes.descriptionWithTypes": "Cette version contient des nœuds que le runtime de déploiement ne prend pas encore en charge : {{nodeTypes}}. Supprimez-les ou remplacez-les dans Studio, puis réessayez.",
- "unsupportedDslNodes.title": "Nœuds non pris en charge",
- "unsupportedDslNodes.unknownType": "Type inconnu",
- "versions.cancelCreate": "Annuler",
- "versions.cancelDelete": "Annuler",
- "versions.cancelEdit": "Annuler",
"versions.checkingReleaseContent": "Vérification du contenu de la version...",
- "versions.col.action": "Action",
- "versions.col.author": "Créé par",
- "versions.col.createdAt": "Créé le",
- "versions.col.deployedTo": "Déployé dans",
- "versions.col.release": "Version",
- "versions.col.sourceApp": "Source",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Créer",
- "versions.createFailed": "Échec de la création de la version.",
- "versions.createRelease": "Créer une version",
- "versions.createReleaseDescription": "Créez une version déployable à partir d'une application Workflow ou d'un fichier DSL Workflow.",
- "versions.createSuccess": "Version « {{name}} » créée.",
- "versions.creating": "Création en cours...",
- "versions.currentOn": "Version actuelle sur {{name}}",
- "versions.deleteConfirmDesc": "La version « {{name}} » sera définitivement supprimée. Cette action est irréversible.",
- "versions.deleteConfirmTitle": "Supprimer la version ?",
- "versions.deleteFailed": "Échec de la suppression de la version.",
- "versions.deleteRelease": "Supprimer la version",
- "versions.deleteSuccess": "Version « {{name}} » supprimée.",
- "versions.deployTo": "Déployer dans {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Déploiement en cours",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisation en attente",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Échec",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Invalide",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "En cours d'exécution",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Non déployé",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Annulation du déploiement",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Inconnu",
- "versions.deployingTo": "{{name}} est en cours de déploiement",
- "versions.disabledReason.checkDeploymentsFailed": "Impossible de vérifier l'utilisation du déploiement. Réessayez plus tard.",
- "versions.disabledReason.checkingDeployments": "Vérification de l'utilisation du déploiement",
- "versions.disabledReason.current": "Cette version s'exécute déjà sur {{name}}",
- "versions.disabledReason.deploying": "Attendez la fin du déploiement actif",
- "versions.disabledReason.releaseInUse_one": "Annulez le déploiement de cette version depuis {{count}} environnement avant de la supprimer",
- "versions.disabledReason.releaseInUse_other": "Annulez le déploiement de cette version depuis {{count}} environnements avant de la supprimer",
- "versions.dslReadFailed": "Échec de la lecture du fichier DSL. Choisissez un autre fichier et réessayez.",
- "versions.dslReading": "Lecture du fichier DSL...",
- "versions.dslUnsupportedMode": "Seuls les fichiers DSL Workflow peuvent être utilisés pour les déploiements.",
- "versions.editFailed": "Échec de la mise à jour de la version.",
- "versions.editRelease": "Modifier la version",
- "versions.editReleaseDescription": "Mettez à jour le nom et la description de cette version.",
- "versions.editSuccess": "Version « {{name}} » mise à jour.",
- "versions.emptyDescription": "Créez la première version avant de déployer dans un environnement.",
- "versions.emptyTitle": "Aucune version pour le moment",
- "versions.exportDsl": "Exporter le DSL",
- "versions.exportDslFailed": "Échec de l'export du DSL.",
- "versions.exportingDsl": "Export en cours...",
- "versions.groupHeader.deploy": "Déployer",
- "versions.groupHeader.rollback": "Déployer une version précédente",
- "versions.groupHeader.unavailable": "Indisponible",
- "versions.manualDslOption": "Téléverser le DSL",
- "versions.moreActions": "Plus d'actions",
- "versions.optional": "Facultatif",
- "versions.releaseAlreadyExists": "Une version avec le même contenu existe déjà : {{name}}.",
- "versions.releaseContentCheckFailed": "Échec de la vérification du contenu de la version.",
- "versions.releaseDescriptionLabel": "Description",
- "versions.releaseDescriptionPlaceholder": "Décrivez cette version",
- "versions.releaseNameConflict": "Une version portant ce nom existe déjà. Choisissez un autre nom.",
- "versions.releaseNameLabel": "Nom de la version",
- "versions.releaseNamePlaceholder": "Nom de la version",
- "versions.releaseNameRequired": "Entrez un nom de version.",
- "versions.releaseSourceLabel": "Source de la version",
- "versions.rollbackTo": "Déployer dans {{name}}",
- "versions.saveEdit": "Enregistrer",
- "versions.sourceAppOption": "Application Workflow"
+ "versions.deployTo": "Déployer dans {{name}}"
}
diff --git a/web/i18n/hi-IN/common.json b/web/i18n/hi-IN/common.json
index 0637fa5fd73..36a93beabbc 100644
--- a/web/i18n/hi-IN/common.json
+++ b/web/i18n/hi-IN/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "ऐप विवरण",
"menus.apps": "स्टूडियो",
"menus.datasets": "ज्ञान",
- "menus.deployments": "डिप्लॉयमेंट",
"menus.exploreMarketplace": "मार्केटप्लेस का अन्वेषण करें",
"menus.plugins": "एकीकरण",
"menus.status": "बीटा",
diff --git a/web/i18n/hi-IN/deployments.json b/web/i18n/hi-IN/deployments.json
index 1a8d43fda14..56e8e742246 100644
--- a/web/i18n/hi-IN/deployments.json
+++ b/web/i18n/hi-IN/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "cURL उदाहरण कॉपी करें",
- "access.api.createFailed": "API टोकन उत्पन्न करने में विफल।",
- "access.api.createKey": "API टोकन उत्पन्न करें",
- "access.api.createKeyTitle": "नया API टोकन उत्पन्न करें",
- "access.api.curlExampleTitle": "cURL उदाहरण",
- "access.api.description": "इस डिप्लॉयमेंट को HTTP के माध्यम से एक्सेस करें। प्रत्येक API टोकन एक वातावरण तक सीमित होता है।",
- "access.api.developerTitle": "डेवलपर API",
- "access.api.disabled": "इस डिप्लॉयमेंट के लिए API एक्सेस बंद है।",
- "access.api.disabledHint": "वातावरण-सीमित टोकन उत्पन्न करने के लिए API एक्सेस सक्षम करें।",
- "access.api.docs": "API दस्तावेज़",
- "access.api.docsClose": "API दस्तावेज़ बंद करें",
- "access.api.docsDescription": "इस डिप्लॉयमेंट के लिए वर्कफ़्लो API संदर्भ देखें।",
- "access.api.docsTitle": "वर्कफ़्लो API दस्तावेज़ीकरण",
- "access.api.empty": "API टोकन जारी करना शुरू करने के लिए पहले किसी वातावरण पर डिप्लॉय करें।",
- "access.api.emptyTitle": "कोई डिप्लॉय किया गया वातावरण नहीं",
- "access.api.endpoint": "अनुरोध URL",
- "access.api.keyList": "API टोकन सूची",
- "access.api.nameLabel": "API टोकन नाम",
- "access.api.namePlaceholder": "API टोकन नाम दर्ज करें",
- "access.api.nameRequired": "API टोकन नाम आवश्यक है।",
- "access.api.newKey": "नया API टोकन उत्पन्न करें",
- "access.api.newTokenDescription": "यह API टोकन केवल एक बार दिखाया जाता है। इस पृष्ठ को छोड़ने से पहले इसे कॉपी कर लें।",
- "access.api.newTokenLabel": "API टोकन",
- "access.api.newTokenTitle": "API टोकन उत्पन्न हुआ",
- "access.api.noKeys": "अभी तक कोई API टोकन नहीं। API को कॉल करना शुरू करने के लिए एक उत्पन्न करें।",
- "access.api.noKeysTitle": "अभी तक कोई API टोकन नहीं",
- "access.api.revokeConfirmDescription": "API टोकन \"{{name}}\" तुरंत काम करना बंद कर देगा। यह क्रिया वापस नहीं ली जा सकती।",
- "access.api.revokeConfirmTitle": "API टोकन रद्द करें?",
- "access.api.revokeFailed": "API टोकन रद्द करने में विफल।",
- "access.api.revokeSuccess": "API टोकन रद्द किया गया",
- "access.api.table.action": "क्रिया",
- "access.api.table.environment": "वातावरण",
- "access.api.table.key": "API टोकन",
- "access.api.table.name": "नाम",
- "access.channels.disabled": "इस डिप्लॉयमेंट के लिए एक्सेस चैनल बंद हैं।",
- "access.channels.disabledHint": "WebApp और CLI प्रवेश बिंदुओं को प्रकट करने के लिए एक्सेस चैनल सक्षम करें।",
- "access.channels.title": "एक्सेस चैनल",
- "access.cli.description": "स्क्रिप्ट, स्वचालित वर्कफ़्लो या एजेंट एकीकरण के लिए उपयुक्त, टर्मिनल से difyctl के साथ इनवोक करें।",
- "access.cli.docs": "उपयोग गाइड",
- "access.cli.domain": "डोमेन",
- "access.cli.empty": "CLI एंडपॉइंट कॉन्फ़िगर नहीं किया गया।",
- "access.cli.install": "CLI इंस्टॉल करें",
- "access.cli.title": "CLI",
- "access.copy": "कॉपी करें",
- "access.copyFailed": "कॉपी विफल",
- "access.members.groupCount_one": "{{count}} समूह",
- "access.members.groupCount_other": "{{count}} समूह",
- "access.members.memberCount_one": "{{count}} सदस्य",
- "access.members.memberCount_other": "{{count}} सदस्य",
- "access.permission.anyone": "लिंक वाला कोई भी",
- "access.permission.organization": "प्लेटफ़ॉर्म के सभी सदस्य",
- "access.permission.specific": "प्लेटफ़ॉर्म के विशिष्ट सदस्य",
- "access.permission.specificDesc": "विशिष्ट समूह या सदस्य चुनें",
- "access.permission.updateFailed": "एक्सेस नीति अपडेट करने में विफल।",
- "access.permissions.editAriaLabel": "{{environment}} के लिए एक्सेस कॉन्फ़िगर करें",
- "access.permissions.editDescription": "WebApp और CLI प्रवेश बिंदुओं के लिए एक्सेस अनुमतियाँ सेट करें।",
- "access.permissions.editTitle": "एक्सेस अनुमतियाँ",
- "access.permissions.title": "एक्सेस अनुमतियाँ",
- "access.revoke": "रद्द करें",
- "access.runAccess.noEnvs": "एक्सेस अनुमतियाँ कॉन्फ़िगर करने के लिए किसी वातावरण पर डिप्लॉय करें।",
- "access.runAccess.noEnvsTitle": "कोई डिप्लॉय किया गया वातावरण नहीं",
- "access.runAccess.openWebapp": "WebApp खोलें",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "अंतिम उपयोगकर्ताओं के लिए होस्ट किया गया वेब पेज।",
- "access.runAccess.webappEmpty": "जल्द आ रहा है।",
- "backend.RUNTIME_BACKEND_EXTERNAL": "बाहरी",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "अज्ञात",
- "card.access.api": "API टोकन",
- "card.access.cli": "CLI",
- "card.access.none": "कोई एक्सेस नहीं",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "पहली रिलीज़ बनाएं",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "डिप्लॉयमेंट हटाएं",
- "card.menu.deploy": "वातावरण पर डिप्लॉय करें",
- "card.menu.editInfo": "जानकारी संपादित करें",
- "card.moreActions": "अधिक क्रियाएँ",
- "card.noDescription": "कोई विवरण प्रदान नहीं किया गया।",
"card.notDeployed": "डिप्लॉय नहीं किया गया",
- "card.tooltip.createdAt": "बनाया गया",
- "card.tooltip.deployed": "डिप्लॉय किया गया",
- "card.tooltip.deploymentStatus": "डिप्लॉयमेंट",
- "card.tooltip.notDeployedShort": "डिप्लॉय नहीं किया गया",
- "card.tooltip.releaseName": "रिलीज़ नाम",
- "card.tooltip.source": "स्रोत",
"common.loadFailed": "लोड करने में विफल। बाद में पुनः प्रयास करें।",
- "createGuide.actions.back": "वापस",
- "createGuide.actions.createAndDeploy": "बनाएं और डिप्लॉय करें",
- "createGuide.actions.creating": "बनाया जा रहा है...",
- "createGuide.actions.deploying": "बनाया और डिप्लॉय किया जा रहा है...",
- "createGuide.actions.next": "अगला",
- "createGuide.actions.skipDeploy": "छोड़ें, बाद में डिप्लॉय करें",
- "createGuide.dsl.defaultAppName": "आयातित DSL ऐप",
- "createGuide.dsl.description": "डिप्लॉयमेंट, पहली रिलीज़ और वैकल्पिक वातावरण डिप्लॉयमेंट बनाने के लिए एक वर्कफ़्लो DSL पैकेज अपलोड करें।",
- "createGuide.dsl.dropDescription": "एक वर्कफ़्लो YAML DSL पैकेज अपलोड करें। डिप्लॉय से पहले इस फ़ाइल से डिप्लॉयमेंट विकल्प हल किए जाते हैं।",
- "createGuide.dsl.dropTitle": "वर्कफ़्लो DSL पैकेज अपलोड करें",
- "createGuide.dsl.readFailed": "DSL फ़ाइल पढ़ने में विफल। दूसरी फ़ाइल चुनें और पुनः प्रयास करें।",
- "createGuide.dsl.reading": "DSL फ़ाइल पढ़ी जा रही है...",
- "createGuide.dsl.title": "DSL आयात करें",
- "createGuide.dsl.unsupportedMode": "डिप्लॉयमेंट के लिए केवल वर्कफ़्लो DSL फ़ाइलों का उपयोग किया जा सकता है।",
- "createGuide.errors.createReleaseFailed": "डिप्लॉयमेंट या रिलीज़ बनाने में विफल।",
- "createGuide.errors.deployFailed": "वातावरण पर डिप्लॉय करने में विफल।",
- "createGuide.method.description": "पहली रिलीज़ बनाने के लिए उपयोग किया जाने वाला स्रोत चुनें।",
- "createGuide.methods.bindApp.description": "रिलीज़ स्रोत के रूप में स्टूडियो में मौजूदा वर्कफ़्लो ऐप का उपयोग करें।",
- "createGuide.methods.bindApp.title": "मौजूदा वर्कफ़्लो ऐप बाइंड करें",
- "createGuide.methods.importDsl.description": "एक वर्कफ़्लो YAML DSL पैकेज अपलोड करें और डिप्लॉयमेंट UI के माध्यम से जारी रखें।",
- "createGuide.methods.importDsl.title": "DSL आयात करें",
- "createGuide.nav.back": "डिप्लॉयमेंट",
- "createGuide.release.defaultName": "प्रारंभिक रिलीज़",
- "createGuide.release.deployInfo": "डिप्लॉयमेंट जानकारी",
- "createGuide.release.description": "डिप्लॉयमेंट जानकारी और पहली रिलीज़ का विवरण भरें।",
- "createGuide.release.firstVersion": "पहली रिलीज़",
- "createGuide.release.instanceDescription": "डिप्लॉयमेंट विवरण",
- "createGuide.release.instanceDescriptionPlaceholder": "बताएं कि इस डिप्लॉयमेंट का उपयोग किस लिए किया जाता है",
- "createGuide.release.instanceName": "डिप्लॉयमेंट नाम",
- "createGuide.release.instanceNameConflict": "इस नाम वाला एक डिप्लॉयमेंट पहले से मौजूद है। दूसरा नाम चुनें।",
- "createGuide.release.releaseDescription": "रिलीज़ विवरण",
- "createGuide.release.releaseDescriptionPlaceholder": "इस रिलीज़ का वर्णन करें",
- "createGuide.release.releaseName": "रिलीज़ नाम",
- "createGuide.release.title": "बुनियादी जानकारी",
- "createGuide.source.clearSearch": "ऐप खोज साफ़ करें",
- "createGuide.source.description": "पहली रिलीज़ बनाने के लिए उपयोग किया जाने वाला स्रोत चुनें।",
- "createGuide.source.empty": "कोई वर्कफ़्लो ऐप नहीं मिला।",
- "createGuide.source.searchPlaceholder": "ऐप्स खोजें",
- "createGuide.source.sourceApp": "वर्कफ़्लो ऐप",
- "createGuide.source.title": "रिलीज़ स्रोत",
- "createGuide.steps.method": "रिलीज़ स्रोत",
- "createGuide.steps.release": "बुनियादी जानकारी",
- "createGuide.steps.source": "रिलीज़ स्रोत",
- "createGuide.steps.target": "वातावरण पर डिप्लॉय करें",
- "createGuide.target.bindingCount_one": "{{count}} बाइंडिंग",
- "createGuide.target.bindingCount_other": "{{count}} बाइंडिंग",
- "createGuide.target.bindingHint": "इस रिलीज़ द्वारा उपयोग किए जाने वाले क्रेडेंशियल चुनें।",
- "createGuide.target.bindings": "क्रेडेंशियल",
- "createGuide.target.description": "एक लक्ष्य वातावरण चुनें और वहां इस रिलीज़ को आवश्यक रनटाइम सेटिंग्स प्रदान करें। यह चरण छोड़ा जा सकता है।",
- "createGuide.target.envVarCount_one": "{{count}} वेरिएबल",
- "createGuide.target.envVarCount_other": "{{count}} वेरिएबल",
- "createGuide.target.envVarHint": "इस रिलीज़ को आवश्यक प्रत्येक वातावरण वेरिएबल के लिए, एक कस्टम मान दर्ज करें या ऐप में परिभाषित मान का उपयोग करें।",
- "createGuide.target.envVarPlaceholder": "मान दर्ज करें",
- "createGuide.target.envVarSource.ariaLabel": "{{key}} के लिए वेरिएबल मान स्रोत चुनें",
- "createGuide.target.envVarSource.default": "ऐप मान",
- "createGuide.target.envVarSource.lastDeployment": "अंतिम डिप्लॉय किया गया मान",
- "createGuide.target.envVarSource.literal": "कस्टम मान",
- "createGuide.target.envVarType.number": "संख्या",
- "createGuide.target.envVarType.secret": "गोपनीय",
- "createGuide.target.envVarType.string": "स्ट्रिंग",
- "createGuide.target.envVars": "वातावरण वेरिएबल",
- "createGuide.target.environment": "लक्ष्य वातावरण",
- "createGuide.target.loadBindingsFailed": "क्रेडेंशियल लोड करने में विफल।",
- "createGuide.target.loadEnvironmentsFailed": "डिप्लॉय वातावरण लोड करने में विफल।",
- "createGuide.target.missingRequiredBinding": "इस आवश्यक बाइंडिंग के लिए एक क्रेडेंशियल चुनें।",
- "createGuide.target.noBindingRequired": "किसी क्रेडेंशियल की आवश्यकता नहीं।",
- "createGuide.target.noCredentialCandidates": "कोई उपलब्ध क्रेडेंशियल नहीं।",
- "createGuide.target.noEnvironmentOptions": "कोई डिप्लॉय वातावरण उपलब्ध नहीं।",
- "createGuide.target.selectCredential": "एक क्रेडेंशियल चुनें",
- "createGuide.target.title": "वातावरण पर डिप्लॉय करें",
- "createGuide.title": "नया डिप्लॉयमेंट",
- "createModal.appPickerPlaceholder": "एक वर्कफ़्लो ऐप चुनें",
- "createModal.appSearchEmpty": "कोई मेल खाने वाला वर्कफ़्लो ऐप नहीं",
- "createModal.appSearchPlaceholder": "वर्कफ़्लो ऐप्स खोजें…",
- "createModal.cancel": "रद्द करें",
- "createModal.loadingApps": "ऐप्स लोड हो रहे हैं…",
- "deployDrawer.bindingCount_one": "{{count}} बाइंडिंग",
- "deployDrawer.bindingCount_other": "{{count}} बाइंडिंग",
"deployDrawer.bindingOptionsFailed": "क्रेडेंशियल विकल्प लोड करने में विफल।",
"deployDrawer.bindingSelectionHint": "इस डिप्लॉयमेंट द्वारा उपयोग किए जाने वाले क्रेडेंशियल चुनें।",
- "deployDrawer.cancel": "रद्द करें",
- "deployDrawer.close": "डिप्लॉयमेंट ड्रॉवर बंद करें",
- "deployDrawer.defaultSelect": "चुनें...",
- "deployDrawer.deploy": "वातावरण पर डिप्लॉय करें",
- "deployDrawer.deployFailed": "डिप्लॉयमेंट शुरू करने में विफल।",
"deployDrawer.deploying": "डिप्लॉय हो रहा है...",
- "deployDrawer.description": "डिप्लॉय करने के लिए एक रिलीज़ और लक्ष्य वातावरण चुनें।",
- "deployDrawer.envVarCount_one": "{{count}} वेरिएबल",
- "deployDrawer.envVarCount_other": "{{count}} वेरिएबल",
- "deployDrawer.envVarHint": "इस रिलीज़ को आवश्यक प्रत्येक वातावरण वेरिएबल के लिए, एक कस्टम मान दर्ज करें या ऐप में परिभाषित मान का उपयोग करें।",
- "deployDrawer.envVarPlaceholder": "मान दर्ज करें",
"deployDrawer.envVarSource.ariaLabel": "{{key}} के लिए वेरिएबल मान स्रोत चुनें",
- "deployDrawer.envVarSource.default": "ऐप मान",
"deployDrawer.envVarSource.lastDeployment": "अंतिम डिप्लॉय किया गया मान",
"deployDrawer.envVarSource.literal": "कस्टम मान",
"deployDrawer.envVarType.number": "संख्या",
"deployDrawer.envVarType.secret": "गोपनीय",
"deployDrawer.envVarType.string": "स्ट्रिंग",
"deployDrawer.envVars": "वातावरण वेरिएबल",
- "deployDrawer.existingReleaseHint": "यह रिलीज़ यथावत डिप्लॉय की जाएगी। कोई नई रिलीज़ नहीं बनाई जाएगी।",
- "deployDrawer.lockedHint": "वर्तमान वातावरण पर लॉक",
- "deployDrawer.missingRequiredBinding": "इस आवश्यक बाइंडिंग के लिए एक क्रेडेंशियल चुनें।",
- "deployDrawer.missingRequiredEnvVar": "इस आवश्यक वातावरण वेरिएबल के लिए एक मान दर्ज करें।",
- "deployDrawer.noBindingRequired": "आवश्यक नहीं",
"deployDrawer.noCredentialCandidates": "कोई उपलब्ध क्रेडेंशियल नहीं।",
"deployDrawer.noNewEnvironmentAvailable": "सभी उपलब्ध वातावरणों में पहले से ही एक डिप्लॉयमेंट है।",
- "deployDrawer.noOtherReleaseAvailable": "इस वातावरण के लिए कोई अन्य रिलीज़ उपलब्ध नहीं है।",
- "deployDrawer.noReleaseAvailable": "किसी वातावरण पर डिप्लॉय करने से पहले एक रिलीज़ बनाएं।",
- "deployDrawer.notFound": "डिप्लॉयमेंट नहीं मिला।",
- "deployDrawer.releaseLabel": "रिलीज़",
"deployDrawer.runtimeCredentials": "क्रेडेंशियल",
"deployDrawer.selectCredential": "एक क्रेडेंशियल चुनें",
- "deployDrawer.selectEnv": "एक वातावरण चुनें",
- "deployDrawer.selectRelease": "एक रिलीज़ चुनें",
- "deployDrawer.targetEnv": "लक्ष्य वातावरण",
- "deployDrawer.title": "वातावरण पर डिप्लॉय करें",
- "deployTab.closeError": "बंद करें",
"deployTab.col.actions": "क्रियाएँ",
- "deployTab.col.currentRelease": "वर्तमान रिलीज़",
"deployTab.col.environment": "वातावरण",
"deployTab.col.status": "स्थिति",
"deployTab.confirmUndeploy": "अनडिप्लॉय करें",
- "deployTab.deployOtherVersion": "अन्य रिलीज़ डिप्लॉय करें",
- "deployTab.emptyDescription": "इस डिप्लॉयमेंट को उपयोगकर्ताओं के लिए उपलब्ध कराने हेतु एक रिलीज़ और लक्ष्य वातावरण चुनें।",
- "deployTab.emptyTitle": "अभी तक कोई वातावरण नहीं चल रहा",
- "deployTab.errorCode": "कोड",
- "deployTab.errorDialogDesc": "पुनः प्रयास करने या अन्य रिलीज़ डिप्लॉय करने से पहले अंतिम विफल डिप्लॉयमेंट की समीक्षा करें।",
- "deployTab.errorDialogTitle": "{{name}} में डिप्लॉयमेंट त्रुटि",
- "deployTab.errorMessage": "संदेश",
- "deployTab.errorPhase": "चरण",
"deployTab.moreActions": "अधिक क्रियाएँ",
- "deployTab.newDeployment": "नए वातावरण पर डिप्लॉय करें",
- "deployTab.panel.unknownError": "डिप्लॉयमेंट विफल।",
"deployTab.redeploy": "पुनः डिप्लॉय करें",
- "deployTab.retry": "पुनः प्रयास करें",
- "deployTab.status.deployFailed": "डिप्लॉय विफल",
- "deployTab.status.deployingRelease": "डिप्लॉय हो रहा है ({{release}})",
- "deployTab.status.runningOutOfSync": "चल रहा है (सिंक लंबित)",
- "deployTab.status.runningWithFailed": "चल रहा है (अंतिम डिप्लॉयमेंट विफल)",
"deployTab.undeploy": "अनडिप्लॉय करें",
- "deployTab.undeployConfirmDesc": "एनवायरनमेंट एंडपॉइंट अनुपलब्ध हो जाएगा, लेकिन वर्शन हटाया नहीं जाएगा।",
- "deployTab.undeployConfirmTitle": "{{name}} को अनडिप्लॉय करें?",
"deployTab.undeployConfirmWarning": "पुष्टि के बाद, यह एनवायरनमेंट अनडिप्लॉयिंग स्थिति में चला जाएगा और कार्रवाइयां अस्थायी रूप से अक्षम रहेंगी।",
- "deployTab.viewError": "त्रुटि देखें",
- "detail.mobileTabs": "डिप्लॉयमेंट अनुभाग",
- "detail.notFound": "डिप्लॉयमेंट नहीं मिला",
- "documentTitle.create": "नया डिप्लॉयमेंट · डिप्लॉयमेंट",
- "documentTitle.detail": "डिप्लॉयमेंट · डिप्लॉयमेंट",
- "documentTitle.list": "डिप्लॉयमेंट",
- "filter.allEnvs": "सभी वातावरण",
- "filter.searchPlaceholder": "डिप्लॉयमेंट खोजें",
- "health.ENVIRONMENT_STATUS_ADMISSION": "प्रवेश",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "बूटस्ट्रैपिंग",
- "health.ENVIRONMENT_STATUS_DELETING": "हटाया जा रहा है",
"health.ENVIRONMENT_STATUS_FAILED": "अनुपलब्ध",
- "health.ENVIRONMENT_STATUS_READY": "उपलब्ध",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "अज्ञात",
- "list.clearFilters": "फ़िल्टर साफ़ करें",
- "list.clearSearch": "डिप्लॉयमेंट खोज साफ़ करें",
- "list.createDeployment": "नया",
- "list.emptyDescription": "रिलीज़, वातावरण और एक्सेस का प्रबंधन करने के लिए वर्कफ़्लो ऐप या वर्कफ़्लो DSL पैकेज से एक डिप्लॉयमेंट बनाएं।",
- "list.emptyFilteredDescription": "वर्तमान खोज या वातावरण फ़िल्टर से कोई डिप्लॉयमेंट मेल नहीं खाता।",
- "list.emptyFilteredTitle": "कोई मेल खाने वाला डिप्लॉयमेंट नहीं",
"list.emptyTitle": "अभी तक कोई डिप्लॉयमेंट नहीं",
- "mode.ENVIRONMENT_MODE_ISOLATED": "पृथक",
- "mode.ENVIRONMENT_MODE_SHARED": "साझा",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "अज्ञात",
- "overview.accessMeta.apiTokens": "API टोकन प्रबंधित करें",
- "overview.accessMeta.cli": "CLI एक्सेस देखें",
- "overview.accessMeta.webApp": "WebApp एक्सेस प्रबंधित करें",
- "overview.accessStatus": "एक्सेस",
- "overview.api": "API टोकन",
- "overview.apiKeysCount_one": "{{count}} API टोकन",
- "overview.apiKeysCount_other": "{{count}} API टोकन",
- "overview.apiTokenSummary.environments_one": "{{count}} डिप्लॉय किया गया वातावरण",
- "overview.apiTokenSummary.environments_other": "{{count}} डिप्लॉय किए गए वातावरण",
- "overview.cardAction.deployLatest": "नवीनतम रिलीज़ डिप्लॉय करें",
- "overview.cardAction.redeploy": "पुनः डिप्लॉय करें",
- "overview.cardAction.viewProgress": "डिप्लॉयमेंट देखें",
- "overview.chip.behindTooltip_one": "नवीनतम से 1 रिलीज़ पीछे। अपडेट करने के लिए नवीनतम रिलीज़ डिप्लॉय करें।",
- "overview.chip.behindTooltip_other": "नवीनतम से {{count}} रिलीज़ पीछे। अपडेट करने के लिए नवीनतम रिलीज़ डिप्लॉय करें।",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "डिप्लॉय हो रहा है",
- "overview.chip.deployingTooltip": "डिप्लॉयमेंट प्रगति पर है।",
- "overview.chip.empty": "खाली",
- "overview.chip.emptyTooltip": "इस वातावरण पर कोई रिलीज़ डिप्लॉय नहीं की गई है।",
- "overview.chip.failed": "विफल",
- "overview.chip.failedTooltip": "नवीनतम डिप्लॉयमेंट प्रयास विफल रहा।",
"overview.chip.latest": "नवीनतम",
- "overview.chip.latestTooltip": "यह वातावरण नवीनतम रिलीज़ चला रहा है।",
- "overview.chip.needsReleaseFirst": "पहले एक रिलीज़ बनाएं",
- "overview.chip.olderRelease": "पुराना",
- "overview.chip.olderReleaseTooltip": "यह वातावरण पुरानी रिलीज़ चला रहा है।",
- "overview.chip.openInDeployTab": "डिप्लॉयमेंट प्रगति देखें",
- "overview.disabled": "अक्षम",
- "overview.enabled": "सक्षम",
- "overview.hero.byName": "{{name}} द्वारा",
- "overview.hero.empty": "अभी तक कोई रिलीज़ नहीं",
- "overview.hero.emptyDescription": "डिप्लॉय करने से पहले वर्तमान स्रोत से एक रिलीज़ बनाएं।",
- "overview.latestRelease.releaseCount_one": "{{count}} रिलीज़",
- "overview.latestRelease.releaseCount_other": "{{count}} रिलीज़",
- "overview.latestReleaseTitle": "नवीनतम रिलीज़",
- "overview.previousReleases.viewAll": "सभी देखें",
- "overview.strip.deployToNewEnvironment": "नए वातावरण पर डिप्लॉय करें",
- "overview.strip.emptyDeployableDescription": "जब आप तैयार हों तो नवीनतम रिलीज़ को किसी वातावरण पर डिप्लॉय करें।",
- "overview.strip.emptyDescription": "किसी वातावरण पर डिप्लॉय करने से पहले एक रिलीज़ बनाएं।",
- "overview.strip.emptyTitle": "अभी तक कोई इंस्टेंस नहीं",
- "overview.strip.title": "इंस्टेंस",
- "settings.delete": "डिप्लॉयमेंट हटाएं",
- "settings.deleteConfirmDesc": "{{name}} हटाएं? प्रत्येक इंस्टेंस सभी वातावरणों में चलना बंद कर देगा और हटा दिया जाएगा। इसे वापस नहीं लिया जा सकता।",
- "settings.deleteConfirmTitle": "डिप्लॉयमेंट हटाएं",
- "settings.deleteFailed": "डिप्लॉयमेंट हटाने में विफल।",
- "settings.deleted": "डिप्लॉयमेंट हटाया गया",
- "settings.description": "विवरण",
- "settings.name": "डिप्लॉयमेंट नाम",
- "settings.save": "परिवर्तन सहेजें",
- "settings.updateFailed": "डिप्लॉयमेंट अपडेट करने में विफल।",
- "settings.updated": "डिप्लॉयमेंट अपडेट किया गया",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "डिप्लॉय हो रहा है",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "सिंक लंबित",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "डिप्लॉय विफल",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "अमान्य",
"status.RUNTIME_INSTANCE_STATUS_READY": "चल रहा है",
@@ -370,87 +89,6 @@
"studio.versionValue": "वर्शन का मान",
"studio.versionsBehind_one": "{{count}} वर्शन पीछे",
"studio.versionsBehind_other": "{{count}} वर्शन पीछे",
- "tabs.access.description": "एक्सेस चैनल और एक्सेस अनुमतियाँ प्रबंधित करें।",
- "tabs.access.name": "एक्सेस",
- "tabs.api-tokens.description": "API टोकन प्रबंधित करें और HTTP पर इंस्टेंस इनवोक करें।",
- "tabs.api-tokens.name": "API टोकन",
- "tabs.instances.description": "डिप्लॉय किए गए वातावरणों में इंस्टेंस देखें और प्रबंधित करें।",
- "tabs.instances.name": "इंस्टेंस",
- "tabs.overview.description": "वातावरणों में डिप्लॉयमेंट की स्थिति देखें।",
- "tabs.overview.name": "अवलोकन",
- "tabs.releases.description": "रिलीज़ बनाएं, डिप्लॉय करें और प्रबंधित करें।",
- "tabs.releases.name": "रिलीज़",
- "unsupportedDslNodes.description": "इस रिलीज़ में ऐसे नोड हैं जिनका डिप्लॉयमेंट रनटाइम अभी समर्थन नहीं करता है। उन्हें स्टूडियो में हटाएं या बदलें, फिर पुनः प्रयास करें।",
- "unsupportedDslNodes.descriptionWithTypes": "इस रिलीज़ में ऐसे नोड हैं जिनका डिप्लॉयमेंट रनटाइम अभी समर्थन नहीं करता है: {{nodeTypes}}. उन्हें स्टूडियो में हटाएं या बदलें, फिर पुनः प्रयास करें।",
- "unsupportedDslNodes.title": "असमर्थित नोड",
- "unsupportedDslNodes.unknownType": "अज्ञात प्रकार",
- "versions.cancelCreate": "रद्द करें",
- "versions.cancelDelete": "रद्द करें",
- "versions.cancelEdit": "रद्द करें",
"versions.checkingReleaseContent": "रिलीज़ सामग्री जांची जा रही है...",
- "versions.col.action": "क्रिया",
- "versions.col.author": "द्वारा बनाया गया",
- "versions.col.createdAt": "बनाया गया",
- "versions.col.deployedTo": "डिप्लॉय किया गया",
- "versions.col.release": "रिलीज़",
- "versions.col.sourceApp": "स्रोत",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "बनाएं",
- "versions.createFailed": "रिलीज़ बनाने में विफल।",
- "versions.createRelease": "रिलीज़ बनाएं",
- "versions.createReleaseDescription": "वर्कफ़्लो ऐप या वर्कफ़्लो DSL फ़ाइल से एक डिप्लॉय करने योग्य रिलीज़ बनाएं।",
- "versions.createSuccess": "रिलीज़ \"{{name}}\" बनाई गई।",
- "versions.creating": "बनाया जा रहा है...",
- "versions.currentOn": "{{name}} पर वर्तमान रिलीज़",
- "versions.deleteConfirmDesc": "रिलीज़ \"{{name}}\" स्थायी रूप से हटा दी जाएगी। इसे वापस नहीं लिया जा सकता।",
- "versions.deleteConfirmTitle": "रिलीज़ हटाएं?",
- "versions.deleteFailed": "रिलीज़ हटाने में विफल।",
- "versions.deleteRelease": "रिलीज़ हटाएं",
- "versions.deleteSuccess": "रिलीज़ \"{{name}}\" हटाई गई।",
- "versions.deployTo": "{{name}} पर डिप्लॉय करें",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "डिप्लॉय हो रहा है",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "सिंक लंबित",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "विफल",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "अमान्य",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "चल रहा है",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "डिप्लॉय नहीं किया गया",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "अनडिप्लॉय हो रहा है",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "अज्ञात",
- "versions.deployingTo": "{{name}} डिप्लॉय हो रहा है",
- "versions.disabledReason.checkDeploymentsFailed": "डिप्लॉयमेंट उपयोग सत्यापित नहीं किया जा सका। बाद में पुनः प्रयास करें।",
- "versions.disabledReason.checkingDeployments": "डिप्लॉयमेंट उपयोग जांचा जा रहा है",
- "versions.disabledReason.current": "यह रिलीज़ पहले से ही {{name}} पर चल रही है",
- "versions.disabledReason.deploying": "सक्रिय डिप्लॉयमेंट के पूर्ण होने की प्रतीक्षा करें",
- "versions.disabledReason.releaseInUse_one": "इसे हटाने से पहले इस रिलीज़ को {{count}} वातावरण से अनडिप्लॉय करें",
- "versions.disabledReason.releaseInUse_other": "इसे हटाने से पहले इस रिलीज़ को {{count}} वातावरणों से अनडिप्लॉय करें",
- "versions.dslReadFailed": "DSL फ़ाइल पढ़ने में विफल। दूसरी फ़ाइल चुनें और पुनः प्रयास करें।",
- "versions.dslReading": "DSL फ़ाइल पढ़ी जा रही है...",
- "versions.dslUnsupportedMode": "डिप्लॉयमेंट के लिए केवल वर्कफ़्लो DSL फ़ाइलों का उपयोग किया जा सकता है।",
- "versions.editFailed": "रिलीज़ अपडेट करने में विफल।",
- "versions.editRelease": "रिलीज़ संपादित करें",
- "versions.editReleaseDescription": "इस रिलीज़ का नाम और विवरण अपडेट करें।",
- "versions.editSuccess": "रिलीज़ \"{{name}}\" अपडेट की गई।",
- "versions.emptyDescription": "किसी वातावरण पर डिप्लॉय करने से पहले पहली रिलीज़ बनाएं।",
- "versions.emptyTitle": "अभी तक कोई रिलीज़ नहीं",
- "versions.exportDsl": "DSL निर्यात करें",
- "versions.exportDslFailed": "DSL निर्यात करने में विफल।",
- "versions.exportingDsl": "निर्यात किया जा रहा है...",
- "versions.groupHeader.deploy": "डिप्लॉय करें",
- "versions.groupHeader.rollback": "पिछला संस्करण डिप्लॉय करें",
- "versions.groupHeader.unavailable": "अनुपलब्ध",
- "versions.manualDslOption": "DSL अपलोड करें",
- "versions.moreActions": "अधिक क्रियाएँ",
- "versions.optional": "वैकल्पिक",
- "versions.releaseAlreadyExists": "उसी सामग्री वाली एक रिलीज़ पहले से मौजूद है: {{name}}.",
- "versions.releaseContentCheckFailed": "रिलीज़ सामग्री जांचने में विफल।",
- "versions.releaseDescriptionLabel": "विवरण",
- "versions.releaseDescriptionPlaceholder": "इस रिलीज़ का वर्णन करें",
- "versions.releaseNameConflict": "इस नाम वाली रिलीज़ पहले से मौजूद है। कोई दूसरा नाम चुनें।",
- "versions.releaseNameLabel": "रिलीज़ नाम",
- "versions.releaseNamePlaceholder": "रिलीज़ नाम",
- "versions.releaseNameRequired": "एक रिलीज़ नाम दर्ज करें।",
- "versions.releaseSourceLabel": "रिलीज़ स्रोत",
- "versions.rollbackTo": "{{name}} पर डिप्लॉय करें",
- "versions.saveEdit": "सहेजें",
- "versions.sourceAppOption": "वर्कफ़्लो ऐप"
+ "versions.deployTo": "{{name}} पर डिप्लॉय करें"
}
diff --git a/web/i18n/id-ID/common.json b/web/i18n/id-ID/common.json
index 70d75ce4a80..3e4a1e3a7f5 100644
--- a/web/i18n/id-ID/common.json
+++ b/web/i18n/id-ID/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Detail Aplikasi",
"menus.apps": "Aplikasi",
"menus.datasets": "Pengetahuan",
- "menus.deployments": "Penerapan",
"menus.exploreMarketplace": "Jelajahi Marketplace",
"menus.plugins": "Integrasi",
"menus.status": "beta",
diff --git a/web/i18n/id-ID/deployments.json b/web/i18n/id-ID/deployments.json
index cf158ed9882..3fba5686487 100644
--- a/web/i18n/id-ID/deployments.json
+++ b/web/i18n/id-ID/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Salin contoh cURL",
- "access.api.createFailed": "Gagal membuat API Token.",
- "access.api.createKey": "Buat API Token",
- "access.api.createKeyTitle": "Buat API Token baru",
- "access.api.curlExampleTitle": "Contoh cURL",
- "access.api.description": "Akses penerapan ini melalui HTTP. Setiap API Token dibatasi pada satu lingkungan.",
- "access.api.developerTitle": "API Developer",
- "access.api.disabled": "Akses API dimatikan untuk penerapan ini.",
- "access.api.disabledHint": "Aktifkan akses API untuk membuat token yang dibatasi per lingkungan.",
- "access.api.docs": "Dokumentasi API",
- "access.api.docsClose": "Tutup dokumentasi API",
- "access.api.docsDescription": "Lihat referensi API Workflow untuk penerapan ini.",
- "access.api.docsTitle": "Dokumentasi API Workflow",
- "access.api.empty": "Terapkan ke lingkungan terlebih dahulu untuk mulai menerbitkan API Token.",
- "access.api.emptyTitle": "Tidak ada lingkungan yang diterapkan",
- "access.api.endpoint": "URL Permintaan",
- "access.api.keyList": "Daftar API Token",
- "access.api.nameLabel": "Nama API Token",
- "access.api.namePlaceholder": "Masukkan nama API Token",
- "access.api.nameRequired": "Nama API Token wajib diisi.",
- "access.api.newKey": "Buat API Token Baru",
- "access.api.newTokenDescription": "API Token ini hanya ditampilkan sekali. Salin sebelum meninggalkan halaman ini.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token berhasil dibuat",
- "access.api.noKeys": "Belum ada API Token. Buat satu untuk mulai memanggil API.",
- "access.api.noKeysTitle": "Belum ada API Token",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" akan segera berhenti berfungsi. Tindakan ini tidak dapat dibatalkan.",
- "access.api.revokeConfirmTitle": "Cabut API Token?",
- "access.api.revokeFailed": "Gagal mencabut API Token.",
- "access.api.revokeSuccess": "API Token dicabut",
- "access.api.table.action": "Aksi",
- "access.api.table.environment": "Lingkungan",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Nama",
- "access.channels.disabled": "Saluran akses dimatikan untuk penerapan ini.",
- "access.channels.disabledHint": "Aktifkan saluran akses untuk menampilkan titik masuk WebApp dan CLI.",
- "access.channels.title": "Saluran akses",
- "access.cli.description": "Panggil dari terminal dengan difyctl, cocok untuk skrip, alur kerja otomatis, atau integrasi Agent.",
- "access.cli.docs": "Panduan penggunaan",
- "access.cli.domain": "Domain",
- "access.cli.empty": "Endpoint CLI belum dikonfigurasi.",
- "access.cli.install": "Instal CLI",
- "access.cli.title": "CLI",
- "access.copy": "Salin",
- "access.copyFailed": "Gagal menyalin",
- "access.members.groupCount_one": "{{count}} grup",
- "access.members.groupCount_other": "{{count}} grup",
- "access.members.memberCount_one": "{{count}} anggota",
- "access.members.memberCount_other": "{{count}} anggota",
- "access.permission.anyone": "Siapa saja dengan tautan",
- "access.permission.organization": "Semua anggota dalam platform",
- "access.permission.specific": "Anggota tertentu dalam platform",
- "access.permission.specificDesc": "Pilih grup atau anggota tertentu",
- "access.permission.updateFailed": "Gagal memperbarui kebijakan akses.",
- "access.permissions.editAriaLabel": "Konfigurasikan akses untuk {{environment}}",
- "access.permissions.editDescription": "Atur izin akses untuk titik masuk WebApp dan CLI.",
- "access.permissions.editTitle": "Izin akses",
- "access.permissions.title": "Izin akses",
- "access.revoke": "Cabut",
- "access.runAccess.noEnvs": "Terapkan ke lingkungan untuk mengonfigurasi izin akses.",
- "access.runAccess.noEnvsTitle": "Tidak ada lingkungan yang diterapkan",
- "access.runAccess.openWebapp": "Buka WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Halaman web yang dihosting untuk pengguna akhir.",
- "access.runAccess.webappEmpty": "Segera hadir.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Eksternal",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Tidak diketahui",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Tidak ada akses",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Buat Rilis Pertama",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Hapus penerapan",
- "card.menu.deploy": "Terapkan ke Lingkungan",
- "card.menu.editInfo": "Edit Info",
- "card.moreActions": "Aksi lainnya",
- "card.noDescription": "Tidak ada deskripsi.",
"card.notDeployed": "Belum diterapkan",
- "card.tooltip.createdAt": "Dibuat",
- "card.tooltip.deployed": "Diterapkan",
- "card.tooltip.deploymentStatus": "Penerapan",
- "card.tooltip.notDeployedShort": "Belum diterapkan",
- "card.tooltip.releaseName": "Nama Rilis",
- "card.tooltip.source": "Sumber",
"common.loadFailed": "Gagal memuat. Coba lagi nanti.",
- "createGuide.actions.back": "Kembali",
- "createGuide.actions.createAndDeploy": "Buat & Terapkan",
- "createGuide.actions.creating": "Membuat...",
- "createGuide.actions.deploying": "Membuat & menerapkan...",
- "createGuide.actions.next": "Selanjutnya",
- "createGuide.actions.skipDeploy": "Lewati, terapkan nanti",
- "createGuide.dsl.defaultAppName": "Aplikasi DSL yang diimpor",
- "createGuide.dsl.description": "Unggah paket DSL Workflow untuk membuat penerapan, rilis pertama, dan penerapan lingkungan opsional.",
- "createGuide.dsl.dropDescription": "Unggah paket YAML DSL Workflow. Opsi penerapan diselesaikan dari file ini sebelum penerapan.",
- "createGuide.dsl.dropTitle": "Unggah paket DSL Workflow",
- "createGuide.dsl.readFailed": "Gagal membaca file DSL. Pilih file lain dan coba lagi.",
- "createGuide.dsl.reading": "Membaca file DSL...",
- "createGuide.dsl.title": "Impor DSL",
- "createGuide.dsl.unsupportedMode": "Hanya file DSL Workflow yang dapat digunakan untuk penerapan.",
- "createGuide.errors.createReleaseFailed": "Gagal membuat penerapan atau rilis.",
- "createGuide.errors.deployFailed": "Gagal menerapkan ke lingkungan.",
- "createGuide.method.description": "Pilih sumber yang digunakan untuk membuat rilis pertama.",
- "createGuide.methods.bindApp.description": "Gunakan Aplikasi Workflow yang ada di Studio sebagai sumber rilis.",
- "createGuide.methods.bindApp.title": "Hubungkan Aplikasi Workflow yang ada",
- "createGuide.methods.importDsl.description": "Unggah paket YAML DSL Workflow dan lanjutkan melalui UI penerapan.",
- "createGuide.methods.importDsl.title": "Impor DSL",
- "createGuide.nav.back": "Penerapan",
- "createGuide.release.defaultName": "rilis awal",
- "createGuide.release.deployInfo": "Info Penerapan",
- "createGuide.release.description": "Isi info penerapan dan detail rilis pertama.",
- "createGuide.release.firstVersion": "Rilis Pertama",
- "createGuide.release.instanceDescription": "Deskripsi Penerapan",
- "createGuide.release.instanceDescriptionPlaceholder": "Jelaskan untuk apa penerapan ini digunakan",
- "createGuide.release.instanceName": "Nama Penerapan",
- "createGuide.release.instanceNameConflict": "Penerapan dengan nama ini sudah ada. Pilih nama lain.",
- "createGuide.release.releaseDescription": "Deskripsi Rilis",
- "createGuide.release.releaseDescriptionPlaceholder": "Jelaskan rilis ini",
- "createGuide.release.releaseName": "Nama Rilis",
- "createGuide.release.title": "Info Dasar",
- "createGuide.source.clearSearch": "Hapus pencarian aplikasi",
- "createGuide.source.description": "Pilih sumber yang digunakan untuk membuat rilis pertama.",
- "createGuide.source.empty": "Tidak ditemukan Aplikasi Workflow.",
- "createGuide.source.searchPlaceholder": "Cari aplikasi",
- "createGuide.source.sourceApp": "Aplikasi Workflow",
- "createGuide.source.title": "Sumber Rilis",
- "createGuide.steps.method": "Sumber Rilis",
- "createGuide.steps.release": "Info Dasar",
- "createGuide.steps.source": "Sumber Rilis",
- "createGuide.steps.target": "Terapkan ke Lingkungan",
- "createGuide.target.bindingCount_one": "{{count}} pengikatan",
- "createGuide.target.bindingCount_other": "{{count}} pengikatan",
- "createGuide.target.bindingHint": "Pilih kredensial yang digunakan oleh rilis ini.",
- "createGuide.target.bindings": "Kredensial",
- "createGuide.target.description": "Pilih lingkungan target dan berikan pengaturan runtime yang dibutuhkan rilis ini di sana. Langkah ini dapat dilewati.",
- "createGuide.target.envVarCount_one": "{{count}} variabel",
- "createGuide.target.envVarCount_other": "{{count}} variabel",
- "createGuide.target.envVarHint": "Untuk setiap variabel lingkungan yang dibutuhkan rilis ini, masukkan nilai kustom atau gunakan nilai yang didefinisikan dalam aplikasi.",
- "createGuide.target.envVarPlaceholder": "Masukkan nilai",
- "createGuide.target.envVarSource.ariaLabel": "Pilih sumber nilai variabel untuk {{key}}",
- "createGuide.target.envVarSource.default": "Nilai aplikasi",
- "createGuide.target.envVarSource.lastDeployment": "Nilai terakhir diterapkan",
- "createGuide.target.envVarSource.literal": "Nilai kustom",
- "createGuide.target.envVarType.number": "Angka",
- "createGuide.target.envVarType.secret": "Rahasia",
- "createGuide.target.envVarType.string": "String",
- "createGuide.target.envVars": "Variabel Lingkungan",
- "createGuide.target.environment": "Lingkungan Target",
- "createGuide.target.loadBindingsFailed": "Gagal memuat kredensial.",
- "createGuide.target.loadEnvironmentsFailed": "Gagal memuat lingkungan penerapan.",
- "createGuide.target.missingRequiredBinding": "Pilih kredensial untuk pengikatan yang wajib ini.",
- "createGuide.target.noBindingRequired": "Tidak ada kredensial yang diperlukan.",
- "createGuide.target.noCredentialCandidates": "Tidak ada kredensial yang tersedia.",
- "createGuide.target.noEnvironmentOptions": "Tidak ada lingkungan penerapan yang tersedia.",
- "createGuide.target.selectCredential": "Pilih kredensial",
- "createGuide.target.title": "Terapkan ke Lingkungan",
- "createGuide.title": "Penerapan Baru",
- "createModal.appPickerPlaceholder": "Pilih Aplikasi Workflow",
- "createModal.appSearchEmpty": "Tidak ada Aplikasi Workflow yang cocok",
- "createModal.appSearchPlaceholder": "Cari Aplikasi Workflow…",
- "createModal.cancel": "Batal",
- "createModal.loadingApps": "Memuat aplikasi…",
- "deployDrawer.bindingCount_one": "{{count}} pengikatan",
- "deployDrawer.bindingCount_other": "{{count}} pengikatan",
"deployDrawer.bindingOptionsFailed": "Gagal memuat opsi kredensial.",
"deployDrawer.bindingSelectionHint": "Pilih kredensial yang digunakan oleh penerapan ini.",
- "deployDrawer.cancel": "Batal",
- "deployDrawer.close": "Tutup drawer penerapan",
- "deployDrawer.defaultSelect": "Pilih...",
- "deployDrawer.deploy": "Terapkan ke Lingkungan",
- "deployDrawer.deployFailed": "Gagal memulai penerapan.",
"deployDrawer.deploying": "Menerapkan...",
- "deployDrawer.description": "Pilih rilis dan lingkungan target untuk menerapkan.",
- "deployDrawer.envVarCount_one": "{{count}} variabel",
- "deployDrawer.envVarCount_other": "{{count}} variabel",
- "deployDrawer.envVarHint": "Untuk setiap variabel lingkungan yang dibutuhkan rilis ini, masukkan nilai kustom atau gunakan nilai yang didefinisikan dalam aplikasi.",
- "deployDrawer.envVarPlaceholder": "Masukkan nilai",
"deployDrawer.envVarSource.ariaLabel": "Pilih sumber nilai variabel untuk {{key}}",
- "deployDrawer.envVarSource.default": "Nilai aplikasi",
"deployDrawer.envVarSource.lastDeployment": "Nilai terakhir diterapkan",
"deployDrawer.envVarSource.literal": "Nilai kustom",
"deployDrawer.envVarType.number": "Angka",
"deployDrawer.envVarType.secret": "Rahasia",
"deployDrawer.envVarType.string": "String",
"deployDrawer.envVars": "Variabel Lingkungan",
- "deployDrawer.existingReleaseHint": "Rilis ini akan diterapkan apa adanya. Tidak ada rilis baru yang akan dibuat.",
- "deployDrawer.lockedHint": "Terkunci pada lingkungan saat ini",
- "deployDrawer.missingRequiredBinding": "Pilih kredensial untuk pengikatan yang wajib ini.",
- "deployDrawer.missingRequiredEnvVar": "Masukkan nilai untuk variabel lingkungan yang wajib ini.",
- "deployDrawer.noBindingRequired": "Tidak wajib",
"deployDrawer.noCredentialCandidates": "Tidak ada kredensial yang tersedia.",
"deployDrawer.noNewEnvironmentAvailable": "Semua lingkungan yang tersedia sudah memiliki penerapan.",
- "deployDrawer.noOtherReleaseAvailable": "Tidak ada rilis lain yang tersedia untuk lingkungan ini.",
- "deployDrawer.noReleaseAvailable": "Buat rilis sebelum menerapkan ke lingkungan.",
- "deployDrawer.notFound": "Penerapan tidak ditemukan.",
- "deployDrawer.releaseLabel": "Rilis",
"deployDrawer.runtimeCredentials": "Kredensial",
"deployDrawer.selectCredential": "Pilih kredensial",
- "deployDrawer.selectEnv": "Pilih lingkungan",
- "deployDrawer.selectRelease": "Pilih rilis",
- "deployDrawer.targetEnv": "Lingkungan Target",
- "deployDrawer.title": "Terapkan ke Lingkungan",
- "deployTab.closeError": "Tutup",
"deployTab.col.actions": "Aksi",
- "deployTab.col.currentRelease": "Rilis Saat Ini",
"deployTab.col.environment": "Lingkungan",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Batalkan Penerapan",
- "deployTab.deployOtherVersion": "Terapkan Rilis Lain",
- "deployTab.emptyDescription": "Pilih rilis dan lingkungan target untuk membuat penerapan ini tersedia bagi pengguna.",
- "deployTab.emptyTitle": "Belum ada lingkungan yang berjalan",
- "deployTab.errorCode": "Kode",
- "deployTab.errorDialogDesc": "Tinjau penerapan terakhir yang gagal sebelum mencoba lagi atau menerapkan rilis lain.",
- "deployTab.errorDialogTitle": "Kesalahan penerapan di {{name}}",
- "deployTab.errorMessage": "Pesan",
- "deployTab.errorPhase": "Fase",
"deployTab.moreActions": "Aksi lainnya",
- "deployTab.newDeployment": "Terapkan ke Lingkungan Baru",
- "deployTab.panel.unknownError": "Penerapan gagal.",
"deployTab.redeploy": "Terapkan Ulang",
- "deployTab.retry": "Coba lagi",
- "deployTab.status.deployFailed": "Penerapan gagal",
- "deployTab.status.deployingRelease": "Menerapkan ({{release}})",
- "deployTab.status.runningOutOfSync": "Berjalan (sinkronisasi tertunda)",
- "deployTab.status.runningWithFailed": "Berjalan (penerapan terakhir gagal)",
"deployTab.undeploy": "Batalkan Penerapan",
- "deployTab.undeployConfirmDesc": "Endpoint lingkungan akan menjadi tidak tersedia, tetapi versi tidak akan dihapus.",
- "deployTab.undeployConfirmTitle": "Batalkan penerapan {{name}}?",
"deployTab.undeployConfirmWarning": "Setelah dikonfirmasi, lingkungan ini akan masuk ke status pembatalan penerapan dan tindakan akan dinonaktifkan sementara.",
- "deployTab.viewError": "Lihat kesalahan",
- "detail.mobileTabs": "Bagian penerapan",
- "detail.notFound": "Penerapan tidak ditemukan",
- "documentTitle.create": "Penerapan baru · Penerapan",
- "documentTitle.detail": "Penerapan · Penerapan",
- "documentTitle.list": "Penerapan",
- "filter.allEnvs": "Semua lingkungan",
- "filter.searchPlaceholder": "Cari penerapan",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Penerimaan",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Bootstrapping",
- "health.ENVIRONMENT_STATUS_DELETING": "Menghapus",
"health.ENVIRONMENT_STATUS_FAILED": "Tidak tersedia",
- "health.ENVIRONMENT_STATUS_READY": "Tersedia",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Tidak diketahui",
- "list.clearFilters": "Hapus filter",
- "list.clearSearch": "Hapus pencarian penerapan",
- "list.createDeployment": "Baru",
- "list.emptyDescription": "Buat penerapan dari Aplikasi Workflow atau paket DSL Workflow untuk mengelola rilis, lingkungan, dan akses.",
- "list.emptyFilteredDescription": "Tidak ada penerapan yang cocok dengan pencarian atau filter lingkungan saat ini.",
- "list.emptyFilteredTitle": "Tidak ada penerapan yang cocok",
"list.emptyTitle": "Belum ada penerapan",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Terisolasi",
- "mode.ENVIRONMENT_MODE_SHARED": "Bersama",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Tidak diketahui",
- "overview.accessMeta.apiTokens": "Kelola API Tokens",
- "overview.accessMeta.cli": "Lihat akses CLI",
- "overview.accessMeta.webApp": "Kelola akses WebApp",
- "overview.accessStatus": "Akses",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} lingkungan yang diterapkan",
- "overview.apiTokenSummary.environments_other": "{{count}} lingkungan yang diterapkan",
- "overview.cardAction.deployLatest": "Terapkan Rilis Terbaru",
- "overview.cardAction.redeploy": "Terapkan Ulang",
- "overview.cardAction.viewProgress": "Lihat penerapan",
- "overview.chip.behindTooltip_one": "1 rilis di belakang yang terbaru. Terapkan rilis terbaru untuk memperbarui.",
- "overview.chip.behindTooltip_other": "{{count}} rilis di belakang yang terbaru. Terapkan rilis terbaru untuk memperbarui.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "menerapkan",
- "overview.chip.deployingTooltip": "Penerapan sedang berlangsung.",
- "overview.chip.empty": "kosong",
- "overview.chip.emptyTooltip": "Tidak ada rilis yang diterapkan ke lingkungan ini.",
- "overview.chip.failed": "gagal",
- "overview.chip.failedTooltip": "Upaya penerapan terakhir gagal.",
"overview.chip.latest": "terbaru",
- "overview.chip.latestTooltip": "Lingkungan ini menjalankan rilis terbaru.",
- "overview.chip.needsReleaseFirst": "Buat Rilis terlebih dahulu",
- "overview.chip.olderRelease": "lebih lama",
- "overview.chip.olderReleaseTooltip": "Lingkungan ini menjalankan rilis yang lebih lama.",
- "overview.chip.openInDeployTab": "Lihat progres penerapan",
- "overview.disabled": "Dinonaktifkan",
- "overview.enabled": "Diaktifkan",
- "overview.hero.byName": "oleh {{name}}",
- "overview.hero.empty": "Belum ada rilis",
- "overview.hero.emptyDescription": "Buat rilis dari sumber saat ini sebelum menerapkan.",
- "overview.latestRelease.releaseCount_one": "{{count}} rilis",
- "overview.latestRelease.releaseCount_other": "{{count}} rilis",
- "overview.latestReleaseTitle": "Rilis Terbaru",
- "overview.previousReleases.viewAll": "Lihat Semua",
- "overview.strip.deployToNewEnvironment": "Terapkan ke lingkungan baru",
- "overview.strip.emptyDeployableDescription": "Terapkan rilis terbaru ke lingkungan saat Anda siap.",
- "overview.strip.emptyDescription": "Buat rilis sebelum menerapkan ke lingkungan.",
- "overview.strip.emptyTitle": "Belum ada instansi",
- "overview.strip.title": "Instansi",
- "settings.delete": "Hapus Penerapan",
- "settings.deleteConfirmDesc": "Hapus {{name}}? Setiap instansi akan berhenti berjalan dan dihapus di semua lingkungan. Ini tidak dapat dibatalkan.",
- "settings.deleteConfirmTitle": "Hapus penerapan",
- "settings.deleteFailed": "Gagal menghapus penerapan.",
- "settings.deleted": "Penerapan dihapus",
- "settings.description": "Deskripsi",
- "settings.name": "Nama penerapan",
- "settings.save": "Simpan Perubahan",
- "settings.updateFailed": "Gagal memperbarui penerapan.",
- "settings.updated": "Penerapan diperbarui",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Menerapkan",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sinkronisasi tertunda",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Penerapan gagal",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Tidak valid",
"status.RUNTIME_INSTANCE_STATUS_READY": "Berjalan",
@@ -370,87 +89,6 @@
"studio.versionValue": "Nilai versi",
"studio.versionsBehind_one": "Tertinggal {{count}} versi",
"studio.versionsBehind_other": "Tertinggal {{count}} versi",
- "tabs.access.description": "Kelola saluran akses dan izin akses.",
- "tabs.access.name": "Akses",
- "tabs.api-tokens.description": "Kelola API Tokens dan panggil instansi melalui HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "Lihat dan kelola instansi di lingkungan yang diterapkan.",
- "tabs.instances.name": "Instansi",
- "tabs.overview.description": "Lihat status penerapan di seluruh lingkungan.",
- "tabs.overview.name": "Ikhtisar",
- "tabs.releases.description": "Buat, terapkan, dan kelola rilis.",
- "tabs.releases.name": "Rilis",
- "unsupportedDslNodes.description": "Rilis ini berisi node yang belum didukung oleh runtime penerapan. Hapus atau ganti di Studio, lalu coba lagi.",
- "unsupportedDslNodes.descriptionWithTypes": "Rilis ini berisi node yang belum didukung oleh runtime penerapan: {{nodeTypes}}. Hapus atau ganti di Studio, lalu coba lagi.",
- "unsupportedDslNodes.title": "Node tidak didukung",
- "unsupportedDslNodes.unknownType": "Tipe tidak diketahui",
- "versions.cancelCreate": "Batal",
- "versions.cancelDelete": "Batal",
- "versions.cancelEdit": "Batal",
"versions.checkingReleaseContent": "Memeriksa konten rilis...",
- "versions.col.action": "Aksi",
- "versions.col.author": "Dibuat oleh",
- "versions.col.createdAt": "Dibuat pada",
- "versions.col.deployedTo": "Diterapkan ke",
- "versions.col.release": "Rilis",
- "versions.col.sourceApp": "Sumber",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Buat",
- "versions.createFailed": "Gagal membuat rilis.",
- "versions.createRelease": "Buat Rilis",
- "versions.createReleaseDescription": "Buat rilis yang dapat diterapkan dari Aplikasi Workflow atau file DSL Workflow.",
- "versions.createSuccess": "Rilis \"{{name}}\" dibuat.",
- "versions.creating": "Membuat...",
- "versions.currentOn": "Rilis Saat Ini di {{name}}",
- "versions.deleteConfirmDesc": "Rilis \"{{name}}\" akan dihapus secara permanen. Ini tidak dapat dibatalkan.",
- "versions.deleteConfirmTitle": "Hapus rilis?",
- "versions.deleteFailed": "Gagal menghapus rilis.",
- "versions.deleteRelease": "Hapus Rilis",
- "versions.deleteSuccess": "Rilis \"{{name}}\" dihapus.",
- "versions.deployTo": "Terapkan ke {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Menerapkan",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sinkronisasi tertunda",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Gagal",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Tidak valid",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Berjalan",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Belum diterapkan",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Membatalkan penerapan",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Tidak diketahui",
- "versions.deployingTo": "{{name}} sedang diterapkan",
- "versions.disabledReason.checkDeploymentsFailed": "Tidak dapat memverifikasi penggunaan penerapan. Coba lagi nanti.",
- "versions.disabledReason.checkingDeployments": "Memeriksa penggunaan penerapan",
- "versions.disabledReason.current": "Rilis ini sudah berjalan di {{name}}",
- "versions.disabledReason.deploying": "Tunggu penerapan aktif selesai",
- "versions.disabledReason.releaseInUse_one": "Batalkan penerapan rilis ini dari {{count}} lingkungan sebelum menghapusnya",
- "versions.disabledReason.releaseInUse_other": "Batalkan penerapan rilis ini dari {{count}} lingkungan sebelum menghapusnya",
- "versions.dslReadFailed": "Gagal membaca file DSL. Pilih file lain dan coba lagi.",
- "versions.dslReading": "Membaca file DSL...",
- "versions.dslUnsupportedMode": "Hanya file DSL Workflow yang dapat digunakan untuk penerapan.",
- "versions.editFailed": "Gagal memperbarui rilis.",
- "versions.editRelease": "Edit Rilis",
- "versions.editReleaseDescription": "Perbarui nama dan deskripsi rilis ini.",
- "versions.editSuccess": "Rilis \"{{name}}\" diperbarui.",
- "versions.emptyDescription": "Buat rilis pertama sebelum menerapkan ke lingkungan.",
- "versions.emptyTitle": "Belum ada rilis",
- "versions.exportDsl": "Ekspor DSL",
- "versions.exportDslFailed": "Gagal mengekspor DSL.",
- "versions.exportingDsl": "Mengekspor...",
- "versions.groupHeader.deploy": "Terapkan",
- "versions.groupHeader.rollback": "Terapkan versi sebelumnya",
- "versions.groupHeader.unavailable": "Tidak tersedia",
- "versions.manualDslOption": "Unggah DSL",
- "versions.moreActions": "Aksi lainnya",
- "versions.optional": "Opsional",
- "versions.releaseAlreadyExists": "Rilis dengan konten yang sama sudah ada: {{name}}.",
- "versions.releaseContentCheckFailed": "Gagal memeriksa konten rilis.",
- "versions.releaseDescriptionLabel": "Deskripsi",
- "versions.releaseDescriptionPlaceholder": "Jelaskan rilis ini",
- "versions.releaseNameConflict": "Rilis dengan nama ini sudah ada. Pilih nama lain.",
- "versions.releaseNameLabel": "Nama Rilis",
- "versions.releaseNamePlaceholder": "Nama Rilis",
- "versions.releaseNameRequired": "Masukkan nama rilis.",
- "versions.releaseSourceLabel": "Sumber Rilis",
- "versions.rollbackTo": "Terapkan ke {{name}}",
- "versions.saveEdit": "Simpan",
- "versions.sourceAppOption": "Aplikasi Workflow"
+ "versions.deployTo": "Terapkan ke {{name}}"
}
diff --git a/web/i18n/it-IT/common.json b/web/i18n/it-IT/common.json
index 260039ae7c4..6398593cfdb 100644
--- a/web/i18n/it-IT/common.json
+++ b/web/i18n/it-IT/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Dettagli dell'app",
"menus.apps": "Studio",
"menus.datasets": "Conoscenza",
- "menus.deployments": "Distribuzioni",
"menus.exploreMarketplace": "Esplora il Marketplace",
"menus.plugins": "Integrazione",
"menus.status": "beta",
diff --git a/web/i18n/it-IT/deployments.json b/web/i18n/it-IT/deployments.json
index 15335c7a8ff..34a5d654e95 100644
--- a/web/i18n/it-IT/deployments.json
+++ b/web/i18n/it-IT/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copia esempio cURL",
- "access.api.createFailed": "Impossibile generare l'API Token.",
- "access.api.createKey": "Genera API Token",
- "access.api.createKeyTitle": "Genera nuovo API Token",
- "access.api.curlExampleTitle": "Esempio cURL",
- "access.api.description": "Accedi a questa distribuzione tramite HTTP. Ogni API Token è limitato a un ambiente.",
- "access.api.developerTitle": "API per sviluppatori",
- "access.api.disabled": "L'accesso API è disattivato per questa distribuzione.",
- "access.api.disabledHint": "Abilita l'accesso API per generare token limitati all'ambiente.",
- "access.api.docs": "Documentazione API",
- "access.api.docsClose": "Chiudi documentazione API",
- "access.api.docsDescription": "Visualizza il riferimento dell'API Workflow per questa distribuzione.",
- "access.api.docsTitle": "Documentazione dell'API Workflow",
- "access.api.empty": "Distribuisci prima in un ambiente per iniziare a emettere API Token.",
- "access.api.emptyTitle": "Nessun ambiente distribuito",
- "access.api.endpoint": "URL della richiesta",
- "access.api.keyList": "Elenco API Token",
- "access.api.nameLabel": "Nome dell'API Token",
- "access.api.namePlaceholder": "Inserisci un nome per l'API Token",
- "access.api.nameRequired": "Il nome dell'API Token è obbligatorio.",
- "access.api.newKey": "Genera nuovo API Token",
- "access.api.newTokenDescription": "Questo API Token viene mostrato una sola volta. Copialo prima di lasciare questa pagina.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token generato",
- "access.api.noKeys": "Ancora nessun API Token. Generane uno per iniziare a chiamare l'API.",
- "access.api.noKeysTitle": "Ancora nessun API Token",
- "access.api.revokeConfirmDescription": "L'API Token \"{{name}}\" smetterà di funzionare immediatamente. Questa azione non può essere annullata.",
- "access.api.revokeConfirmTitle": "Revocare l'API Token?",
- "access.api.revokeFailed": "Impossibile revocare l'API Token.",
- "access.api.revokeSuccess": "API Token revocato",
- "access.api.table.action": "Azione",
- "access.api.table.environment": "Ambiente",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Nome",
- "access.channels.disabled": "I canali di accesso sono disattivati per questa distribuzione.",
- "access.channels.disabledHint": "Abilita i canali di accesso per esporre i punti di ingresso WebApp e CLI.",
- "access.channels.title": "Canali di accesso",
- "access.cli.description": "Esegui dal terminale con difyctl, adatto per script, flussi di lavoro automatizzati o integrazioni con Agent.",
- "access.cli.docs": "Guida all'uso",
- "access.cli.domain": "Dominio",
- "access.cli.empty": "Endpoint CLI non configurato.",
- "access.cli.install": "Installa CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copia",
- "access.copyFailed": "Copia non riuscita",
- "access.members.groupCount_one": "{{count}} gruppo",
- "access.members.groupCount_other": "{{count}} gruppi",
- "access.members.memberCount_one": "{{count}} membro",
- "access.members.memberCount_other": "{{count}} membri",
- "access.permission.anyone": "Chiunque abbia il link",
- "access.permission.organization": "Tutti i membri della piattaforma",
- "access.permission.specific": "Membri specifici della piattaforma",
- "access.permission.specificDesc": "Seleziona gruppi o membri specifici",
- "access.permission.updateFailed": "Impossibile aggiornare la policy di accesso.",
- "access.permissions.editAriaLabel": "Configura l'accesso per {{environment}}",
- "access.permissions.editDescription": "Imposta le autorizzazioni di accesso per i punti di ingresso WebApp e CLI.",
- "access.permissions.editTitle": "Autorizzazioni di accesso",
- "access.permissions.title": "Autorizzazioni di accesso",
- "access.revoke": "Revoca",
- "access.runAccess.noEnvs": "Distribuisci in un ambiente per configurare le autorizzazioni di accesso.",
- "access.runAccess.noEnvsTitle": "Nessun ambiente distribuito",
- "access.runAccess.openWebapp": "Apri WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Pagina web ospitata per gli utenti finali.",
- "access.runAccess.webappEmpty": "Prossimamente.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Esterno",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Sconosciuto",
- "card.access.api": "API Token",
- "card.access.cli": "CLI",
- "card.access.none": "Nessun accesso",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Crea prima release",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Elimina distribuzione",
- "card.menu.deploy": "Distribuisci nell'ambiente",
- "card.menu.editInfo": "Modifica informazioni",
- "card.moreActions": "Altre azioni",
- "card.noDescription": "Nessuna descrizione fornita.",
"card.notDeployed": "Non distribuito",
- "card.tooltip.createdAt": "Creato",
- "card.tooltip.deployed": "Distribuito",
- "card.tooltip.deploymentStatus": "Distribuzione",
- "card.tooltip.notDeployedShort": "Non distribuito",
- "card.tooltip.releaseName": "Nome release",
- "card.tooltip.source": "Origine",
"common.loadFailed": "Caricamento non riuscito. Riprova più tardi.",
- "createGuide.actions.back": "Indietro",
- "createGuide.actions.createAndDeploy": "Crea e distribuisci",
- "createGuide.actions.creating": "Creazione in corso...",
- "createGuide.actions.deploying": "Creazione e distribuzione in corso...",
- "createGuide.actions.next": "Avanti",
- "createGuide.actions.skipDeploy": "Salta, distribuisci più tardi",
- "createGuide.dsl.defaultAppName": "App DSL importata",
- "createGuide.dsl.description": "Carica un pacchetto DSL Workflow per creare la distribuzione, la prima release e l'eventuale distribuzione nell'ambiente.",
- "createGuide.dsl.dropDescription": "Carica un pacchetto DSL Workflow YAML. Le opzioni di distribuzione vengono risolte da questo file prima della distribuzione.",
- "createGuide.dsl.dropTitle": "Carica pacchetto DSL Workflow",
- "createGuide.dsl.readFailed": "Impossibile leggere il file DSL. Scegli un altro file e riprova.",
- "createGuide.dsl.reading": "Lettura del file DSL in corso...",
- "createGuide.dsl.title": "Importa DSL",
- "createGuide.dsl.unsupportedMode": "Per le distribuzioni possono essere utilizzati solo file DSL Workflow.",
- "createGuide.errors.createReleaseFailed": "Impossibile creare la distribuzione o la release.",
- "createGuide.errors.deployFailed": "Impossibile distribuire nell'ambiente.",
- "createGuide.method.description": "Scegli l'origine usata per creare la prima release.",
- "createGuide.methods.bindApp.description": "Utilizza un'app Workflow esistente in Studio come origine della release.",
- "createGuide.methods.bindApp.title": "Collega app Workflow esistente",
- "createGuide.methods.importDsl.description": "Carica un pacchetto DSL Workflow YAML e procedi attraverso l'interfaccia di distribuzione.",
- "createGuide.methods.importDsl.title": "Importa DSL",
- "createGuide.nav.back": "Distribuzioni",
- "createGuide.release.defaultName": "release iniziale",
- "createGuide.release.deployInfo": "Informazioni distribuzione",
- "createGuide.release.description": "Compila le informazioni sulla distribuzione e i dettagli della prima release.",
- "createGuide.release.firstVersion": "Prima release",
- "createGuide.release.instanceDescription": "Descrizione distribuzione",
- "createGuide.release.instanceDescriptionPlaceholder": "Descrivi a cosa serve questa distribuzione",
- "createGuide.release.instanceName": "Nome distribuzione",
- "createGuide.release.instanceNameConflict": "Esiste già una distribuzione con questo nome. Scegli un altro nome.",
- "createGuide.release.releaseDescription": "Descrizione release",
- "createGuide.release.releaseDescriptionPlaceholder": "Descrivi questa release",
- "createGuide.release.releaseName": "Nome release",
- "createGuide.release.title": "Informazioni di base",
- "createGuide.source.clearSearch": "Cancella ricerca app",
- "createGuide.source.description": "Scegli l'origine usata per creare la prima release.",
- "createGuide.source.empty": "Nessuna app Workflow trovata.",
- "createGuide.source.searchPlaceholder": "Cerca app",
- "createGuide.source.sourceApp": "App Workflow",
- "createGuide.source.title": "Origine release",
- "createGuide.steps.method": "Origine release",
- "createGuide.steps.release": "Informazioni di base",
- "createGuide.steps.source": "Origine release",
- "createGuide.steps.target": "Distribuisci nell'ambiente",
- "createGuide.target.bindingCount_one": "{{count}} binding",
- "createGuide.target.bindingCount_other": "{{count}} binding",
- "createGuide.target.bindingHint": "Scegli le credenziali utilizzate da questa release.",
- "createGuide.target.bindings": "Credenziali",
- "createGuide.target.description": "Scegli un ambiente di destinazione e fornisci le impostazioni runtime di cui questa release ha bisogno. Questo passaggio può essere saltato.",
- "createGuide.target.envVarCount_one": "{{count}} variabile",
- "createGuide.target.envVarCount_other": "{{count}} variabili",
- "createGuide.target.envVarHint": "Per ogni variabile d'ambiente di cui questa release ha bisogno, inserisci un valore personalizzato o usa il valore definito nell'app.",
- "createGuide.target.envVarPlaceholder": "Inserisci valore",
- "createGuide.target.envVarSource.ariaLabel": "Seleziona l'origine del valore della variabile per {{key}}",
- "createGuide.target.envVarSource.default": "Valore dell'app",
- "createGuide.target.envVarSource.lastDeployment": "Ultimo valore distribuito",
- "createGuide.target.envVarSource.literal": "Valore personalizzato",
- "createGuide.target.envVarType.number": "Numero",
- "createGuide.target.envVarType.secret": "Segreto",
- "createGuide.target.envVarType.string": "Stringa",
- "createGuide.target.envVars": "Variabili d'ambiente",
- "createGuide.target.environment": "Ambiente di destinazione",
- "createGuide.target.loadBindingsFailed": "Impossibile caricare le credenziali.",
- "createGuide.target.loadEnvironmentsFailed": "Impossibile caricare gli ambienti di distribuzione.",
- "createGuide.target.missingRequiredBinding": "Seleziona una credenziale per questo binding obbligatorio.",
- "createGuide.target.noBindingRequired": "Nessuna credenziale richiesta.",
- "createGuide.target.noCredentialCandidates": "Nessuna credenziale disponibile.",
- "createGuide.target.noEnvironmentOptions": "Nessun ambiente di distribuzione disponibile.",
- "createGuide.target.selectCredential": "Seleziona una credenziale",
- "createGuide.target.title": "Distribuisci nell'ambiente",
- "createGuide.title": "Nuova distribuzione",
- "createModal.appPickerPlaceholder": "Seleziona un'app Workflow",
- "createModal.appSearchEmpty": "Nessuna app Workflow corrispondente",
- "createModal.appSearchPlaceholder": "Cerca app Workflow…",
- "createModal.cancel": "Annulla",
- "createModal.loadingApps": "Caricamento app…",
- "deployDrawer.bindingCount_one": "{{count}} binding",
- "deployDrawer.bindingCount_other": "{{count}} binding",
"deployDrawer.bindingOptionsFailed": "Impossibile caricare le opzioni delle credenziali.",
"deployDrawer.bindingSelectionHint": "Scegli le credenziali utilizzate da questa distribuzione.",
- "deployDrawer.cancel": "Annulla",
- "deployDrawer.close": "Chiudi pannello distribuzione",
- "deployDrawer.defaultSelect": "Seleziona...",
- "deployDrawer.deploy": "Distribuisci nell'ambiente",
- "deployDrawer.deployFailed": "Impossibile avviare la distribuzione.",
"deployDrawer.deploying": "Distribuzione in corso...",
- "deployDrawer.description": "Seleziona una release e un ambiente di destinazione da distribuire.",
- "deployDrawer.envVarCount_one": "{{count}} variabile",
- "deployDrawer.envVarCount_other": "{{count}} variabili",
- "deployDrawer.envVarHint": "Per ogni variabile d'ambiente di cui questa release ha bisogno, inserisci un valore personalizzato o usa il valore definito nell'app.",
- "deployDrawer.envVarPlaceholder": "Inserisci valore",
"deployDrawer.envVarSource.ariaLabel": "Seleziona l'origine del valore della variabile per {{key}}",
- "deployDrawer.envVarSource.default": "Valore dell'app",
"deployDrawer.envVarSource.lastDeployment": "Ultimo valore distribuito",
"deployDrawer.envVarSource.literal": "Valore personalizzato",
"deployDrawer.envVarType.number": "Numero",
"deployDrawer.envVarType.secret": "Segreto",
"deployDrawer.envVarType.string": "Stringa",
"deployDrawer.envVars": "Variabili d'ambiente",
- "deployDrawer.existingReleaseHint": "Questa release verrà distribuita così com'è. Non verrà creata alcuna nuova release.",
- "deployDrawer.lockedHint": "Bloccato all'ambiente corrente",
- "deployDrawer.missingRequiredBinding": "Seleziona una credenziale per questo binding obbligatorio.",
- "deployDrawer.missingRequiredEnvVar": "Inserisci un valore per questa variabile d'ambiente obbligatoria.",
- "deployDrawer.noBindingRequired": "Non richiesto",
"deployDrawer.noCredentialCandidates": "Nessuna credenziale disponibile.",
"deployDrawer.noNewEnvironmentAvailable": "Tutti gli ambienti disponibili hanno già una distribuzione.",
- "deployDrawer.noOtherReleaseAvailable": "Nessun'altra release disponibile per questo ambiente.",
- "deployDrawer.noReleaseAvailable": "Crea una release prima di distribuire in un ambiente.",
- "deployDrawer.notFound": "Distribuzione non trovata.",
- "deployDrawer.releaseLabel": "Release",
"deployDrawer.runtimeCredentials": "Credenziali",
"deployDrawer.selectCredential": "Seleziona una credenziale",
- "deployDrawer.selectEnv": "Seleziona un ambiente",
- "deployDrawer.selectRelease": "Seleziona una release",
- "deployDrawer.targetEnv": "Ambiente di destinazione",
- "deployDrawer.title": "Distribuisci nell'ambiente",
- "deployTab.closeError": "Chiudi",
"deployTab.col.actions": "Azioni",
- "deployTab.col.currentRelease": "Release corrente",
"deployTab.col.environment": "Ambiente",
"deployTab.col.status": "Stato",
"deployTab.confirmUndeploy": "Annulla distribuzione",
- "deployTab.deployOtherVersion": "Distribuisci un'altra release",
- "deployTab.emptyDescription": "Scegli una release e un ambiente di destinazione per rendere disponibile questa distribuzione agli utenti.",
- "deployTab.emptyTitle": "Nessun ambiente ancora in esecuzione",
- "deployTab.errorCode": "Codice",
- "deployTab.errorDialogDesc": "Esamina l'ultima distribuzione non riuscita prima di riprovare o distribuire un'altra release.",
- "deployTab.errorDialogTitle": "Errore di distribuzione in {{name}}",
- "deployTab.errorMessage": "Messaggio",
- "deployTab.errorPhase": "Fase",
"deployTab.moreActions": "Altre azioni",
- "deployTab.newDeployment": "Distribuisci in un nuovo ambiente",
- "deployTab.panel.unknownError": "Distribuzione non riuscita.",
"deployTab.redeploy": "Ridistribuisci",
- "deployTab.retry": "Riprova",
- "deployTab.status.deployFailed": "Distribuzione non riuscita",
- "deployTab.status.deployingRelease": "Distribuzione in corso ({{release}})",
- "deployTab.status.runningOutOfSync": "In esecuzione (sincronizzazione in sospeso)",
- "deployTab.status.runningWithFailed": "In esecuzione (ultima distribuzione non riuscita)",
"deployTab.undeploy": "Annulla distribuzione",
- "deployTab.undeployConfirmDesc": "L'endpoint dell'ambiente non sarà più disponibile, ma la versione non verrà eliminata.",
- "deployTab.undeployConfirmTitle": "Annullare la distribuzione di {{name}}?",
"deployTab.undeployConfirmWarning": "Dopo la conferma, questo ambiente entrerà nello stato di annullamento della distribuzione e le azioni saranno temporaneamente disabilitate.",
- "deployTab.viewError": "Visualizza errore",
- "detail.mobileTabs": "Sezioni distribuzione",
- "detail.notFound": "Distribuzione non trovata",
- "documentTitle.create": "Nuova distribuzione · Distribuzioni",
- "documentTitle.detail": "Distribuzione · Distribuzioni",
- "documentTitle.list": "Distribuzioni",
- "filter.allEnvs": "Tutti gli ambienti",
- "filter.searchPlaceholder": "Cerca distribuzioni",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Ammissione",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Avvio",
- "health.ENVIRONMENT_STATUS_DELETING": "Eliminazione",
"health.ENVIRONMENT_STATUS_FAILED": "Non disponibile",
- "health.ENVIRONMENT_STATUS_READY": "Disponibile",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Sconosciuto",
- "list.clearFilters": "Cancella filtri",
- "list.clearSearch": "Cancella ricerca distribuzioni",
- "list.createDeployment": "Nuova",
- "list.emptyDescription": "Crea una distribuzione da un'app Workflow o da un pacchetto DSL Workflow per gestire release, ambienti e accessi.",
- "list.emptyFilteredDescription": "Nessuna distribuzione corrisponde alla ricerca o al filtro per ambiente correnti.",
- "list.emptyFilteredTitle": "Nessuna distribuzione corrispondente",
"list.emptyTitle": "Ancora nessuna distribuzione",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Isolato",
- "mode.ENVIRONMENT_MODE_SHARED": "Condiviso",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Sconosciuto",
- "overview.accessMeta.apiTokens": "Gestisci API Token",
- "overview.accessMeta.cli": "Visualizza accesso CLI",
- "overview.accessMeta.webApp": "Gestisci accesso WebApp",
- "overview.accessStatus": "Accesso",
- "overview.api": "API Token",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Token",
- "overview.apiTokenSummary.environments_one": "{{count}} ambiente distribuito",
- "overview.apiTokenSummary.environments_other": "{{count}} ambienti distribuiti",
- "overview.cardAction.deployLatest": "Distribuisci l'ultima release",
- "overview.cardAction.redeploy": "Ridistribuisci",
- "overview.cardAction.viewProgress": "Visualizza distribuzione",
- "overview.chip.behindTooltip_one": "1 release indietro rispetto all'ultima. Distribuisci l'ultima release per aggiornare.",
- "overview.chip.behindTooltip_other": "{{count}} release indietro rispetto all'ultima. Distribuisci l'ultima release per aggiornare.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "in distribuzione",
- "overview.chip.deployingTooltip": "La distribuzione è in corso.",
- "overview.chip.empty": "vuoto",
- "overview.chip.emptyTooltip": "Nessuna release è distribuita in questo ambiente.",
- "overview.chip.failed": "non riuscita",
- "overview.chip.failedTooltip": "L'ultimo tentativo di distribuzione non è riuscito.",
"overview.chip.latest": "più recente",
- "overview.chip.latestTooltip": "Questo ambiente sta eseguendo l'ultima release.",
- "overview.chip.needsReleaseFirst": "Crea prima una release",
- "overview.chip.olderRelease": "precedente",
- "overview.chip.olderReleaseTooltip": "Questo ambiente sta eseguendo una release precedente.",
- "overview.chip.openInDeployTab": "Visualizza avanzamento distribuzione",
- "overview.disabled": "Disabilitato",
- "overview.enabled": "Abilitato",
- "overview.hero.byName": "da {{name}}",
- "overview.hero.empty": "Ancora nessuna release",
- "overview.hero.emptyDescription": "Crea una release dall'origine corrente prima di distribuire.",
- "overview.latestRelease.releaseCount_one": "{{count}} release",
- "overview.latestRelease.releaseCount_other": "{{count}} release",
- "overview.latestReleaseTitle": "Ultima release",
- "overview.previousReleases.viewAll": "Visualizza tutte",
- "overview.strip.deployToNewEnvironment": "Distribuisci in un nuovo ambiente",
- "overview.strip.emptyDeployableDescription": "Distribuisci l'ultima release in un ambiente quando sei pronto.",
- "overview.strip.emptyDescription": "Crea una release prima di distribuire in un ambiente.",
- "overview.strip.emptyTitle": "Ancora nessuna istanza",
- "overview.strip.title": "Istanze",
- "settings.delete": "Elimina distribuzione",
- "settings.deleteConfirmDesc": "Eliminare {{name}}? Ogni istanza smetterà di funzionare e verrà rimossa da tutti gli ambienti. Non può essere annullato.",
- "settings.deleteConfirmTitle": "Elimina distribuzione",
- "settings.deleteFailed": "Impossibile eliminare la distribuzione.",
- "settings.deleted": "Distribuzione eliminata",
- "settings.description": "Descrizione",
- "settings.name": "Nome distribuzione",
- "settings.save": "Salva modifiche",
- "settings.updateFailed": "Impossibile aggiornare la distribuzione.",
- "settings.updated": "Distribuzione aggiornata",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "In distribuzione",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronizzazione in sospeso",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Distribuzione non riuscita",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Non valido",
"status.RUNTIME_INSTANCE_STATUS_READY": "In esecuzione",
@@ -370,87 +89,6 @@
"studio.versionValue": "Valore della versione",
"studio.versionsBehind_one": "{{count}} versione indietro",
"studio.versionsBehind_other": "{{count}} versioni indietro",
- "tabs.access.description": "Gestisci i canali e le autorizzazioni di accesso.",
- "tabs.access.name": "Accesso",
- "tabs.api-tokens.description": "Gestisci API Token e richiama le istanze tramite HTTP.",
- "tabs.api-tokens.name": "API Token",
- "tabs.instances.description": "Visualizza e gestisci le istanze negli ambienti distribuiti.",
- "tabs.instances.name": "Istanze",
- "tabs.overview.description": "Visualizza lo stato della distribuzione tra gli ambienti.",
- "tabs.overview.name": "Panoramica",
- "tabs.releases.description": "Crea, distribuisci e gestisci le release.",
- "tabs.releases.name": "Release",
- "unsupportedDslNodes.description": "Questa release contiene nodi non ancora supportati dal runtime di distribuzione. Rimuovili o sostituiscili in Studio, quindi riprova.",
- "unsupportedDslNodes.descriptionWithTypes": "Questa release contiene nodi non ancora supportati dal runtime di distribuzione: {{nodeTypes}}. Rimuovili o sostituiscili in Studio, quindi riprova.",
- "unsupportedDslNodes.title": "Nodi non supportati",
- "unsupportedDslNodes.unknownType": "Tipo sconosciuto",
- "versions.cancelCreate": "Annulla",
- "versions.cancelDelete": "Annulla",
- "versions.cancelEdit": "Annulla",
"versions.checkingReleaseContent": "Verifica del contenuto della release in corso...",
- "versions.col.action": "Azione",
- "versions.col.author": "Creato da",
- "versions.col.createdAt": "Creato il",
- "versions.col.deployedTo": "Distribuito in",
- "versions.col.release": "Release",
- "versions.col.sourceApp": "Origine",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Crea",
- "versions.createFailed": "Impossibile creare la release.",
- "versions.createRelease": "Crea release",
- "versions.createReleaseDescription": "Crea una release distribuibile da un'app Workflow o da un file DSL Workflow.",
- "versions.createSuccess": "Release \"{{name}}\" creata.",
- "versions.creating": "Creazione in corso...",
- "versions.currentOn": "Release corrente su {{name}}",
- "versions.deleteConfirmDesc": "La release \"{{name}}\" verrà eliminata definitivamente. Non può essere annullato.",
- "versions.deleteConfirmTitle": "Eliminare la release?",
- "versions.deleteFailed": "Impossibile eliminare la release.",
- "versions.deleteRelease": "Elimina release",
- "versions.deleteSuccess": "Release \"{{name}}\" eliminata.",
- "versions.deployTo": "Distribuisci in {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "In distribuzione",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronizzazione in sospeso",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Non riuscita",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Non valido",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "In esecuzione",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Non distribuito",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Annullamento distribuzione",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Sconosciuto",
- "versions.deployingTo": "{{name}} è in distribuzione",
- "versions.disabledReason.checkDeploymentsFailed": "Impossibile verificare l'utilizzo della distribuzione. Riprova più tardi.",
- "versions.disabledReason.checkingDeployments": "Verifica utilizzo distribuzione",
- "versions.disabledReason.current": "Questa release è già in esecuzione su {{name}}",
- "versions.disabledReason.deploying": "Attendi il completamento della distribuzione attiva",
- "versions.disabledReason.releaseInUse_one": "Annulla la distribuzione di questa release da {{count}} ambiente prima di eliminarla",
- "versions.disabledReason.releaseInUse_other": "Annulla la distribuzione di questa release da {{count}} ambienti prima di eliminarla",
- "versions.dslReadFailed": "Impossibile leggere il file DSL. Scegli un altro file e riprova.",
- "versions.dslReading": "Lettura del file DSL in corso...",
- "versions.dslUnsupportedMode": "Per le distribuzioni possono essere utilizzati solo file DSL Workflow.",
- "versions.editFailed": "Impossibile aggiornare la release.",
- "versions.editRelease": "Modifica release",
- "versions.editReleaseDescription": "Aggiorna il nome e la descrizione di questa release.",
- "versions.editSuccess": "Release \"{{name}}\" aggiornata.",
- "versions.emptyDescription": "Crea la prima release prima di distribuire in un ambiente.",
- "versions.emptyTitle": "Ancora nessuna release",
- "versions.exportDsl": "Esporta DSL",
- "versions.exportDslFailed": "Impossibile esportare il DSL.",
- "versions.exportingDsl": "Esportazione in corso...",
- "versions.groupHeader.deploy": "Distribuisci",
- "versions.groupHeader.rollback": "Distribuisci versione precedente",
- "versions.groupHeader.unavailable": "Non disponibile",
- "versions.manualDslOption": "Carica DSL",
- "versions.moreActions": "Altre azioni",
- "versions.optional": "Opzionale",
- "versions.releaseAlreadyExists": "Esiste già una release con lo stesso contenuto: {{name}}.",
- "versions.releaseContentCheckFailed": "Impossibile verificare il contenuto della release.",
- "versions.releaseDescriptionLabel": "Descrizione",
- "versions.releaseDescriptionPlaceholder": "Descrivi questa release",
- "versions.releaseNameConflict": "Esiste già una release con questo nome. Scegli un altro nome.",
- "versions.releaseNameLabel": "Nome release",
- "versions.releaseNamePlaceholder": "Nome release",
- "versions.releaseNameRequired": "Inserisci un nome per la release.",
- "versions.releaseSourceLabel": "Origine release",
- "versions.rollbackTo": "Distribuisci in {{name}}",
- "versions.saveEdit": "Salva",
- "versions.sourceAppOption": "App Workflow"
+ "versions.deployTo": "Distribuisci in {{name}}"
}
diff --git a/web/i18n/ja-JP/common.json b/web/i18n/ja-JP/common.json
index 94a26b2e4fb..e417d4b53ad 100644
--- a/web/i18n/ja-JP/common.json
+++ b/web/i18n/ja-JP/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "アプリの詳細",
"menus.apps": "スタジオ",
"menus.datasets": "ナレッジ",
- "menus.deployments": "デプロイ",
"menus.exploreMarketplace": "マーケットプレイスを探索する",
"menus.plugins": "インテグレーション",
"menus.status": "ベータ版",
diff --git a/web/i18n/ja-JP/deployments.json b/web/i18n/ja-JP/deployments.json
index f937e9b6525..123589c1f30 100644
--- a/web/i18n/ja-JP/deployments.json
+++ b/web/i18n/ja-JP/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "cURL の例をコピー",
- "access.api.createFailed": "API トークンの生成に失敗しました。",
- "access.api.createKey": "API トークンを生成",
- "access.api.createKeyTitle": "新しい API トークンを生成",
- "access.api.curlExampleTitle": "cURL の例",
- "access.api.description": "HTTP 経由でこのデプロイにアクセスします。各 API トークンは 1 つの環境にスコープされます。",
- "access.api.developerTitle": "開発者 API",
- "access.api.disabled": "このデプロイでは API アクセスがオフになっています。",
- "access.api.disabledHint": "API アクセスを有効にして、環境スコープのトークンを生成します。",
- "access.api.docs": "API ドキュメント",
- "access.api.docsClose": "API ドキュメントを閉じる",
- "access.api.docsDescription": "このデプロイのワークフロー API リファレンスを表示します。",
- "access.api.docsTitle": "ワークフロー API ドキュメント",
- "access.api.empty": "API トークンの発行を開始するには、まず環境にデプロイしてください。",
- "access.api.emptyTitle": "デプロイされた環境がありません",
- "access.api.endpoint": "リクエスト URL",
- "access.api.keyList": "API トークン一覧",
- "access.api.nameLabel": "API トークン名",
- "access.api.namePlaceholder": "API トークン名を入力",
- "access.api.nameRequired": "API トークン名は必須です。",
- "access.api.newKey": "新しい API トークンを生成",
- "access.api.newTokenDescription": "この API トークンは一度しか表示されません。このページを離れる前にコピーしてください。",
- "access.api.newTokenLabel": "API トークン",
- "access.api.newTokenTitle": "API トークンが生成されました",
- "access.api.noKeys": "API トークンはまだありません。生成して API の呼び出しを開始します。",
- "access.api.noKeysTitle": "API トークンはまだありません",
- "access.api.revokeConfirmDescription": "API トークン「{{name}}」はすぐに動作しなくなります。この操作は取り消せません。",
- "access.api.revokeConfirmTitle": "API トークンを取り消しますか?",
- "access.api.revokeFailed": "API トークンの取り消しに失敗しました。",
- "access.api.revokeSuccess": "API トークンを取り消しました",
- "access.api.table.action": "アクション",
- "access.api.table.environment": "環境",
- "access.api.table.key": "API トークン",
- "access.api.table.name": "名前",
- "access.channels.disabled": "このデプロイではアクセスチャネルがオフになっています。",
- "access.channels.disabledHint": "アクセスチャネルを有効にして、WebApp と CLI のエントリポイントを公開します。",
- "access.channels.title": "アクセスチャネル",
- "access.cli.description": "difyctl を使ってターミナルから呼び出します。スクリプト、自動化されたワークフロー、エージェント連携に適しています。",
- "access.cli.docs": "使い方ガイド",
- "access.cli.domain": "ドメイン",
- "access.cli.empty": "CLI エンドポイントが設定されていません。",
- "access.cli.install": "CLI をインストール",
- "access.cli.title": "CLI",
- "access.copy": "コピー",
- "access.copyFailed": "コピーに失敗しました",
- "access.members.groupCount_one": "{{count}} グループ",
- "access.members.groupCount_other": "{{count}} グループ",
- "access.members.memberCount_one": "{{count}} メンバー",
- "access.members.memberCount_other": "{{count}} メンバー",
- "access.permission.anyone": "リンクを知っている全員",
- "access.permission.organization": "プラットフォーム内のすべてのメンバー",
- "access.permission.specific": "プラットフォーム内の特定のメンバー",
- "access.permission.specificDesc": "特定のグループまたはメンバーを選択",
- "access.permission.updateFailed": "アクセスポリシーの更新に失敗しました。",
- "access.permissions.editAriaLabel": "{{environment}} のアクセスを設定",
- "access.permissions.editDescription": "WebApp と CLI エントリポイントのアクセス権限を設定します。",
- "access.permissions.editTitle": "アクセス権限",
- "access.permissions.title": "アクセス権限",
- "access.revoke": "取り消す",
- "access.runAccess.noEnvs": "アクセス権限を設定するには、環境にデプロイしてください。",
- "access.runAccess.noEnvsTitle": "デプロイされた環境がありません",
- "access.runAccess.openWebapp": "WebApp を開く",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "エンドユーザー向けのホストされた Web ページ。",
- "access.runAccess.webappEmpty": "近日公開。",
- "backend.RUNTIME_BACKEND_EXTERNAL": "外部",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "不明",
- "card.access.api": "API トークン",
- "card.access.cli": "CLI",
- "card.access.none": "アクセスなし",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "最初のリリースを作成",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "デプロイを削除",
- "card.menu.deploy": "環境にデプロイ",
- "card.menu.editInfo": "情報を編集",
- "card.moreActions": "その他のアクション",
- "card.noDescription": "説明はありません。",
"card.notDeployed": "未デプロイ",
- "card.tooltip.createdAt": "作成日",
- "card.tooltip.deployed": "デプロイ済み",
- "card.tooltip.deploymentStatus": "デプロイ",
- "card.tooltip.notDeployedShort": "未デプロイ",
- "card.tooltip.releaseName": "リリース名",
- "card.tooltip.source": "ソース",
"common.loadFailed": "読み込みに失敗しました。後でもう一度お試しください。",
- "createGuide.actions.back": "戻る",
- "createGuide.actions.createAndDeploy": "作成してデプロイ",
- "createGuide.actions.creating": "作成中...",
- "createGuide.actions.deploying": "作成してデプロイ中...",
- "createGuide.actions.next": "次へ",
- "createGuide.actions.skipDeploy": "スキップ、後でデプロイ",
- "createGuide.dsl.defaultAppName": "インポートされた DSL アプリ",
- "createGuide.dsl.description": "ワークフロー DSL パッケージをアップロードして、デプロイ、最初のリリース、オプションの環境デプロイを作成します。",
- "createGuide.dsl.dropDescription": "ワークフロー YAML DSL パッケージをアップロードします。デプロイ前にこのファイルからデプロイオプションが解決されます。",
- "createGuide.dsl.dropTitle": "ワークフロー DSL パッケージをアップロード",
- "createGuide.dsl.readFailed": "DSL ファイルの読み込みに失敗しました。別のファイルを選択してもう一度お試しください。",
- "createGuide.dsl.reading": "DSL ファイルを読み込み中...",
- "createGuide.dsl.title": "DSL をインポート",
- "createGuide.dsl.unsupportedMode": "デプロイにはワークフロー DSL ファイルのみ使用できます。",
- "createGuide.errors.createReleaseFailed": "デプロイまたはリリースの作成に失敗しました。",
- "createGuide.errors.deployFailed": "環境へのデプロイに失敗しました。",
- "createGuide.method.description": "最初のリリースの作成に使用するソースを選択します。",
- "createGuide.methods.bindApp.description": "スタジオの既存のワークフローアプリをリリースソースとして使用します。",
- "createGuide.methods.bindApp.title": "既存のワークフローアプリにバインド",
- "createGuide.methods.importDsl.description": "ワークフロー YAML DSL パッケージをアップロードして、デプロイ UI を続行します。",
- "createGuide.methods.importDsl.title": "DSL をインポート",
- "createGuide.nav.back": "デプロイ",
- "createGuide.release.defaultName": "初期リリース",
- "createGuide.release.deployInfo": "デプロイ情報",
- "createGuide.release.description": "デプロイ情報と最初のリリースの詳細を入力します。",
- "createGuide.release.firstVersion": "最初のリリース",
- "createGuide.release.instanceDescription": "デプロイの説明",
- "createGuide.release.instanceDescriptionPlaceholder": "このデプロイの用途を説明してください",
- "createGuide.release.instanceName": "デプロイ名",
- "createGuide.release.instanceNameConflict": "この名前のデプロイは既に存在します。別の名前を選択してください。",
- "createGuide.release.releaseDescription": "リリースの説明",
- "createGuide.release.releaseDescriptionPlaceholder": "このリリースを説明してください",
- "createGuide.release.releaseName": "リリース名",
- "createGuide.release.title": "基本情報",
- "createGuide.source.clearSearch": "アプリ検索をクリア",
- "createGuide.source.description": "最初のリリースの作成に使用するソースを選択します。",
- "createGuide.source.empty": "ワークフローアプリが見つかりません。",
- "createGuide.source.searchPlaceholder": "アプリを検索",
- "createGuide.source.sourceApp": "ワークフローアプリ",
- "createGuide.source.title": "リリースソース",
- "createGuide.steps.method": "リリースソース",
- "createGuide.steps.release": "基本情報",
- "createGuide.steps.source": "リリースソース",
- "createGuide.steps.target": "環境にデプロイ",
- "createGuide.target.bindingCount_one": "{{count}} バインディング",
- "createGuide.target.bindingCount_other": "{{count}} バインディング",
- "createGuide.target.bindingHint": "このリリースで使用する認証情報を選択します。",
- "createGuide.target.bindings": "認証情報",
- "createGuide.target.description": "ターゲット環境を選択し、そこでこのリリースが必要とするランタイム設定を指定します。このステップはスキップできます。",
- "createGuide.target.envVarCount_one": "{{count}} 変数",
- "createGuide.target.envVarCount_other": "{{count}} 変数",
- "createGuide.target.envVarHint": "このリリースに必要な各環境変数について、カスタム値を入力するか、アプリで定義された値を使用します。",
- "createGuide.target.envVarPlaceholder": "値を入力",
- "createGuide.target.envVarSource.ariaLabel": "{{key}} の変数値ソースを選択",
- "createGuide.target.envVarSource.default": "アプリの値",
- "createGuide.target.envVarSource.lastDeployment": "最後にデプロイされた値",
- "createGuide.target.envVarSource.literal": "カスタム値",
- "createGuide.target.envVarType.number": "数値",
- "createGuide.target.envVarType.secret": "シークレット",
- "createGuide.target.envVarType.string": "文字列",
- "createGuide.target.envVars": "環境変数",
- "createGuide.target.environment": "ターゲット環境",
- "createGuide.target.loadBindingsFailed": "認証情報の読み込みに失敗しました。",
- "createGuide.target.loadEnvironmentsFailed": "デプロイ環境の読み込みに失敗しました。",
- "createGuide.target.missingRequiredBinding": "この必須バインディングの認証情報を選択してください。",
- "createGuide.target.noBindingRequired": "認証情報は不要です。",
- "createGuide.target.noCredentialCandidates": "利用可能な認証情報がありません。",
- "createGuide.target.noEnvironmentOptions": "利用可能なデプロイ環境がありません。",
- "createGuide.target.selectCredential": "認証情報を選択",
- "createGuide.target.title": "環境にデプロイ",
- "createGuide.title": "新しいデプロイ",
- "createModal.appPickerPlaceholder": "ワークフローアプリを選択",
- "createModal.appSearchEmpty": "一致するワークフローアプリがありません",
- "createModal.appSearchPlaceholder": "ワークフローアプリを検索…",
- "createModal.cancel": "キャンセル",
- "createModal.loadingApps": "アプリを読み込み中…",
- "deployDrawer.bindingCount_one": "{{count}} バインディング",
- "deployDrawer.bindingCount_other": "{{count}} バインディング",
"deployDrawer.bindingOptionsFailed": "認証情報オプションの読み込みに失敗しました。",
"deployDrawer.bindingSelectionHint": "このデプロイで使用する認証情報を選択します。",
- "deployDrawer.cancel": "キャンセル",
- "deployDrawer.close": "デプロイドロワーを閉じる",
- "deployDrawer.defaultSelect": "選択...",
- "deployDrawer.deploy": "環境にデプロイ",
- "deployDrawer.deployFailed": "デプロイの開始に失敗しました。",
"deployDrawer.deploying": "デプロイ中...",
- "deployDrawer.description": "デプロイするリリースとターゲット環境を選択します。",
- "deployDrawer.envVarCount_one": "{{count}} 変数",
- "deployDrawer.envVarCount_other": "{{count}} 変数",
- "deployDrawer.envVarHint": "このリリースに必要な各環境変数について、カスタム値を入力するか、アプリで定義された値を使用します。",
- "deployDrawer.envVarPlaceholder": "値を入力",
"deployDrawer.envVarSource.ariaLabel": "{{key}} の変数値ソースを選択",
- "deployDrawer.envVarSource.default": "アプリの値",
"deployDrawer.envVarSource.lastDeployment": "最後にデプロイされた値",
"deployDrawer.envVarSource.literal": "カスタム値",
"deployDrawer.envVarType.number": "数値",
"deployDrawer.envVarType.secret": "シークレット",
"deployDrawer.envVarType.string": "文字列",
"deployDrawer.envVars": "環境変数",
- "deployDrawer.existingReleaseHint": "このリリースはそのままデプロイされます。新しいリリースは作成されません。",
- "deployDrawer.lockedHint": "現在の環境にロックされています",
- "deployDrawer.missingRequiredBinding": "この必須バインディングの認証情報を選択してください。",
- "deployDrawer.missingRequiredEnvVar": "この必須環境変数の値を入力してください。",
- "deployDrawer.noBindingRequired": "不要",
"deployDrawer.noCredentialCandidates": "利用可能な認証情報がありません。",
"deployDrawer.noNewEnvironmentAvailable": "利用可能なすべての環境には既にデプロイがあります。",
- "deployDrawer.noOtherReleaseAvailable": "この環境で利用可能な他のリリースはありません。",
- "deployDrawer.noReleaseAvailable": "環境にデプロイする前にリリースを作成してください。",
- "deployDrawer.notFound": "デプロイが見つかりません。",
- "deployDrawer.releaseLabel": "リリース",
"deployDrawer.runtimeCredentials": "認証情報",
"deployDrawer.selectCredential": "認証情報を選択",
- "deployDrawer.selectEnv": "環境を選択",
- "deployDrawer.selectRelease": "リリースを選択",
- "deployDrawer.targetEnv": "ターゲット環境",
- "deployDrawer.title": "環境にデプロイ",
- "deployTab.closeError": "閉じる",
"deployTab.col.actions": "アクション",
- "deployTab.col.currentRelease": "現在のリリース",
"deployTab.col.environment": "環境",
"deployTab.col.status": "ステータス",
"deployTab.confirmUndeploy": "アンデプロイ",
- "deployTab.deployOtherVersion": "別のリリースをデプロイ",
- "deployTab.emptyDescription": "リリースとターゲット環境を選択して、このデプロイをユーザーが利用できるようにします。",
- "deployTab.emptyTitle": "実行中の環境はまだありません",
- "deployTab.errorCode": "コード",
- "deployTab.errorDialogDesc": "再試行する前、または別のリリースをデプロイする前に、最後に失敗したデプロイを確認してください。",
- "deployTab.errorDialogTitle": "{{name}} でのデプロイエラー",
- "deployTab.errorMessage": "メッセージ",
- "deployTab.errorPhase": "フェーズ",
"deployTab.moreActions": "その他のアクション",
- "deployTab.newDeployment": "新しい環境にデプロイ",
- "deployTab.panel.unknownError": "デプロイに失敗しました。",
"deployTab.redeploy": "再デプロイ",
- "deployTab.retry": "再試行",
- "deployTab.status.deployFailed": "デプロイ失敗",
- "deployTab.status.deployingRelease": "デプロイ中 ({{release}})",
- "deployTab.status.runningOutOfSync": "実行中 (同期保留中)",
- "deployTab.status.runningWithFailed": "実行中 (前回のデプロイは失敗)",
"deployTab.undeploy": "アンデプロイ",
- "deployTab.undeployConfirmDesc": "環境のエンドポイントは利用できなくなりますが、バージョンは削除されません。",
- "deployTab.undeployConfirmTitle": "{{name}} をアンデプロイしますか?",
"deployTab.undeployConfirmWarning": "確認後、この環境はアンデプロイ中の状態になり、操作は一時的に無効になります。",
- "deployTab.viewError": "エラーを表示",
- "detail.mobileTabs": "デプロイセクション",
- "detail.notFound": "デプロイが見つかりません",
- "documentTitle.create": "新しいデプロイ · デプロイ",
- "documentTitle.detail": "デプロイ · デプロイ",
- "documentTitle.list": "デプロイ",
- "filter.allEnvs": "すべての環境",
- "filter.searchPlaceholder": "デプロイを検索",
- "health.ENVIRONMENT_STATUS_ADMISSION": "アドミッション",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "ブートストラップ中",
- "health.ENVIRONMENT_STATUS_DELETING": "削除中",
"health.ENVIRONMENT_STATUS_FAILED": "利用不可",
- "health.ENVIRONMENT_STATUS_READY": "利用可能",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "不明",
- "list.clearFilters": "フィルタをクリア",
- "list.clearSearch": "デプロイ検索をクリア",
- "list.createDeployment": "新規",
- "list.emptyDescription": "ワークフローアプリまたはワークフロー DSL パッケージからデプロイを作成して、リリース、環境、アクセスを管理します。",
- "list.emptyFilteredDescription": "現在の検索条件または環境フィルタに一致するデプロイがありません。",
- "list.emptyFilteredTitle": "一致するデプロイがありません",
"list.emptyTitle": "デプロイはまだありません",
- "mode.ENVIRONMENT_MODE_ISOLATED": "分離",
- "mode.ENVIRONMENT_MODE_SHARED": "共有",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "不明",
- "overview.accessMeta.apiTokens": "API トークンを管理",
- "overview.accessMeta.cli": "CLI アクセスを表示",
- "overview.accessMeta.webApp": "WebApp アクセスを管理",
- "overview.accessStatus": "アクセス",
- "overview.api": "API トークン",
- "overview.apiKeysCount_one": "{{count}} API トークン",
- "overview.apiKeysCount_other": "{{count}} API トークン",
- "overview.apiTokenSummary.environments_one": "{{count}} 個のデプロイ済み環境",
- "overview.apiTokenSummary.environments_other": "{{count}} 個のデプロイ済み環境",
- "overview.cardAction.deployLatest": "最新リリースをデプロイ",
- "overview.cardAction.redeploy": "再デプロイ",
- "overview.cardAction.viewProgress": "デプロイを表示",
- "overview.chip.behindTooltip_one": "最新より 1 リリース遅れています。最新リリースをデプロイして更新してください。",
- "overview.chip.behindTooltip_other": "最新より {{count}} リリース遅れています。最新リリースをデプロイして更新してください。",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "デプロイ中",
- "overview.chip.deployingTooltip": "デプロイが進行中です。",
- "overview.chip.empty": "空",
- "overview.chip.emptyTooltip": "この環境にデプロイされているリリースはありません。",
- "overview.chip.failed": "失敗",
- "overview.chip.failedTooltip": "最新のデプロイ試行は失敗しました。",
"overview.chip.latest": "最新",
- "overview.chip.latestTooltip": "この環境は最新のリリースを実行しています。",
- "overview.chip.needsReleaseFirst": "先にリリースを作成してください",
- "overview.chip.olderRelease": "古い",
- "overview.chip.olderReleaseTooltip": "この環境は古いリリースを実行しています。",
- "overview.chip.openInDeployTab": "デプロイの進捗を表示",
- "overview.disabled": "無効",
- "overview.enabled": "有効",
- "overview.hero.byName": "{{name}} 作成",
- "overview.hero.empty": "リリースはまだありません",
- "overview.hero.emptyDescription": "デプロイ前に現在のソースからリリースを作成してください。",
- "overview.latestRelease.releaseCount_one": "{{count}} リリース",
- "overview.latestRelease.releaseCount_other": "{{count}} リリース",
- "overview.latestReleaseTitle": "最新リリース",
- "overview.previousReleases.viewAll": "すべて表示",
- "overview.strip.deployToNewEnvironment": "新しい環境にデプロイ",
- "overview.strip.emptyDeployableDescription": "準備ができたら、最新リリースを環境にデプロイしてください。",
- "overview.strip.emptyDescription": "環境にデプロイする前にリリースを作成してください。",
- "overview.strip.emptyTitle": "インスタンスはまだありません",
- "overview.strip.title": "インスタンス",
- "settings.delete": "デプロイを削除",
- "settings.deleteConfirmDesc": "{{name}} を削除しますか?すべてのインスタンスがすべての環境で停止し、削除されます。この操作は取り消せません。",
- "settings.deleteConfirmTitle": "デプロイを削除",
- "settings.deleteFailed": "デプロイの削除に失敗しました。",
- "settings.deleted": "デプロイを削除しました",
- "settings.description": "説明",
- "settings.name": "デプロイ名",
- "settings.save": "変更を保存",
- "settings.updateFailed": "デプロイの更新に失敗しました。",
- "settings.updated": "デプロイを更新しました",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "デプロイ中",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "同期保留中",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "デプロイ失敗",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "無効",
"status.RUNTIME_INSTANCE_STATUS_READY": "実行中",
@@ -370,87 +89,6 @@
"studio.versionValue": "バージョンの値",
"studio.versionsBehind_one": "{{count}} バージョン遅れ",
"studio.versionsBehind_other": "{{count}} バージョン遅れ",
- "tabs.access.description": "アクセスチャネルとアクセス権限を管理します。",
- "tabs.access.name": "アクセス",
- "tabs.api-tokens.description": "API トークンを管理し、HTTP 経由でインスタンスを呼び出します。",
- "tabs.api-tokens.name": "API トークン",
- "tabs.instances.description": "デプロイされた環境のインスタンスを表示および管理します。",
- "tabs.instances.name": "インスタンス",
- "tabs.overview.description": "環境全体でのデプロイのステータスを表示します。",
- "tabs.overview.name": "概要",
- "tabs.releases.description": "リリースを作成、デプロイ、管理します。",
- "tabs.releases.name": "リリース",
- "unsupportedDslNodes.description": "このリリースには、デプロイランタイムがまだサポートしていないノードが含まれています。スタジオでそれらを削除または置き換えてから、もう一度お試しください。",
- "unsupportedDslNodes.descriptionWithTypes": "このリリースには、デプロイランタイムがまだサポートしていないノードが含まれています: {{nodeTypes}}。スタジオでそれらを削除または置き換えてから、もう一度お試しください。",
- "unsupportedDslNodes.title": "サポートされていないノード",
- "unsupportedDslNodes.unknownType": "不明な型",
- "versions.cancelCreate": "キャンセル",
- "versions.cancelDelete": "キャンセル",
- "versions.cancelEdit": "キャンセル",
"versions.checkingReleaseContent": "リリース内容を確認中...",
- "versions.col.action": "アクション",
- "versions.col.author": "作成者",
- "versions.col.createdAt": "作成日",
- "versions.col.deployedTo": "デプロイ先",
- "versions.col.release": "リリース",
- "versions.col.sourceApp": "ソース",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "作成",
- "versions.createFailed": "リリースの作成に失敗しました。",
- "versions.createRelease": "リリースを作成",
- "versions.createReleaseDescription": "ワークフローアプリまたはワークフロー DSL ファイルからデプロイ可能なリリースを作成します。",
- "versions.createSuccess": "リリース「{{name}}」を作成しました。",
- "versions.creating": "作成中...",
- "versions.currentOn": "{{name}} の現在のリリース",
- "versions.deleteConfirmDesc": "リリース「{{name}}」は永続的に削除されます。この操作は取り消せません。",
- "versions.deleteConfirmTitle": "リリースを削除しますか?",
- "versions.deleteFailed": "リリースの削除に失敗しました。",
- "versions.deleteRelease": "リリースを削除",
- "versions.deleteSuccess": "リリース「{{name}}」を削除しました。",
- "versions.deployTo": "{{name}} にデプロイ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "デプロイ中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "同期保留中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "失敗",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "無効",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "実行中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "未デプロイ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "アンデプロイ中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "不明",
- "versions.deployingTo": "{{name}} にデプロイ中",
- "versions.disabledReason.checkDeploymentsFailed": "デプロイの使用状況を確認できませんでした。後でもう一度お試しください。",
- "versions.disabledReason.checkingDeployments": "デプロイの使用状況を確認中",
- "versions.disabledReason.current": "このリリースは既に {{name}} で実行されています",
- "versions.disabledReason.deploying": "アクティブなデプロイが完了するまでお待ちください",
- "versions.disabledReason.releaseInUse_one": "削除する前に、このリリースを {{count}} 環境からアンデプロイしてください",
- "versions.disabledReason.releaseInUse_other": "削除する前に、このリリースを {{count}} 環境からアンデプロイしてください",
- "versions.dslReadFailed": "DSL ファイルの読み込みに失敗しました。別のファイルを選択してもう一度お試しください。",
- "versions.dslReading": "DSL ファイルを読み込み中...",
- "versions.dslUnsupportedMode": "デプロイにはワークフロー DSL ファイルのみ使用できます。",
- "versions.editFailed": "リリースの更新に失敗しました。",
- "versions.editRelease": "リリースを編集",
- "versions.editReleaseDescription": "このリリースの名前と説明を更新します。",
- "versions.editSuccess": "リリース「{{name}}」を更新しました。",
- "versions.emptyDescription": "環境にデプロイする前に、最初のリリースを作成してください。",
- "versions.emptyTitle": "リリースはまだありません",
- "versions.exportDsl": "DSL をエクスポート",
- "versions.exportDslFailed": "DSL のエクスポートに失敗しました。",
- "versions.exportingDsl": "エクスポート中...",
- "versions.groupHeader.deploy": "デプロイ",
- "versions.groupHeader.rollback": "以前のバージョンをデプロイ",
- "versions.groupHeader.unavailable": "利用不可",
- "versions.manualDslOption": "DSL をアップロード",
- "versions.moreActions": "その他のアクション",
- "versions.optional": "任意",
- "versions.releaseAlreadyExists": "同じ内容のリリースが既に存在します: {{name}}。",
- "versions.releaseContentCheckFailed": "リリース内容の確認に失敗しました。",
- "versions.releaseDescriptionLabel": "説明",
- "versions.releaseDescriptionPlaceholder": "このリリースを説明してください",
- "versions.releaseNameConflict": "このリリース名は既に存在します。別の名前を選択してください。",
- "versions.releaseNameLabel": "リリース名",
- "versions.releaseNamePlaceholder": "リリース名",
- "versions.releaseNameRequired": "リリース名を入力してください。",
- "versions.releaseSourceLabel": "リリースソース",
- "versions.rollbackTo": "{{name}} にデプロイ",
- "versions.saveEdit": "保存",
- "versions.sourceAppOption": "ワークフローアプリ"
+ "versions.deployTo": "{{name}} にデプロイ"
}
diff --git a/web/i18n/ko-KR/common.json b/web/i18n/ko-KR/common.json
index d541775d51f..2b8227785e5 100644
--- a/web/i18n/ko-KR/common.json
+++ b/web/i18n/ko-KR/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "앱 세부정보",
"menus.apps": "스튜디오",
"menus.datasets": "지식",
- "menus.deployments": "배포",
"menus.exploreMarketplace": "Marketplace 둘러보기",
"menus.plugins": "통합",
"menus.status": "베타 버전",
diff --git a/web/i18n/ko-KR/deployments.json b/web/i18n/ko-KR/deployments.json
index f36fcb60ba1..b4f37e7f7dd 100644
--- a/web/i18n/ko-KR/deployments.json
+++ b/web/i18n/ko-KR/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "cURL 예제 복사",
- "access.api.createFailed": "API 토큰 생성에 실패했습니다.",
- "access.api.createKey": "API 토큰 생성",
- "access.api.createKeyTitle": "새 API 토큰 생성",
- "access.api.curlExampleTitle": "cURL 예제",
- "access.api.description": "이 배포에 HTTP로 액세스합니다. 각 API 토큰은 하나의 환경으로 범위가 지정됩니다.",
- "access.api.developerTitle": "개발자 API",
- "access.api.disabled": "이 배포에서 API 액세스가 비활성화되어 있습니다.",
- "access.api.disabledHint": "환경별 범위 토큰을 생성하려면 API 액세스를 활성화하세요.",
- "access.api.docs": "API 문서",
- "access.api.docsClose": "API 문서 닫기",
- "access.api.docsDescription": "이 배포에 대한 워크플로우 API 레퍼런스를 확인합니다.",
- "access.api.docsTitle": "워크플로우 API 문서",
- "access.api.empty": "API 토큰을 발급하려면 먼저 환경에 배포하세요.",
- "access.api.emptyTitle": "배포된 환경 없음",
- "access.api.endpoint": "요청 URL",
- "access.api.keyList": "API 토큰 목록",
- "access.api.nameLabel": "API 토큰 이름",
- "access.api.namePlaceholder": "API 토큰 이름을 입력하세요",
- "access.api.nameRequired": "API 토큰 이름은 필수입니다.",
- "access.api.newKey": "새 API 토큰 생성",
- "access.api.newTokenDescription": "이 API 토큰은 한 번만 표시됩니다. 이 페이지를 떠나기 전에 복사하세요.",
- "access.api.newTokenLabel": "API 토큰",
- "access.api.newTokenTitle": "API 토큰이 생성되었습니다",
- "access.api.noKeys": "아직 API 토큰이 없습니다. API 호출을 시작하려면 토큰을 생성하세요.",
- "access.api.noKeysTitle": "아직 API 토큰이 없습니다",
- "access.api.revokeConfirmDescription": "API 토큰 \"{{name}}\"이(가) 즉시 작동을 중지합니다. 이 작업은 취소할 수 없습니다.",
- "access.api.revokeConfirmTitle": "API 토큰을 폐기하시겠습니까?",
- "access.api.revokeFailed": "API 토큰 폐기에 실패했습니다.",
- "access.api.revokeSuccess": "API 토큰이 폐기되었습니다",
- "access.api.table.action": "작업",
- "access.api.table.environment": "환경",
- "access.api.table.key": "API 토큰",
- "access.api.table.name": "이름",
- "access.channels.disabled": "이 배포에서 액세스 채널이 비활성화되어 있습니다.",
- "access.channels.disabledHint": "WebApp 및 CLI 진입점을 노출하려면 액세스 채널을 활성화하세요.",
- "access.channels.title": "액세스 채널",
- "access.cli.description": "터미널에서 difyctl로 호출합니다. 스크립트, 자동화된 워크플로우 또는 에이전트 통합에 적합합니다.",
- "access.cli.docs": "사용 가이드",
- "access.cli.domain": "도메인",
- "access.cli.empty": "CLI 엔드포인트가 구성되지 않았습니다.",
- "access.cli.install": "CLI 설치",
- "access.cli.title": "CLI",
- "access.copy": "복사",
- "access.copyFailed": "복사 실패",
- "access.members.groupCount_one": "{{count}}개 그룹",
- "access.members.groupCount_other": "{{count}}개 그룹",
- "access.members.memberCount_one": "{{count}}명 구성원",
- "access.members.memberCount_other": "{{count}}명 구성원",
- "access.permission.anyone": "링크가 있는 모든 사람",
- "access.permission.organization": "플랫폼 내 모든 구성원",
- "access.permission.specific": "플랫폼 내 특정 구성원",
- "access.permission.specificDesc": "특정 그룹 또는 구성원을 선택하세요",
- "access.permission.updateFailed": "액세스 정책 업데이트에 실패했습니다.",
- "access.permissions.editAriaLabel": "{{environment}}에 대한 액세스 구성",
- "access.permissions.editDescription": "WebApp 및 CLI 진입점에 대한 액세스 권한을 설정합니다.",
- "access.permissions.editTitle": "액세스 권한",
- "access.permissions.title": "액세스 권한",
- "access.revoke": "폐기",
- "access.runAccess.noEnvs": "액세스 권한을 구성하려면 환경에 배포하세요.",
- "access.runAccess.noEnvsTitle": "배포된 환경 없음",
- "access.runAccess.openWebapp": "WebApp 열기",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "최종 사용자를 위한 호스팅된 웹 페이지입니다.",
- "access.runAccess.webappEmpty": "곧 제공됩니다.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "외부",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "알 수 없음",
- "card.access.api": "API 토큰",
- "card.access.cli": "CLI",
- "card.access.none": "액세스 없음",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "첫 번째 릴리스 만들기",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "배포 삭제",
- "card.menu.deploy": "환경에 배포",
- "card.menu.editInfo": "정보 편집",
- "card.moreActions": "더 많은 작업",
- "card.noDescription": "제공된 설명이 없습니다.",
"card.notDeployed": "배포되지 않음",
- "card.tooltip.createdAt": "생성됨",
- "card.tooltip.deployed": "배포됨",
- "card.tooltip.deploymentStatus": "배포",
- "card.tooltip.notDeployedShort": "배포되지 않음",
- "card.tooltip.releaseName": "릴리스 이름",
- "card.tooltip.source": "소스",
"common.loadFailed": "로드에 실패했습니다. 나중에 다시 시도해 주세요.",
- "createGuide.actions.back": "뒤로",
- "createGuide.actions.createAndDeploy": "생성 및 배포",
- "createGuide.actions.creating": "생성 중...",
- "createGuide.actions.deploying": "생성 및 배포 중...",
- "createGuide.actions.next": "다음",
- "createGuide.actions.skipDeploy": "건너뛰기, 나중에 배포",
- "createGuide.dsl.defaultAppName": "가져온 DSL 앱",
- "createGuide.dsl.description": "워크플로우 DSL 패키지를 업로드하여 배포, 첫 번째 릴리스 및 선택적 환경 배포를 생성합니다.",
- "createGuide.dsl.dropDescription": "워크플로우 YAML DSL 패키지를 업로드하세요. 배포 옵션은 배포 전에 이 파일에서 확인됩니다.",
- "createGuide.dsl.dropTitle": "워크플로우 DSL 패키지 업로드",
- "createGuide.dsl.readFailed": "DSL 파일을 읽지 못했습니다. 다른 파일을 선택하고 다시 시도하세요.",
- "createGuide.dsl.reading": "DSL 파일 읽는 중...",
- "createGuide.dsl.title": "DSL 가져오기",
- "createGuide.dsl.unsupportedMode": "워크플로우 DSL 파일만 배포에 사용할 수 있습니다.",
- "createGuide.errors.createReleaseFailed": "배포 또는 릴리스 생성에 실패했습니다.",
- "createGuide.errors.deployFailed": "환경에 배포하지 못했습니다.",
- "createGuide.method.description": "첫 번째 릴리스를 생성하는 데 사용할 소스를 선택하세요.",
- "createGuide.methods.bindApp.description": "스튜디오의 기존 워크플로우 앱을 릴리스 소스로 사용합니다.",
- "createGuide.methods.bindApp.title": "기존 워크플로우 앱 바인딩",
- "createGuide.methods.importDsl.description": "워크플로우 YAML DSL 패키지를 업로드하고 배포 UI를 통해 계속합니다.",
- "createGuide.methods.importDsl.title": "DSL 가져오기",
- "createGuide.nav.back": "배포",
- "createGuide.release.defaultName": "최초 릴리스",
- "createGuide.release.deployInfo": "배포 정보",
- "createGuide.release.description": "배포 정보와 첫 번째 릴리스 세부 정보를 입력합니다.",
- "createGuide.release.firstVersion": "첫 번째 릴리스",
- "createGuide.release.instanceDescription": "배포 설명",
- "createGuide.release.instanceDescriptionPlaceholder": "이 배포의 사용 목적을 설명하세요",
- "createGuide.release.instanceName": "배포 이름",
- "createGuide.release.instanceNameConflict": "이 이름의 배포가 이미 존재합니다. 다른 이름을 선택하세요.",
- "createGuide.release.releaseDescription": "릴리스 설명",
- "createGuide.release.releaseDescriptionPlaceholder": "이 릴리스를 설명하세요",
- "createGuide.release.releaseName": "릴리스 이름",
- "createGuide.release.title": "기본 정보",
- "createGuide.source.clearSearch": "앱 검색 지우기",
- "createGuide.source.description": "첫 번째 릴리스를 생성하는 데 사용할 소스를 선택하세요.",
- "createGuide.source.empty": "워크플로우 앱이 없습니다.",
- "createGuide.source.searchPlaceholder": "앱 검색",
- "createGuide.source.sourceApp": "워크플로우 앱",
- "createGuide.source.title": "릴리스 소스",
- "createGuide.steps.method": "릴리스 소스",
- "createGuide.steps.release": "기본 정보",
- "createGuide.steps.source": "릴리스 소스",
- "createGuide.steps.target": "환경에 배포",
- "createGuide.target.bindingCount_one": "{{count}}개 바인딩",
- "createGuide.target.bindingCount_other": "{{count}}개 바인딩",
- "createGuide.target.bindingHint": "이 릴리스에서 사용할 자격 증명을 선택하세요.",
- "createGuide.target.bindings": "자격 증명",
- "createGuide.target.description": "대상 환경을 선택하고 이 릴리스가 필요로 하는 런타임 설정을 제공하세요. 이 단계는 건너뛸 수 있습니다.",
- "createGuide.target.envVarCount_one": "{{count}}개 변수",
- "createGuide.target.envVarCount_other": "{{count}}개 변수",
- "createGuide.target.envVarHint": "이 릴리스가 필요로 하는 각 환경 변수에 대해 사용자 지정 값을 입력하거나 앱에 정의된 값을 사용하세요.",
- "createGuide.target.envVarPlaceholder": "값을 입력하세요",
- "createGuide.target.envVarSource.ariaLabel": "{{key}}의 변수 값 소스 선택",
- "createGuide.target.envVarSource.default": "앱 값",
- "createGuide.target.envVarSource.lastDeployment": "마지막 배포 값",
- "createGuide.target.envVarSource.literal": "사용자 지정 값",
- "createGuide.target.envVarType.number": "숫자",
- "createGuide.target.envVarType.secret": "시크릿",
- "createGuide.target.envVarType.string": "문자열",
- "createGuide.target.envVars": "환경 변수",
- "createGuide.target.environment": "대상 환경",
- "createGuide.target.loadBindingsFailed": "자격 증명을 로드하지 못했습니다.",
- "createGuide.target.loadEnvironmentsFailed": "배포 환경을 로드하지 못했습니다.",
- "createGuide.target.missingRequiredBinding": "이 필수 바인딩에 대한 자격 증명을 선택하세요.",
- "createGuide.target.noBindingRequired": "자격 증명이 필요하지 않습니다.",
- "createGuide.target.noCredentialCandidates": "사용 가능한 자격 증명이 없습니다.",
- "createGuide.target.noEnvironmentOptions": "사용 가능한 배포 환경이 없습니다.",
- "createGuide.target.selectCredential": "자격 증명을 선택하세요",
- "createGuide.target.title": "환경에 배포",
- "createGuide.title": "새 배포",
- "createModal.appPickerPlaceholder": "워크플로우 앱을 선택하세요",
- "createModal.appSearchEmpty": "일치하는 워크플로우 앱이 없습니다",
- "createModal.appSearchPlaceholder": "워크플로우 앱 검색…",
- "createModal.cancel": "취소",
- "createModal.loadingApps": "앱 로드 중…",
- "deployDrawer.bindingCount_one": "{{count}}개 바인딩",
- "deployDrawer.bindingCount_other": "{{count}}개 바인딩",
"deployDrawer.bindingOptionsFailed": "자격 증명 옵션을 로드하지 못했습니다.",
"deployDrawer.bindingSelectionHint": "이 배포에서 사용할 자격 증명을 선택하세요.",
- "deployDrawer.cancel": "취소",
- "deployDrawer.close": "배포 드로어 닫기",
- "deployDrawer.defaultSelect": "선택...",
- "deployDrawer.deploy": "환경에 배포",
- "deployDrawer.deployFailed": "배포 시작에 실패했습니다.",
"deployDrawer.deploying": "배포 중...",
- "deployDrawer.description": "배포할 릴리스와 대상 환경을 선택하세요.",
- "deployDrawer.envVarCount_one": "{{count}}개 변수",
- "deployDrawer.envVarCount_other": "{{count}}개 변수",
- "deployDrawer.envVarHint": "이 릴리스가 필요로 하는 각 환경 변수에 대해 사용자 지정 값을 입력하거나 앱에 정의된 값을 사용하세요.",
- "deployDrawer.envVarPlaceholder": "값을 입력하세요",
"deployDrawer.envVarSource.ariaLabel": "{{key}}의 변수 값 소스 선택",
- "deployDrawer.envVarSource.default": "앱 값",
"deployDrawer.envVarSource.lastDeployment": "마지막 배포 값",
"deployDrawer.envVarSource.literal": "사용자 지정 값",
"deployDrawer.envVarType.number": "숫자",
"deployDrawer.envVarType.secret": "시크릿",
"deployDrawer.envVarType.string": "문자열",
"deployDrawer.envVars": "환경 변수",
- "deployDrawer.existingReleaseHint": "이 릴리스는 그대로 배포됩니다. 새 릴리스는 생성되지 않습니다.",
- "deployDrawer.lockedHint": "현재 환경에 잠김",
- "deployDrawer.missingRequiredBinding": "이 필수 바인딩에 대한 자격 증명을 선택하세요.",
- "deployDrawer.missingRequiredEnvVar": "이 필수 환경 변수의 값을 입력하세요.",
- "deployDrawer.noBindingRequired": "필수 아님",
"deployDrawer.noCredentialCandidates": "사용 가능한 자격 증명이 없습니다.",
"deployDrawer.noNewEnvironmentAvailable": "사용 가능한 모든 환경에 이미 배포가 있습니다.",
- "deployDrawer.noOtherReleaseAvailable": "이 환경에 사용할 수 있는 다른 릴리스가 없습니다.",
- "deployDrawer.noReleaseAvailable": "환경에 배포하기 전에 릴리스를 생성하세요.",
- "deployDrawer.notFound": "배포를 찾을 수 없습니다.",
- "deployDrawer.releaseLabel": "릴리스",
"deployDrawer.runtimeCredentials": "자격 증명",
"deployDrawer.selectCredential": "자격 증명을 선택하세요",
- "deployDrawer.selectEnv": "환경을 선택하세요",
- "deployDrawer.selectRelease": "릴리스를 선택하세요",
- "deployDrawer.targetEnv": "대상 환경",
- "deployDrawer.title": "환경에 배포",
- "deployTab.closeError": "닫기",
"deployTab.col.actions": "작업",
- "deployTab.col.currentRelease": "현재 릴리스",
"deployTab.col.environment": "환경",
"deployTab.col.status": "상태",
"deployTab.confirmUndeploy": "배포 취소",
- "deployTab.deployOtherVersion": "다른 릴리스 배포",
- "deployTab.emptyDescription": "이 배포를 사용자가 사용할 수 있도록 하려면 릴리스와 대상 환경을 선택하세요.",
- "deployTab.emptyTitle": "아직 실행 중인 환경이 없습니다",
- "deployTab.errorCode": "코드",
- "deployTab.errorDialogDesc": "재시도하거나 다른 릴리스를 배포하기 전에 마지막으로 실패한 배포를 검토하세요.",
- "deployTab.errorDialogTitle": "{{name}}의 배포 오류",
- "deployTab.errorMessage": "메시지",
- "deployTab.errorPhase": "단계",
"deployTab.moreActions": "더 많은 작업",
- "deployTab.newDeployment": "새 환경에 배포",
- "deployTab.panel.unknownError": "배포에 실패했습니다.",
"deployTab.redeploy": "재배포",
- "deployTab.retry": "다시 시도",
- "deployTab.status.deployFailed": "배포 실패",
- "deployTab.status.deployingRelease": "배포 중 ({{release}})",
- "deployTab.status.runningOutOfSync": "실행 중 (동기화 대기 중)",
- "deployTab.status.runningWithFailed": "실행 중 (마지막 배포 실패)",
"deployTab.undeploy": "배포 취소",
- "deployTab.undeployConfirmDesc": "환경 엔드포인트를 사용할 수 없게 되지만 버전은 삭제되지 않습니다.",
- "deployTab.undeployConfirmTitle": "{{name}} 배포를 취소하시겠습니까?",
"deployTab.undeployConfirmWarning": "확인 후 이 환경은 배포 취소 중 상태로 전환되며 작업이 일시적으로 비활성화됩니다.",
- "deployTab.viewError": "오류 보기",
- "detail.mobileTabs": "배포 섹션",
- "detail.notFound": "배포를 찾을 수 없음",
- "documentTitle.create": "새 배포 · 배포",
- "documentTitle.detail": "배포 · 배포",
- "documentTitle.list": "배포",
- "filter.allEnvs": "모든 환경",
- "filter.searchPlaceholder": "배포 검색",
- "health.ENVIRONMENT_STATUS_ADMISSION": "승인",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "부트스트래핑",
- "health.ENVIRONMENT_STATUS_DELETING": "삭제 중",
"health.ENVIRONMENT_STATUS_FAILED": "사용 불가",
- "health.ENVIRONMENT_STATUS_READY": "사용 가능",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "알 수 없음",
- "list.clearFilters": "필터 지우기",
- "list.clearSearch": "배포 검색 지우기",
- "list.createDeployment": "새로 만들기",
- "list.emptyDescription": "워크플로우 앱 또는 워크플로우 DSL 패키지에서 배포를 생성하여 릴리스, 환경 및 액세스를 관리하세요.",
- "list.emptyFilteredDescription": "현재 검색 또는 환경 필터와 일치하는 배포가 없습니다.",
- "list.emptyFilteredTitle": "일치하는 배포 없음",
"list.emptyTitle": "아직 배포가 없습니다",
- "mode.ENVIRONMENT_MODE_ISOLATED": "격리됨",
- "mode.ENVIRONMENT_MODE_SHARED": "공유됨",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "알 수 없음",
- "overview.accessMeta.apiTokens": "API 토큰 관리",
- "overview.accessMeta.cli": "CLI 액세스 보기",
- "overview.accessMeta.webApp": "WebApp 액세스 관리",
- "overview.accessStatus": "액세스",
- "overview.api": "API 토큰",
- "overview.apiKeysCount_one": "{{count}}개 API 토큰",
- "overview.apiKeysCount_other": "{{count}}개 API 토큰",
- "overview.apiTokenSummary.environments_one": "{{count}}개 배포된 환경",
- "overview.apiTokenSummary.environments_other": "{{count}}개 배포된 환경",
- "overview.cardAction.deployLatest": "최신 릴리스 배포",
- "overview.cardAction.redeploy": "재배포",
- "overview.cardAction.viewProgress": "배포 보기",
- "overview.chip.behindTooltip_one": "최신 릴리스보다 1개 뒤처져 있습니다. 업데이트하려면 최신 릴리스를 배포하세요.",
- "overview.chip.behindTooltip_other": "최신 릴리스보다 {{count}}개 뒤처져 있습니다. 업데이트하려면 최신 릴리스를 배포하세요.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "배포 중",
- "overview.chip.deployingTooltip": "배포가 진행 중입니다.",
- "overview.chip.empty": "비어 있음",
- "overview.chip.emptyTooltip": "이 환경에 배포된 릴리스가 없습니다.",
- "overview.chip.failed": "실패",
- "overview.chip.failedTooltip": "최근 배포 시도가 실패했습니다.",
"overview.chip.latest": "최신",
- "overview.chip.latestTooltip": "이 환경은 최신 릴리스를 실행하고 있습니다.",
- "overview.chip.needsReleaseFirst": "먼저 릴리스를 생성하세요",
- "overview.chip.olderRelease": "이전",
- "overview.chip.olderReleaseTooltip": "이 환경은 이전 릴리스를 실행하고 있습니다.",
- "overview.chip.openInDeployTab": "배포 진행 상황 보기",
- "overview.disabled": "비활성화됨",
- "overview.enabled": "활성화됨",
- "overview.hero.byName": "{{name}} 작성",
- "overview.hero.empty": "아직 릴리스가 없습니다",
- "overview.hero.emptyDescription": "배포하기 전에 현재 소스에서 릴리스를 생성하세요.",
- "overview.latestRelease.releaseCount_one": "{{count}}개 릴리스",
- "overview.latestRelease.releaseCount_other": "{{count}}개 릴리스",
- "overview.latestReleaseTitle": "최신 릴리스",
- "overview.previousReleases.viewAll": "모두 보기",
- "overview.strip.deployToNewEnvironment": "새 환경에 배포",
- "overview.strip.emptyDeployableDescription": "준비되면 최신 릴리스를 환경에 배포하세요.",
- "overview.strip.emptyDescription": "환경에 배포하기 전에 릴리스를 생성하세요.",
- "overview.strip.emptyTitle": "아직 인스턴스가 없습니다",
- "overview.strip.title": "인스턴스",
- "settings.delete": "배포 삭제",
- "settings.deleteConfirmDesc": "{{name}}을(를) 삭제하시겠습니까? 모든 인스턴스가 실행을 중지하고 모든 환경에서 제거됩니다. 이 작업은 취소할 수 없습니다.",
- "settings.deleteConfirmTitle": "배포 삭제",
- "settings.deleteFailed": "배포 삭제에 실패했습니다.",
- "settings.deleted": "배포가 삭제되었습니다",
- "settings.description": "설명",
- "settings.name": "배포 이름",
- "settings.save": "변경 사항 저장",
- "settings.updateFailed": "배포 업데이트에 실패했습니다.",
- "settings.updated": "배포가 업데이트되었습니다",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "배포 중",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "동기화 대기 중",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "배포 실패",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "유효하지 않음",
"status.RUNTIME_INSTANCE_STATUS_READY": "실행 중",
@@ -370,87 +89,6 @@
"studio.versionValue": "버전 값",
"studio.versionsBehind_one": "{{count}}개 버전 뒤처짐",
"studio.versionsBehind_other": "{{count}}개 버전 뒤처짐",
- "tabs.access.description": "액세스 채널 및 액세스 권한을 관리합니다.",
- "tabs.access.name": "액세스",
- "tabs.api-tokens.description": "API 토큰을 관리하고 HTTP를 통해 인스턴스를 호출합니다.",
- "tabs.api-tokens.name": "API 토큰",
- "tabs.instances.description": "배포된 환경에서 인스턴스를 보고 관리합니다.",
- "tabs.instances.name": "인스턴스",
- "tabs.overview.description": "환경 전반에 걸친 배포 상태를 확인합니다.",
- "tabs.overview.name": "개요",
- "tabs.releases.description": "릴리스를 생성, 배포 및 관리합니다.",
- "tabs.releases.name": "릴리스",
- "unsupportedDslNodes.description": "이 릴리스에는 배포 런타임이 아직 지원하지 않는 노드가 포함되어 있습니다. 스튜디오에서 제거하거나 교체한 후 다시 시도하세요.",
- "unsupportedDslNodes.descriptionWithTypes": "이 릴리스에는 배포 런타임이 아직 지원하지 않는 노드가 포함되어 있습니다: {{nodeTypes}}. 스튜디오에서 제거하거나 교체한 후 다시 시도하세요.",
- "unsupportedDslNodes.title": "지원되지 않는 노드",
- "unsupportedDslNodes.unknownType": "알 수 없는 유형",
- "versions.cancelCreate": "취소",
- "versions.cancelDelete": "취소",
- "versions.cancelEdit": "취소",
"versions.checkingReleaseContent": "릴리스 콘텐츠 확인 중...",
- "versions.col.action": "작업",
- "versions.col.author": "작성자",
- "versions.col.createdAt": "생성 시각",
- "versions.col.deployedTo": "배포 대상",
- "versions.col.release": "릴리스",
- "versions.col.sourceApp": "소스",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "생성",
- "versions.createFailed": "릴리스 생성에 실패했습니다.",
- "versions.createRelease": "릴리스 생성",
- "versions.createReleaseDescription": "워크플로우 앱 또는 워크플로우 DSL 파일에서 배포 가능한 릴리스를 생성합니다.",
- "versions.createSuccess": "릴리스 \"{{name}}\"이(가) 생성되었습니다.",
- "versions.creating": "생성 중...",
- "versions.currentOn": "{{name}}의 현재 릴리스",
- "versions.deleteConfirmDesc": "릴리스 \"{{name}}\"이(가) 영구적으로 삭제됩니다. 이 작업은 취소할 수 없습니다.",
- "versions.deleteConfirmTitle": "릴리스를 삭제하시겠습니까?",
- "versions.deleteFailed": "릴리스 삭제에 실패했습니다.",
- "versions.deleteRelease": "릴리스 삭제",
- "versions.deleteSuccess": "릴리스 \"{{name}}\"이(가) 삭제되었습니다.",
- "versions.deployTo": "{{name}}에 배포",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "배포 중",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "동기화 대기 중",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "실패",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "유효하지 않음",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "실행 중",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "배포되지 않음",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "배포 취소 중",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "알 수 없음",
- "versions.deployingTo": "{{name}}에 배포 중",
- "versions.disabledReason.checkDeploymentsFailed": "배포 사용을 확인할 수 없습니다. 나중에 다시 시도하세요.",
- "versions.disabledReason.checkingDeployments": "배포 사용 확인 중",
- "versions.disabledReason.current": "이 릴리스는 이미 {{name}}에서 실행 중입니다",
- "versions.disabledReason.deploying": "활성 배포가 완료될 때까지 기다리세요",
- "versions.disabledReason.releaseInUse_one": "삭제하기 전에 이 릴리스를 {{count}}개 환경에서 배포 취소하세요",
- "versions.disabledReason.releaseInUse_other": "삭제하기 전에 이 릴리스를 {{count}}개 환경에서 배포 취소하세요",
- "versions.dslReadFailed": "DSL 파일을 읽지 못했습니다. 다른 파일을 선택하고 다시 시도하세요.",
- "versions.dslReading": "DSL 파일 읽는 중...",
- "versions.dslUnsupportedMode": "워크플로우 DSL 파일만 배포에 사용할 수 있습니다.",
- "versions.editFailed": "릴리스 업데이트에 실패했습니다.",
- "versions.editRelease": "릴리스 편집",
- "versions.editReleaseDescription": "이 릴리스의 이름과 설명을 업데이트합니다.",
- "versions.editSuccess": "릴리스 \"{{name}}\"이(가) 업데이트되었습니다.",
- "versions.emptyDescription": "환경에 배포하기 전에 첫 번째 릴리스를 생성하세요.",
- "versions.emptyTitle": "아직 릴리스가 없습니다",
- "versions.exportDsl": "DSL 내보내기",
- "versions.exportDslFailed": "DSL 내보내기에 실패했습니다.",
- "versions.exportingDsl": "내보내는 중...",
- "versions.groupHeader.deploy": "배포",
- "versions.groupHeader.rollback": "이전 버전 배포",
- "versions.groupHeader.unavailable": "사용 불가",
- "versions.manualDslOption": "DSL 업로드",
- "versions.moreActions": "더 많은 작업",
- "versions.optional": "선택 사항",
- "versions.releaseAlreadyExists": "같은 콘텐츠의 릴리스가 이미 존재합니다: {{name}}.",
- "versions.releaseContentCheckFailed": "릴리스 콘텐츠 확인에 실패했습니다.",
- "versions.releaseDescriptionLabel": "설명",
- "versions.releaseDescriptionPlaceholder": "이 릴리스를 설명하세요",
- "versions.releaseNameConflict": "이 릴리스 이름은 이미 존재합니다. 다른 이름을 선택하세요.",
- "versions.releaseNameLabel": "릴리스 이름",
- "versions.releaseNamePlaceholder": "릴리스 이름",
- "versions.releaseNameRequired": "릴리스 이름을 입력하세요.",
- "versions.releaseSourceLabel": "릴리스 소스",
- "versions.rollbackTo": "{{name}}에 배포",
- "versions.saveEdit": "저장",
- "versions.sourceAppOption": "워크플로우 앱"
+ "versions.deployTo": "{{name}}에 배포"
}
diff --git a/web/i18n/lo-LA/common.json b/web/i18n/lo-LA/common.json
index 28ba50eb83f..758143e154e 100644
--- a/web/i18n/lo-LA/common.json
+++ b/web/i18n/lo-LA/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "ລາຍລະອຽດແອັບ",
"menus.apps": "ສະຕູດິໂອ",
"menus.datasets": "ຖານຄວາມຮູ້",
- "menus.deployments": "ການຕິດຕັ້ງ",
"menus.exploreMarketplace": "ສຳຫຼວດຕະຫຼາດແອັບ",
"menus.plugins": "ການເຊື່ອມຕໍ່",
"menus.status": "ເບຕ້າ",
diff --git a/web/i18n/lo-LA/deployments.json b/web/i18n/lo-LA/deployments.json
index 4b15585c9d7..e4788c6c7c2 100644
--- a/web/i18n/lo-LA/deployments.json
+++ b/web/i18n/lo-LA/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "ຄັດລອກຕົວຢ່າງ cURL",
- "access.api.createFailed": "ສ້າງໂທເຄັນ API ບໍ່ສຳເລັດ.",
- "access.api.createKey": "ສ້າງໂທເຄັນ API",
- "access.api.createKeyTitle": "ສ້າງໂທເຄັນ API ໃໝ່",
- "access.api.curlExampleTitle": "ຕົວຢ່າງ cURL",
- "access.api.description": "ເຂົ້າເຖິງການຕິດຕັ້ງນີ້ຜ່ານ HTTP. ແຕ່ລະໂທເຄັນ API ຈະຖືກຈຳກັດຂອບເຂດໄວ້ໃນແຕ່ລະສະພາບແວດລ້ອມ.",
- "access.api.developerTitle": "API ສຳລັບນັກພັດທະນາ",
- "access.api.disabled": "ການເຂົ້າເຖິງ API ຖືກປິດໄວ້ສຳລັບການຕິດຕັ້ງນີ້.",
- "access.api.disabledHint": "ເປີດໃຊ້ການເຂົ້າເຖິງ API ເພື່ອສ້າງໂທເຄັນສຳລັບແຕ່ລະສະພາບແວດລ້ອມ.",
- "access.api.docs": "ເອກະສານ API",
- "access.api.docsClose": "ປິດເອກະສານ API",
- "access.api.docsDescription": "ເບິ່ງລາຍລະອຽດ Workflow API ສຳລັບການຕິດຕັ້ງນີ້.",
- "access.api.docsTitle": "ເອກະສານ Workflow API",
- "access.api.empty": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມກ່ອນ ເພື່ອເລີ່ມການອອກໂທເຄັນ API.",
- "access.api.emptyTitle": "ບໍ່ມີສະພາບແວດລ້ອມທີ່ຖືກຕິດຕັ້ງ",
- "access.api.endpoint": "URL ຂອງການຮ້ອງຂໍ",
- "access.api.keyList": "ລາຍຊື່ໂທເຄັນ API",
- "access.api.nameLabel": "ຊື່ໂທເຄັນ API",
- "access.api.namePlaceholder": "ປ້ອນຊື່ໂທເຄັນ API",
- "access.api.nameRequired": "ຈຳເປັນຕ້ອງໃສ່ຊື່ໂທເຄັນ API.",
- "access.api.newKey": "ສ້າງໂທເຄັນ API ໃໝ່",
- "access.api.newTokenDescription": "ໂທເຄັນ API ນີ້ຈະສະແດງພຽງແຕ່ຄັ້ງດຽວເທົ່ານັ້ນ. ກະລຸນາຄັດລອກໄວ້ກ່ອນອອກຈາກໜ້ານີ້.",
- "access.api.newTokenLabel": "ໂທເຄັນ API",
- "access.api.newTokenTitle": "ສ້າງໂທເຄັນ API ສຳເລັດແລ້ວ",
- "access.api.noKeys": "ຍັງບໍ່ມີໂທເຄັນ API. ສ້າງຂຶ້ນມາເພື່ອເລີ່ມການເອີ້ນໃຊ້ API.",
- "access.api.noKeysTitle": "ຍັງບໍ່ມີໂທເຄັນ API",
- "access.api.revokeConfirmDescription": "ໂທເຄັນ API \"{{name}}\" ຈະຢຸດເຮັດວຽກທັນທີ. ການດຳເນີນການນີ້ບໍ່ສາມາດກັບຄືນໄດ້.",
- "access.api.revokeConfirmTitle": "ຍົກເລີກໂທເຄັນ API?",
- "access.api.revokeFailed": "ຍົກເລີກໂທເຄັນ API ບໍ່ສຳເລັດ.",
- "access.api.revokeSuccess": "ຍົກເລີກໂທເຄັນ API ແລ້ວ",
- "access.api.table.action": "ການຈັດການ",
- "access.api.table.environment": "ສະພາບແວດລ້ອມ",
- "access.api.table.key": "ໂທເຄັນ API",
- "access.api.table.name": "ຊື່",
- "access.channels.disabled": "ຊ່ອງທາງການເຂົ້າເຖິງຖືກປິດໄວ້ສຳລັບການຕິດຕັ້ງນີ້.",
- "access.channels.disabledHint": "ເປີດໃຊ້ຊ່ອງທາງການເຂົ້າເຖິງເພື່ອສະແດງຈຸດເຊື່ອມຕໍ່ WebApp ແລະ CLI.",
- "access.channels.title": "ຊ່ອງທາງການເຂົ້າເຖິງ",
- "access.cli.description": "ເອີ້ນໃຊ້ຈາກເທີມິນໍ (Terminal) ດ້ວຍ difyctl, ເໝາະສຳລັບສະຄຣິບ, ເວີກໂຟລອັດຕະໂນມັດ ຫຼື ການເຊື່ອມຕໍ່ກັບ Agent.",
- "access.cli.docs": "ຄູ່ມືການໃຊ້ງານ",
- "access.cli.domain": "ໂດເມນ",
- "access.cli.empty": "ຍັງບໍ່ໄດ້ກຳນົດຄ່າຈຸດເຊື່ອມຕໍ່ CLI.",
- "access.cli.install": "ຕິດຕັ້ງ CLI",
- "access.cli.title": "CLI",
- "access.copy": "ຄັດລອກ",
- "access.copyFailed": "ຄັດລອກບໍ່ສຳເລັດ",
- "access.members.groupCount_one": "{{count}} ກຸ່ມ",
- "access.members.groupCount_other": "{{count}} ກຸ່ມ",
- "access.members.memberCount_one": "{{count}} ສະມາຊິກ",
- "access.members.memberCount_other": "{{count}} ສະມາຊິກ",
- "access.permission.anyone": "ທຸກຄົນທີ່ມີລິ້ງ",
- "access.permission.organization": "ສະມາຊິກທັງໝົດໃນແພລັດຟອມ",
- "access.permission.specific": "ສະມາຊິກສະເພາະໃນແພລັດຟອມ",
- "access.permission.specificDesc": "ເລືອກກຸ່ມ ຫຼື ສະມາຊິກສະເພາະ",
- "access.permission.updateFailed": "ອັບເດດນະໂຍບາຍການເຂົ້າເຖິງບໍ່ສຳເລັດ.",
- "access.permissions.editAriaLabel": "ກຳນົດຄ່າການເຂົ້າເຖິງສຳລັບ {{environment}}",
- "access.permissions.editDescription": "ຕັ້ງຄ່າສິດການເຂົ້າເຖິງສຳລັບ WebApp ແລະ ຈຸດເຊື່ອມຕໍ່ CLI.",
- "access.permissions.editTitle": "ສິດການເຂົ້າເຖິງ",
- "access.permissions.title": "ສິດການເຂົ້າເຖິງ",
- "access.revoke": "ຍົກເລີກ",
- "access.runAccess.noEnvs": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມເພື່ອຕັ້ງຄ່າສິດການເຂົ້າເຖິງ.",
- "access.runAccess.noEnvsTitle": "ບໍ່ມີສະພາບແວດລ້ອມທີ່ຖືກຕິດຕັ້ງ",
- "access.runAccess.openWebapp": "ເປີດ WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "ໜ້າເວັບສຳລັບຜູ້ໃຊ້ທົ່ວໄປ.",
- "access.runAccess.webappEmpty": "ຈະມາໃນໄວໆນີ້.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "ພາຍນອກ (External)",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "ບໍ່ຮູ້ຈັກ",
- "card.access.api": "ໂທເຄັນ API",
- "card.access.cli": "CLI",
- "card.access.none": "ບໍ່ມີການເຂົ້າເຖິງ",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "ສ້າງລຸ້ນທຳອິດ",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "ລຶບການຕິດຕັ້ງ",
- "card.menu.deploy": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ",
- "card.menu.editInfo": "ແກ້ໄຂຂໍ້ມູນ",
- "card.moreActions": "ການຈັດການເພີ່ມເຕີມ",
- "card.noDescription": "ບໍ່ມີລາຍລະອຽດ.",
"card.notDeployed": "ຍັງບໍ່ໄດ້ຕິດຕັ້ງ",
- "card.tooltip.createdAt": "ສ້າງເມື່ອ",
- "card.tooltip.deployed": "ຕິດຕັ້ງແລ້ວ",
- "card.tooltip.deploymentStatus": "ສະຖານະການຕິດຕັ້ງ",
- "card.tooltip.notDeployedShort": "ຍັງບໍ່ໄດ້ຕິດຕັ້ງ",
- "card.tooltip.releaseName": "ຊື່ລຸ້ນ (Release Name)",
- "card.tooltip.source": "ແຫຼ່ງທີ່ມາ",
"common.loadFailed": "ໂຫຼດຂໍ້ມູນບໍ່ສຳເລັດ. ກະລຸນາລອງໃໝ່ພາຍຫຼັງ.",
- "createGuide.actions.back": "ກັບຄືນ",
- "createGuide.actions.createAndDeploy": "ສ້າງ ແລະ ຕິດຕັ້ງ",
- "createGuide.actions.creating": "ກຳລັງສ້າງ...",
- "createGuide.actions.deploying": "ກຳລັງສ້າງ ແລະ ຕິດຕັ້ງ...",
- "createGuide.actions.next": "ຖັດໄປ",
- "createGuide.actions.skipDeploy": "ຂ້າມ, ຕິດຕັ້ງພາຍຫຼັງ",
- "createGuide.dsl.defaultAppName": "ແອັບທີ່ນຳເຂົ້າຈາກ DSL",
- "createGuide.dsl.description": "ອັບໂຫຼດແພັກເກັດ Workflow DSL ເພື່ອສ້າງການຕິດຕັ້ງ, ລຸ້ນທຳອິດ, ແລະ ການຕິດຕັ້ງສະພາບແວດລ້ອມ (ຖ້າຕ້ອງການ).",
- "createGuide.dsl.dropDescription": "ອັບໂຫຼດແພັກເກັດ Workflow YAML DSL. ຕົວເລືອກການຕິດຕັ້ງຈະຖືກກວດສອບຈາກໄຟລ໌ນີ້ກ່ອນການຕິດຕັ້ງ.",
- "createGuide.dsl.dropTitle": "ອັບໂຫຼດແພັກເກັດ Workflow DSL",
- "createGuide.dsl.readFailed": "ອ່ານໄຟລ໌ DSL ບໍ່ສຳເລັດ. ກະລຸນາເລືອກໄຟລ໌ອື່ນ ແລະ ລອງໃໝ່.",
- "createGuide.dsl.reading": "ກຳລັງອ່ານໄຟລ໌ DSL...",
- "createGuide.dsl.title": "ນຳເຂົ້າ DSL",
- "createGuide.dsl.unsupportedMode": "ສະເພາະໄຟລ໌ Workflow DSL ເທົ່ານັ້ນທີ່ສາມາດໃຊ້ໃນການຕິດຕັ້ງໄດ້.",
- "createGuide.errors.createReleaseFailed": "ສ້າງການຕິດຕັ້ງ ຫຼື ລຸ້ນບໍ່ສຳເລັດ.",
- "createGuide.errors.deployFailed": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມບໍ່ສຳເລັດ.",
- "createGuide.method.description": "ເລືອກແຫຼ່ງທີ່ມາທີ່ຈະໃຊ້ໃນການສ້າງລຸ້ນທຳອິດ.",
- "createGuide.methods.bindApp.description": "ໃຊ້ Workflow App ທີ່ມີຢູ່ໃນ Studio ເປັນແຫຼ່ງຂອງລຸ້ນ.",
- "createGuide.methods.bindApp.title": "ເຊື່ອມກັບ Workflow App ທີ່ມີຢູ່",
- "createGuide.methods.importDsl.description": "ອັບໂຫຼດແພັກເກັດ Workflow YAML DSL ແລະ ດຳເນີນການຕໍ່ຜ່ານ UI ການຕິດຕັ້ງ.",
- "createGuide.methods.importDsl.title": "ນຳເຂົ້າ DSL",
- "createGuide.nav.back": "ລາຍການຕິດຕັ້ງ",
- "createGuide.release.defaultName": "ລຸ້ນເລີ່ມຕົ້ນ",
- "createGuide.release.deployInfo": "ຂໍ້ມູນການຕິດຕັ້ງ",
- "createGuide.release.description": "ກະລຸນາປ້ອນຂໍ້ມູນການຕິດຕັ້ງ ແລະ ລາຍລະອຽດຂອງລຸ້ນທຳອິດ.",
- "createGuide.release.firstVersion": "ລຸ້ນທຳອິດ",
- "createGuide.release.instanceDescription": "ລາຍລະອຽດການຕິດຕັ້ງ",
- "createGuide.release.instanceDescriptionPlaceholder": "ອະທິບາຍວ່າການຕິດຕັ້ງນີ້ໃຊ້ເພື່ອຫຍັງ",
- "createGuide.release.instanceName": "ຊື່ການຕິດຕັ້ງ",
- "createGuide.release.instanceNameConflict": "ມີຊື່ການຕິດຕັ້ງນີ້ຢູ່ແລ້ວ. ກະລຸນາເລືອກຊື່ອື່ນ.",
- "createGuide.release.releaseDescription": "ລາຍລະອຽດຂອງລຸ້ນ",
- "createGuide.release.releaseDescriptionPlaceholder": "ອະທິບາຍກ່ຽວກັບລຸ້ນນີ້",
- "createGuide.release.releaseName": "ຊື່ລຸ້ນ",
- "createGuide.release.title": "ຂໍ້ມູນເບື້ອງຕົ້ນ",
- "createGuide.source.clearSearch": "ລ້າງການຄົ້ນຫາແອັບ",
- "createGuide.source.description": "ເລືອກແຫຼ່ງທີ່ມາທີ່ຈະໃຊ້ໃນການສ້າງລຸ້ນທຳອິດ.",
- "createGuide.source.empty": "ບໍ່ພົບ Workflow App.",
- "createGuide.source.searchPlaceholder": "ຄົ້ນຫາແອັບ",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "ແຫຼ່ງທີ່ມາຂອງລຸ້ນ",
- "createGuide.steps.method": "ແຫຼ່ງທີ່ມາຂອງລຸ້ນ",
- "createGuide.steps.release": "ຂໍ້ມູນເບື້ອງຕົ້ນ",
- "createGuide.steps.source": "ແຫຼ່ງທີ່ມາຂອງລຸ້ນ",
- "createGuide.steps.target": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ",
- "createGuide.target.bindingCount_one": "{{count}} ການເຊື່ອມຕໍ່",
- "createGuide.target.bindingCount_other": "{{count}} ການເຊື່ອມຕໍ່",
- "createGuide.target.bindingHint": "ເລືອກຂໍ້ມູນການເຂົ້າລະບົບ (Credentials) ທີ່ຈະໃຊ້ໃນລຸ້ນນີ້.",
- "createGuide.target.bindings": "ຂໍ້ມູນການເຂົ້າລະບົບ",
- "createGuide.target.description": "ເລືອກສະພາບແວດລ້ອມເປົ້າໝາຍ ແລະ ຕັ້ງຄ່າການເຮັດວຽກທີ່ລຸ້ນນີ້ຕ້ອງການ. ຂັ້ນຕອນນີ້ສາມາດຂ້າມໄດ້.",
- "createGuide.target.envVarCount_one": "{{count}} ຕົວປ່ຽນ",
- "createGuide.target.envVarCount_other": "{{count}} ຕົວປ່ຽນ",
- "createGuide.target.envVarHint": "ສຳລັບແຕ່ລະຕົວປ່ຽນສະພາບແວດລ້ອມ, ປ້ອນຄ່າທີ່ກຳນົດເອງ ຫຼື ໃຊ້ຄ່າທີ່ກຳນົດໄວ້ໃນແອັບ.",
- "createGuide.target.envVarPlaceholder": "ປ້ອນຄ່າ",
- "createGuide.target.envVarSource.ariaLabel": "ເລືອກແຫຼ່ງທີ່ມາຂອງຄ່າຕົວປ່ຽນສຳລັບ {{key}}",
- "createGuide.target.envVarSource.default": "ຄ່າຈາກແອັບ",
- "createGuide.target.envVarSource.lastDeployment": "ຄ່າທີ່ຕິດຕັ້ງຫຼ້າສຸດ",
- "createGuide.target.envVarSource.literal": "ຄ່າທີ່ກຳນົດເອງ",
- "createGuide.target.envVarType.number": "ຕົວເລກ",
- "createGuide.target.envVarType.secret": "ລະຫັດລັບ (Secret)",
- "createGuide.target.envVarType.string": "ຂໍ້ຄວາມ (String)",
- "createGuide.target.envVars": "ຕົວປ່ຽນສະພາບແວດລ້ອມ",
- "createGuide.target.environment": "ສະພາບແວດລ້ອມເປົ້າໝາຍ",
- "createGuide.target.loadBindingsFailed": "ໂຫຼດຂໍ້ມູນການເຂົ້າລະບົບບໍ່ສຳເລັດ.",
- "createGuide.target.loadEnvironmentsFailed": "ໂຫຼດສະພາບແວດລ້ອມການຕິດຕັ້ງບໍ່ສຳເລັດ.",
- "createGuide.target.missingRequiredBinding": "ກະລຸນາເລືອກຂໍ້ມູນການເຂົ້າລະບົບສຳລັບການເຊື່ອມຕໍ່ທີ່ຈຳເປັນນີ້.",
- "createGuide.target.noBindingRequired": "ບໍ່ຈຳເປັນຕ້ອງໃຊ້ຂໍ້ມູນການເຂົ້າລະບົບ.",
- "createGuide.target.noCredentialCandidates": "ບໍ່ມີຂໍ້ມູນການເຂົ້າລະບົບທີ່ສາມາດໃຊ້ໄດ້.",
- "createGuide.target.noEnvironmentOptions": "ບໍ່ມີສະພາບແວດລ້ອມການຕິດຕັ້ງທີ່ສາມາດໃຊ້ໄດ້.",
- "createGuide.target.selectCredential": "ເລືອກຂໍ້ມູນການເຂົ້າລະບົບ",
- "createGuide.target.title": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ",
- "createGuide.title": "ການຕິດຕັ້ງໃໝ່",
- "createModal.appPickerPlaceholder": "ເລືອກ Workflow App",
- "createModal.appSearchEmpty": "ບໍ່ພົບ Workflow App ທີ່ກົງກັນ",
- "createModal.appSearchPlaceholder": "ຄົ້ນຫາ Workflow App...",
- "createModal.cancel": "ຍົກເລີກ",
- "createModal.loadingApps": "ກຳລັງໂຫຼດແອັບ...",
- "deployDrawer.bindingCount_one": "{{count}} ການເຊື່ອມຕໍ່",
- "deployDrawer.bindingCount_other": "{{count}} ການເຊື່ອມຕໍ່",
"deployDrawer.bindingOptionsFailed": "ໂຫຼດຕົວເລືອກຂໍ້ມູນການເຂົ້າລະບົບບໍ່ສຳເລັດ.",
"deployDrawer.bindingSelectionHint": "ເລືອກຂໍ້ມູນການເຂົ້າລະບົບທີ່ຈະໃຊ້ໃນການຕິດຕັ້ງນີ້.",
- "deployDrawer.cancel": "ຍົກເລີກ",
- "deployDrawer.close": "ປິດໜ້າຈໍການຕິດຕັ້ງ",
- "deployDrawer.defaultSelect": "ເລືອກ...",
- "deployDrawer.deploy": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ",
- "deployDrawer.deployFailed": "ເລີ່ມການຕິດຕັ້ງບໍ່ສຳເລັດ.",
"deployDrawer.deploying": "ກຳລັງຕິດຕັ້ງ...",
- "deployDrawer.description": "ເລືອກລຸ້ນ ແລະ ສະພາບແວດລ້ອມເປົ້າໝາຍເພື່ອຕິດຕັ້ງ.",
- "deployDrawer.envVarCount_one": "{{count}} ຕົວປ່ຽນ",
- "deployDrawer.envVarCount_other": "{{count}} ຕົວປ່ຽນ",
- "deployDrawer.envVarHint": "ສຳລັບແຕ່ລະຕົວປ່ຽນສະພາບແວດລ້ອມ, ປ້ອນຄ່າທີ່ກຳນົດເອງ ຫຼື ໃຊ້ຄ່າທີ່ກຳນົດໄວ້ໃນແອັບ.",
- "deployDrawer.envVarPlaceholder": "ປ້ອນຄ່າ",
"deployDrawer.envVarSource.ariaLabel": "ເລືອກແຫຼ່ງທີ່ມາຂອງຄ່າຕົວປ່ຽນສຳລັບ {{key}}",
- "deployDrawer.envVarSource.default": "ຄ່າຈາກແອັບ",
"deployDrawer.envVarSource.lastDeployment": "ຄ່າທີ່ຕິດຕັ້ງຫຼ້າສຸດ",
"deployDrawer.envVarSource.literal": "ຄ່າທີ່ກຳນົດເອງ",
"deployDrawer.envVarType.number": "ຕົວເລກ",
"deployDrawer.envVarType.secret": "ລະຫັດລັບ (Secret)",
"deployDrawer.envVarType.string": "ຂໍ້ຄວາມ (String)",
"deployDrawer.envVars": "ຕົວປ່ຽນສະພາບແວດລ້ອມ",
- "deployDrawer.existingReleaseHint": "ລຸ້ນນີ້ຈະຖືກຕິດຕັ້ງຕາມສະພາບເດີມ. ຈະບໍ່ມີການສ້າງລຸ້ນໃໝ່.",
- "deployDrawer.lockedHint": "ຖືກລັອກໄວ້ກັບສະພາບແວດລ້ອມປັດຈຸບັນ",
- "deployDrawer.missingRequiredBinding": "ເລືອກຂໍ້ມູນການເຂົ້າລະບົບສຳລັບການເຊື່ອມຕໍ່ທີ່ຈຳເປັນນີ້.",
- "deployDrawer.missingRequiredEnvVar": "ກະລຸນາປ້ອນຄ່າສຳລັບຕົວປ່ຽນສະພາບແວດລ້ອມທີ່ຈຳເປັນນີ້.",
- "deployDrawer.noBindingRequired": "ບໍ່ຈຳເປັນ",
"deployDrawer.noCredentialCandidates": "ບໍ່ມີຂໍ້ມູນການເຂົ້າລະບົບທີ່ສາມາດໃຊ້ໄດ້.",
"deployDrawer.noNewEnvironmentAvailable": "ສະພາບແວດລ້ອມທີ່ມີຢູ່ທັງໝົດຖືກຕິດຕັ້ງແລ້ວ.",
- "deployDrawer.noOtherReleaseAvailable": "ບໍ່ມີລຸ້ນອື່ນສຳລັບສະພາບແວດລ້ອມນີ້.",
- "deployDrawer.noReleaseAvailable": "ກະລຸນາສ້າງລຸ້ນກ່ອນຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ.",
- "deployDrawer.notFound": "ບໍ່ພົບການຕິດຕັ້ງ.",
- "deployDrawer.releaseLabel": "ລຸ້ນ (Release)",
"deployDrawer.runtimeCredentials": "ຂໍ້ມູນການເຂົ້າລະບົບ",
"deployDrawer.selectCredential": "ເລືອກຂໍ້ມູນການເຂົ້າລະບົບ",
- "deployDrawer.selectEnv": "ເລືອກສະພາບແວດລ້ອມ",
- "deployDrawer.selectRelease": "ເລືອກລຸ້ນ",
- "deployDrawer.targetEnv": "ສະພາບແວດລ້ອມເປົ້າໝາຍ",
- "deployDrawer.title": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ",
- "deployTab.closeError": "ປິດ",
"deployTab.col.actions": "ການຈັດການ",
- "deployTab.col.currentRelease": "ລຸ້ນປັດຈຸບັນ",
"deployTab.col.environment": "ສະພາບແວດລ້ອມ",
"deployTab.col.status": "ສະຖານະ",
"deployTab.confirmUndeploy": "ຖອນການຕິດຕັ້ງ",
- "deployTab.deployOtherVersion": "ຕິດຕັ້ງລຸ້ນອື່ນ",
- "deployTab.emptyDescription": "ເລືອກລຸ້ນ ແລະ ສະພາບແວດລ້ອມເປົ້າໝາຍເພື່ອໃຫ້ຜູ້ໃຊ້ສາມາດເຂົ້າເຖິງການຕິດຕັ້ງນີ້ໄດ້.",
- "deployTab.emptyTitle": "ຍັງບໍ່ມີສະພາບແວດລ້ອມທີ່ກຳລັງເຮັດວຽກ",
- "deployTab.errorCode": "ລະຫັດຂໍ້ຜິດພາດ",
- "deployTab.errorDialogDesc": "ກວດສອບການຕິດຕັ້ງທີ່ຫຼົ້ມເຫຼວຫຼ້າສຸດກ່ອນທີ່ຈະລອງໃໝ່ ຫຼື ຕິດຕັ້ງລຸ້ນອື່ນ.",
- "deployTab.errorDialogTitle": "ຂໍ້ຜິດພາດໃນການຕິດຕັ້ງ {{name}}",
- "deployTab.errorMessage": "ຂໍ້ຄວາມຂໍ້ຜິດພາດ",
- "deployTab.errorPhase": "ຂັ້ນຕອນທີ່ເກີດຂໍ້ຜິດພາດ",
"deployTab.moreActions": "ການຈັດການເພີ່ມເຕີມ",
- "deployTab.newDeployment": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມໃໝ່",
- "deployTab.panel.unknownError": "ການຕິດຕັ້ງບໍ່ສຳເລັດ.",
"deployTab.redeploy": "ຕິດຕັ້ງໃໝ່",
- "deployTab.retry": "ລອງໃໝ່",
- "deployTab.status.deployFailed": "ຕິດຕັ້ງບໍ່ສຳເລັດ",
- "deployTab.status.deployingRelease": "ກຳລັງຕິດຕັ້ງ ({{release}})",
- "deployTab.status.runningOutOfSync": "ກຳລັງເຮັດວຽກ (ລໍຖ້າການຊິງຄ໌)",
- "deployTab.status.runningWithFailed": "ກຳລັງເຮັດວຽກ (ການຕິດຕັ້ງຫຼ້າສຸດບໍ່ສຳເລັດ)",
"deployTab.undeploy": "ຖອນການຕິດຕັ້ງ",
- "deployTab.undeployConfirmDesc": "ຈຸດເຊື່ອມຕໍ່ (Endpoint) ຂອງສະພາບແວດລ້ອມຈະໃຊ້ງານບໍ່ໄດ້, ແຕ່ເວີຊັນຈະບໍ່ຖືກລຶບ.",
- "deployTab.undeployConfirmTitle": "ຖອນການຕິດຕັ້ງ {{name}}?",
"deployTab.undeployConfirmWarning": "ຫຼັງຈາກຢືນຢັນ, ສະພາບແວດລ້ອມນີ້ຈະເຂົ້າສູ່ສະຖານະກຳລັງຖອນການຕິດຕັ້ງ ແລະ ການດຳເນີນການຕ່າງໆຈະຖືກປິດໄວ້ຊົ່ວຄາວ.",
- "deployTab.viewError": "ເບິ່ງຂໍ້ຜິດພາດ",
- "detail.mobileTabs": "ສ່ວນຕ່າງໆຂອງການຕິດຕັ້ງ",
- "detail.notFound": "ບໍ່ພົບການຕິດຕັ້ງ",
- "documentTitle.create": "ການຕິດຕັ້ງໃໝ່ · ການຕິດຕັ້ງ",
- "documentTitle.detail": "ການຕິດຕັ້ງ · ການຕິດຕັ້ງ",
- "documentTitle.list": "ລາຍການຕິດຕັ້ງ",
- "filter.allEnvs": "ທຸກສະພາບແວດລ້ອມ",
- "filter.searchPlaceholder": "ຄົ້ນຫາການຕິດຕັ້ງ",
- "health.ENVIRONMENT_STATUS_ADMISSION": "ກຳລັງກວດສອບ (Admission)",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "ກຳລັງເລີ່ມຕົ້ນ (Bootstrapping)",
- "health.ENVIRONMENT_STATUS_DELETING": "ກຳລັງລຶບ",
"health.ENVIRONMENT_STATUS_FAILED": "ໃຊ້ງານບໍ່ໄດ້",
- "health.ENVIRONMENT_STATUS_READY": "ພ້ອມໃຊ້ງານ",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "ບໍ່ຮູ້ຈັກ",
- "list.clearFilters": "ລ້າງຕົວຕອງ",
- "list.clearSearch": "ລ້າງການຄົ້ນຫາ",
- "list.createDeployment": "ໃໝ່",
- "list.emptyDescription": "ສ້າງການຕິດຕັ້ງຈາກ Workflow App ຫຼື ແພັກເກັດ Workflow DSL ເພື່ອຈັດການລຸ້ນ, ສະພາບແວດລ້ອມ, ແລະ ການເຂົ້າເຖິງ.",
- "list.emptyFilteredDescription": "ບໍ່ພົບການຕິດຕັ້ງທີ່ກົງກັບການຄົ້ນຫາ ຫຼື ຕົວຕອງສະພາບແວດລ້ອມ.",
- "list.emptyFilteredTitle": "ບໍ່ພົບການຕິດຕັ້ງທີ່ກົງກັນ",
"list.emptyTitle": "ຍັງບໍ່ມີການຕິດຕັ້ງ",
- "mode.ENVIRONMENT_MODE_ISOLATED": "ແຍກຕົວ (Isolated)",
- "mode.ENVIRONMENT_MODE_SHARED": "ໃຊ້ຮ່ວມກັນ (Shared)",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "ບໍ່ຮູ້ຈັກ",
- "overview.accessMeta.apiTokens": "ຈັດການໂທເຄັນ API",
- "overview.accessMeta.cli": "ເບິ່ງການເຂົ້າເຖິງ CLI",
- "overview.accessMeta.webApp": "ຈັດການການເຂົ້າເຖິງ WebApp",
- "overview.accessStatus": "ການເຂົ້າເຖິງ",
- "overview.api": "ໂທເຄັນ API",
- "overview.apiKeysCount_one": "{{count}} ໂທເຄັນ API",
- "overview.apiKeysCount_other": "{{count}} ໂທເຄັນ API",
- "overview.apiTokenSummary.environments_one": "{{count}} ສະພາບແວດລ້ອມທີ່ຕິດຕັ້ງແລ້ວ",
- "overview.apiTokenSummary.environments_other": "{{count}} ສະພາບແວດລ້ອມທີ່ຕິດຕັ້ງແລ້ວ",
- "overview.cardAction.deployLatest": "ຕິດຕັ້ງລຸ້ນຫຼ້າສຸດ",
- "overview.cardAction.redeploy": "ຕິດຕັ້ງໃໝ່",
- "overview.cardAction.viewProgress": "ເບິ່ງຄວາມຄືບໜ້າ",
- "overview.chip.behindTooltip_one": "ຊ້າກວ່າລຸ້ນຫຼ້າສຸດ 1 ລຸ້ນ. ຕິດຕັ້ງລຸ້ນຫຼ້າສຸດເພື່ອອັບເດດ.",
- "overview.chip.behindTooltip_other": "ຊ້າກວ່າລຸ້ນຫຼ້າສຸດ {{count}} ລຸ້ນ. ຕິດຕັ້ງລຸ້ນຫຼ້າສຸດເພື່ອອັບເດດ.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "ກຳລັງຕິດຕັ້ງ",
- "overview.chip.deployingTooltip": "ກຳລັງດຳເນີນການຕິດຕັ້ງ.",
- "overview.chip.empty": "ຫວ່າງເປົ່າ",
- "overview.chip.emptyTooltip": "ຍັງບໍ່ມີລຸ້ນທີ່ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມນີ້.",
- "overview.chip.failed": "ບໍ່ສຳເລັດ",
- "overview.chip.failedTooltip": "ຄວາມພະຍາຍາມຕິດຕັ້ງຫຼ້າສຸດບໍ່ສຳເລັດ.",
"overview.chip.latest": "ຫຼ້າສຸດ",
- "overview.chip.latestTooltip": "ສະພາບແວດລ້ອມນີ້ກຳລັງໃຊ້ງານລຸ້ນຫຼ້າສຸດ.",
- "overview.chip.needsReleaseFirst": "ສ້າງລຸ້ນກ່ອນ",
- "overview.chip.olderRelease": "ລຸ້ນເກົ່າ",
- "overview.chip.olderReleaseTooltip": "ສະພາບແວດລ້ອມນີ້ກຳລັງໃຊ້ງານລຸ້ນທີ່ເກົ່າກວ່າ.",
- "overview.chip.openInDeployTab": "ເບິ່ງຄວາມຄືບໜ້າການຕິດຕັ້ງ",
- "overview.disabled": "ປິດໃຊ້ງານ",
- "overview.enabled": "ເປີດໃຊ້ງານ",
- "overview.hero.byName": "ໂດຍ {{name}}",
- "overview.hero.empty": "ຍັງບໍ່ມີລຸ້ນ",
- "overview.hero.emptyDescription": "ສ້າງລຸ້ນຈາກແຫຼ່ງຂໍ້ມູນປັດຈຸບັນກ່ອນການຕິດຕັ້ງ.",
- "overview.latestRelease.releaseCount_one": "{{count}} ລຸ້ນ",
- "overview.latestRelease.releaseCount_other": "{{count}} ລຸ້ນ",
- "overview.latestReleaseTitle": "ລຸ້ນຫຼ້າສຸດ",
- "overview.previousReleases.viewAll": "ເບິ່ງທັງໝົດ",
- "overview.strip.deployToNewEnvironment": "ຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມໃໝ່",
- "overview.strip.emptyDeployableDescription": "ຕິດຕັ້ງລຸ້ນຫຼ້າສຸດໃສ່ສະພາບແວດລ້ອມເມື່ອທ່ານພ້ອມ.",
- "overview.strip.emptyDescription": "ສ້າງລຸ້ນກ່ອນຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ.",
- "overview.strip.emptyTitle": "ຍັງບໍ່ມີອິນສະແຕນຊ໌ (Instance)",
- "overview.strip.title": "ອິນສະແຕນຊ໌ (Instances)",
- "settings.delete": "ລຶບການຕິດຕັ້ງ",
- "settings.deleteConfirmDesc": "ລຶບ {{name}} ບໍ່? ທຸກອິນສະແຕນຊ໌ຈະຢຸດເຮັດວຽກ ແລະ ຖືກຍ້າຍອອກຈາກທຸກສະພາບແວດລ້ອມ. ການດຳເນີນການນີ້ບໍ່ສາມາດກັບຄືນໄດ້.",
- "settings.deleteConfirmTitle": "ຢືນຢັນການລຶບການຕິດຕັ້ງ",
- "settings.deleteFailed": "ລຶບການຕິດຕັ້ງບໍ່ສຳເລັດ.",
- "settings.deleted": "ລຶບການຕິດຕັ້ງແລ້ວ",
- "settings.description": "ລາຍລະອຽດ",
- "settings.name": "ຊື່ການຕິດຕັ້ງ",
- "settings.save": "ບັນທຶກການປ່ຽນແປງ",
- "settings.updateFailed": "ອັບເດດການຕິດຕັ້ງບໍ່ສຳເລັດ.",
- "settings.updated": "ອັບເດດການຕິດຕັ້ງແລ້ວ",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "ກຳລັງຕິດຕັ້ງ",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "ລໍຖ້າການຊິງຄ໌",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "ຕິດຕັ້ງບໍ່ສຳເລັດ",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "ບໍ່ຖືກຕ້ອງ",
"status.RUNTIME_INSTANCE_STATUS_READY": "ກຳລັງເຮັດວຽກ",
@@ -370,87 +89,6 @@
"studio.versionValue": "ຄ່າຂອງເວີຊັນ",
"studio.versionsBehind_one": "ຊ້າກວ່າ {{count}} ເວີຊັນ",
"studio.versionsBehind_other": "ຊ້າກວ່າ {{count}} ເວີຊັນ",
- "tabs.access.description": "ຈັດການຊ່ອງທາງ ແລະ ສິດການເຂົ້າເຖິງ.",
- "tabs.access.name": "ການເຂົ້າເຖິງ",
- "tabs.api-tokens.description": "ຈັດການໂທເຄັນ API ແລະ ເອີ້ນໃຊ້ອິນສະແຕນຊ໌ຜ່ານ HTTP.",
- "tabs.api-tokens.name": "ໂທເຄັນ API",
- "tabs.instances.description": "ເບິ່ງ ແລະ ຈັດການອິນສະແຕນຊ໌ໃນສະພາບແວດລ້ອມທີ່ຕິດຕັ້ງແລ້ວ.",
- "tabs.instances.name": "ອິນສະແຕນຊ໌",
- "tabs.overview.description": "ເບິ່ງສະຖານະການຕິດຕັ້ງໃນທຸກສະພາບແວດລ້ອມ.",
- "tabs.overview.name": "ພາບລວມ",
- "tabs.releases.description": "ສ້າງ, ຕິດຕັ້ງ ແລະ ຈັດການລຸ້ນຕ່າງໆ.",
- "tabs.releases.name": "ລຸ້ນ (Releases)",
- "unsupportedDslNodes.description": "ລຸ້ນນີ້ມີໂນດ (Node) ທີ່ລະບົບຍັງບໍ່ຮອງຮັບ. ກະລຸນາລຶບ ຫຼື ປ່ຽນແທນໃນ Studio ແລ້ວລອງໃໝ່.",
- "unsupportedDslNodes.descriptionWithTypes": "ລຸ້ນນີ້ມີໂນດທີ່ລະບົບຍັງບໍ່ຮອງຮັບ: {{nodeTypes}}. ກະລຸນາລຶບ ຫຼື ປ່ຽນແທນໃນ Studio ແລ້ວລອງໃໝ່.",
- "unsupportedDslNodes.title": "ໂນດທີ່ບໍ່ຮອງຮັບ",
- "unsupportedDslNodes.unknownType": "ປະເພດທີ່ບໍ່ຮູ້ຈັກ",
- "versions.cancelCreate": "ຍົກເລີກ",
- "versions.cancelDelete": "ຍົກເລີກ",
- "versions.cancelEdit": "ຍົກເລີກ",
"versions.checkingReleaseContent": "ກຳລັງກວດສອບເນື້ອໃນຂອງລຸ້ນ...",
- "versions.col.action": "ການຈັດການ",
- "versions.col.author": "ສ້າງໂດຍ",
- "versions.col.createdAt": "ສ້າງເມື່ອ",
- "versions.col.deployedTo": "ຕິດຕັ້ງໃສ່",
- "versions.col.release": "ລຸ້ນ",
- "versions.col.sourceApp": "ແຫຼ່ງທີ່ມາ",
- "versions.commitTooltip": "ຄອມມິດ (Commit) {{commit}}",
- "versions.create": "ສ້າງ",
- "versions.createFailed": "ສ້າງລຸ້ນບໍ່ສຳເລັດ.",
- "versions.createRelease": "ສ້າງລຸ້ນ",
- "versions.createReleaseDescription": "ສ້າງລຸ້ນທີ່ພ້ອມຕິດຕັ້ງຈາກ Workflow App ຫຼື ໄຟລ໌ Workflow DSL.",
- "versions.createSuccess": "ສ້າງລຸ້ນ \"{{name}}\" ແລ້ວ.",
- "versions.creating": "ກຳລັງສ້າງ...",
- "versions.currentOn": "ລຸ້ນປັດຈຸບັນໃນ {{name}}",
- "versions.deleteConfirmDesc": "ລຸ້ນ \"{{name}}\" ຈະຖືກລຶບຖາວອນ. ການດຳເນີນການນີ້ບໍ່ສາມາດກັບຄືນໄດ້.",
- "versions.deleteConfirmTitle": "ລຶບລຸ້ນນີ້ບໍ?",
- "versions.deleteFailed": "ລຶບລຸ້ນບໍ່ສຳເລັດ.",
- "versions.deleteRelease": "ລຶບລຸ້ນ",
- "versions.deleteSuccess": "ລຶບລຸ້ນ \"{{name}}\" ແລ້ວ.",
- "versions.deployTo": "ຕິດຕັ້ງໃສ່ {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "ກຳລັງຕິດຕັ້ງ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "ລໍຖ້າການຊິງຄ໌",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "ບໍ່ສຳເລັດ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "ບໍ່ຖືກຕ້ອງ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "ກຳລັງເຮັດວຽກ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "ຍັງບໍ່ໄດ້ຕິດຕັ້ງ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "ກຳລັງຖອນການຕິດຕັ້ງ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "ບໍ່ຮູ້ຈັກ",
- "versions.deployingTo": "{{name}} ກຳລັງຕິດຕັ້ງ",
- "versions.disabledReason.checkDeploymentsFailed": "ບໍ່ສາມາດກວດສອບການໃຊ້ງານການຕິດຕັ້ງໄດ້. ກະລຸນາລອງໃໝ່ພາຍຫຼັງ.",
- "versions.disabledReason.checkingDeployments": "ກຳລັງກວດສອບການໃຊ້ງານການຕິດຕັ້ງ",
- "versions.disabledReason.current": "ລຸ້ນນີ້ກຳລັງເຮັດວຽກຢູ່ໃນ {{name}} ແລ້ວ",
- "versions.disabledReason.deploying": "ກະລຸນາລໍຖ້າໃຫ້ການຕິດຕັ້ງທີ່ກຳລັງດຳເນີນຢູ່ສຳເລັດກ່ອນ",
- "versions.disabledReason.releaseInUse_one": "ຖອນການຕິດຕັ້ງລຸ້ນນີ້ອອກຈາກ {{count}} ສະພາບແວດລ້ອມກ່ອນລຶບ",
- "versions.disabledReason.releaseInUse_other": "ຖອນການຕິດຕັ້ງລຸ້ນນີ້ອອກຈາກ {{count}} ສະພາບແວດລ້ອມກ່ອນລຶບ",
- "versions.dslReadFailed": "ອ່ານໄຟລ໌ DSL ບໍ່ສຳເລັດ. ກະລຸນາເລືອກໄຟລ໌ອື່ນ ແລະ ລອງໃໝ່.",
- "versions.dslReading": "ກຳລັງອ່ານໄຟລ໌ DSL...",
- "versions.dslUnsupportedMode": "ສະເພາະໄຟລ໌ Workflow DSL ເທົ່ານັ້ນທີ່ສາມາດໃຊ້ໃນການຕິດຕັ້ງໄດ້.",
- "versions.editFailed": "ອັບເດດລຸ້ນບໍ່ສຳເລັດ.",
- "versions.editRelease": "ແກ້ໄຂລຸ້ນ",
- "versions.editReleaseDescription": "ອັບເດດຊື່ ແລະ ລາຍລະອຽດຂອງລຸ້ນນີ້.",
- "versions.editSuccess": "ອັບເດດລຸ້ນ \"{{name}}\" ແລ້ວ.",
- "versions.emptyDescription": "ສ້າງລຸ້ນທຳອິດກ່ອນການຕິດຕັ້ງໃສ່ສະພາບແວດລ້ອມ.",
- "versions.emptyTitle": "ຍັງບໍ່ມີລຸ້ນ",
- "versions.exportDsl": "ສົ່ງອອກ DSL",
- "versions.exportDslFailed": "ສົ່ງອອກ DSL ບໍ່ສຳເລັດ.",
- "versions.exportingDsl": "ກຳລັງສົ່ງອອກ...",
- "versions.groupHeader.deploy": "ຕິດຕັ້ງ",
- "versions.groupHeader.rollback": "ຕິດຕັ້ງລຸ້ນກ່ອນໜ້າ",
- "versions.groupHeader.unavailable": "ໃຊ້ງານບໍ່ໄດ້",
- "versions.manualDslOption": "ອັບໂຫຼດ DSL",
- "versions.moreActions": "ການຈັດການເພີ່ມເຕີມ",
- "versions.optional": "ທາງເລືອກ",
- "versions.releaseAlreadyExists": "ມີລຸ້ນທີ່ມີເນື້ອໃນດຽວກັນນີ້ຢູ່ແລ້ວ: {{name}}.",
- "versions.releaseContentCheckFailed": "ກວດສອບເນື້ອໃນລຸ້ນບໍ່ສຳເລັດ.",
- "versions.releaseDescriptionLabel": "ລາຍລະອຽດ",
- "versions.releaseDescriptionPlaceholder": "ອະທິບາຍກ່ຽວກັບລຸ້ນນີ້",
- "versions.releaseNameConflict": "ມີຊື່ລຸ້ນນີ້ຢູ່ແລ້ວ. ກະລຸນາເລືອກຊື່ອື່ນ.",
- "versions.releaseNameLabel": "ຊື່ລຸ້ນ",
- "versions.releaseNamePlaceholder": "ຊື່ລຸ້ນ",
- "versions.releaseNameRequired": "ກະລຸນາປ້ອນຊື່ລຸ້ນ.",
- "versions.releaseSourceLabel": "ແຫຼ່ງທີ່ມາຂອງລຸ້ນ",
- "versions.rollbackTo": "ຕິດຕັ້ງໃສ່ {{name}}",
- "versions.saveEdit": "ບັນທຶກ",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "ຕິດຕັ້ງໃສ່ {{name}}"
}
diff --git a/web/i18n/nl-NL/common.json b/web/i18n/nl-NL/common.json
index e23b4966e52..f8ee6ddff6b 100644
--- a/web/i18n/nl-NL/common.json
+++ b/web/i18n/nl-NL/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "App Detail",
"menus.apps": "Studio",
"menus.datasets": "Knowledge",
- "menus.deployments": "Implementaties",
"menus.exploreMarketplace": "Explore Marketplace",
"menus.plugins": "Integraties",
"menus.status": "beta",
diff --git a/web/i18n/nl-NL/deployments.json b/web/i18n/nl-NL/deployments.json
index 8b41c1da032..f5e214e9a92 100644
--- a/web/i18n/nl-NL/deployments.json
+++ b/web/i18n/nl-NL/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Kopieer cURL-voorbeeld",
- "access.api.createFailed": "API-token kon niet worden gegenereerd.",
- "access.api.createKey": "API-token genereren",
- "access.api.createKeyTitle": "Nieuw API-token genereren",
- "access.api.curlExampleTitle": "cURL-voorbeeld",
- "access.api.description": "Toegang tot deze implementatie via HTTP. Elk API-token is gekoppeld aan één omgeving.",
- "access.api.developerTitle": "Developer API",
- "access.api.disabled": "API-toegang is uitgeschakeld voor deze implementatie.",
- "access.api.disabledHint": "Schakel API-toegang in om omgevingsgebonden tokens te genereren.",
- "access.api.docs": "API-documentatie",
- "access.api.docsClose": "API-documentatie sluiten",
- "access.api.docsDescription": "Bekijk de Workflow API-referentie voor deze implementatie.",
- "access.api.docsTitle": "Workflow API-documentatie",
- "access.api.empty": "Implementeer eerst naar een omgeving om API-tokens uit te kunnen geven.",
- "access.api.emptyTitle": "Geen geïmplementeerde omgevingen",
- "access.api.endpoint": "Verzoek-URL",
- "access.api.keyList": "API-tokenlijst",
- "access.api.nameLabel": "Naam API-token",
- "access.api.namePlaceholder": "Voer een naam voor het API-token in",
- "access.api.nameRequired": "Naam API-token is verplicht.",
- "access.api.newKey": "Nieuw API-token genereren",
- "access.api.newTokenDescription": "Dit API-token wordt slechts eenmaal getoond. Kopieer het voordat je deze pagina verlaat.",
- "access.api.newTokenLabel": "API-token",
- "access.api.newTokenTitle": "API-token gegenereerd",
- "access.api.noKeys": "Nog geen API-tokens. Genereer er een om de API aan te roepen.",
- "access.api.noKeysTitle": "Nog geen API-tokens",
- "access.api.revokeConfirmDescription": "Het API-token \"{{name}}\" werkt direct niet meer. Deze actie kan niet ongedaan worden gemaakt.",
- "access.api.revokeConfirmTitle": "API-token intrekken?",
- "access.api.revokeFailed": "API-token kon niet worden ingetrokken.",
- "access.api.revokeSuccess": "API-token ingetrokken",
- "access.api.table.action": "Actie",
- "access.api.table.environment": "Omgeving",
- "access.api.table.key": "API-token",
- "access.api.table.name": "Naam",
- "access.channels.disabled": "Toegangskanalen zijn uitgeschakeld voor deze implementatie.",
- "access.channels.disabledHint": "Schakel toegangskanalen in om WebApp- en CLI-toegangspunten beschikbaar te maken.",
- "access.channels.title": "Toegangskanalen",
- "access.cli.description": "Roep aan vanuit de terminal met difyctl, geschikt voor scripts, geautomatiseerde workflows of Agent-integraties.",
- "access.cli.docs": "Gebruikshandleiding",
- "access.cli.domain": "Domein",
- "access.cli.empty": "CLI-endpoint niet geconfigureerd.",
- "access.cli.install": "CLI installeren",
- "access.cli.title": "CLI",
- "access.copy": "Kopiëren",
- "access.copyFailed": "Kopiëren mislukt",
- "access.members.groupCount_one": "{{count}} groep",
- "access.members.groupCount_other": "{{count}} groepen",
- "access.members.memberCount_one": "{{count}} lid",
- "access.members.memberCount_other": "{{count}} leden",
- "access.permission.anyone": "Iedereen met de link",
- "access.permission.organization": "Alle leden binnen het platform",
- "access.permission.specific": "Specifieke leden binnen het platform",
- "access.permission.specificDesc": "Selecteer specifieke groepen of leden",
- "access.permission.updateFailed": "Toegangsbeleid kon niet worden bijgewerkt.",
- "access.permissions.editAriaLabel": "Toegang configureren voor {{environment}}",
- "access.permissions.editDescription": "Stel toegangsrechten in voor WebApp- en CLI-toegangspunten.",
- "access.permissions.editTitle": "Toegangsrechten",
- "access.permissions.title": "Toegangsrechten",
- "access.revoke": "Intrekken",
- "access.runAccess.noEnvs": "Implementeer naar een omgeving om toegangsrechten te configureren.",
- "access.runAccess.noEnvsTitle": "Geen geïmplementeerde omgevingen",
- "access.runAccess.openWebapp": "WebApp openen",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Gehoste webpagina voor eindgebruikers.",
- "access.runAccess.webappEmpty": "Binnenkort beschikbaar.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Extern",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Onbekend",
- "card.access.api": "API-tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Geen toegang",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Eerste release maken",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Implementatie verwijderen",
- "card.menu.deploy": "Implementeren naar omgeving",
- "card.menu.editInfo": "Info bewerken",
- "card.moreActions": "Meer acties",
- "card.noDescription": "Geen beschrijving opgegeven.",
"card.notDeployed": "Niet geïmplementeerd",
- "card.tooltip.createdAt": "Aangemaakt",
- "card.tooltip.deployed": "Geïmplementeerd",
- "card.tooltip.deploymentStatus": "Implementatie",
- "card.tooltip.notDeployedShort": "Niet geïmplementeerd",
- "card.tooltip.releaseName": "Releasenaam",
- "card.tooltip.source": "Bron",
"common.loadFailed": "Laden mislukt. Probeer het later opnieuw.",
- "createGuide.actions.back": "Terug",
- "createGuide.actions.createAndDeploy": "Maken & implementeren",
- "createGuide.actions.creating": "Aanmaken...",
- "createGuide.actions.deploying": "Aanmaken & implementeren...",
- "createGuide.actions.next": "Volgende",
- "createGuide.actions.skipDeploy": "Overslaan, later implementeren",
- "createGuide.dsl.defaultAppName": "Geïmporteerde DSL-app",
- "createGuide.dsl.description": "Upload een Workflow DSL-pakket om de implementatie, eerste release en optionele omgevingsimplementatie aan te maken.",
- "createGuide.dsl.dropDescription": "Upload een Workflow YAML DSL-pakket. Implementatieopties worden uit dit bestand opgehaald vóór het implementeren.",
- "createGuide.dsl.dropTitle": "Workflow DSL-pakket uploaden",
- "createGuide.dsl.readFailed": "Het DSL-bestand kon niet worden gelezen. Kies een ander bestand en probeer het opnieuw.",
- "createGuide.dsl.reading": "DSL-bestand wordt gelezen...",
- "createGuide.dsl.title": "DSL importeren",
- "createGuide.dsl.unsupportedMode": "Alleen Workflow DSL-bestanden kunnen worden gebruikt voor implementaties.",
- "createGuide.errors.createReleaseFailed": "Aanmaken van de implementatie of release mislukt.",
- "createGuide.errors.deployFailed": "Implementeren naar de omgeving mislukt.",
- "createGuide.method.description": "Kies de bron die wordt gebruikt om de eerste release aan te maken.",
- "createGuide.methods.bindApp.description": "Gebruik een bestaande Workflow App in Studio als releasebron.",
- "createGuide.methods.bindApp.title": "Bestaande Workflow App koppelen",
- "createGuide.methods.importDsl.description": "Upload een Workflow YAML DSL-pakket en ga verder via de implementatie-interface.",
- "createGuide.methods.importDsl.title": "DSL importeren",
- "createGuide.nav.back": "Implementaties",
- "createGuide.release.defaultName": "eerste release",
- "createGuide.release.deployInfo": "Implementatiegegevens",
- "createGuide.release.description": "Vul de implementatiegegevens en details van de eerste release in.",
- "createGuide.release.firstVersion": "Eerste release",
- "createGuide.release.instanceDescription": "Beschrijving implementatie",
- "createGuide.release.instanceDescriptionPlaceholder": "Beschrijf waar deze implementatie voor wordt gebruikt",
- "createGuide.release.instanceName": "Naam implementatie",
- "createGuide.release.instanceNameConflict": "Er bestaat al een implementatie met deze naam. Kies een andere naam.",
- "createGuide.release.releaseDescription": "Releasebeschrijving",
- "createGuide.release.releaseDescriptionPlaceholder": "Beschrijf deze release",
- "createGuide.release.releaseName": "Releasenaam",
- "createGuide.release.title": "Basisinformatie",
- "createGuide.source.clearSearch": "App-zoekopdracht wissen",
- "createGuide.source.description": "Kies de bron die wordt gebruikt om de eerste release aan te maken.",
- "createGuide.source.empty": "Geen Workflow Apps gevonden.",
- "createGuide.source.searchPlaceholder": "Apps zoeken",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Releasebron",
- "createGuide.steps.method": "Releasebron",
- "createGuide.steps.release": "Basisinformatie",
- "createGuide.steps.source": "Releasebron",
- "createGuide.steps.target": "Implementeren naar omgeving",
- "createGuide.target.bindingCount_one": "{{count}} koppeling",
- "createGuide.target.bindingCount_other": "{{count}} koppelingen",
- "createGuide.target.bindingHint": "Kies de inloggegevens die door deze release worden gebruikt.",
- "createGuide.target.bindings": "Inloggegevens",
- "createGuide.target.description": "Kies een doelomgeving en geef de runtime-instellingen op die deze release daar nodig heeft. Deze stap kan worden overgeslagen.",
- "createGuide.target.envVarCount_one": "{{count}} variabele",
- "createGuide.target.envVarCount_other": "{{count}} variabelen",
- "createGuide.target.envVarHint": "Voer voor elke omgevingsvariabele die deze release nodig heeft een aangepaste waarde in of gebruik de waarde die in de app is gedefinieerd.",
- "createGuide.target.envVarPlaceholder": "Voer waarde in",
- "createGuide.target.envVarSource.ariaLabel": "Selecteer de bron van de variabelewaarde voor {{key}}",
- "createGuide.target.envVarSource.default": "App-waarde",
- "createGuide.target.envVarSource.lastDeployment": "Laatst geïmplementeerde waarde",
- "createGuide.target.envVarSource.literal": "Aangepaste waarde",
- "createGuide.target.envVarType.number": "Getal",
- "createGuide.target.envVarType.secret": "Geheim",
- "createGuide.target.envVarType.string": "Tekenreeks",
- "createGuide.target.envVars": "Omgevingsvariabelen",
- "createGuide.target.environment": "Doelomgeving",
- "createGuide.target.loadBindingsFailed": "Inloggegevens konden niet worden geladen.",
- "createGuide.target.loadEnvironmentsFailed": "Implementatieomgevingen konden niet worden geladen.",
- "createGuide.target.missingRequiredBinding": "Selecteer een inloggegeven voor deze verplichte koppeling.",
- "createGuide.target.noBindingRequired": "Geen inloggegevens vereist.",
- "createGuide.target.noCredentialCandidates": "Geen beschikbare inloggegevens.",
- "createGuide.target.noEnvironmentOptions": "Geen implementatieomgevingen beschikbaar.",
- "createGuide.target.selectCredential": "Selecteer een inloggegeven",
- "createGuide.target.title": "Implementeren naar omgeving",
- "createGuide.title": "Nieuwe implementatie",
- "createModal.appPickerPlaceholder": "Selecteer een Workflow App",
- "createModal.appSearchEmpty": "Geen overeenkomende Workflow Apps",
- "createModal.appSearchPlaceholder": "Workflow Apps zoeken…",
- "createModal.cancel": "Annuleren",
- "createModal.loadingApps": "Apps laden…",
- "deployDrawer.bindingCount_one": "{{count}} koppeling",
- "deployDrawer.bindingCount_other": "{{count}} koppelingen",
"deployDrawer.bindingOptionsFailed": "Opties voor inloggegevens konden niet worden geladen.",
"deployDrawer.bindingSelectionHint": "Kies de inloggegevens die door deze implementatie worden gebruikt.",
- "deployDrawer.cancel": "Annuleren",
- "deployDrawer.close": "Implementatielade sluiten",
- "deployDrawer.defaultSelect": "Selecteer...",
- "deployDrawer.deploy": "Implementeren naar omgeving",
- "deployDrawer.deployFailed": "Starten van implementatie mislukt.",
"deployDrawer.deploying": "Implementeren...",
- "deployDrawer.description": "Selecteer een release en doelomgeving om te implementeren.",
- "deployDrawer.envVarCount_one": "{{count}} variabele",
- "deployDrawer.envVarCount_other": "{{count}} variabelen",
- "deployDrawer.envVarHint": "Voer voor elke omgevingsvariabele die deze release nodig heeft een aangepaste waarde in of gebruik de waarde die in de app is gedefinieerd.",
- "deployDrawer.envVarPlaceholder": "Voer waarde in",
"deployDrawer.envVarSource.ariaLabel": "Selecteer de bron van de variabelewaarde voor {{key}}",
- "deployDrawer.envVarSource.default": "App-waarde",
"deployDrawer.envVarSource.lastDeployment": "Laatst geïmplementeerde waarde",
"deployDrawer.envVarSource.literal": "Aangepaste waarde",
"deployDrawer.envVarType.number": "Getal",
"deployDrawer.envVarType.secret": "Geheim",
"deployDrawer.envVarType.string": "Tekenreeks",
"deployDrawer.envVars": "Omgevingsvariabelen",
- "deployDrawer.existingReleaseHint": "Deze release wordt ongewijzigd geïmplementeerd. Er wordt geen nieuwe release aangemaakt.",
- "deployDrawer.lockedHint": "Vergrendeld op huidige omgeving",
- "deployDrawer.missingRequiredBinding": "Selecteer een inloggegeven voor deze verplichte koppeling.",
- "deployDrawer.missingRequiredEnvVar": "Voer een waarde in voor deze verplichte omgevingsvariabele.",
- "deployDrawer.noBindingRequired": "Niet vereist",
"deployDrawer.noCredentialCandidates": "Geen beschikbare inloggegevens.",
"deployDrawer.noNewEnvironmentAvailable": "Alle beschikbare omgevingen hebben al een implementatie.",
- "deployDrawer.noOtherReleaseAvailable": "Er zijn geen andere releases beschikbaar voor deze omgeving.",
- "deployDrawer.noReleaseAvailable": "Maak een release aan voordat je naar een omgeving implementeert.",
- "deployDrawer.notFound": "Implementatie niet gevonden.",
- "deployDrawer.releaseLabel": "Release",
"deployDrawer.runtimeCredentials": "Inloggegevens",
"deployDrawer.selectCredential": "Selecteer een inloggegeven",
- "deployDrawer.selectEnv": "Selecteer een omgeving",
- "deployDrawer.selectRelease": "Selecteer een release",
- "deployDrawer.targetEnv": "Doelomgeving",
- "deployDrawer.title": "Implementeren naar omgeving",
- "deployTab.closeError": "Sluiten",
"deployTab.col.actions": "Acties",
- "deployTab.col.currentRelease": "Huidige release",
"deployTab.col.environment": "Omgeving",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Implementatie ongedaan maken",
- "deployTab.deployOtherVersion": "Andere release implementeren",
- "deployTab.emptyDescription": "Kies een release en doelomgeving om deze implementatie beschikbaar te maken voor gebruikers.",
- "deployTab.emptyTitle": "Er draaien nog geen omgevingen",
- "deployTab.errorCode": "Code",
- "deployTab.errorDialogDesc": "Bekijk de laatst mislukte implementatie voordat je opnieuw probeert of een andere release implementeert.",
- "deployTab.errorDialogTitle": "Implementatiefout in {{name}}",
- "deployTab.errorMessage": "Bericht",
- "deployTab.errorPhase": "Fase",
"deployTab.moreActions": "Meer acties",
- "deployTab.newDeployment": "Implementeren naar nieuwe omgeving",
- "deployTab.panel.unknownError": "Implementatie mislukt.",
"deployTab.redeploy": "Opnieuw implementeren",
- "deployTab.retry": "Opnieuw proberen",
- "deployTab.status.deployFailed": "Implementatie mislukt",
- "deployTab.status.deployingRelease": "Implementeren ({{release}})",
- "deployTab.status.runningOutOfSync": "Actief (synchronisatie in afwachting)",
- "deployTab.status.runningWithFailed": "Actief (laatste implementatie mislukt)",
"deployTab.undeploy": "Implementatie ongedaan maken",
- "deployTab.undeployConfirmDesc": "Het omgevingseindpunt wordt onbeschikbaar, maar de versie wordt niet verwijderd.",
- "deployTab.undeployConfirmTitle": "Implementatie van {{name}} ongedaan maken?",
"deployTab.undeployConfirmWarning": "Na bevestiging krijgt deze omgeving de status 'implementatie ongedaan maken' en worden acties tijdelijk uitgeschakeld.",
- "deployTab.viewError": "Fout bekijken",
- "detail.mobileTabs": "Implementatiesecties",
- "detail.notFound": "Implementatie niet gevonden",
- "documentTitle.create": "Nieuwe implementatie · Implementaties",
- "documentTitle.detail": "Implementatie · Implementaties",
- "documentTitle.list": "Implementaties",
- "filter.allEnvs": "Alle omgevingen",
- "filter.searchPlaceholder": "Implementaties zoeken",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Toelating",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Initialiseren",
- "health.ENVIRONMENT_STATUS_DELETING": "Verwijderen",
"health.ENVIRONMENT_STATUS_FAILED": "Niet beschikbaar",
- "health.ENVIRONMENT_STATUS_READY": "Beschikbaar",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Onbekend",
- "list.clearFilters": "Filters wissen",
- "list.clearSearch": "Zoekopdracht implementaties wissen",
- "list.createDeployment": "Nieuw",
- "list.emptyDescription": "Maak een implementatie aan op basis van een Workflow App of Workflow DSL-pakket om releases, omgevingen en toegang te beheren.",
- "list.emptyFilteredDescription": "Geen implementatie komt overeen met het huidige zoek- of omgevingsfilter.",
- "list.emptyFilteredTitle": "Geen overeenkomende implementaties",
"list.emptyTitle": "Nog geen implementaties",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Geïsoleerd",
- "mode.ENVIRONMENT_MODE_SHARED": "Gedeeld",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Onbekend",
- "overview.accessMeta.apiTokens": "API-tokens beheren",
- "overview.accessMeta.cli": "CLI-toegang bekijken",
- "overview.accessMeta.webApp": "WebApp-toegang beheren",
- "overview.accessStatus": "Toegang",
- "overview.api": "API-tokens",
- "overview.apiKeysCount_one": "{{count}} API-token",
- "overview.apiKeysCount_other": "{{count}} API-tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} geïmplementeerde omgeving",
- "overview.apiTokenSummary.environments_other": "{{count}} geïmplementeerde omgevingen",
- "overview.cardAction.deployLatest": "Nieuwste release implementeren",
- "overview.cardAction.redeploy": "Opnieuw implementeren",
- "overview.cardAction.viewProgress": "Implementatie bekijken",
- "overview.chip.behindTooltip_one": "1 release achter op de nieuwste. Implementeer de nieuwste release om bij te werken.",
- "overview.chip.behindTooltip_other": "{{count}} releases achter op de nieuwste. Implementeer de nieuwste release om bij te werken.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "aan het implementeren",
- "overview.chip.deployingTooltip": "Implementatie is bezig.",
- "overview.chip.empty": "leeg",
- "overview.chip.emptyTooltip": "Er is geen release geïmplementeerd in deze omgeving.",
- "overview.chip.failed": "mislukt",
- "overview.chip.failedTooltip": "De laatste implementatiepoging is mislukt.",
"overview.chip.latest": "nieuwste",
- "overview.chip.latestTooltip": "In deze omgeving draait de nieuwste release.",
- "overview.chip.needsReleaseFirst": "Maak eerst een release aan",
- "overview.chip.olderRelease": "ouder",
- "overview.chip.olderReleaseTooltip": "In deze omgeving draait een oudere release.",
- "overview.chip.openInDeployTab": "Implementatievoortgang bekijken",
- "overview.disabled": "Uitgeschakeld",
- "overview.enabled": "Ingeschakeld",
- "overview.hero.byName": "door {{name}}",
- "overview.hero.empty": "Nog geen releases",
- "overview.hero.emptyDescription": "Maak een release aan vanuit de huidige bron voordat je implementeert.",
- "overview.latestRelease.releaseCount_one": "{{count}} release",
- "overview.latestRelease.releaseCount_other": "{{count}} releases",
- "overview.latestReleaseTitle": "Nieuwste release",
- "overview.previousReleases.viewAll": "Alles bekijken",
- "overview.strip.deployToNewEnvironment": "Implementeren naar nieuwe omgeving",
- "overview.strip.emptyDeployableDescription": "Implementeer de nieuwste release naar een omgeving wanneer je klaar bent.",
- "overview.strip.emptyDescription": "Maak een release aan voordat je naar een omgeving implementeert.",
- "overview.strip.emptyTitle": "Nog geen instanties",
- "overview.strip.title": "Instanties",
- "settings.delete": "Implementatie verwijderen",
- "settings.deleteConfirmDesc": "{{name}} verwijderen? Elke instantie stopt en wordt verwijderd in alle omgevingen. Dit kan niet ongedaan worden gemaakt.",
- "settings.deleteConfirmTitle": "Implementatie verwijderen",
- "settings.deleteFailed": "Verwijderen van implementatie mislukt.",
- "settings.deleted": "Implementatie verwijderd",
- "settings.description": "Beschrijving",
- "settings.name": "Naam implementatie",
- "settings.save": "Wijzigingen opslaan",
- "settings.updateFailed": "Bijwerken van implementatie mislukt.",
- "settings.updated": "Implementatie bijgewerkt",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Implementeren",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisatie in afwachting",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Implementatie mislukt",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Ongeldig",
"status.RUNTIME_INSTANCE_STATUS_READY": "Actief",
@@ -370,87 +89,6 @@
"studio.versionValue": "Versiewaarde",
"studio.versionsBehind_one": "{{count}} versie achter",
"studio.versionsBehind_other": "{{count}} versies achter",
- "tabs.access.description": "Beheer toegangskanalen en toegangsrechten.",
- "tabs.access.name": "Toegang",
- "tabs.api-tokens.description": "Beheer API-tokens en roep instanties aan via HTTP.",
- "tabs.api-tokens.name": "API-tokens",
- "tabs.instances.description": "Bekijk en beheer instanties in geïmplementeerde omgevingen.",
- "tabs.instances.name": "Instanties",
- "tabs.overview.description": "Bekijk de status van de implementatie in alle omgevingen.",
- "tabs.overview.name": "Overzicht",
- "tabs.releases.description": "Maak, implementeer en beheer releases.",
- "tabs.releases.name": "Releases",
- "unsupportedDslNodes.description": "Deze release bevat nodes die de implementatie-runtime nog niet ondersteunt. Verwijder of vervang ze in Studio en probeer het opnieuw.",
- "unsupportedDslNodes.descriptionWithTypes": "Deze release bevat nodes die de implementatie-runtime nog niet ondersteunt: {{nodeTypes}}. Verwijder of vervang ze in Studio en probeer het opnieuw.",
- "unsupportedDslNodes.title": "Niet-ondersteunde nodes",
- "unsupportedDslNodes.unknownType": "Onbekend type",
- "versions.cancelCreate": "Annuleren",
- "versions.cancelDelete": "Annuleren",
- "versions.cancelEdit": "Annuleren",
"versions.checkingReleaseContent": "Release-inhoud controleren...",
- "versions.col.action": "Actie",
- "versions.col.author": "Aangemaakt door",
- "versions.col.createdAt": "Aangemaakt op",
- "versions.col.deployedTo": "Geïmplementeerd in",
- "versions.col.release": "Release",
- "versions.col.sourceApp": "Bron",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Aanmaken",
- "versions.createFailed": "Aanmaken van release mislukt.",
- "versions.createRelease": "Release maken",
- "versions.createReleaseDescription": "Maak een implementeerbare release aan op basis van een Workflow App of Workflow DSL-bestand.",
- "versions.createSuccess": "Release \"{{name}}\" aangemaakt.",
- "versions.creating": "Aanmaken...",
- "versions.currentOn": "Huidige release op {{name}}",
- "versions.deleteConfirmDesc": "Release \"{{name}}\" wordt permanent verwijderd. Dit kan niet ongedaan worden gemaakt.",
- "versions.deleteConfirmTitle": "Release verwijderen?",
- "versions.deleteFailed": "Verwijderen van release mislukt.",
- "versions.deleteRelease": "Release verwijderen",
- "versions.deleteSuccess": "Release \"{{name}}\" verwijderd.",
- "versions.deployTo": "Implementeren naar {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Implementeren",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Synchronisatie in afwachting",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Mislukt",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Ongeldig",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Actief",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Niet geïmplementeerd",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Implementatie ongedaan maken",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Onbekend",
- "versions.deployingTo": "{{name}} wordt geïmplementeerd",
- "versions.disabledReason.checkDeploymentsFailed": "Implementatiegebruik kon niet worden geverifieerd. Probeer het later opnieuw.",
- "versions.disabledReason.checkingDeployments": "Implementatiegebruik controleren",
- "versions.disabledReason.current": "Deze release draait al op {{name}}",
- "versions.disabledReason.deploying": "Wacht tot de actieve implementatie is afgerond",
- "versions.disabledReason.releaseInUse_one": "Maak de implementatie van deze release in {{count}} omgeving ongedaan voordat je hem verwijdert",
- "versions.disabledReason.releaseInUse_other": "Maak de implementatie van deze release in {{count}} omgevingen ongedaan voordat je hem verwijdert",
- "versions.dslReadFailed": "Het DSL-bestand kon niet worden gelezen. Kies een ander bestand en probeer het opnieuw.",
- "versions.dslReading": "DSL-bestand wordt gelezen...",
- "versions.dslUnsupportedMode": "Alleen Workflow DSL-bestanden kunnen worden gebruikt voor implementaties.",
- "versions.editFailed": "Bijwerken van release mislukt.",
- "versions.editRelease": "Release bewerken",
- "versions.editReleaseDescription": "Werk de naam en beschrijving van deze release bij.",
- "versions.editSuccess": "Release \"{{name}}\" bijgewerkt.",
- "versions.emptyDescription": "Maak de eerste release aan voordat je naar een omgeving implementeert.",
- "versions.emptyTitle": "Nog geen releases",
- "versions.exportDsl": "DSL exporteren",
- "versions.exportDslFailed": "Exporteren van DSL mislukt.",
- "versions.exportingDsl": "Exporteren...",
- "versions.groupHeader.deploy": "Implementeren",
- "versions.groupHeader.rollback": "Vorige versie implementeren",
- "versions.groupHeader.unavailable": "Niet beschikbaar",
- "versions.manualDslOption": "DSL uploaden",
- "versions.moreActions": "Meer acties",
- "versions.optional": "Optioneel",
- "versions.releaseAlreadyExists": "Er bestaat al een release met dezelfde inhoud: {{name}}.",
- "versions.releaseContentCheckFailed": "Controleren van release-inhoud mislukt.",
- "versions.releaseDescriptionLabel": "Beschrijving",
- "versions.releaseDescriptionPlaceholder": "Beschrijf deze release",
- "versions.releaseNameConflict": "Er bestaat al een release met deze naam. Kies een andere naam.",
- "versions.releaseNameLabel": "Releasenaam",
- "versions.releaseNamePlaceholder": "Releasenaam",
- "versions.releaseNameRequired": "Voer een releasenaam in.",
- "versions.releaseSourceLabel": "Releasebron",
- "versions.rollbackTo": "Implementeren naar {{name}}",
- "versions.saveEdit": "Opslaan",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "Implementeren naar {{name}}"
}
diff --git a/web/i18n/pl-PL/common.json b/web/i18n/pl-PL/common.json
index 25bd388b8f8..83eef8d9560 100644
--- a/web/i18n/pl-PL/common.json
+++ b/web/i18n/pl-PL/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Szczegóły aplikacji",
"menus.apps": "Studio",
"menus.datasets": "Wiedza",
- "menus.deployments": "Wdrożenia",
"menus.exploreMarketplace": "Zapoznaj się z Marketplace",
"menus.plugins": "Integracjay",
"menus.status": "beta",
diff --git a/web/i18n/pl-PL/deployments.json b/web/i18n/pl-PL/deployments.json
index 60cc269e37f..bc2ece0b2cd 100644
--- a/web/i18n/pl-PL/deployments.json
+++ b/web/i18n/pl-PL/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Skopiuj przykład cURL",
- "access.api.createFailed": "Nie udało się wygenerować Tokenu API.",
- "access.api.createKey": "Wygeneruj Token API",
- "access.api.createKeyTitle": "Wygeneruj nowy Token API",
- "access.api.curlExampleTitle": "Przykład cURL",
- "access.api.description": "Uzyskaj dostęp do tego wdrożenia przez HTTP. Każdy Token API jest ograniczony do jednego środowiska.",
- "access.api.developerTitle": "Developer API",
- "access.api.disabled": "Dostęp przez API jest wyłączony dla tego wdrożenia.",
- "access.api.disabledHint": "Włącz dostęp przez API, aby generować tokeny ograniczone do środowiska.",
- "access.api.docs": "Dokumentacja API",
- "access.api.docsClose": "Zamknij dokumentację API",
- "access.api.docsDescription": "Zobacz dokumentację Workflow API dla tego wdrożenia.",
- "access.api.docsTitle": "Dokumentacja Workflow API",
- "access.api.empty": "Najpierw wdróż do środowiska, aby zacząć wystawiać Tokeny API.",
- "access.api.emptyTitle": "Brak wdrożonych środowisk",
- "access.api.endpoint": "URL żądania",
- "access.api.keyList": "Lista Tokenów API",
- "access.api.nameLabel": "Nazwa Tokenu API",
- "access.api.namePlaceholder": "Podaj nazwę Tokenu API",
- "access.api.nameRequired": "Nazwa Tokenu API jest wymagana.",
- "access.api.newKey": "Wygeneruj nowy Token API",
- "access.api.newTokenDescription": "Ten Token API jest pokazywany tylko raz. Skopiuj go przed opuszczeniem tej strony.",
- "access.api.newTokenLabel": "Token API",
- "access.api.newTokenTitle": "Token API wygenerowany",
- "access.api.noKeys": "Brak Tokenów API. Wygeneruj jeden, aby zacząć wywoływać API.",
- "access.api.noKeysTitle": "Brak Tokenów API",
- "access.api.revokeConfirmDescription": "Token API \"{{name}}\" przestanie działać natychmiast. Tej akcji nie można cofnąć.",
- "access.api.revokeConfirmTitle": "Unieważnić Token API?",
- "access.api.revokeFailed": "Nie udało się unieważnić Tokenu API.",
- "access.api.revokeSuccess": "Token API unieważniony",
- "access.api.table.action": "Akcja",
- "access.api.table.environment": "Środowisko",
- "access.api.table.key": "Token API",
- "access.api.table.name": "Nazwa",
- "access.channels.disabled": "Kanały dostępu są wyłączone dla tego wdrożenia.",
- "access.channels.disabledHint": "Włącz kanały dostępu, aby udostępnić punkty wejścia WebApp i CLI.",
- "access.channels.title": "Kanały dostępu",
- "access.cli.description": "Wywołuj z terminala za pomocą difyctl, odpowiednie dla skryptów, zautomatyzowanych przepływów lub integracji z Agentem.",
- "access.cli.docs": "Przewodnik użytkownika",
- "access.cli.domain": "Domena",
- "access.cli.empty": "Punkt końcowy CLI nie jest skonfigurowany.",
- "access.cli.install": "Zainstaluj CLI",
- "access.cli.title": "CLI",
- "access.copy": "Kopiuj",
- "access.copyFailed": "Kopiowanie nie powiodło się",
- "access.members.groupCount_one": "{{count}} grupa",
- "access.members.groupCount_other": "{{count}} grup",
- "access.members.memberCount_one": "{{count}} członek",
- "access.members.memberCount_other": "{{count}} członków",
- "access.permission.anyone": "Każdy z linkiem",
- "access.permission.organization": "Wszyscy członkowie platformy",
- "access.permission.specific": "Wybrani członkowie platformy",
- "access.permission.specificDesc": "Wybierz określone grupy lub członków",
- "access.permission.updateFailed": "Nie udało się zaktualizować zasad dostępu.",
- "access.permissions.editAriaLabel": "Skonfiguruj dostęp dla {{environment}}",
- "access.permissions.editDescription": "Ustaw uprawnienia dostępu dla punktów wejścia WebApp i CLI.",
- "access.permissions.editTitle": "Uprawnienia dostępu",
- "access.permissions.title": "Uprawnienia dostępu",
- "access.revoke": "Unieważnij",
- "access.runAccess.noEnvs": "Wdróż do środowiska, aby skonfigurować uprawnienia dostępu.",
- "access.runAccess.noEnvsTitle": "Brak wdrożonych środowisk",
- "access.runAccess.openWebapp": "Otwórz WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Hostowana strona internetowa dla użytkowników końcowych.",
- "access.runAccess.webappEmpty": "Wkrótce dostępne.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Zewnętrzny",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Nieznany",
- "card.access.api": "Tokeny API",
- "card.access.cli": "CLI",
- "card.access.none": "Brak dostępu",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Utwórz pierwsze Wydanie",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Usuń wdrożenie",
- "card.menu.deploy": "Wdróż do środowiska",
- "card.menu.editInfo": "Edytuj informacje",
- "card.moreActions": "Więcej akcji",
- "card.noDescription": "Nie podano opisu.",
"card.notDeployed": "Nie wdrożone",
- "card.tooltip.createdAt": "Utworzono",
- "card.tooltip.deployed": "Wdrożone",
- "card.tooltip.deploymentStatus": "Wdrożenie",
- "card.tooltip.notDeployedShort": "Nie wdrożone",
- "card.tooltip.releaseName": "Nazwa Wydania",
- "card.tooltip.source": "Źródło",
"common.loadFailed": "Nie udało się załadować. Spróbuj ponownie później.",
- "createGuide.actions.back": "Wstecz",
- "createGuide.actions.createAndDeploy": "Utwórz i wdróż",
- "createGuide.actions.creating": "Tworzenie...",
- "createGuide.actions.deploying": "Tworzenie i wdrażanie...",
- "createGuide.actions.next": "Dalej",
- "createGuide.actions.skipDeploy": "Pomiń, wdróż później",
- "createGuide.dsl.defaultAppName": "Zaimportowana aplikacja DSL",
- "createGuide.dsl.description": "Prześlij pakiet Workflow DSL, aby utworzyć wdrożenie, pierwsze wydanie i opcjonalne wdrożenie do środowiska.",
- "createGuide.dsl.dropDescription": "Prześlij pakiet YAML DSL Workflow. Opcje wdrożenia są rozwiązywane z tego pliku przed wdrożeniem.",
- "createGuide.dsl.dropTitle": "Prześlij pakiet Workflow DSL",
- "createGuide.dsl.readFailed": "Nie udało się odczytać pliku DSL. Wybierz inny plik i spróbuj ponownie.",
- "createGuide.dsl.reading": "Odczytywanie pliku DSL...",
- "createGuide.dsl.title": "Importuj DSL",
- "createGuide.dsl.unsupportedMode": "Tylko pliki Workflow DSL mogą być używane do wdrożeń.",
- "createGuide.errors.createReleaseFailed": "Nie udało się utworzyć wdrożenia lub wydania.",
- "createGuide.errors.deployFailed": "Nie udało się wdrożyć do środowiska.",
- "createGuide.method.description": "Wybierz źródło użyte do utworzenia pierwszego wydania.",
- "createGuide.methods.bindApp.description": "Użyj istniejącej aplikacji Workflow w Studio jako źródła wydania.",
- "createGuide.methods.bindApp.title": "Podłącz istniejącą aplikację Workflow",
- "createGuide.methods.importDsl.description": "Prześlij pakiet YAML DSL Workflow i kontynuuj przez UI wdrożenia.",
- "createGuide.methods.importDsl.title": "Importuj DSL",
- "createGuide.nav.back": "Wdrożenia",
- "createGuide.release.defaultName": "wydanie początkowe",
- "createGuide.release.deployInfo": "Informacje o wdrożeniu",
- "createGuide.release.description": "Wypełnij informacje o wdrożeniu i szczegóły pierwszego wydania.",
- "createGuide.release.firstVersion": "Pierwsze Wydanie",
- "createGuide.release.instanceDescription": "Opis wdrożenia",
- "createGuide.release.instanceDescriptionPlaceholder": "Opisz, do czego służy to wdrożenie",
- "createGuide.release.instanceName": "Nazwa wdrożenia",
- "createGuide.release.instanceNameConflict": "Wdrożenie o tej nazwie już istnieje. Wybierz inną nazwę.",
- "createGuide.release.releaseDescription": "Opis Wydania",
- "createGuide.release.releaseDescriptionPlaceholder": "Opisz to wydanie",
- "createGuide.release.releaseName": "Nazwa Wydania",
- "createGuide.release.title": "Podstawowe informacje",
- "createGuide.source.clearSearch": "Wyczyść wyszukiwanie aplikacji",
- "createGuide.source.description": "Wybierz źródło użyte do utworzenia pierwszego wydania.",
- "createGuide.source.empty": "Nie znaleziono aplikacji Workflow.",
- "createGuide.source.searchPlaceholder": "Szukaj aplikacji",
- "createGuide.source.sourceApp": "Aplikacja Workflow",
- "createGuide.source.title": "Źródło Wydania",
- "createGuide.steps.method": "Źródło Wydania",
- "createGuide.steps.release": "Podstawowe informacje",
- "createGuide.steps.source": "Źródło Wydania",
- "createGuide.steps.target": "Wdróż do środowiska",
- "createGuide.target.bindingCount_one": "{{count}} powiązanie",
- "createGuide.target.bindingCount_other": "{{count}} powiązań",
- "createGuide.target.bindingHint": "Wybierz poświadczenia używane przez to wydanie.",
- "createGuide.target.bindings": "Poświadczenia",
- "createGuide.target.description": "Wybierz docelowe środowisko i podaj ustawienia środowiska uruchomieniowego, których potrzebuje to wydanie. Ten krok można pominąć.",
- "createGuide.target.envVarCount_one": "{{count}} zmienna",
- "createGuide.target.envVarCount_other": "{{count}} zmiennych",
- "createGuide.target.envVarHint": "Dla każdej zmiennej środowiskowej, której potrzebuje to wydanie, wprowadź wartość niestandardową lub użyj wartości zdefiniowanej w aplikacji.",
- "createGuide.target.envVarPlaceholder": "Wprowadź wartość",
- "createGuide.target.envVarSource.ariaLabel": "Wybierz źródło wartości zmiennej dla {{key}}",
- "createGuide.target.envVarSource.default": "Wartość aplikacji",
- "createGuide.target.envVarSource.lastDeployment": "Ostatnio wdrożona wartość",
- "createGuide.target.envVarSource.literal": "Wartość niestandardowa",
- "createGuide.target.envVarType.number": "Liczba",
- "createGuide.target.envVarType.secret": "Sekret",
- "createGuide.target.envVarType.string": "Ciąg znaków",
- "createGuide.target.envVars": "Zmienne środowiskowe",
- "createGuide.target.environment": "Środowisko docelowe",
- "createGuide.target.loadBindingsFailed": "Nie udało się załadować poświadczeń.",
- "createGuide.target.loadEnvironmentsFailed": "Nie udało się załadować środowisk wdrożenia.",
- "createGuide.target.missingRequiredBinding": "Wybierz poświadczenie dla tego wymaganego powiązania.",
- "createGuide.target.noBindingRequired": "Nie są wymagane poświadczenia.",
- "createGuide.target.noCredentialCandidates": "Brak dostępnych poświadczeń.",
- "createGuide.target.noEnvironmentOptions": "Brak dostępnych środowisk wdrożenia.",
- "createGuide.target.selectCredential": "Wybierz poświadczenie",
- "createGuide.target.title": "Wdróż do środowiska",
- "createGuide.title": "Nowe Wdrożenie",
- "createModal.appPickerPlaceholder": "Wybierz aplikację Workflow",
- "createModal.appSearchEmpty": "Brak pasujących aplikacji Workflow",
- "createModal.appSearchPlaceholder": "Szukaj aplikacji Workflow…",
- "createModal.cancel": "Anuluj",
- "createModal.loadingApps": "Ładowanie aplikacji…",
- "deployDrawer.bindingCount_one": "{{count}} powiązanie",
- "deployDrawer.bindingCount_other": "{{count}} powiązań",
"deployDrawer.bindingOptionsFailed": "Nie udało się załadować opcji poświadczeń.",
"deployDrawer.bindingSelectionHint": "Wybierz poświadczenia używane przez to wdrożenie.",
- "deployDrawer.cancel": "Anuluj",
- "deployDrawer.close": "Zamknij panel wdrożenia",
- "deployDrawer.defaultSelect": "Wybierz...",
- "deployDrawer.deploy": "Wdróż do środowiska",
- "deployDrawer.deployFailed": "Nie udało się rozpocząć wdrożenia.",
"deployDrawer.deploying": "Wdrażanie...",
- "deployDrawer.description": "Wybierz wydanie i środowisko docelowe do wdrożenia.",
- "deployDrawer.envVarCount_one": "{{count}} zmienna",
- "deployDrawer.envVarCount_other": "{{count}} zmiennych",
- "deployDrawer.envVarHint": "Dla każdej zmiennej środowiskowej, której potrzebuje to wydanie, wprowadź wartość niestandardową lub użyj wartości zdefiniowanej w aplikacji.",
- "deployDrawer.envVarPlaceholder": "Wprowadź wartość",
"deployDrawer.envVarSource.ariaLabel": "Wybierz źródło wartości zmiennej dla {{key}}",
- "deployDrawer.envVarSource.default": "Wartość aplikacji",
"deployDrawer.envVarSource.lastDeployment": "Ostatnio wdrożona wartość",
"deployDrawer.envVarSource.literal": "Wartość niestandardowa",
"deployDrawer.envVarType.number": "Liczba",
"deployDrawer.envVarType.secret": "Sekret",
"deployDrawer.envVarType.string": "Ciąg znaków",
"deployDrawer.envVars": "Zmienne środowiskowe",
- "deployDrawer.existingReleaseHint": "To wydanie zostanie wdrożone bez zmian. Nie zostanie utworzone żadne nowe wydanie.",
- "deployDrawer.lockedHint": "Zablokowane do bieżącego środowiska",
- "deployDrawer.missingRequiredBinding": "Wybierz poświadczenie dla tego wymaganego powiązania.",
- "deployDrawer.missingRequiredEnvVar": "Wprowadź wartość dla tej wymaganej zmiennej środowiskowej.",
- "deployDrawer.noBindingRequired": "Nie wymagane",
"deployDrawer.noCredentialCandidates": "Brak dostępnych poświadczeń.",
"deployDrawer.noNewEnvironmentAvailable": "Wszystkie dostępne środowiska mają już wdrożenie.",
- "deployDrawer.noOtherReleaseAvailable": "Brak innych dostępnych wydań dla tego środowiska.",
- "deployDrawer.noReleaseAvailable": "Utwórz wydanie przed wdrożeniem do środowiska.",
- "deployDrawer.notFound": "Nie znaleziono wdrożenia.",
- "deployDrawer.releaseLabel": "Wydanie",
"deployDrawer.runtimeCredentials": "Poświadczenia",
"deployDrawer.selectCredential": "Wybierz poświadczenie",
- "deployDrawer.selectEnv": "Wybierz środowisko",
- "deployDrawer.selectRelease": "Wybierz wydanie",
- "deployDrawer.targetEnv": "Środowisko docelowe",
- "deployDrawer.title": "Wdróż do środowiska",
- "deployTab.closeError": "Zamknij",
"deployTab.col.actions": "Akcje",
- "deployTab.col.currentRelease": "Bieżące Wydanie",
"deployTab.col.environment": "Środowisko",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Wycofaj wdrożenie",
- "deployTab.deployOtherVersion": "Wdróż inne Wydanie",
- "deployTab.emptyDescription": "Wybierz wydanie i środowisko docelowe, aby udostępnić to wdrożenie użytkownikom.",
- "deployTab.emptyTitle": "Żadne środowisko nie jest jeszcze uruchomione",
- "deployTab.errorCode": "Kod",
- "deployTab.errorDialogDesc": "Przejrzyj ostatnie nieudane wdrożenie przed ponowną próbą lub wdrożeniem innego wydania.",
- "deployTab.errorDialogTitle": "Błąd wdrożenia w {{name}}",
- "deployTab.errorMessage": "Wiadomość",
- "deployTab.errorPhase": "Faza",
"deployTab.moreActions": "Więcej akcji",
- "deployTab.newDeployment": "Wdróż do nowego środowiska",
- "deployTab.panel.unknownError": "Wdrożenie nie powiodło się.",
"deployTab.redeploy": "Ponownie wdróż",
- "deployTab.retry": "Ponów",
- "deployTab.status.deployFailed": "Wdrożenie nie powiodło się",
- "deployTab.status.deployingRelease": "Wdrażanie ({{release}})",
- "deployTab.status.runningOutOfSync": "Uruchomione (oczekuje synchronizacja)",
- "deployTab.status.runningWithFailed": "Uruchomione (ostatnie wdrożenie nie powiodło się)",
"deployTab.undeploy": "Wycofaj wdrożenie",
- "deployTab.undeployConfirmDesc": "Punkt końcowy środowiska stanie się niedostępny, ale wersja nie zostanie usunięta.",
- "deployTab.undeployConfirmTitle": "Wycofać wdrożenie {{name}}?",
"deployTab.undeployConfirmWarning": "Po potwierdzeniu to środowisko przejdzie w stan wycofywania wdrożenia, a działania zostaną tymczasowo wyłączone.",
- "deployTab.viewError": "Zobacz błąd",
- "detail.mobileTabs": "Sekcje wdrożenia",
- "detail.notFound": "Nie znaleziono wdrożenia",
- "documentTitle.create": "Nowe wdrożenie · Wdrożenia",
- "documentTitle.detail": "Wdrożenie · Wdrożenia",
- "documentTitle.list": "Wdrożenia",
- "filter.allEnvs": "Wszystkie środowiska",
- "filter.searchPlaceholder": "Szukaj wdrożeń",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Dopuszczenie",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Inicjalizacja",
- "health.ENVIRONMENT_STATUS_DELETING": "Usuwanie",
"health.ENVIRONMENT_STATUS_FAILED": "Niedostępne",
- "health.ENVIRONMENT_STATUS_READY": "Dostępne",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Nieznane",
- "list.clearFilters": "Wyczyść filtry",
- "list.clearSearch": "Wyczyść wyszukiwanie wdrożeń",
- "list.createDeployment": "Nowe",
- "list.emptyDescription": "Utwórz wdrożenie z aplikacji Workflow lub pakietu Workflow DSL, aby zarządzać wydaniami, środowiskami i dostępem.",
- "list.emptyFilteredDescription": "Żadne wdrożenie nie pasuje do bieżącego wyszukiwania lub filtra środowiska.",
- "list.emptyFilteredTitle": "Brak pasujących wdrożeń",
"list.emptyTitle": "Brak wdrożeń",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Izolowane",
- "mode.ENVIRONMENT_MODE_SHARED": "Współdzielone",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Nieznane",
- "overview.accessMeta.apiTokens": "Zarządzaj Tokenami API",
- "overview.accessMeta.cli": "Zobacz dostęp przez CLI",
- "overview.accessMeta.webApp": "Zarządzaj dostępem WebApp",
- "overview.accessStatus": "Dostęp",
- "overview.api": "Tokeny API",
- "overview.apiKeysCount_one": "{{count}} Token API",
- "overview.apiKeysCount_other": "{{count}} Tokenów API",
- "overview.apiTokenSummary.environments_one": "{{count}} wdrożone środowisko",
- "overview.apiTokenSummary.environments_other": "{{count}} wdrożonych środowisk",
- "overview.cardAction.deployLatest": "Wdróż najnowsze Wydanie",
- "overview.cardAction.redeploy": "Ponownie wdróż",
- "overview.cardAction.viewProgress": "Zobacz wdrożenie",
- "overview.chip.behindTooltip_one": "1 wydanie za najnowszym. Wdróż najnowsze wydanie, aby zaktualizować.",
- "overview.chip.behindTooltip_other": "{{count}} wydań za najnowszym. Wdróż najnowsze wydanie, aby zaktualizować.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "wdrażanie",
- "overview.chip.deployingTooltip": "Wdrożenie jest w toku.",
- "overview.chip.empty": "puste",
- "overview.chip.emptyTooltip": "Żadne wydanie nie jest wdrożone w tym środowisku.",
- "overview.chip.failed": "nieudane",
- "overview.chip.failedTooltip": "Ostatnia próba wdrożenia nie powiodła się.",
"overview.chip.latest": "najnowsze",
- "overview.chip.latestTooltip": "To środowisko uruchamia najnowsze wydanie.",
- "overview.chip.needsReleaseFirst": "Najpierw utwórz Wydanie",
- "overview.chip.olderRelease": "starsze",
- "overview.chip.olderReleaseTooltip": "To środowisko uruchamia starsze wydanie.",
- "overview.chip.openInDeployTab": "Zobacz postęp wdrożenia",
- "overview.disabled": "Wyłączone",
- "overview.enabled": "Włączone",
- "overview.hero.byName": "przez {{name}}",
- "overview.hero.empty": "Brak wydań",
- "overview.hero.emptyDescription": "Utwórz wydanie z bieżącego źródła przed wdrożeniem.",
- "overview.latestRelease.releaseCount_one": "{{count}} wydanie",
- "overview.latestRelease.releaseCount_other": "{{count}} wydań",
- "overview.latestReleaseTitle": "Najnowsze Wydanie",
- "overview.previousReleases.viewAll": "Zobacz wszystkie",
- "overview.strip.deployToNewEnvironment": "Wdróż do nowego środowiska",
- "overview.strip.emptyDeployableDescription": "Wdróż najnowsze wydanie do środowiska, gdy będziesz gotów.",
- "overview.strip.emptyDescription": "Utwórz wydanie przed wdrożeniem do środowiska.",
- "overview.strip.emptyTitle": "Brak instancji",
- "overview.strip.title": "Instancje",
- "settings.delete": "Usuń wdrożenie",
- "settings.deleteConfirmDesc": "Usunąć {{name}}? Każda instancja przestanie działać i zostanie usunięta we wszystkich środowiskach. Tej akcji nie można cofnąć.",
- "settings.deleteConfirmTitle": "Usuń wdrożenie",
- "settings.deleteFailed": "Nie udało się usunąć wdrożenia.",
- "settings.deleted": "Wdrożenie usunięte",
- "settings.description": "Opis",
- "settings.name": "Nazwa wdrożenia",
- "settings.save": "Zapisz zmiany",
- "settings.updateFailed": "Nie udało się zaktualizować wdrożenia.",
- "settings.updated": "Wdrożenie zaktualizowane",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Wdrażanie",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Oczekuje synchronizacja",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Wdrożenie nie powiodło się",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Nieprawidłowe",
"status.RUNTIME_INSTANCE_STATUS_READY": "Uruchomione",
@@ -370,87 +89,6 @@
"studio.versionValue": "Wartość wersji",
"studio.versionsBehind_one": "{{count}} wersja wstecz",
"studio.versionsBehind_other": "{{count}} wersji wstecz",
- "tabs.access.description": "Zarządzaj kanałami dostępu i uprawnieniami dostępu.",
- "tabs.access.name": "Dostęp",
- "tabs.api-tokens.description": "Zarządzaj Tokenami API i wywołuj instancje przez HTTP.",
- "tabs.api-tokens.name": "Tokeny API",
- "tabs.instances.description": "Wyświetlaj i zarządzaj instancjami we wdrożonych środowiskach.",
- "tabs.instances.name": "Instancje",
- "tabs.overview.description": "Zobacz status wdrożenia w różnych środowiskach.",
- "tabs.overview.name": "Przegląd",
- "tabs.releases.description": "Twórz, wdrażaj i zarządzaj wydaniami.",
- "tabs.releases.name": "Wydania",
- "unsupportedDslNodes.description": "To wydanie zawiera węzły, których środowisko uruchomieniowe wdrożenia jeszcze nie obsługuje. Usuń je lub zastąp w Studio, a następnie spróbuj ponownie.",
- "unsupportedDslNodes.descriptionWithTypes": "To wydanie zawiera węzły, których środowisko uruchomieniowe wdrożenia jeszcze nie obsługuje: {{nodeTypes}}. Usuń je lub zastąp w Studio, a następnie spróbuj ponownie.",
- "unsupportedDslNodes.title": "Nieobsługiwane węzły",
- "unsupportedDslNodes.unknownType": "Nieznany typ",
- "versions.cancelCreate": "Anuluj",
- "versions.cancelDelete": "Anuluj",
- "versions.cancelEdit": "Anuluj",
"versions.checkingReleaseContent": "Sprawdzanie zawartości wydania...",
- "versions.col.action": "Akcja",
- "versions.col.author": "Utworzone przez",
- "versions.col.createdAt": "Utworzono",
- "versions.col.deployedTo": "Wdrożone do",
- "versions.col.release": "Wydanie",
- "versions.col.sourceApp": "Źródło",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Utwórz",
- "versions.createFailed": "Nie udało się utworzyć wydania.",
- "versions.createRelease": "Utwórz Wydanie",
- "versions.createReleaseDescription": "Utwórz wdrażalne wydanie z aplikacji Workflow lub pliku Workflow DSL.",
- "versions.createSuccess": "Wydanie \"{{name}}\" utworzone.",
- "versions.creating": "Tworzenie...",
- "versions.currentOn": "Bieżące Wydanie na {{name}}",
- "versions.deleteConfirmDesc": "Wydanie \"{{name}}\" zostanie trwale usunięte. Tej akcji nie można cofnąć.",
- "versions.deleteConfirmTitle": "Usunąć wydanie?",
- "versions.deleteFailed": "Nie udało się usunąć wydania.",
- "versions.deleteRelease": "Usuń Wydanie",
- "versions.deleteSuccess": "Wydanie \"{{name}}\" usunięte.",
- "versions.deployTo": "Wdróż do {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Wdrażanie",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Oczekuje synchronizacja",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Nieudane",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Nieprawidłowe",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Uruchomione",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Nie wdrożone",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Wycofywanie wdrożenia",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Nieznane",
- "versions.deployingTo": "{{name}} jest wdrażane",
- "versions.disabledReason.checkDeploymentsFailed": "Nie udało się zweryfikować użycia wdrożenia. Spróbuj ponownie później.",
- "versions.disabledReason.checkingDeployments": "Sprawdzanie użycia wdrożenia",
- "versions.disabledReason.current": "To wydanie już działa na {{name}}",
- "versions.disabledReason.deploying": "Poczekaj na zakończenie aktywnego wdrożenia",
- "versions.disabledReason.releaseInUse_one": "Wycofaj to wydanie z {{count}} środowiska przed jego usunięciem",
- "versions.disabledReason.releaseInUse_other": "Wycofaj to wydanie z {{count}} środowisk przed jego usunięciem",
- "versions.dslReadFailed": "Nie udało się odczytać pliku DSL. Wybierz inny plik i spróbuj ponownie.",
- "versions.dslReading": "Odczytywanie pliku DSL...",
- "versions.dslUnsupportedMode": "Tylko pliki Workflow DSL mogą być używane do wdrożeń.",
- "versions.editFailed": "Nie udało się zaktualizować wydania.",
- "versions.editRelease": "Edytuj Wydanie",
- "versions.editReleaseDescription": "Zaktualizuj nazwę i opis tego wydania.",
- "versions.editSuccess": "Wydanie \"{{name}}\" zaktualizowane.",
- "versions.emptyDescription": "Utwórz pierwsze wydanie przed wdrożeniem do środowiska.",
- "versions.emptyTitle": "Brak wydań",
- "versions.exportDsl": "Eksportuj DSL",
- "versions.exportDslFailed": "Nie udało się wyeksportować DSL.",
- "versions.exportingDsl": "Eksportowanie...",
- "versions.groupHeader.deploy": "Wdróż",
- "versions.groupHeader.rollback": "Wdróż poprzednią wersję",
- "versions.groupHeader.unavailable": "Niedostępne",
- "versions.manualDslOption": "Prześlij DSL",
- "versions.moreActions": "Więcej akcji",
- "versions.optional": "Opcjonalne",
- "versions.releaseAlreadyExists": "Wydanie o tej samej zawartości już istnieje: {{name}}.",
- "versions.releaseContentCheckFailed": "Nie udało się sprawdzić zawartości wydania.",
- "versions.releaseDescriptionLabel": "Opis",
- "versions.releaseDescriptionPlaceholder": "Opisz to wydanie",
- "versions.releaseNameConflict": "Wydanie o tej nazwie już istnieje. Wybierz inną nazwę.",
- "versions.releaseNameLabel": "Nazwa Wydania",
- "versions.releaseNamePlaceholder": "Nazwa Wydania",
- "versions.releaseNameRequired": "Wprowadź nazwę wydania.",
- "versions.releaseSourceLabel": "Źródło Wydania",
- "versions.rollbackTo": "Wdróż do {{name}}",
- "versions.saveEdit": "Zapisz",
- "versions.sourceAppOption": "Aplikacja Workflow"
+ "versions.deployTo": "Wdróż do {{name}}"
}
diff --git a/web/i18n/pt-BR/common.json b/web/i18n/pt-BR/common.json
index c878edbf5ee..47a6e247731 100644
--- a/web/i18n/pt-BR/common.json
+++ b/web/i18n/pt-BR/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Detalhes do aplicativo",
"menus.apps": "Estúdio",
"menus.datasets": "Conhecimento",
- "menus.deployments": "Implantações",
"menus.exploreMarketplace": "Explorar Mercado",
"menus.plugins": "Integrações",
"menus.status": "beta",
diff --git a/web/i18n/pt-BR/deployments.json b/web/i18n/pt-BR/deployments.json
index 7e0cd9572a2..a818aafb1bd 100644
--- a/web/i18n/pt-BR/deployments.json
+++ b/web/i18n/pt-BR/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copiar exemplo cURL",
- "access.api.createFailed": "Falha ao gerar o Token de API.",
- "access.api.createKey": "Gerar Token de API",
- "access.api.createKeyTitle": "Gerar novo Token de API",
- "access.api.curlExampleTitle": "Exemplo cURL",
- "access.api.description": "Acesse esta implantação por HTTP. Cada Token de API tem escopo de um ambiente.",
- "access.api.developerTitle": "API do desenvolvedor",
- "access.api.disabled": "O acesso à API está desativado para esta implantação.",
- "access.api.disabledHint": "Ative o acesso à API para gerar tokens com escopo de ambiente.",
- "access.api.docs": "Documentação da API",
- "access.api.docsClose": "Fechar documentação da API",
- "access.api.docsDescription": "Veja a referência da API de Workflow para esta implantação.",
- "access.api.docsTitle": "Documentação da API de Workflow",
- "access.api.empty": "Implante em um ambiente primeiro para começar a emitir Tokens de API.",
- "access.api.emptyTitle": "Nenhum ambiente implantado",
- "access.api.endpoint": "URL da requisição",
- "access.api.keyList": "Lista de Tokens de API",
- "access.api.nameLabel": "Nome do Token de API",
- "access.api.namePlaceholder": "Insira um nome para o Token de API",
- "access.api.nameRequired": "O nome do Token de API é obrigatório.",
- "access.api.newKey": "Gerar novo Token de API",
- "access.api.newTokenDescription": "Este Token de API é exibido apenas uma vez. Copie-o antes de sair desta página.",
- "access.api.newTokenLabel": "Token de API",
- "access.api.newTokenTitle": "Token de API gerado",
- "access.api.noKeys": "Nenhum Token de API ainda. Gere um para começar a chamar a API.",
- "access.api.noKeysTitle": "Nenhum Token de API ainda",
- "access.api.revokeConfirmDescription": "O Token de API \"{{name}}\" deixará de funcionar imediatamente. Esta ação não pode ser desfeita.",
- "access.api.revokeConfirmTitle": "Revogar Token de API?",
- "access.api.revokeFailed": "Falha ao revogar o Token de API.",
- "access.api.revokeSuccess": "Token de API revogado",
- "access.api.table.action": "Ação",
- "access.api.table.environment": "Ambiente",
- "access.api.table.key": "Token de API",
- "access.api.table.name": "Nome",
- "access.channels.disabled": "Os canais de acesso estão desativados para esta implantação.",
- "access.channels.disabledHint": "Ative os canais de acesso para expor os pontos de entrada do WebApp e da CLI.",
- "access.channels.title": "Canais de acesso",
- "access.cli.description": "Invoque a partir do terminal com o difyctl, adequado para scripts, fluxos de trabalho automatizados ou integrações de Agente.",
- "access.cli.docs": "Guia de uso",
- "access.cli.domain": "Domínio",
- "access.cli.empty": "Endpoint da CLI não configurado.",
- "access.cli.install": "Instalar CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copiar",
- "access.copyFailed": "Falha ao copiar",
- "access.members.groupCount_one": "{{count}} grupo",
- "access.members.groupCount_other": "{{count}} grupos",
- "access.members.memberCount_one": "{{count}} membro",
- "access.members.memberCount_other": "{{count}} membros",
- "access.permission.anyone": "Qualquer pessoa com o link",
- "access.permission.organization": "Todos os membros da plataforma",
- "access.permission.specific": "Membros específicos da plataforma",
- "access.permission.specificDesc": "Selecione grupos ou membros específicos",
- "access.permission.updateFailed": "Falha ao atualizar a política de acesso.",
- "access.permissions.editAriaLabel": "Configurar acesso para {{environment}}",
- "access.permissions.editDescription": "Defina permissões de acesso para os pontos de entrada do WebApp e da CLI.",
- "access.permissions.editTitle": "Permissões de acesso",
- "access.permissions.title": "Permissões de acesso",
- "access.revoke": "Revogar",
- "access.runAccess.noEnvs": "Implante em um ambiente para configurar as permissões de acesso.",
- "access.runAccess.noEnvsTitle": "Nenhum ambiente implantado",
- "access.runAccess.openWebapp": "Abrir WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Página web hospedada para usuários finais.",
- "access.runAccess.webappEmpty": "Em breve.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Externo",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Desconhecido",
- "card.access.api": "Tokens de API",
- "card.access.cli": "CLI",
- "card.access.none": "Sem acesso",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Criar primeira versão",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Excluir implantação",
- "card.menu.deploy": "Implantar no ambiente",
- "card.menu.editInfo": "Editar informações",
- "card.moreActions": "Mais ações",
- "card.noDescription": "Nenhuma descrição fornecida.",
"card.notDeployed": "Não implantado",
- "card.tooltip.createdAt": "Criado",
- "card.tooltip.deployed": "Implantado",
- "card.tooltip.deploymentStatus": "Implantação",
- "card.tooltip.notDeployedShort": "Não implantado",
- "card.tooltip.releaseName": "Nome da versão",
- "card.tooltip.source": "Origem",
"common.loadFailed": "Falha ao carregar. Tente novamente mais tarde.",
- "createGuide.actions.back": "Voltar",
- "createGuide.actions.createAndDeploy": "Criar e implantar",
- "createGuide.actions.creating": "Criando...",
- "createGuide.actions.deploying": "Criando e implantando...",
- "createGuide.actions.next": "Próximo",
- "createGuide.actions.skipDeploy": "Pular, implantar depois",
- "createGuide.dsl.defaultAppName": "App DSL importado",
- "createGuide.dsl.description": "Faça upload de um pacote DSL de Workflow para criar a implantação, a primeira versão e a implantação opcional no ambiente.",
- "createGuide.dsl.dropDescription": "Faça upload de um pacote DSL YAML de Workflow. As opções de implantação são resolvidas a partir deste arquivo antes da implantação.",
- "createGuide.dsl.dropTitle": "Carregar pacote DSL de Workflow",
- "createGuide.dsl.readFailed": "Falha ao ler o arquivo DSL. Escolha outro arquivo e tente novamente.",
- "createGuide.dsl.reading": "Lendo arquivo DSL...",
- "createGuide.dsl.title": "Importar DSL",
- "createGuide.dsl.unsupportedMode": "Apenas arquivos DSL de Workflow podem ser usados para implantações.",
- "createGuide.errors.createReleaseFailed": "Falha ao criar a implantação ou a versão.",
- "createGuide.errors.deployFailed": "Falha ao implantar no ambiente.",
- "createGuide.method.description": "Escolha a origem usada para criar a primeira versão.",
- "createGuide.methods.bindApp.description": "Use um Workflow App existente no Studio como origem da versão.",
- "createGuide.methods.bindApp.title": "Vincular Workflow App existente",
- "createGuide.methods.importDsl.description": "Faça upload de um pacote DSL YAML de Workflow e prossiga pela UI de implantação.",
- "createGuide.methods.importDsl.title": "Importar DSL",
- "createGuide.nav.back": "Implantações",
- "createGuide.release.defaultName": "versão inicial",
- "createGuide.release.deployInfo": "Informações da implantação",
- "createGuide.release.description": "Preencha as informações da implantação e os detalhes da primeira versão.",
- "createGuide.release.firstVersion": "Primeira versão",
- "createGuide.release.instanceDescription": "Descrição da implantação",
- "createGuide.release.instanceDescriptionPlaceholder": "Descreva para que esta implantação é usada",
- "createGuide.release.instanceName": "Nome da implantação",
- "createGuide.release.instanceNameConflict": "Já existe uma implantação com este nome. Escolha outro nome.",
- "createGuide.release.releaseDescription": "Descrição da versão",
- "createGuide.release.releaseDescriptionPlaceholder": "Descreva esta versão",
- "createGuide.release.releaseName": "Nome da versão",
- "createGuide.release.title": "Informações básicas",
- "createGuide.source.clearSearch": "Limpar busca de apps",
- "createGuide.source.description": "Escolha a origem usada para criar a primeira versão.",
- "createGuide.source.empty": "Nenhum Workflow App encontrado.",
- "createGuide.source.searchPlaceholder": "Pesquisar apps",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Origem da versão",
- "createGuide.steps.method": "Origem da versão",
- "createGuide.steps.release": "Informações básicas",
- "createGuide.steps.source": "Origem da versão",
- "createGuide.steps.target": "Implantar no ambiente",
- "createGuide.target.bindingCount_one": "{{count}} vínculo",
- "createGuide.target.bindingCount_other": "{{count}} vínculos",
- "createGuide.target.bindingHint": "Escolha as credenciais usadas por esta versão.",
- "createGuide.target.bindings": "Credenciais",
- "createGuide.target.description": "Escolha um ambiente de destino e forneça as configurações de runtime que esta versão precisa lá. Esta etapa pode ser pulada.",
- "createGuide.target.envVarCount_one": "{{count}} variável",
- "createGuide.target.envVarCount_other": "{{count}} variáveis",
- "createGuide.target.envVarHint": "Para cada variável de ambiente que esta versão precisa, insira um valor personalizado ou use o valor definido no app.",
- "createGuide.target.envVarPlaceholder": "Insira o valor",
- "createGuide.target.envVarSource.ariaLabel": "Selecione a origem do valor da variável para {{key}}",
- "createGuide.target.envVarSource.default": "Valor do app",
- "createGuide.target.envVarSource.lastDeployment": "Último valor implantado",
- "createGuide.target.envVarSource.literal": "Valor personalizado",
- "createGuide.target.envVarType.number": "Número",
- "createGuide.target.envVarType.secret": "Secreto",
- "createGuide.target.envVarType.string": "Texto",
- "createGuide.target.envVars": "Variáveis de ambiente",
- "createGuide.target.environment": "Ambiente de destino",
- "createGuide.target.loadBindingsFailed": "Falha ao carregar as credenciais.",
- "createGuide.target.loadEnvironmentsFailed": "Falha ao carregar os ambientes de implantação.",
- "createGuide.target.missingRequiredBinding": "Selecione uma credencial para este vínculo obrigatório.",
- "createGuide.target.noBindingRequired": "Nenhuma credencial necessária.",
- "createGuide.target.noCredentialCandidates": "Nenhuma credencial disponível.",
- "createGuide.target.noEnvironmentOptions": "Nenhum ambiente de implantação disponível.",
- "createGuide.target.selectCredential": "Selecione uma credencial",
- "createGuide.target.title": "Implantar no ambiente",
- "createGuide.title": "Nova implantação",
- "createModal.appPickerPlaceholder": "Selecione um Workflow App",
- "createModal.appSearchEmpty": "Nenhum Workflow App correspondente",
- "createModal.appSearchPlaceholder": "Pesquisar Workflow Apps…",
- "createModal.cancel": "Cancelar",
- "createModal.loadingApps": "Carregando apps…",
- "deployDrawer.bindingCount_one": "{{count}} vínculo",
- "deployDrawer.bindingCount_other": "{{count}} vínculos",
"deployDrawer.bindingOptionsFailed": "Falha ao carregar as opções de credencial.",
"deployDrawer.bindingSelectionHint": "Escolha as credenciais usadas por esta implantação.",
- "deployDrawer.cancel": "Cancelar",
- "deployDrawer.close": "Fechar painel de implantação",
- "deployDrawer.defaultSelect": "Selecionar...",
- "deployDrawer.deploy": "Implantar no ambiente",
- "deployDrawer.deployFailed": "Falha ao iniciar a implantação.",
"deployDrawer.deploying": "Implantando...",
- "deployDrawer.description": "Selecione uma versão e um ambiente de destino para implantar.",
- "deployDrawer.envVarCount_one": "{{count}} variável",
- "deployDrawer.envVarCount_other": "{{count}} variáveis",
- "deployDrawer.envVarHint": "Para cada variável de ambiente que esta versão precisa, insira um valor personalizado ou use o valor definido no app.",
- "deployDrawer.envVarPlaceholder": "Insira o valor",
"deployDrawer.envVarSource.ariaLabel": "Selecione a origem do valor da variável para {{key}}",
- "deployDrawer.envVarSource.default": "Valor do app",
"deployDrawer.envVarSource.lastDeployment": "Último valor implantado",
"deployDrawer.envVarSource.literal": "Valor personalizado",
"deployDrawer.envVarType.number": "Número",
"deployDrawer.envVarType.secret": "Secreto",
"deployDrawer.envVarType.string": "Texto",
"deployDrawer.envVars": "Variáveis de ambiente",
- "deployDrawer.existingReleaseHint": "Esta versão será implantada como está. Nenhuma nova versão será criada.",
- "deployDrawer.lockedHint": "Bloqueado no ambiente atual",
- "deployDrawer.missingRequiredBinding": "Selecione uma credencial para este vínculo obrigatório.",
- "deployDrawer.missingRequiredEnvVar": "Insira um valor para esta variável de ambiente obrigatória.",
- "deployDrawer.noBindingRequired": "Não obrigatório",
"deployDrawer.noCredentialCandidates": "Nenhuma credencial disponível.",
"deployDrawer.noNewEnvironmentAvailable": "Todos os ambientes disponíveis já possuem uma implantação.",
- "deployDrawer.noOtherReleaseAvailable": "Nenhuma outra versão está disponível para este ambiente.",
- "deployDrawer.noReleaseAvailable": "Crie uma versão antes de implantar em um ambiente.",
- "deployDrawer.notFound": "Implantação não encontrada.",
- "deployDrawer.releaseLabel": "Versão",
"deployDrawer.runtimeCredentials": "Credenciais",
"deployDrawer.selectCredential": "Selecione uma credencial",
- "deployDrawer.selectEnv": "Selecione um ambiente",
- "deployDrawer.selectRelease": "Selecione uma versão",
- "deployDrawer.targetEnv": "Ambiente de destino",
- "deployDrawer.title": "Implantar no ambiente",
- "deployTab.closeError": "Fechar",
"deployTab.col.actions": "Ações",
- "deployTab.col.currentRelease": "Versão atual",
"deployTab.col.environment": "Ambiente",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Desimplantar",
- "deployTab.deployOtherVersion": "Implantar outra versão",
- "deployTab.emptyDescription": "Escolha uma versão e um ambiente de destino para tornar esta implantação disponível aos usuários.",
- "deployTab.emptyTitle": "Nenhum ambiente em execução ainda",
- "deployTab.errorCode": "Código",
- "deployTab.errorDialogDesc": "Revise a última implantação que falhou antes de tentar novamente ou implantar outra versão.",
- "deployTab.errorDialogTitle": "Erro de implantação em {{name}}",
- "deployTab.errorMessage": "Mensagem",
- "deployTab.errorPhase": "Fase",
"deployTab.moreActions": "Mais ações",
- "deployTab.newDeployment": "Implantar em novo ambiente",
- "deployTab.panel.unknownError": "A implantação falhou.",
"deployTab.redeploy": "Reimplantar",
- "deployTab.retry": "Tentar novamente",
- "deployTab.status.deployFailed": "Falha na implantação",
- "deployTab.status.deployingRelease": "Implantando ({{release}})",
- "deployTab.status.runningOutOfSync": "Em execução (sincronização pendente)",
- "deployTab.status.runningWithFailed": "Em execução (última implantação falhou)",
"deployTab.undeploy": "Desimplantar",
- "deployTab.undeployConfirmDesc": "O endpoint do ambiente ficará indisponível, mas a versão não será excluída.",
- "deployTab.undeployConfirmTitle": "Desimplantar {{name}}?",
"deployTab.undeployConfirmWarning": "Após a confirmação, este ambiente entrará no estado de desimplantação e as ações serão temporariamente desabilitadas.",
- "deployTab.viewError": "Ver erro",
- "detail.mobileTabs": "Seções da implantação",
- "detail.notFound": "Implantação não encontrada",
- "documentTitle.create": "Nova implantação · Implantações",
- "documentTitle.detail": "Implantação · Implantações",
- "documentTitle.list": "Implantações",
- "filter.allEnvs": "Todos os ambientes",
- "filter.searchPlaceholder": "Pesquisar implantações",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Admissão",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Inicializando",
- "health.ENVIRONMENT_STATUS_DELETING": "Excluindo",
"health.ENVIRONMENT_STATUS_FAILED": "Indisponível",
- "health.ENVIRONMENT_STATUS_READY": "Disponível",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Desconhecido",
- "list.clearFilters": "Limpar filtros",
- "list.clearSearch": "Limpar busca de implantação",
- "list.createDeployment": "Nova",
- "list.emptyDescription": "Crie uma implantação a partir de um Workflow App ou pacote DSL de Workflow para gerenciar versões, ambientes e acesso.",
- "list.emptyFilteredDescription": "Nenhuma implantação corresponde à busca atual ou ao filtro de ambiente.",
- "list.emptyFilteredTitle": "Nenhuma implantação correspondente",
"list.emptyTitle": "Nenhuma implantação ainda",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Isolado",
- "mode.ENVIRONMENT_MODE_SHARED": "Compartilhado",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Desconhecido",
- "overview.accessMeta.apiTokens": "Gerenciar Tokens de API",
- "overview.accessMeta.cli": "Ver acesso via CLI",
- "overview.accessMeta.webApp": "Gerenciar acesso ao WebApp",
- "overview.accessStatus": "Acesso",
- "overview.api": "Tokens de API",
- "overview.apiKeysCount_one": "{{count}} Token de API",
- "overview.apiKeysCount_other": "{{count}} Tokens de API",
- "overview.apiTokenSummary.environments_one": "{{count}} ambiente implantado",
- "overview.apiTokenSummary.environments_other": "{{count}} ambientes implantados",
- "overview.cardAction.deployLatest": "Implantar última versão",
- "overview.cardAction.redeploy": "Reimplantar",
- "overview.cardAction.viewProgress": "Ver implantação",
- "overview.chip.behindTooltip_one": "1 versão atrás da mais recente. Implante a última versão para atualizar.",
- "overview.chip.behindTooltip_other": "{{count}} versões atrás da mais recente. Implante a última versão para atualizar.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "implantando",
- "overview.chip.deployingTooltip": "A implantação está em andamento.",
- "overview.chip.empty": "vazio",
- "overview.chip.emptyTooltip": "Nenhuma versão está implantada neste ambiente.",
- "overview.chip.failed": "falhou",
- "overview.chip.failedTooltip": "A última tentativa de implantação falhou.",
"overview.chip.latest": "mais recente",
- "overview.chip.latestTooltip": "Este ambiente está executando a versão mais recente.",
- "overview.chip.needsReleaseFirst": "Crie uma versão primeiro",
- "overview.chip.olderRelease": "anterior",
- "overview.chip.olderReleaseTooltip": "Este ambiente está executando uma versão mais antiga.",
- "overview.chip.openInDeployTab": "Ver progresso da implantação",
- "overview.disabled": "Desativado",
- "overview.enabled": "Ativado",
- "overview.hero.byName": "por {{name}}",
- "overview.hero.empty": "Nenhuma versão ainda",
- "overview.hero.emptyDescription": "Crie uma versão a partir da origem atual antes de implantar.",
- "overview.latestRelease.releaseCount_one": "{{count}} versão",
- "overview.latestRelease.releaseCount_other": "{{count}} versões",
- "overview.latestReleaseTitle": "Última versão",
- "overview.previousReleases.viewAll": "Ver todas",
- "overview.strip.deployToNewEnvironment": "Implantar em novo ambiente",
- "overview.strip.emptyDeployableDescription": "Implante a última versão em um ambiente quando estiver pronto.",
- "overview.strip.emptyDescription": "Crie uma versão antes de implantar em um ambiente.",
- "overview.strip.emptyTitle": "Nenhuma instância ainda",
- "overview.strip.title": "Instâncias",
- "settings.delete": "Excluir implantação",
- "settings.deleteConfirmDesc": "Excluir {{name}}? Todas as instâncias serão interrompidas e removidas em todos os ambientes. Isso não pode ser desfeito.",
- "settings.deleteConfirmTitle": "Excluir implantação",
- "settings.deleteFailed": "Falha ao excluir a implantação.",
- "settings.deleted": "Implantação excluída",
- "settings.description": "Descrição",
- "settings.name": "Nome da implantação",
- "settings.save": "Salvar alterações",
- "settings.updateFailed": "Falha ao atualizar a implantação.",
- "settings.updated": "Implantação atualizada",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Implantando",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronização pendente",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Falha na implantação",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Inválido",
"status.RUNTIME_INSTANCE_STATUS_READY": "Em execução",
@@ -370,87 +89,6 @@
"studio.versionValue": "Valor da versão",
"studio.versionsBehind_one": "{{count}} versão atrás",
"studio.versionsBehind_other": "{{count}} versões atrás",
- "tabs.access.description": "Gerencie canais de acesso e permissões de acesso.",
- "tabs.access.name": "Acesso",
- "tabs.api-tokens.description": "Gerencie Tokens de API e invoque instâncias por HTTP.",
- "tabs.api-tokens.name": "Tokens de API",
- "tabs.instances.description": "Veja e gerencie instâncias em ambientes implantados.",
- "tabs.instances.name": "Instâncias",
- "tabs.overview.description": "Veja o status da implantação em todos os ambientes.",
- "tabs.overview.name": "Visão geral",
- "tabs.releases.description": "Crie, implante e gerencie versões.",
- "tabs.releases.name": "Versões",
- "unsupportedDslNodes.description": "Esta versão contém nós que o runtime de implantação ainda não suporta. Remova-os ou substitua-os no Studio e tente novamente.",
- "unsupportedDslNodes.descriptionWithTypes": "Esta versão contém nós que o runtime de implantação ainda não suporta: {{nodeTypes}}. Remova-os ou substitua-os no Studio e tente novamente.",
- "unsupportedDslNodes.title": "Nós não suportados",
- "unsupportedDslNodes.unknownType": "Tipo desconhecido",
- "versions.cancelCreate": "Cancelar",
- "versions.cancelDelete": "Cancelar",
- "versions.cancelEdit": "Cancelar",
"versions.checkingReleaseContent": "Verificando o conteúdo da versão...",
- "versions.col.action": "Ação",
- "versions.col.author": "Criado por",
- "versions.col.createdAt": "Criado em",
- "versions.col.deployedTo": "Implantado em",
- "versions.col.release": "Versão",
- "versions.col.sourceApp": "Origem",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Criar",
- "versions.createFailed": "Falha ao criar a versão.",
- "versions.createRelease": "Criar versão",
- "versions.createReleaseDescription": "Crie uma versão implantável a partir de um Workflow App ou de um arquivo DSL de Workflow.",
- "versions.createSuccess": "Versão \"{{name}}\" criada.",
- "versions.creating": "Criando...",
- "versions.currentOn": "Versão atual em {{name}}",
- "versions.deleteConfirmDesc": "A versão \"{{name}}\" será excluída permanentemente. Isso não pode ser desfeito.",
- "versions.deleteConfirmTitle": "Excluir versão?",
- "versions.deleteFailed": "Falha ao excluir a versão.",
- "versions.deleteRelease": "Excluir versão",
- "versions.deleteSuccess": "Versão \"{{name}}\" excluída.",
- "versions.deployTo": "Implantar em {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Implantando",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronização pendente",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Falhou",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Inválido",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Em execução",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Não implantado",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Desimplantando",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Desconhecido",
- "versions.deployingTo": "{{name}} está implantando",
- "versions.disabledReason.checkDeploymentsFailed": "Não foi possível verificar o uso da implantação. Tente novamente mais tarde.",
- "versions.disabledReason.checkingDeployments": "Verificando uso da implantação",
- "versions.disabledReason.current": "Esta versão já está em execução em {{name}}",
- "versions.disabledReason.deploying": "Aguarde a conclusão da implantação ativa",
- "versions.disabledReason.releaseInUse_one": "Desimplante esta versão de {{count}} ambiente antes de excluí-la",
- "versions.disabledReason.releaseInUse_other": "Desimplante esta versão de {{count}} ambientes antes de excluí-la",
- "versions.dslReadFailed": "Falha ao ler o arquivo DSL. Escolha outro arquivo e tente novamente.",
- "versions.dslReading": "Lendo arquivo DSL...",
- "versions.dslUnsupportedMode": "Apenas arquivos DSL de Workflow podem ser usados para implantações.",
- "versions.editFailed": "Falha ao atualizar a versão.",
- "versions.editRelease": "Editar versão",
- "versions.editReleaseDescription": "Atualize o nome e a descrição desta versão.",
- "versions.editSuccess": "Versão \"{{name}}\" atualizada.",
- "versions.emptyDescription": "Crie a primeira versão antes de implantar em um ambiente.",
- "versions.emptyTitle": "Nenhuma versão ainda",
- "versions.exportDsl": "Exportar DSL",
- "versions.exportDslFailed": "Falha ao exportar DSL.",
- "versions.exportingDsl": "Exportando...",
- "versions.groupHeader.deploy": "Implantar",
- "versions.groupHeader.rollback": "Implantar versão anterior",
- "versions.groupHeader.unavailable": "Indisponível",
- "versions.manualDslOption": "Carregar DSL",
- "versions.moreActions": "Mais ações",
- "versions.optional": "Opcional",
- "versions.releaseAlreadyExists": "Já existe uma versão com o mesmo conteúdo: {{name}}.",
- "versions.releaseContentCheckFailed": "Falha ao verificar o conteúdo da versão.",
- "versions.releaseDescriptionLabel": "Descrição",
- "versions.releaseDescriptionPlaceholder": "Descreva esta versão",
- "versions.releaseNameConflict": "Já existe uma versão com este nome. Escolha outro nome.",
- "versions.releaseNameLabel": "Nome da versão",
- "versions.releaseNamePlaceholder": "Nome da versão",
- "versions.releaseNameRequired": "Insira um nome de versão.",
- "versions.releaseSourceLabel": "Origem da versão",
- "versions.rollbackTo": "Implantar em {{name}}",
- "versions.saveEdit": "Salvar",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "Implantar em {{name}}"
}
diff --git a/web/i18n/ro-RO/common.json b/web/i18n/ro-RO/common.json
index e63da3fa2c8..73143b2c3df 100644
--- a/web/i18n/ro-RO/common.json
+++ b/web/i18n/ro-RO/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Detalii aplicație",
"menus.apps": "Studio",
"menus.datasets": "Cunoștințe",
- "menus.deployments": "Implementări",
"menus.exploreMarketplace": "Explorați Marketplace",
"menus.plugins": "Integrare-uri",
"menus.status": "beta",
diff --git a/web/i18n/ro-RO/deployments.json b/web/i18n/ro-RO/deployments.json
index 761887f85d4..7386c900f4a 100644
--- a/web/i18n/ro-RO/deployments.json
+++ b/web/i18n/ro-RO/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Copiază exemplu cURL",
- "access.api.createFailed": "Generarea API Token a eșuat.",
- "access.api.createKey": "Generează API Token",
- "access.api.createKeyTitle": "Generează un nou API Token",
- "access.api.curlExampleTitle": "Exemplu cURL",
- "access.api.description": "Accesează această implementare prin HTTP. Fiecare API Token este limitat la un singur mediu.",
- "access.api.developerTitle": "API dezvoltator",
- "access.api.disabled": "Accesul API este dezactivat pentru această implementare.",
- "access.api.disabledHint": "Activează accesul API pentru a genera token-uri limitate la mediu.",
- "access.api.docs": "Documentație API",
- "access.api.docsClose": "Închide documentația API",
- "access.api.docsDescription": "Vezi referința API Workflow pentru această implementare.",
- "access.api.docsTitle": "Documentație API Workflow",
- "access.api.empty": "Implementează într-un mediu mai întâi pentru a începe să emiți API Token-uri.",
- "access.api.emptyTitle": "Niciun mediu implementat",
- "access.api.endpoint": "URL cerere",
- "access.api.keyList": "Lista API Token",
- "access.api.nameLabel": "Nume API Token",
- "access.api.namePlaceholder": "Introdu un nume pentru API Token",
- "access.api.nameRequired": "Numele API Token este obligatoriu.",
- "access.api.newKey": "Generează un nou API Token",
- "access.api.newTokenDescription": "Acest API Token este afișat o singură dată. Copiază-l înainte de a părăsi această pagină.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token generat",
- "access.api.noKeys": "Niciun API Token încă. Generează unul pentru a începe să apelezi API-ul.",
- "access.api.noKeysTitle": "Niciun API Token încă",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" va înceta să funcționeze imediat. Această acțiune nu poate fi anulată.",
- "access.api.revokeConfirmTitle": "Revoci API Token?",
- "access.api.revokeFailed": "Revocarea API Token a eșuat.",
- "access.api.revokeSuccess": "API Token revocat",
- "access.api.table.action": "Acțiune",
- "access.api.table.environment": "Mediu",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Nume",
- "access.channels.disabled": "Canalele de acces sunt dezactivate pentru această implementare.",
- "access.channels.disabledHint": "Activează canalele de acces pentru a expune punctele de intrare WebApp și CLI.",
- "access.channels.title": "Canale de acces",
- "access.cli.description": "Apelează din terminal cu difyctl, potrivit pentru scripturi, fluxuri automate sau integrări Agent.",
- "access.cli.docs": "Ghid de utilizare",
- "access.cli.domain": "Domeniu",
- "access.cli.empty": "Endpoint CLI neconfigurat.",
- "access.cli.install": "Instalează CLI",
- "access.cli.title": "CLI",
- "access.copy": "Copiază",
- "access.copyFailed": "Copiere eșuată",
- "access.members.groupCount_one": "{{count}} grup",
- "access.members.groupCount_other": "{{count}} grupuri",
- "access.members.memberCount_one": "{{count}} membru",
- "access.members.memberCount_other": "{{count}} membri",
- "access.permission.anyone": "Oricine cu linkul",
- "access.permission.organization": "Toți membrii din cadrul platformei",
- "access.permission.specific": "Membri specifici din cadrul platformei",
- "access.permission.specificDesc": "Selectează grupuri sau membri specifici",
- "access.permission.updateFailed": "Actualizarea politicii de acces a eșuat.",
- "access.permissions.editAriaLabel": "Configurează accesul pentru {{environment}}",
- "access.permissions.editDescription": "Setează permisiunile de acces pentru punctele de intrare WebApp și CLI.",
- "access.permissions.editTitle": "Permisiuni de acces",
- "access.permissions.title": "Permisiuni de acces",
- "access.revoke": "Revocă",
- "access.runAccess.noEnvs": "Implementează într-un mediu pentru a configura permisiunile de acces.",
- "access.runAccess.noEnvsTitle": "Niciun mediu implementat",
- "access.runAccess.openWebapp": "Deschide WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Pagină web găzduită pentru utilizatorii finali.",
- "access.runAccess.webappEmpty": "În curând.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Extern",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Necunoscut",
- "card.access.api": "API Token-uri",
- "card.access.cli": "CLI",
- "card.access.none": "Fără acces",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Creează prima versiune",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Șterge implementarea",
- "card.menu.deploy": "Implementează în mediu",
- "card.menu.editInfo": "Editează informațiile",
- "card.moreActions": "Mai multe acțiuni",
- "card.noDescription": "Nu a fost furnizată nicio descriere.",
"card.notDeployed": "Neimplementat",
- "card.tooltip.createdAt": "Creat",
- "card.tooltip.deployed": "Implementat",
- "card.tooltip.deploymentStatus": "Implementare",
- "card.tooltip.notDeployedShort": "Neimplementat",
- "card.tooltip.releaseName": "Nume versiune",
- "card.tooltip.source": "Sursă",
"common.loadFailed": "Încărcare eșuată. Încearcă din nou mai târziu.",
- "createGuide.actions.back": "Înapoi",
- "createGuide.actions.createAndDeploy": "Creează și implementează",
- "createGuide.actions.creating": "Se creează...",
- "createGuide.actions.deploying": "Se creează și se implementează...",
- "createGuide.actions.next": "Următorul",
- "createGuide.actions.skipDeploy": "Omite, implementează mai târziu",
- "createGuide.dsl.defaultAppName": "Aplicație DSL importată",
- "createGuide.dsl.description": "Încarcă un pachet DSL Workflow pentru a crea implementarea, prima versiune și implementarea opțională în mediu.",
- "createGuide.dsl.dropDescription": "Încarcă un pachet DSL Workflow YAML. Opțiunile de implementare sunt rezolvate din acest fișier înainte de implementare.",
- "createGuide.dsl.dropTitle": "Încarcă pachetul DSL Workflow",
- "createGuide.dsl.readFailed": "Citirea fișierului DSL a eșuat. Alege alt fișier și încearcă din nou.",
- "createGuide.dsl.reading": "Se citește fișierul DSL...",
- "createGuide.dsl.title": "Importă DSL",
- "createGuide.dsl.unsupportedMode": "Doar fișierele DSL Workflow pot fi utilizate pentru implementări.",
- "createGuide.errors.createReleaseFailed": "Crearea implementării sau a versiunii a eșuat.",
- "createGuide.errors.deployFailed": "Implementarea în mediu a eșuat.",
- "createGuide.method.description": "Alege sursa folosită pentru a crea prima versiune.",
- "createGuide.methods.bindApp.description": "Folosește o aplicație Workflow existentă din Studio ca sursă pentru versiune.",
- "createGuide.methods.bindApp.title": "Asociază aplicația Workflow existentă",
- "createGuide.methods.importDsl.description": "Încarcă un pachet DSL Workflow YAML și continuă prin interfața de implementare.",
- "createGuide.methods.importDsl.title": "Importă DSL",
- "createGuide.nav.back": "Implementări",
- "createGuide.release.defaultName": "versiune inițială",
- "createGuide.release.deployInfo": "Informații implementare",
- "createGuide.release.description": "Completează informațiile implementării și detaliile primei versiuni.",
- "createGuide.release.firstVersion": "Prima versiune",
- "createGuide.release.instanceDescription": "Descriere implementare",
- "createGuide.release.instanceDescriptionPlaceholder": "Descrie pentru ce este folosită această implementare",
- "createGuide.release.instanceName": "Nume implementare",
- "createGuide.release.instanceNameConflict": "O implementare cu acest nume există deja. Alege un alt nume.",
- "createGuide.release.releaseDescription": "Descriere versiune",
- "createGuide.release.releaseDescriptionPlaceholder": "Descrie această versiune",
- "createGuide.release.releaseName": "Nume versiune",
- "createGuide.release.title": "Informații de bază",
- "createGuide.source.clearSearch": "Șterge căutarea aplicațiilor",
- "createGuide.source.description": "Alege sursa folosită pentru a crea prima versiune.",
- "createGuide.source.empty": "Nu s-au găsit aplicații Workflow.",
- "createGuide.source.searchPlaceholder": "Caută aplicații",
- "createGuide.source.sourceApp": "Aplicație Workflow",
- "createGuide.source.title": "Sursă versiune",
- "createGuide.steps.method": "Sursă versiune",
- "createGuide.steps.release": "Informații de bază",
- "createGuide.steps.source": "Sursă versiune",
- "createGuide.steps.target": "Implementează în mediu",
- "createGuide.target.bindingCount_one": "{{count}} asociere",
- "createGuide.target.bindingCount_other": "{{count}} asocieri",
- "createGuide.target.bindingHint": "Alege acreditările folosite de această versiune.",
- "createGuide.target.bindings": "Acreditări",
- "createGuide.target.description": "Alege un mediu țintă și furnizează setările de runtime de care această versiune are nevoie acolo. Acest pas poate fi omis.",
- "createGuide.target.envVarCount_one": "{{count}} variabilă",
- "createGuide.target.envVarCount_other": "{{count}} variabile",
- "createGuide.target.envVarHint": "Pentru fiecare variabilă de mediu de care această versiune are nevoie, introdu o valoare personalizată sau folosește valoarea definită în aplicație.",
- "createGuide.target.envVarPlaceholder": "Introdu valoare",
- "createGuide.target.envVarSource.ariaLabel": "Selectează sursa valorii variabilei pentru {{key}}",
- "createGuide.target.envVarSource.default": "Valoare aplicație",
- "createGuide.target.envVarSource.lastDeployment": "Valoare ultimă implementare",
- "createGuide.target.envVarSource.literal": "Valoare personalizată",
- "createGuide.target.envVarType.number": "Număr",
- "createGuide.target.envVarType.secret": "Secret",
- "createGuide.target.envVarType.string": "Șir",
- "createGuide.target.envVars": "Variabile de mediu",
- "createGuide.target.environment": "Mediu țintă",
- "createGuide.target.loadBindingsFailed": "Încărcarea acreditărilor a eșuat.",
- "createGuide.target.loadEnvironmentsFailed": "Încărcarea mediilor de implementare a eșuat.",
- "createGuide.target.missingRequiredBinding": "Selectează o acreditare pentru această asociere obligatorie.",
- "createGuide.target.noBindingRequired": "Nicio acreditare necesară.",
- "createGuide.target.noCredentialCandidates": "Nicio acreditare disponibilă.",
- "createGuide.target.noEnvironmentOptions": "Niciun mediu de implementare disponibil.",
- "createGuide.target.selectCredential": "Selectează o acreditare",
- "createGuide.target.title": "Implementează în mediu",
- "createGuide.title": "Implementare nouă",
- "createModal.appPickerPlaceholder": "Selectează o aplicație Workflow",
- "createModal.appSearchEmpty": "Nicio aplicație Workflow potrivită",
- "createModal.appSearchPlaceholder": "Caută aplicații Workflow…",
- "createModal.cancel": "Anulează",
- "createModal.loadingApps": "Se încarcă aplicațiile…",
- "deployDrawer.bindingCount_one": "{{count}} asociere",
- "deployDrawer.bindingCount_other": "{{count}} asocieri",
"deployDrawer.bindingOptionsFailed": "Încărcarea opțiunilor de acreditare a eșuat.",
"deployDrawer.bindingSelectionHint": "Alege acreditările folosite de această implementare.",
- "deployDrawer.cancel": "Anulează",
- "deployDrawer.close": "Închide panoul de implementare",
- "deployDrawer.defaultSelect": "Selectează...",
- "deployDrawer.deploy": "Implementează în mediu",
- "deployDrawer.deployFailed": "Pornirea implementării a eșuat.",
"deployDrawer.deploying": "Se implementează...",
- "deployDrawer.description": "Selectează o versiune și un mediu țintă pentru implementare.",
- "deployDrawer.envVarCount_one": "{{count}} variabilă",
- "deployDrawer.envVarCount_other": "{{count}} variabile",
- "deployDrawer.envVarHint": "Pentru fiecare variabilă de mediu de care această versiune are nevoie, introdu o valoare personalizată sau folosește valoarea definită în aplicație.",
- "deployDrawer.envVarPlaceholder": "Introdu valoare",
"deployDrawer.envVarSource.ariaLabel": "Selectează sursa valorii variabilei pentru {{key}}",
- "deployDrawer.envVarSource.default": "Valoare aplicație",
"deployDrawer.envVarSource.lastDeployment": "Valoare ultimă implementare",
"deployDrawer.envVarSource.literal": "Valoare personalizată",
"deployDrawer.envVarType.number": "Număr",
"deployDrawer.envVarType.secret": "Secret",
"deployDrawer.envVarType.string": "Șir",
"deployDrawer.envVars": "Variabile de mediu",
- "deployDrawer.existingReleaseHint": "Această versiune va fi implementată ca atare. Nu va fi creată o versiune nouă.",
- "deployDrawer.lockedHint": "Blocat la mediul curent",
- "deployDrawer.missingRequiredBinding": "Selectează o acreditare pentru această asociere obligatorie.",
- "deployDrawer.missingRequiredEnvVar": "Introdu o valoare pentru această variabilă de mediu obligatorie.",
- "deployDrawer.noBindingRequired": "Nu este obligatoriu",
"deployDrawer.noCredentialCandidates": "Nicio acreditare disponibilă.",
"deployDrawer.noNewEnvironmentAvailable": "Toate mediile disponibile au deja o implementare.",
- "deployDrawer.noOtherReleaseAvailable": "Nu există alte versiuni disponibile pentru acest mediu.",
- "deployDrawer.noReleaseAvailable": "Creează o versiune înainte de a implementa într-un mediu.",
- "deployDrawer.notFound": "Implementarea nu a fost găsită.",
- "deployDrawer.releaseLabel": "Versiune",
"deployDrawer.runtimeCredentials": "Acreditări",
"deployDrawer.selectCredential": "Selectează o acreditare",
- "deployDrawer.selectEnv": "Selectează un mediu",
- "deployDrawer.selectRelease": "Selectează o versiune",
- "deployDrawer.targetEnv": "Mediu țintă",
- "deployDrawer.title": "Implementează în mediu",
- "deployTab.closeError": "Închide",
"deployTab.col.actions": "Acțiuni",
- "deployTab.col.currentRelease": "Versiunea curentă",
"deployTab.col.environment": "Mediu",
"deployTab.col.status": "Stare",
"deployTab.confirmUndeploy": "Anulează implementarea",
- "deployTab.deployOtherVersion": "Implementează altă versiune",
- "deployTab.emptyDescription": "Alege o versiune și un mediu țintă pentru a face această implementare disponibilă utilizatorilor.",
- "deployTab.emptyTitle": "Niciun mediu nu rulează încă",
- "deployTab.errorCode": "Cod",
- "deployTab.errorDialogDesc": "Verifică ultima implementare eșuată înainte de a reîncerca sau de a implementa o altă versiune.",
- "deployTab.errorDialogTitle": "Eroare de implementare în {{name}}",
- "deployTab.errorMessage": "Mesaj",
- "deployTab.errorPhase": "Fază",
"deployTab.moreActions": "Mai multe acțiuni",
- "deployTab.newDeployment": "Implementează într-un mediu nou",
- "deployTab.panel.unknownError": "Implementarea a eșuat.",
"deployTab.redeploy": "Reimplementează",
- "deployTab.retry": "Reîncearcă",
- "deployTab.status.deployFailed": "Implementare eșuată",
- "deployTab.status.deployingRelease": "Se implementează ({{release}})",
- "deployTab.status.runningOutOfSync": "Rulează (sincronizare în așteptare)",
- "deployTab.status.runningWithFailed": "Rulează (ultima implementare a eșuat)",
"deployTab.undeploy": "Anulează implementarea",
- "deployTab.undeployConfirmDesc": "Endpointul mediului va deveni indisponibil, dar versiunea nu va fi ștearsă.",
- "deployTab.undeployConfirmTitle": "Anulezi implementarea {{name}}?",
"deployTab.undeployConfirmWarning": "După confirmare, acest mediu va intra în starea de anulare a implementării, iar acțiunile vor fi dezactivate temporar.",
- "deployTab.viewError": "Vezi eroarea",
- "detail.mobileTabs": "Secțiuni implementare",
- "detail.notFound": "Implementarea nu a fost găsită",
- "documentTitle.create": "Implementare nouă · Implementări",
- "documentTitle.detail": "Implementare · Implementări",
- "documentTitle.list": "Implementări",
- "filter.allEnvs": "Toate mediile",
- "filter.searchPlaceholder": "Caută implementări",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Admitere",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Inițializare",
- "health.ENVIRONMENT_STATUS_DELETING": "Se șterge",
"health.ENVIRONMENT_STATUS_FAILED": "Indisponibil",
- "health.ENVIRONMENT_STATUS_READY": "Disponibil",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Necunoscut",
- "list.clearFilters": "Șterge filtrele",
- "list.clearSearch": "Șterge căutarea implementărilor",
- "list.createDeployment": "Nou",
- "list.emptyDescription": "Creează o implementare dintr-o aplicație Workflow sau dintr-un pachet DSL Workflow pentru a gestiona versiunile, mediile și accesul.",
- "list.emptyFilteredDescription": "Nicio implementare nu corespunde căutării sau filtrului de mediu curent.",
- "list.emptyFilteredTitle": "Nicio implementare corespunzătoare",
"list.emptyTitle": "Nicio implementare încă",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Izolat",
- "mode.ENVIRONMENT_MODE_SHARED": "Partajat",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Necunoscut",
- "overview.accessMeta.apiTokens": "Gestionează API Token-uri",
- "overview.accessMeta.cli": "Vezi accesul CLI",
- "overview.accessMeta.webApp": "Gestionează accesul WebApp",
- "overview.accessStatus": "Acces",
- "overview.api": "API Token-uri",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Token-uri",
- "overview.apiTokenSummary.environments_one": "{{count}} mediu implementat",
- "overview.apiTokenSummary.environments_other": "{{count}} medii implementate",
- "overview.cardAction.deployLatest": "Implementează ultima versiune",
- "overview.cardAction.redeploy": "Reimplementează",
- "overview.cardAction.viewProgress": "Vezi implementarea",
- "overview.chip.behindTooltip_one": "1 versiune în urmă față de cea mai recentă. Implementează ultima versiune pentru a actualiza.",
- "overview.chip.behindTooltip_other": "{{count}} versiuni în urmă față de cea mai recentă. Implementează ultima versiune pentru a actualiza.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "se implementează",
- "overview.chip.deployingTooltip": "Implementarea este în curs.",
- "overview.chip.empty": "gol",
- "overview.chip.emptyTooltip": "Nicio versiune nu este implementată în acest mediu.",
- "overview.chip.failed": "eșuat",
- "overview.chip.failedTooltip": "Ultima încercare de implementare a eșuat.",
"overview.chip.latest": "cea mai recentă",
- "overview.chip.latestTooltip": "Acest mediu rulează cea mai recentă versiune.",
- "overview.chip.needsReleaseFirst": "Creează mai întâi o versiune",
- "overview.chip.olderRelease": "mai veche",
- "overview.chip.olderReleaseTooltip": "Acest mediu rulează o versiune mai veche.",
- "overview.chip.openInDeployTab": "Vezi progresul implementării",
- "overview.disabled": "Dezactivat",
- "overview.enabled": "Activat",
- "overview.hero.byName": "de {{name}}",
- "overview.hero.empty": "Nicio versiune încă",
- "overview.hero.emptyDescription": "Creează o versiune din sursa curentă înainte de implementare.",
- "overview.latestRelease.releaseCount_one": "{{count}} versiune",
- "overview.latestRelease.releaseCount_other": "{{count}} versiuni",
- "overview.latestReleaseTitle": "Ultima versiune",
- "overview.previousReleases.viewAll": "Vezi toate",
- "overview.strip.deployToNewEnvironment": "Implementează în mediu nou",
- "overview.strip.emptyDeployableDescription": "Implementează ultima versiune într-un mediu când ești gata.",
- "overview.strip.emptyDescription": "Creează o versiune înainte de a implementa într-un mediu.",
- "overview.strip.emptyTitle": "Nicio instanță încă",
- "overview.strip.title": "Instanțe",
- "settings.delete": "Șterge implementarea",
- "settings.deleteConfirmDesc": "Ștergi {{name}}? Fiecare instanță va înceta să ruleze și va fi eliminată din toate mediile. Această acțiune nu poate fi anulată.",
- "settings.deleteConfirmTitle": "Șterge implementarea",
- "settings.deleteFailed": "Ștergerea implementării a eșuat.",
- "settings.deleted": "Implementare ștearsă",
- "settings.description": "Descriere",
- "settings.name": "Nume implementare",
- "settings.save": "Salvează modificările",
- "settings.updateFailed": "Actualizarea implementării a eșuat.",
- "settings.updated": "Implementare actualizată",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Se implementează",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronizare în așteptare",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Implementare eșuată",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Invalid",
"status.RUNTIME_INSTANCE_STATUS_READY": "Rulează",
@@ -370,87 +89,6 @@
"studio.versionValue": "Valoarea versiunii",
"studio.versionsBehind_one": "{{count}} versiune în urmă",
"studio.versionsBehind_other": "{{count}} versiuni în urmă",
- "tabs.access.description": "Gestionează canalele de acces și permisiunile de acces.",
- "tabs.access.name": "Acces",
- "tabs.api-tokens.description": "Gestionează API Token-urile și apelează instanțele prin HTTP.",
- "tabs.api-tokens.name": "API Token-uri",
- "tabs.instances.description": "Vezi și gestionează instanțele din mediile implementate.",
- "tabs.instances.name": "Instanțe",
- "tabs.overview.description": "Vezi starea implementării între medii.",
- "tabs.overview.name": "Prezentare generală",
- "tabs.releases.description": "Creează, implementează și gestionează versiuni.",
- "tabs.releases.name": "Versiuni",
- "unsupportedDslNodes.description": "Această versiune conține noduri pe care runtime-ul de implementare nu le suportă încă. Elimină-le sau înlocuiește-le în Studio, apoi încearcă din nou.",
- "unsupportedDslNodes.descriptionWithTypes": "Această versiune conține noduri pe care runtime-ul de implementare nu le suportă încă: {{nodeTypes}}. Elimină-le sau înlocuiește-le în Studio, apoi încearcă din nou.",
- "unsupportedDslNodes.title": "Noduri nesuportate",
- "unsupportedDslNodes.unknownType": "Tip necunoscut",
- "versions.cancelCreate": "Anulează",
- "versions.cancelDelete": "Anulează",
- "versions.cancelEdit": "Anulează",
"versions.checkingReleaseContent": "Se verifică conținutul versiunii...",
- "versions.col.action": "Acțiune",
- "versions.col.author": "Creat de",
- "versions.col.createdAt": "Creat la",
- "versions.col.deployedTo": "Implementat în",
- "versions.col.release": "Versiune",
- "versions.col.sourceApp": "Sursă",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Creează",
- "versions.createFailed": "Crearea versiunii a eșuat.",
- "versions.createRelease": "Creează versiune",
- "versions.createReleaseDescription": "Creează o versiune implementabilă dintr-o aplicație Workflow sau dintr-un fișier DSL Workflow.",
- "versions.createSuccess": "Versiunea \"{{name}}\" a fost creată.",
- "versions.creating": "Se creează...",
- "versions.currentOn": "Versiunea curentă pe {{name}}",
- "versions.deleteConfirmDesc": "Versiunea \"{{name}}\" va fi ștearsă definitiv. Această acțiune nu poate fi anulată.",
- "versions.deleteConfirmTitle": "Ștergi versiunea?",
- "versions.deleteFailed": "Ștergerea versiunii a eșuat.",
- "versions.deleteRelease": "Șterge versiunea",
- "versions.deleteSuccess": "Versiunea \"{{name}}\" a fost ștearsă.",
- "versions.deployTo": "Implementează în {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Se implementează",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sincronizare în așteptare",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Eșuat",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Invalid",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Rulează",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Neimplementat",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Se anulează implementarea",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Necunoscut",
- "versions.deployingTo": "{{name}} se implementează",
- "versions.disabledReason.checkDeploymentsFailed": "Verificarea utilizării implementării nu a reușit. Încearcă din nou mai târziu.",
- "versions.disabledReason.checkingDeployments": "Se verifică utilizarea implementării",
- "versions.disabledReason.current": "Această versiune rulează deja pe {{name}}",
- "versions.disabledReason.deploying": "Așteaptă finalizarea implementării active",
- "versions.disabledReason.releaseInUse_one": "Anulează implementarea acestei versiuni din {{count}} mediu înainte de a o șterge",
- "versions.disabledReason.releaseInUse_other": "Anulează implementarea acestei versiuni din {{count}} medii înainte de a o șterge",
- "versions.dslReadFailed": "Citirea fișierului DSL a eșuat. Alege alt fișier și încearcă din nou.",
- "versions.dslReading": "Se citește fișierul DSL...",
- "versions.dslUnsupportedMode": "Doar fișierele DSL Workflow pot fi utilizate pentru implementări.",
- "versions.editFailed": "Actualizarea versiunii a eșuat.",
- "versions.editRelease": "Editează versiunea",
- "versions.editReleaseDescription": "Actualizează numele și descrierea acestei versiuni.",
- "versions.editSuccess": "Versiunea \"{{name}}\" a fost actualizată.",
- "versions.emptyDescription": "Creează prima versiune înainte de a implementa într-un mediu.",
- "versions.emptyTitle": "Nicio versiune încă",
- "versions.exportDsl": "Exportă DSL",
- "versions.exportDslFailed": "Exportul DSL a eșuat.",
- "versions.exportingDsl": "Se exportă...",
- "versions.groupHeader.deploy": "Implementează",
- "versions.groupHeader.rollback": "Implementează versiunea anterioară",
- "versions.groupHeader.unavailable": "Indisponibil",
- "versions.manualDslOption": "Încarcă DSL",
- "versions.moreActions": "Mai multe acțiuni",
- "versions.optional": "Opțional",
- "versions.releaseAlreadyExists": "O versiune cu același conținut există deja: {{name}}.",
- "versions.releaseContentCheckFailed": "Verificarea conținutului versiunii a eșuat.",
- "versions.releaseDescriptionLabel": "Descriere",
- "versions.releaseDescriptionPlaceholder": "Descrie această versiune",
- "versions.releaseNameConflict": "Există deja o versiune cu acest nume. Alege alt nume.",
- "versions.releaseNameLabel": "Nume versiune",
- "versions.releaseNamePlaceholder": "Nume versiune",
- "versions.releaseNameRequired": "Introdu un nume pentru versiune.",
- "versions.releaseSourceLabel": "Sursă versiune",
- "versions.rollbackTo": "Implementează în {{name}}",
- "versions.saveEdit": "Salvează",
- "versions.sourceAppOption": "Aplicație Workflow"
+ "versions.deployTo": "Implementează în {{name}}"
}
diff --git a/web/i18n/ru-RU/common.json b/web/i18n/ru-RU/common.json
index 05f36d5ad78..1bb0e6222d3 100644
--- a/web/i18n/ru-RU/common.json
+++ b/web/i18n/ru-RU/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Детали приложения",
"menus.apps": "Студия",
"menus.datasets": "Знания",
- "menus.deployments": "Развертывания",
"menus.exploreMarketplace": "Подробнее о Marketplace",
"menus.plugins": "Интеграции",
"menus.status": "бета",
diff --git a/web/i18n/ru-RU/deployments.json b/web/i18n/ru-RU/deployments.json
index 25ac24f2b37..39ba0b25275 100644
--- a/web/i18n/ru-RU/deployments.json
+++ b/web/i18n/ru-RU/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Скопировать пример cURL",
- "access.api.createFailed": "Не удалось сгенерировать API Token.",
- "access.api.createKey": "Сгенерировать API Token",
- "access.api.createKeyTitle": "Сгенерировать новый API Token",
- "access.api.curlExampleTitle": "Пример cURL",
- "access.api.description": "Доступ к этому развертыванию по HTTP. Каждый API Token действует в рамках одной среды.",
- "access.api.developerTitle": "API для разработчиков",
- "access.api.disabled": "Доступ по API для этого развертывания отключен.",
- "access.api.disabledHint": "Включите доступ по API, чтобы генерировать токены в рамках сред.",
- "access.api.docs": "Документация API",
- "access.api.docsClose": "Закрыть документацию API",
- "access.api.docsDescription": "Просмотрите справочник Workflow API для этого развертывания.",
- "access.api.docsTitle": "Документация Workflow API",
- "access.api.empty": "Сначала разверните в среду, чтобы начать выдавать API Tokens.",
- "access.api.emptyTitle": "Нет развернутых сред",
- "access.api.endpoint": "URL запроса",
- "access.api.keyList": "Список API Tokens",
- "access.api.nameLabel": "Имя API Token",
- "access.api.namePlaceholder": "Введите имя API Token",
- "access.api.nameRequired": "Имя API Token обязательно.",
- "access.api.newKey": "Сгенерировать новый API Token",
- "access.api.newTokenDescription": "Этот API Token отображается только один раз. Скопируйте его перед уходом с этой страницы.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token сгенерирован",
- "access.api.noKeys": "Пока нет API Tokens. Сгенерируйте, чтобы начать вызывать API.",
- "access.api.noKeysTitle": "Пока нет API Tokens",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" немедленно перестанет работать. Это действие нельзя отменить.",
- "access.api.revokeConfirmTitle": "Отозвать API Token?",
- "access.api.revokeFailed": "Не удалось отозвать API Token.",
- "access.api.revokeSuccess": "API Token отозван",
- "access.api.table.action": "Действие",
- "access.api.table.environment": "Среда",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Имя",
- "access.channels.disabled": "Каналы доступа для этого развертывания отключены.",
- "access.channels.disabledHint": "Включите каналы доступа, чтобы открыть точки входа WebApp и CLI.",
- "access.channels.title": "Каналы доступа",
- "access.cli.description": "Вызывайте из терминала с помощью difyctl, подходит для скриптов, автоматизированных Workflow или интеграций с агентом.",
- "access.cli.docs": "Руководство по использованию",
- "access.cli.domain": "Домен",
- "access.cli.empty": "Конечная точка CLI не настроена.",
- "access.cli.install": "Установить CLI",
- "access.cli.title": "CLI",
- "access.copy": "Копировать",
- "access.copyFailed": "Не удалось скопировать",
- "access.members.groupCount_one": "{{count}} группа",
- "access.members.groupCount_other": "{{count}} групп",
- "access.members.memberCount_one": "{{count}} участник",
- "access.members.memberCount_other": "{{count}} участников",
- "access.permission.anyone": "Любой, у кого есть ссылка",
- "access.permission.organization": "Все участники платформы",
- "access.permission.specific": "Определённые участники платформы",
- "access.permission.specificDesc": "Выберите определённые группы или участников",
- "access.permission.updateFailed": "Не удалось обновить политику доступа.",
- "access.permissions.editAriaLabel": "Настроить доступ для {{environment}}",
- "access.permissions.editDescription": "Настройте права доступа для точек входа WebApp и CLI.",
- "access.permissions.editTitle": "Права доступа",
- "access.permissions.title": "Права доступа",
- "access.revoke": "Отозвать",
- "access.runAccess.noEnvs": "Разверните в среду, чтобы настроить права доступа.",
- "access.runAccess.noEnvsTitle": "Нет развернутых сред",
- "access.runAccess.openWebapp": "Открыть WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Размещенная веб-страница для конечных пользователей.",
- "access.runAccess.webappEmpty": "Скоро будет доступно.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Внешний",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Неизвестно",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Нет доступа",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Создать первый Релиз",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Удалить развертывание",
- "card.menu.deploy": "Развернуть в Среду",
- "card.menu.editInfo": "Изменить информацию",
- "card.moreActions": "Дополнительные действия",
- "card.noDescription": "Описание не указано.",
"card.notDeployed": "Не развернуто",
- "card.tooltip.createdAt": "Создано",
- "card.tooltip.deployed": "Развернуто",
- "card.tooltip.deploymentStatus": "Развертывание",
- "card.tooltip.notDeployedShort": "Не развернуто",
- "card.tooltip.releaseName": "Имя Релиза",
- "card.tooltip.source": "Источник",
"common.loadFailed": "Не удалось загрузить. Повторите попытку позже.",
- "createGuide.actions.back": "Назад",
- "createGuide.actions.createAndDeploy": "Создать и развернуть",
- "createGuide.actions.creating": "Создание...",
- "createGuide.actions.deploying": "Создание и развертывание...",
- "createGuide.actions.next": "Далее",
- "createGuide.actions.skipDeploy": "Пропустить, развернуть позже",
- "createGuide.dsl.defaultAppName": "Импортированное DSL-приложение",
- "createGuide.dsl.description": "Загрузите пакет Workflow DSL, чтобы создать развертывание, первый Релиз и опциональное развертывание в Среду.",
- "createGuide.dsl.dropDescription": "Загрузите пакет Workflow YAML DSL. Параметры развертывания будут определены из этого файла перед развертыванием.",
- "createGuide.dsl.dropTitle": "Загрузить пакет Workflow DSL",
- "createGuide.dsl.readFailed": "Не удалось прочитать файл DSL. Выберите другой файл и попробуйте снова.",
- "createGuide.dsl.reading": "Чтение файла DSL...",
- "createGuide.dsl.title": "Импорт DSL",
- "createGuide.dsl.unsupportedMode": "Для развертываний можно использовать только файлы Workflow DSL.",
- "createGuide.errors.createReleaseFailed": "Не удалось создать развертывание или Релиз.",
- "createGuide.errors.deployFailed": "Не удалось выполнить развертывание в Среду.",
- "createGuide.method.description": "Выберите источник для создания первого Релиза.",
- "createGuide.methods.bindApp.description": "Используйте существующее Workflow-приложение из Studio как источник Релиза.",
- "createGuide.methods.bindApp.title": "Привязать существующее Workflow-приложение",
- "createGuide.methods.importDsl.description": "Загрузите пакет Workflow YAML DSL и продолжите через UI развертывания.",
- "createGuide.methods.importDsl.title": "Импорт DSL",
- "createGuide.nav.back": "Развертывания",
- "createGuide.release.defaultName": "первоначальный релиз",
- "createGuide.release.deployInfo": "Информация о развертывании",
- "createGuide.release.description": "Заполните информацию о развертывании и детали первого Релиза.",
- "createGuide.release.firstVersion": "Первый Релиз",
- "createGuide.release.instanceDescription": "Описание развертывания",
- "createGuide.release.instanceDescriptionPlaceholder": "Опишите, для чего используется это развертывание",
- "createGuide.release.instanceName": "Имя развертывания",
- "createGuide.release.instanceNameConflict": "Развертывание с таким именем уже существует. Выберите другое имя.",
- "createGuide.release.releaseDescription": "Описание Релиза",
- "createGuide.release.releaseDescriptionPlaceholder": "Опишите этот Релиз",
- "createGuide.release.releaseName": "Имя Релиза",
- "createGuide.release.title": "Базовая информация",
- "createGuide.source.clearSearch": "Очистить поиск приложений",
- "createGuide.source.description": "Выберите источник для создания первого Релиза.",
- "createGuide.source.empty": "Workflow-приложения не найдены.",
- "createGuide.source.searchPlaceholder": "Поиск приложений",
- "createGuide.source.sourceApp": "Workflow-приложение",
- "createGuide.source.title": "Источник Релиза",
- "createGuide.steps.method": "Источник Релиза",
- "createGuide.steps.release": "Базовая информация",
- "createGuide.steps.source": "Источник Релиза",
- "createGuide.steps.target": "Развернуть в Среду",
- "createGuide.target.bindingCount_one": "{{count}} привязка",
- "createGuide.target.bindingCount_other": "{{count}} привязок",
- "createGuide.target.bindingHint": "Выберите Учётные данные, используемые этим Релизом.",
- "createGuide.target.bindings": "Учётные данные",
- "createGuide.target.description": "Выберите целевую Среду и укажите runtime-настройки, нужные этому Релизу. Этот шаг можно пропустить.",
- "createGuide.target.envVarCount_one": "{{count}} переменная",
- "createGuide.target.envVarCount_other": "{{count}} переменных",
- "createGuide.target.envVarHint": "Для каждой переменной окружения, необходимой этому Релизу, введите пользовательское значение или используйте значение, заданное в приложении.",
- "createGuide.target.envVarPlaceholder": "Введите значение",
- "createGuide.target.envVarSource.ariaLabel": "Выберите источник значения переменной для {{key}}",
- "createGuide.target.envVarSource.default": "Значение приложения",
- "createGuide.target.envVarSource.lastDeployment": "Последнее развернутое значение",
- "createGuide.target.envVarSource.literal": "Пользовательское значение",
- "createGuide.target.envVarType.number": "Число",
- "createGuide.target.envVarType.secret": "Секрет",
- "createGuide.target.envVarType.string": "Строка",
- "createGuide.target.envVars": "Переменные окружения",
- "createGuide.target.environment": "Целевая Среда",
- "createGuide.target.loadBindingsFailed": "Не удалось загрузить Учётные данные.",
- "createGuide.target.loadEnvironmentsFailed": "Не удалось загрузить Среды для развертывания.",
- "createGuide.target.missingRequiredBinding": "Выберите Учётные данные для этой обязательной привязки.",
- "createGuide.target.noBindingRequired": "Учётные данные не требуются.",
- "createGuide.target.noCredentialCandidates": "Нет доступных Учётных данных.",
- "createGuide.target.noEnvironmentOptions": "Нет доступных Сред для развертывания.",
- "createGuide.target.selectCredential": "Выберите Учётные данные",
- "createGuide.target.title": "Развернуть в Среду",
- "createGuide.title": "Новое развертывание",
- "createModal.appPickerPlaceholder": "Выберите Workflow-приложение",
- "createModal.appSearchEmpty": "Нет подходящих Workflow-приложений",
- "createModal.appSearchPlaceholder": "Поиск Workflow-приложений…",
- "createModal.cancel": "Отмена",
- "createModal.loadingApps": "Загрузка приложений…",
- "deployDrawer.bindingCount_one": "{{count}} привязка",
- "deployDrawer.bindingCount_other": "{{count}} привязок",
"deployDrawer.bindingOptionsFailed": "Не удалось загрузить варианты Учётных данных.",
"deployDrawer.bindingSelectionHint": "Выберите Учётные данные, используемые этим развертыванием.",
- "deployDrawer.cancel": "Отмена",
- "deployDrawer.close": "Закрыть панель развертывания",
- "deployDrawer.defaultSelect": "Выберите...",
- "deployDrawer.deploy": "Развернуть в Среду",
- "deployDrawer.deployFailed": "Не удалось запустить развертывание.",
"deployDrawer.deploying": "Развертывание...",
- "deployDrawer.description": "Выберите Релиз и целевую Среду для развертывания.",
- "deployDrawer.envVarCount_one": "{{count}} переменная",
- "deployDrawer.envVarCount_other": "{{count}} переменных",
- "deployDrawer.envVarHint": "Для каждой переменной окружения, необходимой этому Релизу, введите пользовательское значение или используйте значение, заданное в приложении.",
- "deployDrawer.envVarPlaceholder": "Введите значение",
"deployDrawer.envVarSource.ariaLabel": "Выберите источник значения переменной для {{key}}",
- "deployDrawer.envVarSource.default": "Значение приложения",
"deployDrawer.envVarSource.lastDeployment": "Последнее развернутое значение",
"deployDrawer.envVarSource.literal": "Пользовательское значение",
"deployDrawer.envVarType.number": "Число",
"deployDrawer.envVarType.secret": "Секрет",
"deployDrawer.envVarType.string": "Строка",
"deployDrawer.envVars": "Переменные окружения",
- "deployDrawer.existingReleaseHint": "Этот Релиз будет развернут как есть. Новый Релиз создан не будет.",
- "deployDrawer.lockedHint": "Зафиксировано в текущей Среде",
- "deployDrawer.missingRequiredBinding": "Выберите Учётные данные для этой обязательной привязки.",
- "deployDrawer.missingRequiredEnvVar": "Введите значение для этой обязательной переменной окружения.",
- "deployDrawer.noBindingRequired": "Не требуется",
"deployDrawer.noCredentialCandidates": "Нет доступных Учётных данных.",
"deployDrawer.noNewEnvironmentAvailable": "Во всех доступных Средах уже есть развертывание.",
- "deployDrawer.noOtherReleaseAvailable": "Других Релизов для этой Среды нет.",
- "deployDrawer.noReleaseAvailable": "Создайте Релиз перед развертыванием в Среду.",
- "deployDrawer.notFound": "Развертывание не найдено.",
- "deployDrawer.releaseLabel": "Релиз",
"deployDrawer.runtimeCredentials": "Учётные данные",
"deployDrawer.selectCredential": "Выберите Учётные данные",
- "deployDrawer.selectEnv": "Выберите Среду",
- "deployDrawer.selectRelease": "Выберите Релиз",
- "deployDrawer.targetEnv": "Целевая Среда",
- "deployDrawer.title": "Развернуть в Среду",
- "deployTab.closeError": "Закрыть",
"deployTab.col.actions": "Действия",
- "deployTab.col.currentRelease": "Текущий Релиз",
"deployTab.col.environment": "Среда",
"deployTab.col.status": "Статус",
"deployTab.confirmUndeploy": "Свернуть развертывание",
- "deployTab.deployOtherVersion": "Развернуть другой Релиз",
- "deployTab.emptyDescription": "Выберите Релиз и целевую Среду, чтобы сделать это развертывание доступным пользователям.",
- "deployTab.emptyTitle": "Запущенных Сред пока нет",
- "deployTab.errorCode": "Код",
- "deployTab.errorDialogDesc": "Просмотрите последнее неудачное развертывание перед повторной попыткой или развертыванием другого Релиза.",
- "deployTab.errorDialogTitle": "Ошибка развертывания в {{name}}",
- "deployTab.errorMessage": "Сообщение",
- "deployTab.errorPhase": "Фаза",
"deployTab.moreActions": "Дополнительные действия",
- "deployTab.newDeployment": "Развернуть в новую Среду",
- "deployTab.panel.unknownError": "Развертывание не удалось.",
"deployTab.redeploy": "Повторно развернуть",
- "deployTab.retry": "Повторить",
- "deployTab.status.deployFailed": "Ошибка развертывания",
- "deployTab.status.deployingRelease": "Развертывание ({{release}})",
- "deployTab.status.runningOutOfSync": "Запущено (ожидается синхронизация)",
- "deployTab.status.runningWithFailed": "Запущено (последнее развертывание не удалось)",
"deployTab.undeploy": "Свернуть развертывание",
- "deployTab.undeployConfirmDesc": "Конечная точка среды станет недоступна, но версия не будет удалена.",
- "deployTab.undeployConfirmTitle": "Отменить развертывание {{name}}?",
"deployTab.undeployConfirmWarning": "После подтверждения эта среда перейдет в состояние отмены развертывания, а действия будут временно недоступны.",
- "deployTab.viewError": "Просмотр ошибки",
- "detail.mobileTabs": "Разделы развертывания",
- "detail.notFound": "Развертывание не найдено",
- "documentTitle.create": "Новое развертывание · Развертывания",
- "documentTitle.detail": "Развертывание · Развертывания",
- "documentTitle.list": "Развертывания",
- "filter.allEnvs": "Все Среды",
- "filter.searchPlaceholder": "Поиск развертываний",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Допуск",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Загрузка",
- "health.ENVIRONMENT_STATUS_DELETING": "Удаление",
"health.ENVIRONMENT_STATUS_FAILED": "Недоступно",
- "health.ENVIRONMENT_STATUS_READY": "Доступно",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Неизвестно",
- "list.clearFilters": "Очистить фильтры",
- "list.clearSearch": "Очистить поиск развертываний",
- "list.createDeployment": "Создать",
- "list.emptyDescription": "Создайте развертывание из Workflow-приложения или пакета Workflow DSL для управления Релизами, Средами и доступом.",
- "list.emptyFilteredDescription": "Ни одно развертывание не соответствует текущему поиску или фильтру Среды.",
- "list.emptyFilteredTitle": "Нет подходящих развертываний",
"list.emptyTitle": "Пока нет развертываний",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Изолированная",
- "mode.ENVIRONMENT_MODE_SHARED": "Общая",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Неизвестно",
- "overview.accessMeta.apiTokens": "Управление API Tokens",
- "overview.accessMeta.cli": "Просмотр доступа CLI",
- "overview.accessMeta.webApp": "Управление доступом WebApp",
- "overview.accessStatus": "Доступ",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} развернутая Среда",
- "overview.apiTokenSummary.environments_other": "{{count}} развернутых Сред",
- "overview.cardAction.deployLatest": "Развернуть последний Релиз",
- "overview.cardAction.redeploy": "Повторно развернуть",
- "overview.cardAction.viewProgress": "Просмотр развертывания",
- "overview.chip.behindTooltip_one": "Отстаёт от последнего на 1 Релиз. Разверните последний Релиз для обновления.",
- "overview.chip.behindTooltip_other": "Отстаёт от последнего на {{count}} Релизов. Разверните последний Релиз для обновления.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "разворачивается",
- "overview.chip.deployingTooltip": "Развертывание выполняется.",
- "overview.chip.empty": "пусто",
- "overview.chip.emptyTooltip": "В эту Среду не развернут ни один Релиз.",
- "overview.chip.failed": "ошибка",
- "overview.chip.failedTooltip": "Последняя попытка развертывания не удалась.",
"overview.chip.latest": "последний",
- "overview.chip.latestTooltip": "В этой Среде работает последний Релиз.",
- "overview.chip.needsReleaseFirst": "Сначала создайте Релиз",
- "overview.chip.olderRelease": "более старый",
- "overview.chip.olderReleaseTooltip": "В этой Среде работает более старый Релиз.",
- "overview.chip.openInDeployTab": "Просмотр прогресса развертывания",
- "overview.disabled": "Отключено",
- "overview.enabled": "Включено",
- "overview.hero.byName": "от {{name}}",
- "overview.hero.empty": "Пока нет Релизов",
- "overview.hero.emptyDescription": "Создайте Релиз из текущего источника перед развертыванием.",
- "overview.latestRelease.releaseCount_one": "{{count}} Релиз",
- "overview.latestRelease.releaseCount_other": "{{count}} Релизов",
- "overview.latestReleaseTitle": "Последний Релиз",
- "overview.previousReleases.viewAll": "Просмотреть все",
- "overview.strip.deployToNewEnvironment": "Развернуть в новую Среду",
- "overview.strip.emptyDeployableDescription": "Разверните последний Релиз в Среду, когда будете готовы.",
- "overview.strip.emptyDescription": "Создайте Релиз перед развертыванием в Среду.",
- "overview.strip.emptyTitle": "Экземпляров пока нет",
- "overview.strip.title": "Экземпляры",
- "settings.delete": "Удалить развертывание",
- "settings.deleteConfirmDesc": "Удалить {{name}}? Каждый экземпляр прекратит работу и будет удалён во всех Средах. Это нельзя отменить.",
- "settings.deleteConfirmTitle": "Удалить развертывание",
- "settings.deleteFailed": "Не удалось удалить развертывание.",
- "settings.deleted": "Развертывание удалено",
- "settings.description": "Описание",
- "settings.name": "Имя развертывания",
- "settings.save": "Сохранить изменения",
- "settings.updateFailed": "Не удалось обновить развертывание.",
- "settings.updated": "Развертывание обновлено",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Развертывание",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Ожидается синхронизация",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Ошибка развертывания",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Недействительный",
"status.RUNTIME_INSTANCE_STATUS_READY": "Запущено",
@@ -370,87 +89,6 @@
"studio.versionValue": "Значение версии",
"studio.versionsBehind_one": "Отставание на {{count}} версию",
"studio.versionsBehind_other": "Отставание на {{count}} версий",
- "tabs.access.description": "Управление каналами доступа и правами доступа.",
- "tabs.access.name": "Доступ",
- "tabs.api-tokens.description": "Управление API Tokens и вызов экземпляров по HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "Просмотр и управление экземплярами в развернутых Средах.",
- "tabs.instances.name": "Экземпляры",
- "tabs.overview.description": "Просмотр статуса развертывания по Средам.",
- "tabs.overview.name": "Обзор",
- "tabs.releases.description": "Создавайте, разворачивайте и управляйте Релизами.",
- "tabs.releases.name": "Релизы",
- "unsupportedDslNodes.description": "Этот Релиз содержит узлы, которые среда выполнения развертывания пока не поддерживает. Удалите или замените их в Studio и попробуйте снова.",
- "unsupportedDslNodes.descriptionWithTypes": "Этот Релиз содержит узлы, которые среда выполнения развертывания пока не поддерживает: {{nodeTypes}}. Удалите или замените их в Studio и попробуйте снова.",
- "unsupportedDslNodes.title": "Неподдерживаемые узлы",
- "unsupportedDslNodes.unknownType": "Неизвестный тип",
- "versions.cancelCreate": "Отмена",
- "versions.cancelDelete": "Отмена",
- "versions.cancelEdit": "Отмена",
"versions.checkingReleaseContent": "Проверка содержимого Релиза...",
- "versions.col.action": "Действие",
- "versions.col.author": "Создано",
- "versions.col.createdAt": "Создано в",
- "versions.col.deployedTo": "Развернуто в",
- "versions.col.release": "Релиз",
- "versions.col.sourceApp": "Источник",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Создать",
- "versions.createFailed": "Не удалось создать Релиз.",
- "versions.createRelease": "Создать Релиз",
- "versions.createReleaseDescription": "Создайте развертываемый Релиз из Workflow-приложения или файла Workflow DSL.",
- "versions.createSuccess": "Релиз \"{{name}}\" создан.",
- "versions.creating": "Создание...",
- "versions.currentOn": "Текущий Релиз на {{name}}",
- "versions.deleteConfirmDesc": "Релиз \"{{name}}\" будет удалён безвозвратно. Это нельзя отменить.",
- "versions.deleteConfirmTitle": "Удалить Релиз?",
- "versions.deleteFailed": "Не удалось удалить Релиз.",
- "versions.deleteRelease": "Удалить Релиз",
- "versions.deleteSuccess": "Релиз \"{{name}}\" удалён.",
- "versions.deployTo": "Развернуть в {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Развертывание",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Ожидается синхронизация",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Ошибка",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Недействительный",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Запущено",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Не развернуто",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Свертывание развертывания",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Неизвестно",
- "versions.deployingTo": "{{name}} разворачивается",
- "versions.disabledReason.checkDeploymentsFailed": "Не удалось проверить использование развертывания. Повторите попытку позже.",
- "versions.disabledReason.checkingDeployments": "Проверка использования развертывания",
- "versions.disabledReason.current": "Этот Релиз уже запущен на {{name}}",
- "versions.disabledReason.deploying": "Дождитесь завершения активного развертывания",
- "versions.disabledReason.releaseInUse_one": "Сверните этот Релиз из {{count}} Среды перед его удалением",
- "versions.disabledReason.releaseInUse_other": "Сверните этот Релиз из {{count}} Сред перед его удалением",
- "versions.dslReadFailed": "Не удалось прочитать файл DSL. Выберите другой файл и попробуйте снова.",
- "versions.dslReading": "Чтение файла DSL...",
- "versions.dslUnsupportedMode": "Для развертываний можно использовать только файлы Workflow DSL.",
- "versions.editFailed": "Не удалось обновить Релиз.",
- "versions.editRelease": "Изменить Релиз",
- "versions.editReleaseDescription": "Обновите имя и описание этого Релиза.",
- "versions.editSuccess": "Релиз \"{{name}}\" обновлён.",
- "versions.emptyDescription": "Создайте первый Релиз перед развертыванием в Среду.",
- "versions.emptyTitle": "Пока нет Релизов",
- "versions.exportDsl": "Экспортировать DSL",
- "versions.exportDslFailed": "Не удалось экспортировать DSL.",
- "versions.exportingDsl": "Экспорт...",
- "versions.groupHeader.deploy": "Развернуть",
- "versions.groupHeader.rollback": "Развернуть предыдущую версию",
- "versions.groupHeader.unavailable": "Недоступно",
- "versions.manualDslOption": "Загрузить DSL",
- "versions.moreActions": "Дополнительные действия",
- "versions.optional": "Необязательно",
- "versions.releaseAlreadyExists": "Релиз с таким же содержимым уже существует: {{name}}.",
- "versions.releaseContentCheckFailed": "Не удалось проверить содержимое Релиза.",
- "versions.releaseDescriptionLabel": "Описание",
- "versions.releaseDescriptionPlaceholder": "Опишите этот Релиз",
- "versions.releaseNameConflict": "Релиз с таким именем уже существует. Выберите другое имя.",
- "versions.releaseNameLabel": "Имя Релиза",
- "versions.releaseNamePlaceholder": "Имя Релиза",
- "versions.releaseNameRequired": "Введите имя Релиза.",
- "versions.releaseSourceLabel": "Источник Релиза",
- "versions.rollbackTo": "Развернуть в {{name}}",
- "versions.saveEdit": "Сохранить",
- "versions.sourceAppOption": "Workflow-приложение"
+ "versions.deployTo": "Развернуть в {{name}}"
}
diff --git a/web/i18n/sl-SI/common.json b/web/i18n/sl-SI/common.json
index 07d933a7b6a..2db1d1715d8 100644
--- a/web/i18n/sl-SI/common.json
+++ b/web/i18n/sl-SI/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Podrobnosti o aplikaciji",
"menus.apps": "Studio",
"menus.datasets": "Znanje",
- "menus.deployments": "Uvedbe",
"menus.exploreMarketplace": "Raziščite Marketplace",
"menus.plugins": "Integracije",
"menus.status": "beta",
diff --git a/web/i18n/sl-SI/deployments.json b/web/i18n/sl-SI/deployments.json
index 735b9178377..9cc10c5307f 100644
--- a/web/i18n/sl-SI/deployments.json
+++ b/web/i18n/sl-SI/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Kopiraj cURL primer",
- "access.api.createFailed": "Ustvarjanje API žetona ni uspelo.",
- "access.api.createKey": "Ustvari API žeton",
- "access.api.createKeyTitle": "Ustvari nov API žeton",
- "access.api.curlExampleTitle": "cURL primer",
- "access.api.description": "Dostopajte do te uvedbe preko HTTP. Vsak API žeton je omejen na eno okolje.",
- "access.api.developerTitle": "Razvijalski API",
- "access.api.disabled": "Dostop do API je za to uvedbo izklopljen.",
- "access.api.disabledHint": "Omogočite dostop do API za ustvarjanje žetonov, omejenih na okolje.",
- "access.api.docs": "API dokumentacija",
- "access.api.docsClose": "Zapri API dokumentacijo",
- "access.api.docsDescription": "Oglejte si referenco Workflow API za to uvedbo.",
- "access.api.docsTitle": "Dokumentacija Workflow API",
- "access.api.empty": "Najprej uvedite v okolje, da začnete izdajati API žetone.",
- "access.api.emptyTitle": "Ni uvedenih okolij",
- "access.api.endpoint": "URL zahteve",
- "access.api.keyList": "Seznam API žetonov",
- "access.api.nameLabel": "Ime API žetona",
- "access.api.namePlaceholder": "Vnesite ime API žetona",
- "access.api.nameRequired": "Ime API žetona je obvezno.",
- "access.api.newKey": "Ustvari nov API žeton",
- "access.api.newTokenDescription": "Ta API žeton je prikazan samo enkrat. Kopirajte ga, preden zapustite to stran.",
- "access.api.newTokenLabel": "API žeton",
- "access.api.newTokenTitle": "API žeton ustvarjen",
- "access.api.noKeys": "Še ni API žetonov. Ustvarite enega za začetek klicanja API.",
- "access.api.noKeysTitle": "Še ni API žetonov",
- "access.api.revokeConfirmDescription": "API žeton \"{{name}}\" bo takoj prenehal delovati. Tega dejanja ni mogoče razveljaviti.",
- "access.api.revokeConfirmTitle": "Prekličete API žeton?",
- "access.api.revokeFailed": "Preklic API žetona ni uspel.",
- "access.api.revokeSuccess": "API žeton preklican",
- "access.api.table.action": "Dejanje",
- "access.api.table.environment": "Okolje",
- "access.api.table.key": "API žeton",
- "access.api.table.name": "Ime",
- "access.channels.disabled": "Kanali dostopa so za to uvedbo izklopljeni.",
- "access.channels.disabledHint": "Omogočite kanale dostopa za izpostavitev vstopnih točk WebApp in CLI.",
- "access.channels.title": "Kanali dostopa",
- "access.cli.description": "Pokličite iz terminala z difyctl, primerno za skripte, avtomatizirane potekov dela ali integracije z agenti.",
- "access.cli.docs": "Vodič za uporabo",
- "access.cli.domain": "Domena",
- "access.cli.empty": "Končna točka CLI ni konfigurirana.",
- "access.cli.install": "Namesti CLI",
- "access.cli.title": "CLI",
- "access.copy": "Kopiraj",
- "access.copyFailed": "Kopiranje ni uspelo",
- "access.members.groupCount_one": "{{count}} skupina",
- "access.members.groupCount_other": "{{count}} skupin",
- "access.members.memberCount_one": "{{count}} član",
- "access.members.memberCount_other": "{{count}} članov",
- "access.permission.anyone": "Vsi s povezavo",
- "access.permission.organization": "Vsi člani znotraj platforme",
- "access.permission.specific": "Določeni člani znotraj platforme",
- "access.permission.specificDesc": "Izberite določene skupine ali člane",
- "access.permission.updateFailed": "Posodobitev pravilnika o dostopu ni uspela.",
- "access.permissions.editAriaLabel": "Konfiguriraj dostop za {{environment}}",
- "access.permissions.editDescription": "Nastavite dovoljenja za dostop do vstopnih točk WebApp in CLI.",
- "access.permissions.editTitle": "Dovoljenja za dostop",
- "access.permissions.title": "Dovoljenja za dostop",
- "access.revoke": "Prekliči",
- "access.runAccess.noEnvs": "Uvedite v okolje za konfiguracijo dovoljenj za dostop.",
- "access.runAccess.noEnvsTitle": "Ni uvedenih okolij",
- "access.runAccess.openWebapp": "Odpri WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Gostujoča spletna stran za končne uporabnike.",
- "access.runAccess.webappEmpty": "Kmalu na voljo.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Zunanji",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Neznano",
- "card.access.api": "API žetoni",
- "card.access.cli": "CLI",
- "card.access.none": "Brez dostopa",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Ustvari prvo izdajo",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Izbriši uvedbo",
- "card.menu.deploy": "Uvedi v okolje",
- "card.menu.editInfo": "Uredi informacije",
- "card.moreActions": "Več dejanj",
- "card.noDescription": "Opis ni naveden.",
"card.notDeployed": "Ni uvedeno",
- "card.tooltip.createdAt": "Ustvarjeno",
- "card.tooltip.deployed": "Uvedeno",
- "card.tooltip.deploymentStatus": "Uvedba",
- "card.tooltip.notDeployedShort": "Ni uvedeno",
- "card.tooltip.releaseName": "Ime izdaje",
- "card.tooltip.source": "Vir",
"common.loadFailed": "Nalaganje ni uspelo. Poskusite znova kasneje.",
- "createGuide.actions.back": "Nazaj",
- "createGuide.actions.createAndDeploy": "Ustvari in uvedi",
- "createGuide.actions.creating": "Ustvarjanje...",
- "createGuide.actions.deploying": "Ustvarjanje in uvajanje...",
- "createGuide.actions.next": "Naprej",
- "createGuide.actions.skipDeploy": "Preskoči, uvedi kasneje",
- "createGuide.dsl.defaultAppName": "Uvožena DSL aplikacija",
- "createGuide.dsl.description": "Naložite paket Workflow DSL za ustvarjanje uvedbe, prve izdaje in neobvezne uvedbe okolja.",
- "createGuide.dsl.dropDescription": "Naložite paket Workflow YAML DSL. Možnosti uvedbe so razrešene iz te datoteke pred uvedbo.",
- "createGuide.dsl.dropTitle": "Naložite paket Workflow DSL",
- "createGuide.dsl.readFailed": "Branje datoteke DSL ni uspelo. Izberite drugo datoteko in poskusite znova.",
- "createGuide.dsl.reading": "Branje datoteke DSL...",
- "createGuide.dsl.title": "Uvozi DSL",
- "createGuide.dsl.unsupportedMode": "Za uvedbe je mogoče uporabiti samo datoteke Workflow DSL.",
- "createGuide.errors.createReleaseFailed": "Ustvarjanje uvedbe ali izdaje ni uspelo.",
- "createGuide.errors.deployFailed": "Uvedba v okolje ni uspela.",
- "createGuide.method.description": "Izberite vir, ki bo uporabljen za ustvarjanje prve izdaje.",
- "createGuide.methods.bindApp.description": "Uporabite obstoječo Workflow aplikacijo v Studiu kot vir izdaje.",
- "createGuide.methods.bindApp.title": "Poveži obstoječo Workflow aplikacijo",
- "createGuide.methods.importDsl.description": "Naložite paket Workflow YAML DSL in nadaljujte preko vmesnika za uvedbo.",
- "createGuide.methods.importDsl.title": "Uvozi DSL",
- "createGuide.nav.back": "Uvedbe",
- "createGuide.release.defaultName": "začetna izdaja",
- "createGuide.release.deployInfo": "Informacije o uvedbi",
- "createGuide.release.description": "Izpolnite informacije o uvedbi in podrobnosti prve izdaje.",
- "createGuide.release.firstVersion": "Prva izdaja",
- "createGuide.release.instanceDescription": "Opis uvedbe",
- "createGuide.release.instanceDescriptionPlaceholder": "Opišite, za kaj se ta uvedba uporablja",
- "createGuide.release.instanceName": "Ime uvedbe",
- "createGuide.release.instanceNameConflict": "Uvedba s tem imenom že obstaja. Izberite drugo ime.",
- "createGuide.release.releaseDescription": "Opis izdaje",
- "createGuide.release.releaseDescriptionPlaceholder": "Opišite to izdajo",
- "createGuide.release.releaseName": "Ime izdaje",
- "createGuide.release.title": "Osnovne informacije",
- "createGuide.source.clearSearch": "Počisti iskanje aplikacij",
- "createGuide.source.description": "Izberite vir, ki bo uporabljen za ustvarjanje prve izdaje.",
- "createGuide.source.empty": "Ni najdenih Workflow aplikacij.",
- "createGuide.source.searchPlaceholder": "Iskanje aplikacij",
- "createGuide.source.sourceApp": "Workflow aplikacija",
- "createGuide.source.title": "Vir izdaje",
- "createGuide.steps.method": "Vir izdaje",
- "createGuide.steps.release": "Osnovne informacije",
- "createGuide.steps.source": "Vir izdaje",
- "createGuide.steps.target": "Uvedi v okolje",
- "createGuide.target.bindingCount_one": "{{count}} povezava",
- "createGuide.target.bindingCount_other": "{{count}} povezav",
- "createGuide.target.bindingHint": "Izberite poverilnice, ki jih uporablja ta izdaja.",
- "createGuide.target.bindings": "Poverilnice",
- "createGuide.target.description": "Izberite ciljno okolje in zagotovite nastavitve izvajanja, ki jih ta izdaja tam potrebuje. Ta korak je mogoče preskočiti.",
- "createGuide.target.envVarCount_one": "{{count}} spremenljivka",
- "createGuide.target.envVarCount_other": "{{count}} spremenljivk",
- "createGuide.target.envVarHint": "Za vsako okoljsko spremenljivko, ki jo ta izdaja potrebuje, vnesite poljubno vrednost ali uporabite vrednost, določeno v aplikaciji.",
- "createGuide.target.envVarPlaceholder": "Vnesite vrednost",
- "createGuide.target.envVarSource.ariaLabel": "Izberite vir vrednosti spremenljivke za {{key}}",
- "createGuide.target.envVarSource.default": "Vrednost aplikacije",
- "createGuide.target.envVarSource.lastDeployment": "Zadnja uvedena vrednost",
- "createGuide.target.envVarSource.literal": "Poljubna vrednost",
- "createGuide.target.envVarType.number": "Število",
- "createGuide.target.envVarType.secret": "Skrivnost",
- "createGuide.target.envVarType.string": "Niz",
- "createGuide.target.envVars": "Okoljske spremenljivke",
- "createGuide.target.environment": "Ciljno okolje",
- "createGuide.target.loadBindingsFailed": "Nalaganje poverilnic ni uspelo.",
- "createGuide.target.loadEnvironmentsFailed": "Nalaganje okolij za uvedbo ni uspelo.",
- "createGuide.target.missingRequiredBinding": "Izberite poverilnico za to obvezno povezavo.",
- "createGuide.target.noBindingRequired": "Poverilnice niso potrebne.",
- "createGuide.target.noCredentialCandidates": "Ni razpoložljivih poverilnic.",
- "createGuide.target.noEnvironmentOptions": "Ni razpoložljivih okolij za uvedbo.",
- "createGuide.target.selectCredential": "Izberite poverilnico",
- "createGuide.target.title": "Uvedi v okolje",
- "createGuide.title": "Nova uvedba",
- "createModal.appPickerPlaceholder": "Izberite Workflow aplikacijo",
- "createModal.appSearchEmpty": "Ni ustreznih Workflow aplikacij",
- "createModal.appSearchPlaceholder": "Iskanje Workflow aplikacij…",
- "createModal.cancel": "Prekliči",
- "createModal.loadingApps": "Nalaganje aplikacij…",
- "deployDrawer.bindingCount_one": "{{count}} povezava",
- "deployDrawer.bindingCount_other": "{{count}} povezav",
"deployDrawer.bindingOptionsFailed": "Nalaganje možnosti poverilnic ni uspelo.",
"deployDrawer.bindingSelectionHint": "Izberite poverilnice, ki jih uporablja ta uvedba.",
- "deployDrawer.cancel": "Prekliči",
- "deployDrawer.close": "Zapri predal za uvedbo",
- "deployDrawer.defaultSelect": "Izberite...",
- "deployDrawer.deploy": "Uvedi v okolje",
- "deployDrawer.deployFailed": "Zagon uvedbe ni uspel.",
"deployDrawer.deploying": "Uvajanje...",
- "deployDrawer.description": "Izberite izdajo in ciljno okolje za uvedbo.",
- "deployDrawer.envVarCount_one": "{{count}} spremenljivka",
- "deployDrawer.envVarCount_other": "{{count}} spremenljivk",
- "deployDrawer.envVarHint": "Za vsako okoljsko spremenljivko, ki jo ta izdaja potrebuje, vnesite poljubno vrednost ali uporabite vrednost, določeno v aplikaciji.",
- "deployDrawer.envVarPlaceholder": "Vnesite vrednost",
"deployDrawer.envVarSource.ariaLabel": "Izberite vir vrednosti spremenljivke za {{key}}",
- "deployDrawer.envVarSource.default": "Vrednost aplikacije",
"deployDrawer.envVarSource.lastDeployment": "Zadnja uvedena vrednost",
"deployDrawer.envVarSource.literal": "Poljubna vrednost",
"deployDrawer.envVarType.number": "Število",
"deployDrawer.envVarType.secret": "Skrivnost",
"deployDrawer.envVarType.string": "Niz",
"deployDrawer.envVars": "Okoljske spremenljivke",
- "deployDrawer.existingReleaseHint": "Ta izdaja bo uvedena takšna, kot je. Nova izdaja ne bo ustvarjena.",
- "deployDrawer.lockedHint": "Zaklenjeno na trenutno okolje",
- "deployDrawer.missingRequiredBinding": "Izberite poverilnico za to obvezno povezavo.",
- "deployDrawer.missingRequiredEnvVar": "Vnesite vrednost za to obvezno okoljsko spremenljivko.",
- "deployDrawer.noBindingRequired": "Ni obvezno",
"deployDrawer.noCredentialCandidates": "Ni razpoložljivih poverilnic.",
"deployDrawer.noNewEnvironmentAvailable": "Vsa razpoložljiva okolja že imajo uvedbo.",
- "deployDrawer.noOtherReleaseAvailable": "Za to okolje ni na voljo drugih izdaj.",
- "deployDrawer.noReleaseAvailable": "Pred uvedbo v okolje ustvarite izdajo.",
- "deployDrawer.notFound": "Uvedba ni najdena.",
- "deployDrawer.releaseLabel": "Izdaja",
"deployDrawer.runtimeCredentials": "Poverilnice",
"deployDrawer.selectCredential": "Izberite poverilnico",
- "deployDrawer.selectEnv": "Izberite okolje",
- "deployDrawer.selectRelease": "Izberite izdajo",
- "deployDrawer.targetEnv": "Ciljno okolje",
- "deployDrawer.title": "Uvedi v okolje",
- "deployTab.closeError": "Zapri",
"deployTab.col.actions": "Dejanja",
- "deployTab.col.currentRelease": "Trenutna izdaja",
"deployTab.col.environment": "Okolje",
"deployTab.col.status": "Status",
"deployTab.confirmUndeploy": "Razveljavi uvedbo",
- "deployTab.deployOtherVersion": "Uvedi drugo izdajo",
- "deployTab.emptyDescription": "Izberite izdajo in ciljno okolje, da uporabnikom omogočite dostop do te uvedbe.",
- "deployTab.emptyTitle": "Nobeno okolje se še ne izvaja",
- "deployTab.errorCode": "Koda",
- "deployTab.errorDialogDesc": "Preglejte zadnjo neuspelo uvedbo pred ponovnim poskusom ali uvedbo druge izdaje.",
- "deployTab.errorDialogTitle": "Napaka uvedbe v {{name}}",
- "deployTab.errorMessage": "Sporočilo",
- "deployTab.errorPhase": "Faza",
"deployTab.moreActions": "Več dejanj",
- "deployTab.newDeployment": "Uvedi v novo okolje",
- "deployTab.panel.unknownError": "Uvedba ni uspela.",
"deployTab.redeploy": "Ponovno uvedi",
- "deployTab.retry": "Poskusi znova",
- "deployTab.status.deployFailed": "Uvedba ni uspela",
- "deployTab.status.deployingRelease": "Uvajanje ({{release}})",
- "deployTab.status.runningOutOfSync": "Se izvaja (sinhronizacija v teku)",
- "deployTab.status.runningWithFailed": "Se izvaja (zadnja uvedba ni uspela)",
"deployTab.undeploy": "Razveljavi uvedbo",
- "deployTab.undeployConfirmDesc": "Končna točka okolja ne bo več na voljo, vendar različica ne bo izbrisana.",
- "deployTab.undeployConfirmTitle": "Razveljavite uvedbo {{name}}?",
"deployTab.undeployConfirmWarning": "Po potrditvi bo to okolje prešlo v stanje razveljavljanja uvedbe, dejanja pa bodo začasno onemogočena.",
- "deployTab.viewError": "Oglej si napako",
- "detail.mobileTabs": "Razdelki uvedbe",
- "detail.notFound": "Uvedba ni najdena",
- "documentTitle.create": "Nova uvedba · Uvedbe",
- "documentTitle.detail": "Uvedba · Uvedbe",
- "documentTitle.list": "Uvedbe",
- "filter.allEnvs": "Vsa okolja",
- "filter.searchPlaceholder": "Iskanje uvedb",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Sprejem",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Zagon",
- "health.ENVIRONMENT_STATUS_DELETING": "Brisanje",
"health.ENVIRONMENT_STATUS_FAILED": "Nedosegljivo",
- "health.ENVIRONMENT_STATUS_READY": "Na voljo",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Neznano",
- "list.clearFilters": "Počisti filtre",
- "list.clearSearch": "Počisti iskanje uvedb",
- "list.createDeployment": "Novo",
- "list.emptyDescription": "Ustvarite uvedbo iz Workflow aplikacije ali paketa Workflow DSL za upravljanje izdaj, okolij in dostopa.",
- "list.emptyFilteredDescription": "Nobena uvedba ne ustreza trenutnemu iskanju ali filtru okolja.",
- "list.emptyFilteredTitle": "Ni ustreznih uvedb",
"list.emptyTitle": "Še ni uvedb",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Izolirano",
- "mode.ENVIRONMENT_MODE_SHARED": "Skupno",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Neznano",
- "overview.accessMeta.apiTokens": "Upravljaj API žetone",
- "overview.accessMeta.cli": "Oglej si dostop CLI",
- "overview.accessMeta.webApp": "Upravljaj dostop WebApp",
- "overview.accessStatus": "Dostop",
- "overview.api": "API žetoni",
- "overview.apiKeysCount_one": "{{count}} API žeton",
- "overview.apiKeysCount_other": "{{count}} API žetonov",
- "overview.apiTokenSummary.environments_one": "{{count}} uvedeno okolje",
- "overview.apiTokenSummary.environments_other": "{{count}} uvedenih okolij",
- "overview.cardAction.deployLatest": "Uvedi najnovejšo izdajo",
- "overview.cardAction.redeploy": "Ponovno uvedi",
- "overview.cardAction.viewProgress": "Oglej si uvedbo",
- "overview.chip.behindTooltip_one": "1 izdaja za najnovejšo. Uvedite najnovejšo izdajo za posodobitev.",
- "overview.chip.behindTooltip_other": "{{count}} izdaj za najnovejšo. Uvedite najnovejšo izdajo za posodobitev.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "uvajanje",
- "overview.chip.deployingTooltip": "Uvajanje je v teku.",
- "overview.chip.empty": "prazno",
- "overview.chip.emptyTooltip": "V tem okolju ni uvedene nobene izdaje.",
- "overview.chip.failed": "neuspelo",
- "overview.chip.failedTooltip": "Zadnji poskus uvedbe ni uspel.",
"overview.chip.latest": "najnovejša",
- "overview.chip.latestTooltip": "V tem okolju se izvaja najnovejša izdaja.",
- "overview.chip.needsReleaseFirst": "Najprej ustvarite izdajo",
- "overview.chip.olderRelease": "starejša",
- "overview.chip.olderReleaseTooltip": "V tem okolju se izvaja starejša izdaja.",
- "overview.chip.openInDeployTab": "Oglej si napredek uvedbe",
- "overview.disabled": "Onemogočeno",
- "overview.enabled": "Omogočeno",
- "overview.hero.byName": "od {{name}}",
- "overview.hero.empty": "Še ni izdaj",
- "overview.hero.emptyDescription": "Pred uvedbo ustvarite izdajo iz trenutnega vira.",
- "overview.latestRelease.releaseCount_one": "{{count}} izdaja",
- "overview.latestRelease.releaseCount_other": "{{count}} izdaj",
- "overview.latestReleaseTitle": "Najnovejša izdaja",
- "overview.previousReleases.viewAll": "Pokaži vse",
- "overview.strip.deployToNewEnvironment": "Uvedi v novo okolje",
- "overview.strip.emptyDeployableDescription": "Ko boste pripravljeni, uvedite najnovejšo izdajo v okolje.",
- "overview.strip.emptyDescription": "Pred uvedbo v okolje ustvarite izdajo.",
- "overview.strip.emptyTitle": "Še ni instanc",
- "overview.strip.title": "Instance",
- "settings.delete": "Izbriši uvedbo",
- "settings.deleteConfirmDesc": "Izbrišete {{name}}? Vsaka instanca se bo prenehala izvajati in bo odstranjena iz vseh okolij. Tega ni mogoče razveljaviti.",
- "settings.deleteConfirmTitle": "Izbriši uvedbo",
- "settings.deleteFailed": "Brisanje uvedbe ni uspelo.",
- "settings.deleted": "Uvedba izbrisana",
- "settings.description": "Opis",
- "settings.name": "Ime uvedbe",
- "settings.save": "Shrani spremembe",
- "settings.updateFailed": "Posodobitev uvedbe ni uspela.",
- "settings.updated": "Uvedba posodobljena",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Uvajanje",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sinhronizacija v teku",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Uvedba ni uspela",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Neveljavno",
"status.RUNTIME_INSTANCE_STATUS_READY": "Se izvaja",
@@ -370,87 +89,6 @@
"studio.versionValue": "Vrednost različice",
"studio.versionsBehind_one": "{{count}} različica zadaj",
"studio.versionsBehind_other": "{{count}} različic zadaj",
- "tabs.access.description": "Upravljajte kanale dostopa in dovoljenja za dostop.",
- "tabs.access.name": "Dostop",
- "tabs.api-tokens.description": "Upravljajte API žetone in kličite instance preko HTTP.",
- "tabs.api-tokens.name": "API žetoni",
- "tabs.instances.description": "Oglejte si in upravljajte instance v uvedenih okoljih.",
- "tabs.instances.name": "Instance",
- "tabs.overview.description": "Oglejte si status uvedbe v različnih okoljih.",
- "tabs.overview.name": "Pregled",
- "tabs.releases.description": "Ustvarjajte, uvajajte in upravljajte izdaje.",
- "tabs.releases.name": "Izdaje",
- "unsupportedDslNodes.description": "Ta izdaja vsebuje vozlišča, ki jih izvajalno okolje uvedbe še ne podpira. Odstranite ali zamenjajte jih v Studiu in poskusite znova.",
- "unsupportedDslNodes.descriptionWithTypes": "Ta izdaja vsebuje vozlišča, ki jih izvajalno okolje uvedbe še ne podpira: {{nodeTypes}}. Odstranite ali zamenjajte jih v Studiu in poskusite znova.",
- "unsupportedDslNodes.title": "Nepodprta vozlišča",
- "unsupportedDslNodes.unknownType": "Neznan tip",
- "versions.cancelCreate": "Prekliči",
- "versions.cancelDelete": "Prekliči",
- "versions.cancelEdit": "Prekliči",
"versions.checkingReleaseContent": "Preverjanje vsebine izdaje...",
- "versions.col.action": "Dejanje",
- "versions.col.author": "Ustvaril",
- "versions.col.createdAt": "Ustvarjeno",
- "versions.col.deployedTo": "Uvedeno v",
- "versions.col.release": "Izdaja",
- "versions.col.sourceApp": "Vir",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Ustvari",
- "versions.createFailed": "Ustvarjanje izdaje ni uspelo.",
- "versions.createRelease": "Ustvari izdajo",
- "versions.createReleaseDescription": "Ustvarite uvedljivo izdajo iz Workflow aplikacije ali datoteke Workflow DSL.",
- "versions.createSuccess": "Izdaja \"{{name}}\" ustvarjena.",
- "versions.creating": "Ustvarjanje...",
- "versions.currentOn": "Trenutna izdaja v {{name}}",
- "versions.deleteConfirmDesc": "Izdaja \"{{name}}\" bo trajno izbrisana. Tega ni mogoče razveljaviti.",
- "versions.deleteConfirmTitle": "Izbriši izdajo?",
- "versions.deleteFailed": "Brisanje izdaje ni uspelo.",
- "versions.deleteRelease": "Izbriši izdajo",
- "versions.deleteSuccess": "Izdaja \"{{name}}\" izbrisana.",
- "versions.deployTo": "Uvedi v {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Uvajanje",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Sinhronizacija v teku",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Neuspelo",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Neveljavno",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Se izvaja",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Ni uvedeno",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Razveljavljanje uvedbe",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Neznano",
- "versions.deployingTo": "{{name}} se uvaja",
- "versions.disabledReason.checkDeploymentsFailed": "Preverjanje uporabe uvedbe ni uspelo. Poskusite znova kasneje.",
- "versions.disabledReason.checkingDeployments": "Preverjanje uporabe uvedbe",
- "versions.disabledReason.current": "Ta izdaja se že izvaja v {{name}}",
- "versions.disabledReason.deploying": "Počakajte, da se aktivna uvedba zaključi",
- "versions.disabledReason.releaseInUse_one": "Pred brisanjem razveljavite uvedbo te izdaje iz {{count}} okolja",
- "versions.disabledReason.releaseInUse_other": "Pred brisanjem razveljavite uvedbo te izdaje iz {{count}} okolij",
- "versions.dslReadFailed": "Branje datoteke DSL ni uspelo. Izberite drugo datoteko in poskusite znova.",
- "versions.dslReading": "Branje datoteke DSL...",
- "versions.dslUnsupportedMode": "Za uvedbe je mogoče uporabiti samo datoteke Workflow DSL.",
- "versions.editFailed": "Posodobitev izdaje ni uspela.",
- "versions.editRelease": "Uredi izdajo",
- "versions.editReleaseDescription": "Posodobite ime in opis te izdaje.",
- "versions.editSuccess": "Izdaja \"{{name}}\" posodobljena.",
- "versions.emptyDescription": "Pred uvedbo v okolje ustvarite prvo izdajo.",
- "versions.emptyTitle": "Še ni izdaj",
- "versions.exportDsl": "Izvozi DSL",
- "versions.exportDslFailed": "Izvoz DSL ni uspel.",
- "versions.exportingDsl": "Izvažanje...",
- "versions.groupHeader.deploy": "Uvedi",
- "versions.groupHeader.rollback": "Uvedi prejšnjo različico",
- "versions.groupHeader.unavailable": "Ni na voljo",
- "versions.manualDslOption": "Naloži DSL",
- "versions.moreActions": "Več dejanj",
- "versions.optional": "Neobvezno",
- "versions.releaseAlreadyExists": "Izdaja z enako vsebino že obstaja: {{name}}.",
- "versions.releaseContentCheckFailed": "Preverjanje vsebine izdaje ni uspelo.",
- "versions.releaseDescriptionLabel": "Opis",
- "versions.releaseDescriptionPlaceholder": "Opišite to izdajo",
- "versions.releaseNameConflict": "Izdaja s tem imenom že obstaja. Izberite drugo ime.",
- "versions.releaseNameLabel": "Ime izdaje",
- "versions.releaseNamePlaceholder": "Ime izdaje",
- "versions.releaseNameRequired": "Vnesite ime izdaje.",
- "versions.releaseSourceLabel": "Vir izdaje",
- "versions.rollbackTo": "Uvedi v {{name}}",
- "versions.saveEdit": "Shrani",
- "versions.sourceAppOption": "Workflow aplikacija"
+ "versions.deployTo": "Uvedi v {{name}}"
}
diff --git a/web/i18n/th-TH/common.json b/web/i18n/th-TH/common.json
index e417613010e..a0c937308b2 100644
--- a/web/i18n/th-TH/common.json
+++ b/web/i18n/th-TH/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "รายละเอียดแอป",
"menus.apps": "สตูดิโอ",
"menus.datasets": "ความรู้",
- "menus.deployments": "การปรับใช้",
"menus.exploreMarketplace": "สํารวจ Marketplace",
"menus.plugins": "การผสานรวม",
"menus.status": "Beta",
diff --git a/web/i18n/th-TH/deployments.json b/web/i18n/th-TH/deployments.json
index 50754e20b56..e5fa0532c16 100644
--- a/web/i18n/th-TH/deployments.json
+++ b/web/i18n/th-TH/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "คัดลอกตัวอย่าง cURL",
- "access.api.createFailed": "ไม่สามารถสร้าง API Token ได้",
- "access.api.createKey": "สร้าง API Token",
- "access.api.createKeyTitle": "สร้าง API Token ใหม่",
- "access.api.curlExampleTitle": "ตัวอย่าง cURL",
- "access.api.description": "เข้าถึงการปรับใช้นี้ผ่าน HTTP API Token แต่ละตัวจะถูกกำหนดขอบเขตให้กับสภาพแวดล้อมเดียว",
- "access.api.developerTitle": "API สำหรับนักพัฒนา",
- "access.api.disabled": "การเข้าถึง API ถูกปิดสำหรับการปรับใช้นี้",
- "access.api.disabledHint": "เปิดใช้งานการเข้าถึง API เพื่อสร้างโทเค็นที่กำหนดขอบเขตตามสภาพแวดล้อม",
- "access.api.docs": "เอกสาร API",
- "access.api.docsClose": "ปิดเอกสาร API",
- "access.api.docsDescription": "ดูเอกสารอ้างอิง API ของ Workflow สำหรับการปรับใช้นี้",
- "access.api.docsTitle": "เอกสาร API ของ Workflow",
- "access.api.empty": "ปรับใช้กับสภาพแวดล้อมก่อนเพื่อเริ่มสร้าง API Token",
- "access.api.emptyTitle": "ไม่มีสภาพแวดล้อมที่ปรับใช้แล้ว",
- "access.api.endpoint": "URL ของคำขอ",
- "access.api.keyList": "รายการ API Token",
- "access.api.nameLabel": "ชื่อ API Token",
- "access.api.namePlaceholder": "ป้อนชื่อ API Token",
- "access.api.nameRequired": "ต้องระบุชื่อ API Token",
- "access.api.newKey": "สร้าง API Token ใหม่",
- "access.api.newTokenDescription": "API Token นี้จะแสดงเพียงครั้งเดียวเท่านั้น คัดลอกก่อนออกจากหน้านี้",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "สร้าง API Token แล้ว",
- "access.api.noKeys": "ยังไม่มี API Token สร้างขึ้นเพื่อเริ่มเรียกใช้ API",
- "access.api.noKeysTitle": "ยังไม่มี API Token",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" จะหยุดทำงานทันที การดำเนินการนี้ไม่สามารถยกเลิกได้",
- "access.api.revokeConfirmTitle": "เพิกถอน API Token?",
- "access.api.revokeFailed": "ไม่สามารถเพิกถอน API Token ได้",
- "access.api.revokeSuccess": "เพิกถอน API Token แล้ว",
- "access.api.table.action": "การดำเนินการ",
- "access.api.table.environment": "สภาพแวดล้อม",
- "access.api.table.key": "API Token",
- "access.api.table.name": "ชื่อ",
- "access.channels.disabled": "ช่องทางการเข้าถึงถูกปิดสำหรับการปรับใช้นี้",
- "access.channels.disabledHint": "เปิดใช้งานช่องทางการเข้าถึงเพื่อเปิดเผยจุดเข้าใช้งาน WebApp และ CLI",
- "access.channels.title": "ช่องทางการเข้าถึง",
- "access.cli.description": "เรียกใช้จากเทอร์มินัลด้วย difyctl เหมาะสำหรับสคริปต์ เวิร์กโฟลว์อัตโนมัติ หรือการรวม Agent",
- "access.cli.docs": "คู่มือการใช้งาน",
- "access.cli.domain": "โดเมน",
- "access.cli.empty": "ไม่ได้กำหนดค่าจุดเชื่อมต่อ CLI",
- "access.cli.install": "ติดตั้ง CLI",
- "access.cli.title": "CLI",
- "access.copy": "คัดลอก",
- "access.copyFailed": "การคัดลอกล้มเหลว",
- "access.members.groupCount_one": "{{count}} กลุ่ม",
- "access.members.groupCount_other": "{{count}} กลุ่ม",
- "access.members.memberCount_one": "{{count}} สมาชิก",
- "access.members.memberCount_other": "{{count}} สมาชิก",
- "access.permission.anyone": "ใครก็ตามที่มีลิงก์",
- "access.permission.organization": "สมาชิกทั้งหมดในแพลตฟอร์ม",
- "access.permission.specific": "สมาชิกที่ระบุในแพลตฟอร์ม",
- "access.permission.specificDesc": "เลือกกลุ่มหรือสมาชิกที่ระบุ",
- "access.permission.updateFailed": "ไม่สามารถอัปเดตนโยบายการเข้าถึงได้",
- "access.permissions.editAriaLabel": "กำหนดค่าการเข้าถึงสำหรับ {{environment}}",
- "access.permissions.editDescription": "ตั้งค่าสิทธิ์การเข้าถึงสำหรับจุดเข้าใช้งาน WebApp และ CLI",
- "access.permissions.editTitle": "สิทธิ์การเข้าถึง",
- "access.permissions.title": "สิทธิ์การเข้าถึง",
- "access.revoke": "เพิกถอน",
- "access.runAccess.noEnvs": "ปรับใช้กับสภาพแวดล้อมเพื่อกำหนดค่าสิทธิ์การเข้าถึง",
- "access.runAccess.noEnvsTitle": "ไม่มีสภาพแวดล้อมที่ปรับใช้แล้ว",
- "access.runAccess.openWebapp": "เปิด WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "หน้าเว็บที่โฮสต์สำหรับผู้ใช้ปลายทาง",
- "access.runAccess.webappEmpty": "เร็ว ๆ นี้",
- "backend.RUNTIME_BACKEND_EXTERNAL": "ภายนอก",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "ไม่ทราบ",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "ไม่มีการเข้าถึง",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "สร้างรีลีสแรก",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "ลบการปรับใช้",
- "card.menu.deploy": "ปรับใช้กับสภาพแวดล้อม",
- "card.menu.editInfo": "แก้ไขข้อมูล",
- "card.moreActions": "การดำเนินการเพิ่มเติม",
- "card.noDescription": "ไม่มีคำอธิบาย",
"card.notDeployed": "ยังไม่ได้ปรับใช้",
- "card.tooltip.createdAt": "สร้างเมื่อ",
- "card.tooltip.deployed": "ปรับใช้แล้ว",
- "card.tooltip.deploymentStatus": "การปรับใช้",
- "card.tooltip.notDeployedShort": "ยังไม่ได้ปรับใช้",
- "card.tooltip.releaseName": "ชื่อรีลีส",
- "card.tooltip.source": "แหล่งที่มา",
"common.loadFailed": "โหลดล้มเหลว ลองอีกครั้งในภายหลัง",
- "createGuide.actions.back": "ย้อนกลับ",
- "createGuide.actions.createAndDeploy": "สร้างและปรับใช้",
- "createGuide.actions.creating": "กำลังสร้าง...",
- "createGuide.actions.deploying": "กำลังสร้างและปรับใช้...",
- "createGuide.actions.next": "ถัดไป",
- "createGuide.actions.skipDeploy": "ข้าม ปรับใช้ภายหลัง",
- "createGuide.dsl.defaultAppName": "แอปที่นำเข้าจาก DSL",
- "createGuide.dsl.description": "อัปโหลดแพ็คเกจ Workflow DSL เพื่อสร้างการปรับใช้ รีลีสแรก และการปรับใช้สภาพแวดล้อมเสริม",
- "createGuide.dsl.dropDescription": "อัปโหลดแพ็คเกจ Workflow YAML DSL ตัวเลือกการปรับใช้จะถูกแก้ไขจากไฟล์นี้ก่อนการปรับใช้",
- "createGuide.dsl.dropTitle": "อัปโหลดแพ็คเกจ Workflow DSL",
- "createGuide.dsl.readFailed": "ไม่สามารถอ่านไฟล์ DSL ได้ เลือกไฟล์อื่นและลองอีกครั้ง",
- "createGuide.dsl.reading": "กำลังอ่านไฟล์ DSL...",
- "createGuide.dsl.title": "นำเข้า DSL",
- "createGuide.dsl.unsupportedMode": "สามารถใช้เฉพาะไฟล์ Workflow DSL สำหรับการปรับใช้",
- "createGuide.errors.createReleaseFailed": "ไม่สามารถสร้างการปรับใช้หรือรีลีสได้",
- "createGuide.errors.deployFailed": "ไม่สามารถปรับใช้กับสภาพแวดล้อมได้",
- "createGuide.method.description": "เลือกแหล่งที่ใช้สำหรับสร้างรีลีสแรก",
- "createGuide.methods.bindApp.description": "ใช้ Workflow App ที่มีอยู่ใน Studio เป็นแหล่งรีลีส",
- "createGuide.methods.bindApp.title": "ผูกกับ Workflow App ที่มีอยู่",
- "createGuide.methods.importDsl.description": "อัปโหลดแพ็คเกจ Workflow YAML DSL และดำเนินการต่อผ่าน UI การปรับใช้",
- "createGuide.methods.importDsl.title": "นำเข้า DSL",
- "createGuide.nav.back": "การปรับใช้",
- "createGuide.release.defaultName": "รีลีสเริ่มต้น",
- "createGuide.release.deployInfo": "ข้อมูลการปรับใช้",
- "createGuide.release.description": "กรอกข้อมูลการปรับใช้และรายละเอียดของรีลีสแรก",
- "createGuide.release.firstVersion": "รีลีสแรก",
- "createGuide.release.instanceDescription": "คำอธิบายการปรับใช้",
- "createGuide.release.instanceDescriptionPlaceholder": "อธิบายว่าการปรับใช้นี้ใช้สำหรับอะไร",
- "createGuide.release.instanceName": "ชื่อการปรับใช้",
- "createGuide.release.instanceNameConflict": "มีการปรับใช้ที่มีชื่อนี้อยู่แล้ว เลือกชื่ออื่น",
- "createGuide.release.releaseDescription": "คำอธิบายรีลีส",
- "createGuide.release.releaseDescriptionPlaceholder": "อธิบายรีลีสนี้",
- "createGuide.release.releaseName": "ชื่อรีลีส",
- "createGuide.release.title": "ข้อมูลพื้นฐาน",
- "createGuide.source.clearSearch": "ล้างการค้นหาแอป",
- "createGuide.source.description": "เลือกแหล่งที่ใช้สำหรับสร้างรีลีสแรก",
- "createGuide.source.empty": "ไม่พบ Workflow App",
- "createGuide.source.searchPlaceholder": "ค้นหาแอป",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "แหล่งรีลีส",
- "createGuide.steps.method": "แหล่งรีลีส",
- "createGuide.steps.release": "ข้อมูลพื้นฐาน",
- "createGuide.steps.source": "แหล่งรีลีส",
- "createGuide.steps.target": "ปรับใช้กับสภาพแวดล้อม",
- "createGuide.target.bindingCount_one": "{{count}} การผูก",
- "createGuide.target.bindingCount_other": "{{count}} การผูก",
- "createGuide.target.bindingHint": "เลือกข้อมูลรับรองที่รีลีสนี้ใช้",
- "createGuide.target.bindings": "ข้อมูลรับรอง",
- "createGuide.target.description": "เลือกสภาพแวดล้อมเป้าหมายและระบุการตั้งค่ารันไทม์ที่รีลีสนี้ต้องการ ขั้นตอนนี้สามารถข้ามได้",
- "createGuide.target.envVarCount_one": "{{count}} ตัวแปร",
- "createGuide.target.envVarCount_other": "{{count}} ตัวแปร",
- "createGuide.target.envVarHint": "สำหรับแต่ละตัวแปรสภาพแวดล้อมที่รีลีสนี้ต้องการ ป้อนค่าที่กำหนดเองหรือใช้ค่าที่กำหนดในแอป",
- "createGuide.target.envVarPlaceholder": "ป้อนค่า",
- "createGuide.target.envVarSource.ariaLabel": "เลือกแหล่งค่าของตัวแปรสำหรับ {{key}}",
- "createGuide.target.envVarSource.default": "ค่าของแอป",
- "createGuide.target.envVarSource.lastDeployment": "ค่าที่ปรับใช้ครั้งล่าสุด",
- "createGuide.target.envVarSource.literal": "ค่าที่กำหนดเอง",
- "createGuide.target.envVarType.number": "ตัวเลข",
- "createGuide.target.envVarType.secret": "ความลับ",
- "createGuide.target.envVarType.string": "ข้อความ",
- "createGuide.target.envVars": "ตัวแปรสภาพแวดล้อม",
- "createGuide.target.environment": "สภาพแวดล้อมเป้าหมาย",
- "createGuide.target.loadBindingsFailed": "ไม่สามารถโหลดข้อมูลรับรองได้",
- "createGuide.target.loadEnvironmentsFailed": "ไม่สามารถโหลดสภาพแวดล้อมการปรับใช้ได้",
- "createGuide.target.missingRequiredBinding": "เลือกข้อมูลรับรองสำหรับการผูกที่จำเป็นนี้",
- "createGuide.target.noBindingRequired": "ไม่จำเป็นต้องใช้ข้อมูลรับรอง",
- "createGuide.target.noCredentialCandidates": "ไม่มีข้อมูลรับรองที่ใช้ได้",
- "createGuide.target.noEnvironmentOptions": "ไม่มีสภาพแวดล้อมการปรับใช้",
- "createGuide.target.selectCredential": "เลือกข้อมูลรับรอง",
- "createGuide.target.title": "ปรับใช้กับสภาพแวดล้อม",
- "createGuide.title": "การปรับใช้ใหม่",
- "createModal.appPickerPlaceholder": "เลือก Workflow App",
- "createModal.appSearchEmpty": "ไม่พบ Workflow App ที่ตรงกัน",
- "createModal.appSearchPlaceholder": "ค้นหา Workflow App…",
- "createModal.cancel": "ยกเลิก",
- "createModal.loadingApps": "กำลังโหลดแอป…",
- "deployDrawer.bindingCount_one": "{{count}} การผูก",
- "deployDrawer.bindingCount_other": "{{count}} การผูก",
"deployDrawer.bindingOptionsFailed": "ไม่สามารถโหลดตัวเลือกข้อมูลรับรองได้",
"deployDrawer.bindingSelectionHint": "เลือกข้อมูลรับรองที่ใช้โดยการปรับใช้นี้",
- "deployDrawer.cancel": "ยกเลิก",
- "deployDrawer.close": "ปิดลิ้นชักการปรับใช้",
- "deployDrawer.defaultSelect": "เลือก...",
- "deployDrawer.deploy": "ปรับใช้กับสภาพแวดล้อม",
- "deployDrawer.deployFailed": "ไม่สามารถเริ่มการปรับใช้ได้",
"deployDrawer.deploying": "กำลังปรับใช้...",
- "deployDrawer.description": "เลือกรีลีสและสภาพแวดล้อมเป้าหมายเพื่อปรับใช้",
- "deployDrawer.envVarCount_one": "{{count}} ตัวแปร",
- "deployDrawer.envVarCount_other": "{{count}} ตัวแปร",
- "deployDrawer.envVarHint": "สำหรับแต่ละตัวแปรสภาพแวดล้อมที่รีลีสนี้ต้องการ ป้อนค่าที่กำหนดเองหรือใช้ค่าที่กำหนดในแอป",
- "deployDrawer.envVarPlaceholder": "ป้อนค่า",
"deployDrawer.envVarSource.ariaLabel": "เลือกแหล่งค่าของตัวแปรสำหรับ {{key}}",
- "deployDrawer.envVarSource.default": "ค่าของแอป",
"deployDrawer.envVarSource.lastDeployment": "ค่าที่ปรับใช้ครั้งล่าสุด",
"deployDrawer.envVarSource.literal": "ค่าที่กำหนดเอง",
"deployDrawer.envVarType.number": "ตัวเลข",
"deployDrawer.envVarType.secret": "ความลับ",
"deployDrawer.envVarType.string": "ข้อความ",
"deployDrawer.envVars": "ตัวแปรสภาพแวดล้อม",
- "deployDrawer.existingReleaseHint": "รีลีสนี้จะถูกปรับใช้ตามที่เป็นอยู่ จะไม่มีการสร้างรีลีสใหม่",
- "deployDrawer.lockedHint": "ล็อกไว้ที่สภาพแวดล้อมปัจจุบัน",
- "deployDrawer.missingRequiredBinding": "เลือกข้อมูลรับรองสำหรับการผูกที่จำเป็นนี้",
- "deployDrawer.missingRequiredEnvVar": "ป้อนค่าสำหรับตัวแปรสภาพแวดล้อมที่จำเป็นนี้",
- "deployDrawer.noBindingRequired": "ไม่จำเป็น",
"deployDrawer.noCredentialCandidates": "ไม่มีข้อมูลรับรองที่ใช้ได้",
"deployDrawer.noNewEnvironmentAvailable": "สภาพแวดล้อมที่ใช้ได้ทั้งหมดมีการปรับใช้แล้ว",
- "deployDrawer.noOtherReleaseAvailable": "ไม่มีรีลีสอื่นสำหรับสภาพแวดล้อมนี้",
- "deployDrawer.noReleaseAvailable": "สร้างรีลีสก่อนปรับใช้กับสภาพแวดล้อม",
- "deployDrawer.notFound": "ไม่พบการปรับใช้",
- "deployDrawer.releaseLabel": "รีลีส",
"deployDrawer.runtimeCredentials": "ข้อมูลรับรอง",
"deployDrawer.selectCredential": "เลือกข้อมูลรับรอง",
- "deployDrawer.selectEnv": "เลือกสภาพแวดล้อม",
- "deployDrawer.selectRelease": "เลือกรีลีส",
- "deployDrawer.targetEnv": "สภาพแวดล้อมเป้าหมาย",
- "deployDrawer.title": "ปรับใช้กับสภาพแวดล้อม",
- "deployTab.closeError": "ปิด",
"deployTab.col.actions": "การดำเนินการ",
- "deployTab.col.currentRelease": "รีลีสปัจจุบัน",
"deployTab.col.environment": "สภาพแวดล้อม",
"deployTab.col.status": "สถานะ",
"deployTab.confirmUndeploy": "ยกเลิกการปรับใช้",
- "deployTab.deployOtherVersion": "ปรับใช้รีลีสอื่น",
- "deployTab.emptyDescription": "เลือกรีลีสและสภาพแวดล้อมเป้าหมายเพื่อทำให้การปรับใช้นี้พร้อมใช้งานสำหรับผู้ใช้",
- "deployTab.emptyTitle": "ยังไม่มีสภาพแวดล้อมที่ทำงานอยู่",
- "deployTab.errorCode": "รหัส",
- "deployTab.errorDialogDesc": "ตรวจสอบการปรับใช้ที่ล้มเหลวล่าสุดก่อนลองใหม่หรือปรับใช้รีลีสอื่น",
- "deployTab.errorDialogTitle": "ข้อผิดพลาดในการปรับใช้ใน {{name}}",
- "deployTab.errorMessage": "ข้อความ",
- "deployTab.errorPhase": "ระยะ",
"deployTab.moreActions": "การดำเนินการเพิ่มเติม",
- "deployTab.newDeployment": "ปรับใช้กับสภาพแวดล้อมใหม่",
- "deployTab.panel.unknownError": "การปรับใช้ล้มเหลว",
"deployTab.redeploy": "ปรับใช้ใหม่",
- "deployTab.retry": "ลองอีกครั้ง",
- "deployTab.status.deployFailed": "การปรับใช้ล้มเหลว",
- "deployTab.status.deployingRelease": "กำลังปรับใช้ ({{release}})",
- "deployTab.status.runningOutOfSync": "กำลังทำงาน (รอการซิงค์)",
- "deployTab.status.runningWithFailed": "กำลังทำงาน (การปรับใช้ครั้งล่าสุดล้มเหลว)",
"deployTab.undeploy": "ยกเลิกการปรับใช้",
- "deployTab.undeployConfirmDesc": "ปลายทางของสภาพแวดล้อมจะไม่พร้อมใช้งาน แต่เวอร์ชันจะไม่ถูกลบ",
- "deployTab.undeployConfirmTitle": "ยกเลิกการปรับใช้ {{name}}?",
"deployTab.undeployConfirmWarning": "หลังจากยืนยัน สภาพแวดล้อมนี้จะเข้าสู่สถานะกำลังยกเลิกการปรับใช้ และการดำเนินการต่าง ๆ จะถูกปิดใช้งานชั่วคราว",
- "deployTab.viewError": "ดูข้อผิดพลาด",
- "detail.mobileTabs": "ส่วนการปรับใช้",
- "detail.notFound": "ไม่พบการปรับใช้",
- "documentTitle.create": "การปรับใช้ใหม่ · การปรับใช้",
- "documentTitle.detail": "การปรับใช้ · การปรับใช้",
- "documentTitle.list": "การปรับใช้",
- "filter.allEnvs": "สภาพแวดล้อมทั้งหมด",
- "filter.searchPlaceholder": "ค้นหาการปรับใช้",
- "health.ENVIRONMENT_STATUS_ADMISSION": "การรับเข้า",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "กำลังเริ่มต้น",
- "health.ENVIRONMENT_STATUS_DELETING": "กำลังลบ",
"health.ENVIRONMENT_STATUS_FAILED": "ไม่พร้อมใช้งาน",
- "health.ENVIRONMENT_STATUS_READY": "พร้อมใช้งาน",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "ไม่ทราบ",
- "list.clearFilters": "ล้างตัวกรอง",
- "list.clearSearch": "ล้างการค้นหาการปรับใช้",
- "list.createDeployment": "ใหม่",
- "list.emptyDescription": "สร้างการปรับใช้จาก Workflow App หรือแพ็คเกจ Workflow DSL เพื่อจัดการรีลีส สภาพแวดล้อม และการเข้าถึง",
- "list.emptyFilteredDescription": "ไม่มีการปรับใช้ที่ตรงกับการค้นหาหรือตัวกรองสภาพแวดล้อมปัจจุบัน",
- "list.emptyFilteredTitle": "ไม่มีการปรับใช้ที่ตรงกัน",
"list.emptyTitle": "ยังไม่มีการปรับใช้",
- "mode.ENVIRONMENT_MODE_ISOLATED": "แยก",
- "mode.ENVIRONMENT_MODE_SHARED": "ใช้ร่วมกัน",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "ไม่ทราบ",
- "overview.accessMeta.apiTokens": "จัดการ API Tokens",
- "overview.accessMeta.cli": "ดูการเข้าถึง CLI",
- "overview.accessMeta.webApp": "จัดการการเข้าถึง WebApp",
- "overview.accessStatus": "การเข้าถึง",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} สภาพแวดล้อมที่ปรับใช้แล้ว",
- "overview.apiTokenSummary.environments_other": "{{count}} สภาพแวดล้อมที่ปรับใช้แล้ว",
- "overview.cardAction.deployLatest": "ปรับใช้รีลีสล่าสุด",
- "overview.cardAction.redeploy": "ปรับใช้ใหม่",
- "overview.cardAction.viewProgress": "ดูการปรับใช้",
- "overview.chip.behindTooltip_one": "ล้าหลังรีลีสล่าสุด 1 รีลีส ปรับใช้รีลีสล่าสุดเพื่ออัปเดต",
- "overview.chip.behindTooltip_other": "ล้าหลังรีลีสล่าสุด {{count}} รีลีส ปรับใช้รีลีสล่าสุดเพื่ออัปเดต",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "กำลังปรับใช้",
- "overview.chip.deployingTooltip": "การปรับใช้กำลังดำเนินการ",
- "overview.chip.empty": "ว่าง",
- "overview.chip.emptyTooltip": "ไม่มีรีลีสที่ปรับใช้กับสภาพแวดล้อมนี้",
- "overview.chip.failed": "ล้มเหลว",
- "overview.chip.failedTooltip": "ความพยายามในการปรับใช้ล่าสุดล้มเหลว",
"overview.chip.latest": "ล่าสุด",
- "overview.chip.latestTooltip": "สภาพแวดล้อมนี้กำลังใช้งานรีลีสล่าสุด",
- "overview.chip.needsReleaseFirst": "สร้างรีลีสก่อน",
- "overview.chip.olderRelease": "เก่ากว่า",
- "overview.chip.olderReleaseTooltip": "สภาพแวดล้อมนี้กำลังใช้งานรีลีสที่เก่ากว่า",
- "overview.chip.openInDeployTab": "ดูความคืบหน้าของการปรับใช้",
- "overview.disabled": "ปิดใช้งาน",
- "overview.enabled": "เปิดใช้งาน",
- "overview.hero.byName": "โดย {{name}}",
- "overview.hero.empty": "ยังไม่มีรีลีส",
- "overview.hero.emptyDescription": "สร้างรีลีสจากแหล่งที่มาปัจจุบันก่อนปรับใช้",
- "overview.latestRelease.releaseCount_one": "{{count}} รีลีส",
- "overview.latestRelease.releaseCount_other": "{{count}} รีลีส",
- "overview.latestReleaseTitle": "รีลีสล่าสุด",
- "overview.previousReleases.viewAll": "ดูทั้งหมด",
- "overview.strip.deployToNewEnvironment": "ปรับใช้กับสภาพแวดล้อมใหม่",
- "overview.strip.emptyDeployableDescription": "ปรับใช้รีลีสล่าสุดกับสภาพแวดล้อมเมื่อคุณพร้อม",
- "overview.strip.emptyDescription": "สร้างรีลีสก่อนปรับใช้กับสภาพแวดล้อม",
- "overview.strip.emptyTitle": "ยังไม่มีอินสแตนซ์",
- "overview.strip.title": "อินสแตนซ์",
- "settings.delete": "ลบการปรับใช้",
- "settings.deleteConfirmDesc": "ลบ {{name}}? ทุกอินสแตนซ์จะหยุดทำงานและถูกลบในทุกสภาพแวดล้อม การดำเนินการนี้ไม่สามารถยกเลิกได้",
- "settings.deleteConfirmTitle": "ลบการปรับใช้",
- "settings.deleteFailed": "ไม่สามารถลบการปรับใช้ได้",
- "settings.deleted": "ลบการปรับใช้แล้ว",
- "settings.description": "คำอธิบาย",
- "settings.name": "ชื่อการปรับใช้",
- "settings.save": "บันทึกการเปลี่ยนแปลง",
- "settings.updateFailed": "ไม่สามารถอัปเดตการปรับใช้ได้",
- "settings.updated": "อัปเดตการปรับใช้แล้ว",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "กำลังปรับใช้",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "รอการซิงค์",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "การปรับใช้ล้มเหลว",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "ไม่ถูกต้อง",
"status.RUNTIME_INSTANCE_STATUS_READY": "กำลังทำงาน",
@@ -370,87 +89,6 @@
"studio.versionValue": "ค่าของเวอร์ชัน",
"studio.versionsBehind_one": "ล้าหลัง {{count}} เวอร์ชัน",
"studio.versionsBehind_other": "ล้าหลัง {{count}} เวอร์ชัน",
- "tabs.access.description": "จัดการช่องทางการเข้าถึงและสิทธิ์การเข้าถึง",
- "tabs.access.name": "การเข้าถึง",
- "tabs.api-tokens.description": "จัดการ API Tokens และเรียกใช้อินสแตนซ์ผ่าน HTTP",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "ดูและจัดการอินสแตนซ์ในสภาพแวดล้อมที่ปรับใช้แล้ว",
- "tabs.instances.name": "อินสแตนซ์",
- "tabs.overview.description": "ดูสถานะการปรับใช้ข้ามสภาพแวดล้อม",
- "tabs.overview.name": "ภาพรวม",
- "tabs.releases.description": "สร้าง ปรับใช้ และจัดการรีลีส",
- "tabs.releases.name": "รีลีส",
- "unsupportedDslNodes.description": "รีลีสนี้มีโหนดที่รันไทม์ของการปรับใช้ยังไม่รองรับ ลบหรือแทนที่ใน Studio แล้วลองอีกครั้ง",
- "unsupportedDslNodes.descriptionWithTypes": "รีลีสนี้มีโหนดที่รันไทม์ของการปรับใช้ยังไม่รองรับ: {{nodeTypes}} ลบหรือแทนที่ใน Studio แล้วลองอีกครั้ง",
- "unsupportedDslNodes.title": "โหนดที่ไม่รองรับ",
- "unsupportedDslNodes.unknownType": "ประเภทที่ไม่ทราบ",
- "versions.cancelCreate": "ยกเลิก",
- "versions.cancelDelete": "ยกเลิก",
- "versions.cancelEdit": "ยกเลิก",
"versions.checkingReleaseContent": "กำลังตรวจสอบเนื้อหารีลีส...",
- "versions.col.action": "การดำเนินการ",
- "versions.col.author": "สร้างโดย",
- "versions.col.createdAt": "สร้างเมื่อ",
- "versions.col.deployedTo": "ปรับใช้กับ",
- "versions.col.release": "รีลีส",
- "versions.col.sourceApp": "แหล่งที่มา",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "สร้าง",
- "versions.createFailed": "ไม่สามารถสร้างรีลีสได้",
- "versions.createRelease": "สร้างรีลีส",
- "versions.createReleaseDescription": "สร้างรีลีสที่ปรับใช้ได้จาก Workflow App หรือไฟล์ Workflow DSL",
- "versions.createSuccess": "สร้างรีลีส \"{{name}}\" แล้ว",
- "versions.creating": "กำลังสร้าง...",
- "versions.currentOn": "รีลีสปัจจุบันใน {{name}}",
- "versions.deleteConfirmDesc": "รีลีส \"{{name}}\" จะถูกลบอย่างถาวร การดำเนินการนี้ไม่สามารถยกเลิกได้",
- "versions.deleteConfirmTitle": "ลบรีลีส?",
- "versions.deleteFailed": "ไม่สามารถลบรีลีสได้",
- "versions.deleteRelease": "ลบรีลีส",
- "versions.deleteSuccess": "ลบรีลีส \"{{name}}\" แล้ว",
- "versions.deployTo": "ปรับใช้กับ {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "กำลังปรับใช้",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "รอการซิงค์",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "ล้มเหลว",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "ไม่ถูกต้อง",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "กำลังทำงาน",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "ยังไม่ได้ปรับใช้",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "กำลังยกเลิกการปรับใช้",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "ไม่ทราบ",
- "versions.deployingTo": "{{name}} กำลังปรับใช้",
- "versions.disabledReason.checkDeploymentsFailed": "ไม่สามารถตรวจสอบการใช้งานการปรับใช้ได้ ลองอีกครั้งในภายหลัง",
- "versions.disabledReason.checkingDeployments": "กำลังตรวจสอบการใช้งานการปรับใช้",
- "versions.disabledReason.current": "รีลีสนี้กำลังทำงานอยู่บน {{name}} แล้ว",
- "versions.disabledReason.deploying": "รอให้การปรับใช้ที่กำลังดำเนินการเสร็จสิ้น",
- "versions.disabledReason.releaseInUse_one": "ยกเลิกการปรับใช้รีลีสนี้จาก {{count}} สภาพแวดล้อมก่อนลบ",
- "versions.disabledReason.releaseInUse_other": "ยกเลิกการปรับใช้รีลีสนี้จาก {{count}} สภาพแวดล้อมก่อนลบ",
- "versions.dslReadFailed": "ไม่สามารถอ่านไฟล์ DSL ได้ เลือกไฟล์อื่นและลองอีกครั้ง",
- "versions.dslReading": "กำลังอ่านไฟล์ DSL...",
- "versions.dslUnsupportedMode": "สามารถใช้เฉพาะไฟล์ Workflow DSL สำหรับการปรับใช้",
- "versions.editFailed": "ไม่สามารถอัปเดตรีลีสได้",
- "versions.editRelease": "แก้ไขรีลีส",
- "versions.editReleaseDescription": "อัปเดตชื่อและคำอธิบายของรีลีสนี้",
- "versions.editSuccess": "อัปเดตรีลีส \"{{name}}\" แล้ว",
- "versions.emptyDescription": "สร้างรีลีสแรกก่อนปรับใช้กับสภาพแวดล้อม",
- "versions.emptyTitle": "ยังไม่มีรีลีส",
- "versions.exportDsl": "ส่งออก DSL",
- "versions.exportDslFailed": "ไม่สามารถส่งออก DSL ได้",
- "versions.exportingDsl": "กำลังส่งออก...",
- "versions.groupHeader.deploy": "ปรับใช้",
- "versions.groupHeader.rollback": "ปรับใช้เวอร์ชันก่อนหน้า",
- "versions.groupHeader.unavailable": "ไม่พร้อมใช้งาน",
- "versions.manualDslOption": "อัปโหลด DSL",
- "versions.moreActions": "การดำเนินการเพิ่มเติม",
- "versions.optional": "ไม่บังคับ",
- "versions.releaseAlreadyExists": "มีรีลีสที่มีเนื้อหาเดียวกันอยู่แล้ว: {{name}}",
- "versions.releaseContentCheckFailed": "ไม่สามารถตรวจสอบเนื้อหารีลีสได้",
- "versions.releaseDescriptionLabel": "คำอธิบาย",
- "versions.releaseDescriptionPlaceholder": "อธิบายรีลีสนี้",
- "versions.releaseNameConflict": "มีรีลีสชื่อนี้อยู่แล้ว โปรดเลือกชื่ออื่น",
- "versions.releaseNameLabel": "ชื่อรีลีส",
- "versions.releaseNamePlaceholder": "ชื่อรีลีส",
- "versions.releaseNameRequired": "ป้อนชื่อรีลีส",
- "versions.releaseSourceLabel": "แหล่งรีลีส",
- "versions.rollbackTo": "ปรับใช้กับ {{name}}",
- "versions.saveEdit": "บันทึก",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "ปรับใช้กับ {{name}}"
}
diff --git a/web/i18n/tr-TR/common.json b/web/i18n/tr-TR/common.json
index 041722d078c..30a5e4cbb60 100644
--- a/web/i18n/tr-TR/common.json
+++ b/web/i18n/tr-TR/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Uygulama Detayı",
"menus.apps": "Studio",
"menus.datasets": "Bilgi",
- "menus.deployments": "Dağıtımlar",
"menus.exploreMarketplace": "Pazar Yeri'ni Keşfedin",
"menus.plugins": "Entegrasyonlar",
"menus.status": "beta",
diff --git a/web/i18n/tr-TR/deployments.json b/web/i18n/tr-TR/deployments.json
index 67d947a5f24..61b6fdb47b0 100644
--- a/web/i18n/tr-TR/deployments.json
+++ b/web/i18n/tr-TR/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "cURL örneğini kopyala",
- "access.api.createFailed": "API Token oluşturulamadı.",
- "access.api.createKey": "API Token Oluştur",
- "access.api.createKeyTitle": "Yeni API Token oluştur",
- "access.api.curlExampleTitle": "cURL örneği",
- "access.api.description": "Bu dağıtıma HTTP üzerinden erişin. Her API Token tek bir ortamla sınırlıdır.",
- "access.api.developerTitle": "Geliştirici API'si",
- "access.api.disabled": "Bu dağıtım için API erişimi kapalı.",
- "access.api.disabledHint": "Ortam kapsamlı tokenler oluşturmak için API erişimini etkinleştirin.",
- "access.api.docs": "API Dokümanları",
- "access.api.docsClose": "API dokümanlarını kapat",
- "access.api.docsDescription": "Bu dağıtım için Workflow API referansını görüntüleyin.",
- "access.api.docsTitle": "Workflow API dokümantasyonu",
- "access.api.empty": "API Token vermeye başlamak için önce bir ortama dağıtın.",
- "access.api.emptyTitle": "Dağıtılmış ortam yok",
- "access.api.endpoint": "İstek URL'si",
- "access.api.keyList": "API Token listesi",
- "access.api.nameLabel": "API Token adı",
- "access.api.namePlaceholder": "Bir API Token adı girin",
- "access.api.nameRequired": "API Token adı zorunludur.",
- "access.api.newKey": "Yeni API Token Oluştur",
- "access.api.newTokenDescription": "Bu API Token yalnızca bir kez gösterilir. Bu sayfadan ayrılmadan önce kopyalayın.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token oluşturuldu",
- "access.api.noKeys": "Henüz API Token yok. API'yi çağırmaya başlamak için bir tane oluşturun.",
- "access.api.noKeysTitle": "Henüz API Token yok",
- "access.api.revokeConfirmDescription": "\"{{name}}\" adlı API Token hemen çalışmayı durduracak. Bu işlem geri alınamaz.",
- "access.api.revokeConfirmTitle": "API Token iptal edilsin mi?",
- "access.api.revokeFailed": "API Token iptal edilemedi.",
- "access.api.revokeSuccess": "API Token iptal edildi",
- "access.api.table.action": "İşlem",
- "access.api.table.environment": "Ortam",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Ad",
- "access.channels.disabled": "Bu dağıtım için erişim kanalları kapalı.",
- "access.channels.disabledHint": "WebApp ve CLI giriş noktalarını açmak için erişim kanallarını etkinleştirin.",
- "access.channels.title": "Erişim kanalları",
- "access.cli.description": "Komut dosyaları, otomatik iş akışları veya Agent entegrasyonları için uygun olan difyctl ile terminalden çağırın.",
- "access.cli.docs": "Kullanım kılavuzu",
- "access.cli.domain": "Alan adı",
- "access.cli.empty": "CLI uç noktası yapılandırılmamış.",
- "access.cli.install": "CLI'yi yükle",
- "access.cli.title": "CLI",
- "access.copy": "Kopyala",
- "access.copyFailed": "Kopyalama başarısız",
- "access.members.groupCount_one": "{{count}} grup",
- "access.members.groupCount_other": "{{count}} grup",
- "access.members.memberCount_one": "{{count}} üye",
- "access.members.memberCount_other": "{{count}} üye",
- "access.permission.anyone": "Bağlantıya sahip herkes",
- "access.permission.organization": "Platformdaki tüm üyeler",
- "access.permission.specific": "Platformdaki belirli üyeler",
- "access.permission.specificDesc": "Belirli grupları veya üyeleri seçin",
- "access.permission.updateFailed": "Erişim politikası güncellenemedi.",
- "access.permissions.editAriaLabel": "{{environment}} için erişimi yapılandır",
- "access.permissions.editDescription": "WebApp ve CLI giriş noktaları için erişim izinlerini ayarlayın.",
- "access.permissions.editTitle": "Erişim izinleri",
- "access.permissions.title": "Erişim izinleri",
- "access.revoke": "İptal et",
- "access.runAccess.noEnvs": "Erişim izinlerini yapılandırmak için bir ortama dağıtın.",
- "access.runAccess.noEnvsTitle": "Dağıtılmış ortam yok",
- "access.runAccess.openWebapp": "WebApp'i aç",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Son kullanıcılar için barındırılan web sayfası.",
- "access.runAccess.webappEmpty": "Yakında.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Harici",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Bilinmiyor",
- "card.access.api": "API Tokenleri",
- "card.access.cli": "CLI",
- "card.access.none": "Erişim yok",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "İlk Sürümü Oluştur",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Dağıtımı sil",
- "card.menu.deploy": "Ortama Dağıt",
- "card.menu.editInfo": "Bilgileri Düzenle",
- "card.moreActions": "Daha fazla işlem",
- "card.noDescription": "Açıklama sağlanmadı.",
"card.notDeployed": "Dağıtılmadı",
- "card.tooltip.createdAt": "Oluşturuldu",
- "card.tooltip.deployed": "Dağıtıldı",
- "card.tooltip.deploymentStatus": "Dağıtım",
- "card.tooltip.notDeployedShort": "Dağıtılmadı",
- "card.tooltip.releaseName": "Sürüm Adı",
- "card.tooltip.source": "Kaynak",
"common.loadFailed": "Yüklenemedi. Daha sonra tekrar deneyin.",
- "createGuide.actions.back": "Geri",
- "createGuide.actions.createAndDeploy": "Oluştur ve Dağıt",
- "createGuide.actions.creating": "Oluşturuluyor...",
- "createGuide.actions.deploying": "Oluşturuluyor ve dağıtılıyor...",
- "createGuide.actions.next": "İleri",
- "createGuide.actions.skipDeploy": "Atla, sonra dağıt",
- "createGuide.dsl.defaultAppName": "İçe aktarılmış DSL uygulaması",
- "createGuide.dsl.description": "Dağıtımı, ilk sürümü ve isteğe bağlı ortam dağıtımını oluşturmak için bir Workflow DSL paketi yükleyin.",
- "createGuide.dsl.dropDescription": "Bir Workflow YAML DSL paketi yükleyin. Dağıtım seçenekleri, dağıtımdan önce bu dosyadan çözümlenir.",
- "createGuide.dsl.dropTitle": "Workflow DSL paketi yükle",
- "createGuide.dsl.readFailed": "DSL dosyası okunamadı. Başka bir dosya seçip tekrar deneyin.",
- "createGuide.dsl.reading": "DSL dosyası okunuyor...",
- "createGuide.dsl.title": "DSL İçe Aktar",
- "createGuide.dsl.unsupportedMode": "Dağıtımlar için yalnızca Workflow DSL dosyaları kullanılabilir.",
- "createGuide.errors.createReleaseFailed": "Dağıtım veya sürüm oluşturulamadı.",
- "createGuide.errors.deployFailed": "Ortama dağıtılamadı.",
- "createGuide.method.description": "İlk sürümü oluşturmak için kullanılan kaynağı seçin.",
- "createGuide.methods.bindApp.description": "Sürüm kaynağı olarak Studio'daki mevcut bir Workflow App'ı kullanın.",
- "createGuide.methods.bindApp.title": "Mevcut Workflow App'ı bağla",
- "createGuide.methods.importDsl.description": "Bir Workflow YAML DSL paketi yükleyin ve dağıtım arayüzünden devam edin.",
- "createGuide.methods.importDsl.title": "DSL İçe Aktar",
- "createGuide.nav.back": "Dağıtımlar",
- "createGuide.release.defaultName": "ilk sürüm",
- "createGuide.release.deployInfo": "Dağıtım Bilgileri",
- "createGuide.release.description": "Dağıtım bilgilerini ve ilk sürüm ayrıntılarını doldurun.",
- "createGuide.release.firstVersion": "İlk Sürüm",
- "createGuide.release.instanceDescription": "Dağıtım Açıklaması",
- "createGuide.release.instanceDescriptionPlaceholder": "Bu dağıtımın ne için kullanıldığını açıklayın",
- "createGuide.release.instanceName": "Dağıtım Adı",
- "createGuide.release.instanceNameConflict": "Bu ada sahip bir dağıtım zaten var. Başka bir ad seçin.",
- "createGuide.release.releaseDescription": "Sürüm Açıklaması",
- "createGuide.release.releaseDescriptionPlaceholder": "Bu sürümü açıklayın",
- "createGuide.release.releaseName": "Sürüm Adı",
- "createGuide.release.title": "Temel Bilgiler",
- "createGuide.source.clearSearch": "Uygulama aramasını temizle",
- "createGuide.source.description": "İlk sürümü oluşturmak için kullanılan kaynağı seçin.",
- "createGuide.source.empty": "Workflow App bulunamadı.",
- "createGuide.source.searchPlaceholder": "Uygulama ara",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Sürüm Kaynağı",
- "createGuide.steps.method": "Sürüm Kaynağı",
- "createGuide.steps.release": "Temel Bilgiler",
- "createGuide.steps.source": "Sürüm Kaynağı",
- "createGuide.steps.target": "Ortama Dağıt",
- "createGuide.target.bindingCount_one": "{{count}} bağlama",
- "createGuide.target.bindingCount_other": "{{count}} bağlama",
- "createGuide.target.bindingHint": "Bu sürüm tarafından kullanılan kimlik bilgilerini seçin.",
- "createGuide.target.bindings": "Kimlik bilgileri",
- "createGuide.target.description": "Bir hedef ortam seçin ve bu sürümün orada ihtiyaç duyduğu çalışma zamanı ayarlarını sağlayın. Bu adım atlanabilir.",
- "createGuide.target.envVarCount_one": "{{count}} değişken",
- "createGuide.target.envVarCount_other": "{{count}} değişken",
- "createGuide.target.envVarHint": "Bu sürümün ihtiyaç duyduğu her ortam değişkeni için özel bir değer girin veya uygulamada tanımlanan değeri kullanın.",
- "createGuide.target.envVarPlaceholder": "Değer girin",
- "createGuide.target.envVarSource.ariaLabel": "{{key}} için değişken değer kaynağını seçin",
- "createGuide.target.envVarSource.default": "Uygulama değeri",
- "createGuide.target.envVarSource.lastDeployment": "Son dağıtılan değer",
- "createGuide.target.envVarSource.literal": "Özel değer",
- "createGuide.target.envVarType.number": "Sayı",
- "createGuide.target.envVarType.secret": "Gizli",
- "createGuide.target.envVarType.string": "Metin",
- "createGuide.target.envVars": "Ortam Değişkenleri",
- "createGuide.target.environment": "Hedef Ortam",
- "createGuide.target.loadBindingsFailed": "Kimlik bilgileri yüklenemedi.",
- "createGuide.target.loadEnvironmentsFailed": "Dağıtım ortamları yüklenemedi.",
- "createGuide.target.missingRequiredBinding": "Bu zorunlu bağlama için bir kimlik bilgisi seçin.",
- "createGuide.target.noBindingRequired": "Kimlik bilgisi gerekmiyor.",
- "createGuide.target.noCredentialCandidates": "Kullanılabilir kimlik bilgisi yok.",
- "createGuide.target.noEnvironmentOptions": "Kullanılabilir dağıtım ortamı yok.",
- "createGuide.target.selectCredential": "Bir kimlik bilgisi seçin",
- "createGuide.target.title": "Ortama Dağıt",
- "createGuide.title": "Yeni Dağıtım",
- "createModal.appPickerPlaceholder": "Bir Workflow App seçin",
- "createModal.appSearchEmpty": "Eşleşen Workflow App yok",
- "createModal.appSearchPlaceholder": "Workflow App ara…",
- "createModal.cancel": "İptal",
- "createModal.loadingApps": "Uygulamalar yükleniyor…",
- "deployDrawer.bindingCount_one": "{{count}} bağlama",
- "deployDrawer.bindingCount_other": "{{count}} bağlama",
"deployDrawer.bindingOptionsFailed": "Kimlik bilgisi seçenekleri yüklenemedi.",
"deployDrawer.bindingSelectionHint": "Bu dağıtım tarafından kullanılan kimlik bilgilerini seçin.",
- "deployDrawer.cancel": "İptal",
- "deployDrawer.close": "Dağıtım çekmecesini kapat",
- "deployDrawer.defaultSelect": "Seçin...",
- "deployDrawer.deploy": "Ortama Dağıt",
- "deployDrawer.deployFailed": "Dağıtım başlatılamadı.",
"deployDrawer.deploying": "Dağıtılıyor...",
- "deployDrawer.description": "Dağıtmak için bir sürüm ve hedef ortam seçin.",
- "deployDrawer.envVarCount_one": "{{count}} değişken",
- "deployDrawer.envVarCount_other": "{{count}} değişken",
- "deployDrawer.envVarHint": "Bu sürümün ihtiyaç duyduğu her ortam değişkeni için özel bir değer girin veya uygulamada tanımlanan değeri kullanın.",
- "deployDrawer.envVarPlaceholder": "Değer girin",
"deployDrawer.envVarSource.ariaLabel": "{{key}} için değişken değer kaynağını seçin",
- "deployDrawer.envVarSource.default": "Uygulama değeri",
"deployDrawer.envVarSource.lastDeployment": "Son dağıtılan değer",
"deployDrawer.envVarSource.literal": "Özel değer",
"deployDrawer.envVarType.number": "Sayı",
"deployDrawer.envVarType.secret": "Gizli",
"deployDrawer.envVarType.string": "Metin",
"deployDrawer.envVars": "Ortam Değişkenleri",
- "deployDrawer.existingReleaseHint": "Bu sürüm olduğu gibi dağıtılacak. Yeni bir sürüm oluşturulmayacak.",
- "deployDrawer.lockedHint": "Geçerli ortama kilitli",
- "deployDrawer.missingRequiredBinding": "Bu zorunlu bağlama için bir kimlik bilgisi seçin.",
- "deployDrawer.missingRequiredEnvVar": "Bu zorunlu ortam değişkeni için bir değer girin.",
- "deployDrawer.noBindingRequired": "Gerekli değil",
"deployDrawer.noCredentialCandidates": "Kullanılabilir kimlik bilgisi yok.",
"deployDrawer.noNewEnvironmentAvailable": "Tüm kullanılabilir ortamların zaten bir dağıtımı var.",
- "deployDrawer.noOtherReleaseAvailable": "Bu ortam için başka kullanılabilir sürüm yok.",
- "deployDrawer.noReleaseAvailable": "Bir ortama dağıtmadan önce bir sürüm oluşturun.",
- "deployDrawer.notFound": "Dağıtım bulunamadı.",
- "deployDrawer.releaseLabel": "Sürüm",
"deployDrawer.runtimeCredentials": "Kimlik bilgileri",
"deployDrawer.selectCredential": "Bir kimlik bilgisi seçin",
- "deployDrawer.selectEnv": "Bir ortam seçin",
- "deployDrawer.selectRelease": "Bir sürüm seçin",
- "deployDrawer.targetEnv": "Hedef Ortam",
- "deployDrawer.title": "Ortama Dağıt",
- "deployTab.closeError": "Kapat",
"deployTab.col.actions": "İşlemler",
- "deployTab.col.currentRelease": "Geçerli Sürüm",
"deployTab.col.environment": "Ortam",
"deployTab.col.status": "Durum",
"deployTab.confirmUndeploy": "Dağıtımı Geri Al",
- "deployTab.deployOtherVersion": "Başka Bir Sürüm Dağıt",
- "deployTab.emptyDescription": "Bu dağıtımı kullanıcılara sunmak için bir sürüm ve hedef ortam seçin.",
- "deployTab.emptyTitle": "Henüz çalışan ortam yok",
- "deployTab.errorCode": "Kod",
- "deployTab.errorDialogDesc": "Tekrar denemeden veya başka bir sürüm dağıtmadan önce son başarısız dağıtımı inceleyin.",
- "deployTab.errorDialogTitle": "{{name}} ortamında dağıtım hatası",
- "deployTab.errorMessage": "Mesaj",
- "deployTab.errorPhase": "Aşama",
"deployTab.moreActions": "Daha fazla işlem",
- "deployTab.newDeployment": "Yeni Ortama Dağıt",
- "deployTab.panel.unknownError": "Dağıtım başarısız oldu.",
"deployTab.redeploy": "Yeniden Dağıt",
- "deployTab.retry": "Tekrar Dene",
- "deployTab.status.deployFailed": "Dağıtım başarısız",
- "deployTab.status.deployingRelease": "Dağıtılıyor ({{release}})",
- "deployTab.status.runningOutOfSync": "Çalışıyor (eşitleme bekleniyor)",
- "deployTab.status.runningWithFailed": "Çalışıyor (son dağıtım başarısız)",
"deployTab.undeploy": "Dağıtımı Geri Al",
- "deployTab.undeployConfirmDesc": "Ortam uç noktası kullanılamaz hale gelecek, ancak sürüm silinmeyecek.",
- "deployTab.undeployConfirmTitle": "{{name}} dağıtımdan kaldırılsın mı?",
"deployTab.undeployConfirmWarning": "Onaydan sonra bu ortam dağıtımdan kaldırılıyor durumuna geçecek ve işlemler geçici olarak devre dışı bırakılacak.",
- "deployTab.viewError": "Hatayı görüntüle",
- "detail.mobileTabs": "Dağıtım bölümleri",
- "detail.notFound": "Dağıtım bulunamadı",
- "documentTitle.create": "Yeni dağıtım · Dağıtımlar",
- "documentTitle.detail": "Dağıtım · Dağıtımlar",
- "documentTitle.list": "Dağıtımlar",
- "filter.allEnvs": "Tüm ortamlar",
- "filter.searchPlaceholder": "Dağıtımları ara",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Kabul",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Başlatılıyor",
- "health.ENVIRONMENT_STATUS_DELETING": "Siliniyor",
"health.ENVIRONMENT_STATUS_FAILED": "Kullanılamıyor",
- "health.ENVIRONMENT_STATUS_READY": "Kullanılabilir",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Bilinmiyor",
- "list.clearFilters": "Filtreleri temizle",
- "list.clearSearch": "Dağıtım aramasını temizle",
- "list.createDeployment": "Yeni",
- "list.emptyDescription": "Sürümleri, ortamları ve erişimi yönetmek için bir Workflow App veya Workflow DSL paketinden bir dağıtım oluşturun.",
- "list.emptyFilteredDescription": "Geçerli arama veya ortam filtresiyle eşleşen dağıtım yok.",
- "list.emptyFilteredTitle": "Eşleşen dağıtım yok",
"list.emptyTitle": "Henüz dağıtım yok",
- "mode.ENVIRONMENT_MODE_ISOLATED": "İzole",
- "mode.ENVIRONMENT_MODE_SHARED": "Paylaşılan",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Bilinmiyor",
- "overview.accessMeta.apiTokens": "API Tokenlerini yönet",
- "overview.accessMeta.cli": "CLI erişimini görüntüle",
- "overview.accessMeta.webApp": "WebApp erişimini yönet",
- "overview.accessStatus": "Erişim",
- "overview.api": "API Tokenleri",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Token",
- "overview.apiTokenSummary.environments_one": "{{count}} dağıtılmış ortam",
- "overview.apiTokenSummary.environments_other": "{{count}} dağıtılmış ortam",
- "overview.cardAction.deployLatest": "En Son Sürümü Dağıt",
- "overview.cardAction.redeploy": "Yeniden Dağıt",
- "overview.cardAction.viewProgress": "Dağıtımı görüntüle",
- "overview.chip.behindTooltip_one": "En son sürümün 1 sürüm gerisinde. Güncellemek için en son sürümü dağıtın.",
- "overview.chip.behindTooltip_other": "En son sürümün {{count}} sürüm gerisinde. Güncellemek için en son sürümü dağıtın.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "dağıtılıyor",
- "overview.chip.deployingTooltip": "Dağıtım sürüyor.",
- "overview.chip.empty": "boş",
- "overview.chip.emptyTooltip": "Bu ortama hiçbir sürüm dağıtılmadı.",
- "overview.chip.failed": "başarısız",
- "overview.chip.failedTooltip": "Son dağıtım denemesi başarısız oldu.",
"overview.chip.latest": "en son",
- "overview.chip.latestTooltip": "Bu ortam en son sürümü çalıştırıyor.",
- "overview.chip.needsReleaseFirst": "Önce bir Sürüm oluşturun",
- "overview.chip.olderRelease": "eski",
- "overview.chip.olderReleaseTooltip": "Bu ortam daha eski bir sürümü çalıştırıyor.",
- "overview.chip.openInDeployTab": "Dağıtım ilerlemesini görüntüle",
- "overview.disabled": "Devre dışı",
- "overview.enabled": "Etkin",
- "overview.hero.byName": "{{name}} tarafından",
- "overview.hero.empty": "Henüz sürüm yok",
- "overview.hero.emptyDescription": "Dağıtmadan önce mevcut kaynaktan bir sürüm oluşturun.",
- "overview.latestRelease.releaseCount_one": "{{count}} sürüm",
- "overview.latestRelease.releaseCount_other": "{{count}} sürüm",
- "overview.latestReleaseTitle": "En Son Sürüm",
- "overview.previousReleases.viewAll": "Tümünü Görüntüle",
- "overview.strip.deployToNewEnvironment": "Yeni ortama dağıt",
- "overview.strip.emptyDeployableDescription": "Hazır olduğunuzda en son sürümü bir ortama dağıtın.",
- "overview.strip.emptyDescription": "Bir ortama dağıtmadan önce bir sürüm oluşturun.",
- "overview.strip.emptyTitle": "Henüz örnek yok",
- "overview.strip.title": "Örnekler",
- "settings.delete": "Dağıtımı Sil",
- "settings.deleteConfirmDesc": "{{name}} silinsin mi? Her örnek tüm ortamlarda çalışmayı durduracak ve kaldırılacak. Bu geri alınamaz.",
- "settings.deleteConfirmTitle": "Dağıtımı sil",
- "settings.deleteFailed": "Dağıtım silinemedi.",
- "settings.deleted": "Dağıtım silindi",
- "settings.description": "Açıklama",
- "settings.name": "Dağıtım adı",
- "settings.save": "Değişiklikleri Kaydet",
- "settings.updateFailed": "Dağıtım güncellenemedi.",
- "settings.updated": "Dağıtım güncellendi",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Dağıtılıyor",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Eşitleme bekleniyor",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Dağıtım başarısız",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Geçersiz",
"status.RUNTIME_INSTANCE_STATUS_READY": "Çalışıyor",
@@ -370,87 +89,6 @@
"studio.versionValue": "Sürüm değeri",
"studio.versionsBehind_one": "{{count}} sürüm geride",
"studio.versionsBehind_other": "{{count}} sürüm geride",
- "tabs.access.description": "Erişim kanallarını ve erişim izinlerini yönetin.",
- "tabs.access.name": "Erişim",
- "tabs.api-tokens.description": "API Tokenlerini yönetin ve örnekleri HTTP üzerinden çağırın.",
- "tabs.api-tokens.name": "API Tokenleri",
- "tabs.instances.description": "Dağıtılmış ortamlardaki örnekleri görüntüleyin ve yönetin.",
- "tabs.instances.name": "Örnekler",
- "tabs.overview.description": "Dağıtımın ortamlar arasındaki durumunu görüntüleyin.",
- "tabs.overview.name": "Genel Bakış",
- "tabs.releases.description": "Sürümleri oluşturun, dağıtın ve yönetin.",
- "tabs.releases.name": "Sürümler",
- "unsupportedDslNodes.description": "Bu sürüm, dağıtım çalışma zamanının henüz desteklemediği düğümler içeriyor. Studio'da bunları kaldırın veya değiştirin, ardından tekrar deneyin.",
- "unsupportedDslNodes.descriptionWithTypes": "Bu sürüm, dağıtım çalışma zamanının henüz desteklemediği düğümler içeriyor: {{nodeTypes}}. Studio'da bunları kaldırın veya değiştirin, ardından tekrar deneyin.",
- "unsupportedDslNodes.title": "Desteklenmeyen düğümler",
- "unsupportedDslNodes.unknownType": "Bilinmeyen tür",
- "versions.cancelCreate": "İptal",
- "versions.cancelDelete": "İptal",
- "versions.cancelEdit": "İptal",
"versions.checkingReleaseContent": "Sürüm içeriği kontrol ediliyor...",
- "versions.col.action": "İşlem",
- "versions.col.author": "Oluşturan",
- "versions.col.createdAt": "Oluşturulma tarihi",
- "versions.col.deployedTo": "Dağıtıldığı yer",
- "versions.col.release": "Sürüm",
- "versions.col.sourceApp": "Kaynak",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Oluştur",
- "versions.createFailed": "Sürüm oluşturulamadı.",
- "versions.createRelease": "Sürüm Oluştur",
- "versions.createReleaseDescription": "Bir Workflow App veya Workflow DSL dosyasından dağıtılabilir bir sürüm oluşturun.",
- "versions.createSuccess": "\"{{name}}\" sürümü oluşturuldu.",
- "versions.creating": "Oluşturuluyor...",
- "versions.currentOn": "{{name}} üzerindeki Geçerli Sürüm",
- "versions.deleteConfirmDesc": "\"{{name}}\" sürümü kalıcı olarak silinecek. Bu geri alınamaz.",
- "versions.deleteConfirmTitle": "Sürüm silinsin mi?",
- "versions.deleteFailed": "Sürüm silinemedi.",
- "versions.deleteRelease": "Sürümü Sil",
- "versions.deleteSuccess": "\"{{name}}\" sürümü silindi.",
- "versions.deployTo": "{{name}} ortamına dağıt",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Dağıtılıyor",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Eşitleme bekleniyor",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Başarısız",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Geçersiz",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Çalışıyor",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Dağıtılmadı",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Dağıtım geri alınıyor",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Bilinmiyor",
- "versions.deployingTo": "{{name}} dağıtılıyor",
- "versions.disabledReason.checkDeploymentsFailed": "Dağıtım kullanımı doğrulanamadı. Daha sonra tekrar deneyin.",
- "versions.disabledReason.checkingDeployments": "Dağıtım kullanımı kontrol ediliyor",
- "versions.disabledReason.current": "Bu sürüm zaten {{name}} üzerinde çalışıyor",
- "versions.disabledReason.deploying": "Aktif dağıtımın bitmesini bekleyin",
- "versions.disabledReason.releaseInUse_one": "Silmeden önce bu sürümün {{count}} ortamdan dağıtımını geri alın",
- "versions.disabledReason.releaseInUse_other": "Silmeden önce bu sürümün {{count}} ortamdan dağıtımını geri alın",
- "versions.dslReadFailed": "DSL dosyası okunamadı. Başka bir dosya seçip tekrar deneyin.",
- "versions.dslReading": "DSL dosyası okunuyor...",
- "versions.dslUnsupportedMode": "Dağıtımlar için yalnızca Workflow DSL dosyaları kullanılabilir.",
- "versions.editFailed": "Sürüm güncellenemedi.",
- "versions.editRelease": "Sürümü Düzenle",
- "versions.editReleaseDescription": "Bu sürümün adını ve açıklamasını güncelleyin.",
- "versions.editSuccess": "\"{{name}}\" sürümü güncellendi.",
- "versions.emptyDescription": "Bir ortama dağıtmadan önce ilk sürümü oluşturun.",
- "versions.emptyTitle": "Henüz sürüm yok",
- "versions.exportDsl": "DSL Dışa Aktar",
- "versions.exportDslFailed": "DSL dışa aktarılamadı.",
- "versions.exportingDsl": "Dışa aktarılıyor...",
- "versions.groupHeader.deploy": "Dağıt",
- "versions.groupHeader.rollback": "Önceki sürümü dağıt",
- "versions.groupHeader.unavailable": "Kullanılamıyor",
- "versions.manualDslOption": "DSL Yükle",
- "versions.moreActions": "Daha fazla işlem",
- "versions.optional": "İsteğe bağlı",
- "versions.releaseAlreadyExists": "Aynı içeriğe sahip bir sürüm zaten var: {{name}}.",
- "versions.releaseContentCheckFailed": "Sürüm içeriği kontrol edilemedi.",
- "versions.releaseDescriptionLabel": "Açıklama",
- "versions.releaseDescriptionPlaceholder": "Bu sürümü açıklayın",
- "versions.releaseNameConflict": "Bu ada sahip bir sürüm zaten var. Başka bir ad seçin.",
- "versions.releaseNameLabel": "Sürüm Adı",
- "versions.releaseNamePlaceholder": "Sürüm Adı",
- "versions.releaseNameRequired": "Bir sürüm adı girin.",
- "versions.releaseSourceLabel": "Sürüm Kaynağı",
- "versions.rollbackTo": "{{name}} ortamına dağıt",
- "versions.saveEdit": "Kaydet",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "{{name}} ortamına dağıt"
}
diff --git a/web/i18n/uk-UA/common.json b/web/i18n/uk-UA/common.json
index bd2c871c927..5ff904fa8e0 100644
--- a/web/i18n/uk-UA/common.json
+++ b/web/i18n/uk-UA/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Деталі програми",
"menus.apps": "Студія",
"menus.datasets": "Знання",
- "menus.deployments": "Розгортання",
"menus.exploreMarketplace": "Дізнайтеся більше про Marketplace",
"menus.plugins": "Інтеграції",
"menus.status": "бета",
diff --git a/web/i18n/uk-UA/deployments.json b/web/i18n/uk-UA/deployments.json
index 322c3ac9d47..010d6e626be 100644
--- a/web/i18n/uk-UA/deployments.json
+++ b/web/i18n/uk-UA/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Копіювати приклад cURL",
- "access.api.createFailed": "Не вдалося згенерувати API Token.",
- "access.api.createKey": "Згенерувати API Token",
- "access.api.createKeyTitle": "Згенерувати новий API Token",
- "access.api.curlExampleTitle": "Приклад cURL",
- "access.api.description": "Доступ до цього розгортання через HTTP. Кожен API Token прив'язаний до одного середовища.",
- "access.api.developerTitle": "API для розробників",
- "access.api.disabled": "Доступ до API вимкнено для цього розгортання.",
- "access.api.disabledHint": "Увімкніть доступ до API, щоб генерувати токени, прив'язані до середовища.",
- "access.api.docs": "Документація API",
- "access.api.docsClose": "Закрити документацію API",
- "access.api.docsDescription": "Перегляньте довідник Workflow API для цього розгортання.",
- "access.api.docsTitle": "Документація Workflow API",
- "access.api.empty": "Розгорніть у середовищі, щоб почати випускати API Tokens.",
- "access.api.emptyTitle": "Немає розгорнутих середовищ",
- "access.api.endpoint": "URL запиту",
- "access.api.keyList": "Список API Tokens",
- "access.api.nameLabel": "Назва API Token",
- "access.api.namePlaceholder": "Введіть назву API Token",
- "access.api.nameRequired": "Назва API Token є обов'язковою.",
- "access.api.newKey": "Згенерувати новий API Token",
- "access.api.newTokenDescription": "Цей API Token показується лише один раз. Скопіюйте його перед тим, як залишити цю сторінку.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token згенеровано",
- "access.api.noKeys": "Поки що немає API Tokens. Згенеруйте один, щоб почати викликати API.",
- "access.api.noKeysTitle": "Поки що немає API Tokens",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" негайно припинить роботу. Цю дію не можна скасувати.",
- "access.api.revokeConfirmTitle": "Відкликати API Token?",
- "access.api.revokeFailed": "Не вдалося відкликати API Token.",
- "access.api.revokeSuccess": "API Token відкликано",
- "access.api.table.action": "Дія",
- "access.api.table.environment": "Середовище",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Назва",
- "access.channels.disabled": "Канали доступу вимкнено для цього розгортання.",
- "access.channels.disabledHint": "Увімкніть канали доступу, щоб надати точки входу WebApp та CLI.",
- "access.channels.title": "Канали доступу",
- "access.cli.description": "Викликайте з терміналу за допомогою difyctl, підходить для скриптів, автоматизованих процесів або інтеграцій з агентами.",
- "access.cli.docs": "Посібник з використання",
- "access.cli.domain": "Домен",
- "access.cli.empty": "Точку входу CLI не налаштовано.",
- "access.cli.install": "Встановити CLI",
- "access.cli.title": "CLI",
- "access.copy": "Копіювати",
- "access.copyFailed": "Не вдалося скопіювати",
- "access.members.groupCount_one": "{{count}} група",
- "access.members.groupCount_other": "{{count}} груп",
- "access.members.memberCount_one": "{{count}} учасник",
- "access.members.memberCount_other": "{{count}} учасників",
- "access.permission.anyone": "Будь-хто з посиланням",
- "access.permission.organization": "Усі учасники платформи",
- "access.permission.specific": "Певні учасники платформи",
- "access.permission.specificDesc": "Виберіть певні групи або учасників",
- "access.permission.updateFailed": "Не вдалося оновити політику доступу.",
- "access.permissions.editAriaLabel": "Налаштувати доступ для {{environment}}",
- "access.permissions.editDescription": "Налаштуйте дозволи доступу для точок входу WebApp та CLI.",
- "access.permissions.editTitle": "Дозволи доступу",
- "access.permissions.title": "Дозволи доступу",
- "access.revoke": "Відкликати",
- "access.runAccess.noEnvs": "Розгорніть у середовищі, щоб налаштувати дозволи доступу.",
- "access.runAccess.noEnvsTitle": "Немає розгорнутих середовищ",
- "access.runAccess.openWebapp": "Відкрити WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Розміщена вебсторінка для кінцевих користувачів.",
- "access.runAccess.webappEmpty": "Скоро.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Зовнішній",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Невідомо",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Немає доступу",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Створити перший Реліз",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Видалити розгортання",
- "card.menu.deploy": "Розгорнути в Середовище",
- "card.menu.editInfo": "Редагувати інформацію",
- "card.moreActions": "Більше дій",
- "card.noDescription": "Опис не надано.",
"card.notDeployed": "Не розгорнуто",
- "card.tooltip.createdAt": "Створено",
- "card.tooltip.deployed": "Розгорнуто",
- "card.tooltip.deploymentStatus": "Розгортання",
- "card.tooltip.notDeployedShort": "Не розгорнуто",
- "card.tooltip.releaseName": "Назва Релізу",
- "card.tooltip.source": "Джерело",
"common.loadFailed": "Не вдалося завантажити. Спробуйте пізніше.",
- "createGuide.actions.back": "Назад",
- "createGuide.actions.createAndDeploy": "Створити й розгорнути",
- "createGuide.actions.creating": "Створення...",
- "createGuide.actions.deploying": "Створення та розгортання...",
- "createGuide.actions.next": "Далі",
- "createGuide.actions.skipDeploy": "Пропустити, розгорнути пізніше",
- "createGuide.dsl.defaultAppName": "Імпортована DSL програма",
- "createGuide.dsl.description": "Завантажте пакет Workflow DSL, щоб створити розгортання, перший реліз і необов'язкове розгортання середовища.",
- "createGuide.dsl.dropDescription": "Завантажте пакет Workflow YAML DSL. Параметри розгортання визначаються з цього файлу перед розгортанням.",
- "createGuide.dsl.dropTitle": "Завантажити пакет Workflow DSL",
- "createGuide.dsl.readFailed": "Не вдалося прочитати файл DSL. Виберіть інший файл і спробуйте ще раз.",
- "createGuide.dsl.reading": "Читання файлу DSL...",
- "createGuide.dsl.title": "Імпортувати DSL",
- "createGuide.dsl.unsupportedMode": "Для розгортань можна використовувати лише файли Workflow DSL.",
- "createGuide.errors.createReleaseFailed": "Не вдалося створити розгортання або реліз.",
- "createGuide.errors.deployFailed": "Не вдалося розгорнути у середовищі.",
- "createGuide.method.description": "Виберіть джерело, яке використовуватиметься для створення першого релізу.",
- "createGuide.methods.bindApp.description": "Використовуйте існуючу програму Workflow в Studio як джерело релізу.",
- "createGuide.methods.bindApp.title": "Прив'язати існуючу програму Workflow",
- "createGuide.methods.importDsl.description": "Завантажте пакет Workflow YAML DSL і продовжте через UI розгортання.",
- "createGuide.methods.importDsl.title": "Імпортувати DSL",
- "createGuide.nav.back": "Розгортання",
- "createGuide.release.defaultName": "початковий реліз",
- "createGuide.release.deployInfo": "Інформація про розгортання",
- "createGuide.release.description": "Заповніть інформацію про розгортання та деталі першого релізу.",
- "createGuide.release.firstVersion": "Перший Реліз",
- "createGuide.release.instanceDescription": "Опис розгортання",
- "createGuide.release.instanceDescriptionPlaceholder": "Опишіть, для чого використовується це розгортання",
- "createGuide.release.instanceName": "Назва розгортання",
- "createGuide.release.instanceNameConflict": "Розгортання з такою назвою вже існує. Виберіть іншу назву.",
- "createGuide.release.releaseDescription": "Опис Релізу",
- "createGuide.release.releaseDescriptionPlaceholder": "Опишіть цей реліз",
- "createGuide.release.releaseName": "Назва Релізу",
- "createGuide.release.title": "Базова інформація",
- "createGuide.source.clearSearch": "Очистити пошук програм",
- "createGuide.source.description": "Виберіть джерело, яке використовуватиметься для створення першого релізу.",
- "createGuide.source.empty": "Програм Workflow не знайдено.",
- "createGuide.source.searchPlaceholder": "Пошук програм",
- "createGuide.source.sourceApp": "Workflow програма",
- "createGuide.source.title": "Джерело Релізу",
- "createGuide.steps.method": "Джерело Релізу",
- "createGuide.steps.release": "Базова інформація",
- "createGuide.steps.source": "Джерело Релізу",
- "createGuide.steps.target": "Розгорнути в Середовище",
- "createGuide.target.bindingCount_one": "{{count}} прив'язка",
- "createGuide.target.bindingCount_other": "{{count}} прив'язок",
- "createGuide.target.bindingHint": "Виберіть облікові дані, які використовуватиме цей реліз.",
- "createGuide.target.bindings": "Облікові дані",
- "createGuide.target.description": "Виберіть цільове Середовище та надайте необхідні налаштування виконання, які потрібні цьому релізу. Цей крок можна пропустити.",
- "createGuide.target.envVarCount_one": "{{count}} змінна",
- "createGuide.target.envVarCount_other": "{{count}} змінних",
- "createGuide.target.envVarHint": "Для кожної змінної середовища, необхідної цьому релізу, введіть власне значення або використовуйте значення, визначене у програмі.",
- "createGuide.target.envVarPlaceholder": "Введіть значення",
- "createGuide.target.envVarSource.ariaLabel": "Виберіть джерело значення змінної для {{key}}",
- "createGuide.target.envVarSource.default": "Значення програми",
- "createGuide.target.envVarSource.lastDeployment": "Останнє розгорнуте значення",
- "createGuide.target.envVarSource.literal": "Власне значення",
- "createGuide.target.envVarType.number": "Число",
- "createGuide.target.envVarType.secret": "Секрет",
- "createGuide.target.envVarType.string": "Рядок",
- "createGuide.target.envVars": "Змінні середовища",
- "createGuide.target.environment": "Цільове Середовище",
- "createGuide.target.loadBindingsFailed": "Не вдалося завантажити облікові дані.",
- "createGuide.target.loadEnvironmentsFailed": "Не вдалося завантажити середовища розгортання.",
- "createGuide.target.missingRequiredBinding": "Виберіть облікові дані для цієї обов'язкової прив'язки.",
- "createGuide.target.noBindingRequired": "Облікові дані не потрібні.",
- "createGuide.target.noCredentialCandidates": "Немає доступних облікових даних.",
- "createGuide.target.noEnvironmentOptions": "Немає доступних середовищ розгортання.",
- "createGuide.target.selectCredential": "Виберіть облікові дані",
- "createGuide.target.title": "Розгорнути в Середовище",
- "createGuide.title": "Нове розгортання",
- "createModal.appPickerPlaceholder": "Виберіть Workflow програму",
- "createModal.appSearchEmpty": "Немає відповідних Workflow програм",
- "createModal.appSearchPlaceholder": "Пошук Workflow програм…",
- "createModal.cancel": "Скасувати",
- "createModal.loadingApps": "Завантаження програм…",
- "deployDrawer.bindingCount_one": "{{count}} прив'язка",
- "deployDrawer.bindingCount_other": "{{count}} прив'язок",
"deployDrawer.bindingOptionsFailed": "Не вдалося завантажити параметри облікових даних.",
"deployDrawer.bindingSelectionHint": "Виберіть облікові дані, які використовуватиме це розгортання.",
- "deployDrawer.cancel": "Скасувати",
- "deployDrawer.close": "Закрити панель розгортання",
- "deployDrawer.defaultSelect": "Виберіть...",
- "deployDrawer.deploy": "Розгорнути в Середовище",
- "deployDrawer.deployFailed": "Не вдалося розпочати розгортання.",
"deployDrawer.deploying": "Розгортання...",
- "deployDrawer.description": "Виберіть реліз та цільове середовище для розгортання.",
- "deployDrawer.envVarCount_one": "{{count}} змінна",
- "deployDrawer.envVarCount_other": "{{count}} змінних",
- "deployDrawer.envVarHint": "Для кожної змінної середовища, необхідної цьому релізу, введіть власне значення або використовуйте значення, визначене у програмі.",
- "deployDrawer.envVarPlaceholder": "Введіть значення",
"deployDrawer.envVarSource.ariaLabel": "Виберіть джерело значення змінної для {{key}}",
- "deployDrawer.envVarSource.default": "Значення програми",
"deployDrawer.envVarSource.lastDeployment": "Останнє розгорнуте значення",
"deployDrawer.envVarSource.literal": "Власне значення",
"deployDrawer.envVarType.number": "Число",
"deployDrawer.envVarType.secret": "Секрет",
"deployDrawer.envVarType.string": "Рядок",
"deployDrawer.envVars": "Змінні середовища",
- "deployDrawer.existingReleaseHint": "Цей реліз буде розгорнуто як є. Новий реліз не створюватиметься.",
- "deployDrawer.lockedHint": "Зафіксовано до поточного середовища",
- "deployDrawer.missingRequiredBinding": "Виберіть облікові дані для цієї обов'язкової прив'язки.",
- "deployDrawer.missingRequiredEnvVar": "Введіть значення для цієї обов'язкової змінної середовища.",
- "deployDrawer.noBindingRequired": "Не потрібно",
"deployDrawer.noCredentialCandidates": "Немає доступних облікових даних.",
"deployDrawer.noNewEnvironmentAvailable": "У всіх доступних середовищах вже є розгортання.",
- "deployDrawer.noOtherReleaseAvailable": "Для цього середовища немає інших доступних релізів.",
- "deployDrawer.noReleaseAvailable": "Створіть реліз перед розгортанням у середовищі.",
- "deployDrawer.notFound": "Розгортання не знайдено.",
- "deployDrawer.releaseLabel": "Реліз",
"deployDrawer.runtimeCredentials": "Облікові дані",
"deployDrawer.selectCredential": "Виберіть облікові дані",
- "deployDrawer.selectEnv": "Виберіть Середовище",
- "deployDrawer.selectRelease": "Виберіть Реліз",
- "deployDrawer.targetEnv": "Цільове Середовище",
- "deployDrawer.title": "Розгорнути в Середовище",
- "deployTab.closeError": "Закрити",
"deployTab.col.actions": "Дії",
- "deployTab.col.currentRelease": "Поточний Реліз",
"deployTab.col.environment": "Середовище",
"deployTab.col.status": "Статус",
"deployTab.confirmUndeploy": "Скасувати розгортання",
- "deployTab.deployOtherVersion": "Розгорнути інший Реліз",
- "deployTab.emptyDescription": "Виберіть реліз і цільове Середовище, щоб зробити це розгортання доступним для користувачів.",
- "deployTab.emptyTitle": "Жодне Середовище ще не запущено",
- "deployTab.errorCode": "Код",
- "deployTab.errorDialogDesc": "Перегляньте останнє невдале розгортання перед повторною спробою або розгортанням іншого релізу.",
- "deployTab.errorDialogTitle": "Помилка розгортання в {{name}}",
- "deployTab.errorMessage": "Повідомлення",
- "deployTab.errorPhase": "Фаза",
"deployTab.moreActions": "Більше дій",
- "deployTab.newDeployment": "Розгорнути в нове Середовище",
- "deployTab.panel.unknownError": "Розгортання не вдалося.",
"deployTab.redeploy": "Перерозгорнути",
- "deployTab.retry": "Повторити",
- "deployTab.status.deployFailed": "Розгортання не вдалося",
- "deployTab.status.deployingRelease": "Розгортання ({{release}})",
- "deployTab.status.runningOutOfSync": "Запущено (очікує синхронізації)",
- "deployTab.status.runningWithFailed": "Запущено (останнє розгортання не вдалося)",
"deployTab.undeploy": "Скасувати розгортання",
- "deployTab.undeployConfirmDesc": "Кінцева точка середовища стане недоступною, але версію не буде видалено.",
- "deployTab.undeployConfirmTitle": "Скасувати розгортання {{name}}?",
"deployTab.undeployConfirmWarning": "Після підтвердження це середовище перейде у стан скасування розгортання, а дії буде тимчасово вимкнено.",
- "deployTab.viewError": "Переглянути помилку",
- "detail.mobileTabs": "Розділи розгортання",
- "detail.notFound": "Розгортання не знайдено",
- "documentTitle.create": "Нове розгортання · Розгортання",
- "documentTitle.detail": "Розгортання · Розгортання",
- "documentTitle.list": "Розгортання",
- "filter.allEnvs": "Усі Середовища",
- "filter.searchPlaceholder": "Пошук розгортань",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Прийняття",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Ініціалізація",
- "health.ENVIRONMENT_STATUS_DELETING": "Видалення",
"health.ENVIRONMENT_STATUS_FAILED": "Недоступно",
- "health.ENVIRONMENT_STATUS_READY": "Доступно",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Невідомо",
- "list.clearFilters": "Очистити фільтри",
- "list.clearSearch": "Очистити пошук розгортань",
- "list.createDeployment": "Створити",
- "list.emptyDescription": "Створіть розгортання з Workflow програми або пакета Workflow DSL, щоб керувати релізами, середовищами та доступом.",
- "list.emptyFilteredDescription": "Жодне розгортання не відповідає поточному пошуку або фільтру Середовища.",
- "list.emptyFilteredTitle": "Немає відповідних розгортань",
"list.emptyTitle": "Поки що немає розгортань",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Ізольований",
- "mode.ENVIRONMENT_MODE_SHARED": "Спільний",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Невідомий",
- "overview.accessMeta.apiTokens": "Керувати API Tokens",
- "overview.accessMeta.cli": "Переглянути доступ CLI",
- "overview.accessMeta.webApp": "Керувати доступом WebApp",
- "overview.accessStatus": "Доступ",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} розгорнуте Середовище",
- "overview.apiTokenSummary.environments_other": "{{count}} розгорнутих Середовищ",
- "overview.cardAction.deployLatest": "Розгорнути останній Реліз",
- "overview.cardAction.redeploy": "Перерозгорнути",
- "overview.cardAction.viewProgress": "Переглянути розгортання",
- "overview.chip.behindTooltip_one": "На 1 реліз позаду останнього. Розгорніть останній реліз для оновлення.",
- "overview.chip.behindTooltip_other": "На {{count}} релізів позаду останнього. Розгорніть останній реліз для оновлення.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "розгортається",
- "overview.chip.deployingTooltip": "Розгортання триває.",
- "overview.chip.empty": "порожнє",
- "overview.chip.emptyTooltip": "У цьому Середовищі не розгорнуто жодного релізу.",
- "overview.chip.failed": "не вдалося",
- "overview.chip.failedTooltip": "Остання спроба розгортання не вдалася.",
"overview.chip.latest": "останній",
- "overview.chip.latestTooltip": "Це Середовище працює на останньому релізі.",
- "overview.chip.needsReleaseFirst": "Створіть Реліз спочатку",
- "overview.chip.olderRelease": "старіший",
- "overview.chip.olderReleaseTooltip": "Це Середовище працює на старішому релізі.",
- "overview.chip.openInDeployTab": "Переглянути прогрес розгортання",
- "overview.disabled": "Вимкнено",
- "overview.enabled": "Увімкнено",
- "overview.hero.byName": "автор: {{name}}",
- "overview.hero.empty": "Поки що немає релізів",
- "overview.hero.emptyDescription": "Створіть реліз з поточного джерела перед розгортанням.",
- "overview.latestRelease.releaseCount_one": "{{count}} реліз",
- "overview.latestRelease.releaseCount_other": "{{count}} релізів",
- "overview.latestReleaseTitle": "Останній Реліз",
- "overview.previousReleases.viewAll": "Переглянути всі",
- "overview.strip.deployToNewEnvironment": "Розгорнути в нове Середовище",
- "overview.strip.emptyDeployableDescription": "Розгорніть останній реліз у Середовищі, коли будете готові.",
- "overview.strip.emptyDescription": "Створіть реліз перед розгортанням у Середовищі.",
- "overview.strip.emptyTitle": "Поки що немає Екземплярів",
- "overview.strip.title": "Екземпляри",
- "settings.delete": "Видалити розгортання",
- "settings.deleteConfirmDesc": "Видалити {{name}}? Кожен Екземпляр перестане працювати та буде видалений у всіх Середовищах. Цю дію не можна скасувати.",
- "settings.deleteConfirmTitle": "Видалити розгортання",
- "settings.deleteFailed": "Не вдалося видалити розгортання.",
- "settings.deleted": "Розгортання видалено",
- "settings.description": "Опис",
- "settings.name": "Назва розгортання",
- "settings.save": "Зберегти зміни",
- "settings.updateFailed": "Не вдалося оновити розгортання.",
- "settings.updated": "Розгортання оновлено",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Розгортається",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Очікує синхронізації",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Розгортання не вдалося",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Недійсний",
"status.RUNTIME_INSTANCE_STATUS_READY": "Запущено",
@@ -370,87 +89,6 @@
"studio.versionValue": "Значення версії",
"studio.versionsBehind_one": "Відставання на {{count}} версію",
"studio.versionsBehind_other": "Відставання на {{count}} версій",
- "tabs.access.description": "Керуйте каналами доступу та дозволами доступу.",
- "tabs.access.name": "Доступ",
- "tabs.api-tokens.description": "Керуйте API Tokens та викликайте Екземпляри через HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "Переглядайте та керуйте Екземплярами в розгорнутих Середовищах.",
- "tabs.instances.name": "Екземпляри",
- "tabs.overview.description": "Перегляньте статус розгортання в різних Середовищах.",
- "tabs.overview.name": "Огляд",
- "tabs.releases.description": "Створюйте, розгортайте та керуйте релізами.",
- "tabs.releases.name": "Релізи",
- "unsupportedDslNodes.description": "Цей реліз містить вузли, які ще не підтримуються середовищем виконання розгортання. Видаліть або замініть їх у Studio, потім спробуйте ще раз.",
- "unsupportedDslNodes.descriptionWithTypes": "Цей реліз містить вузли, які ще не підтримуються середовищем виконання розгортання: {{nodeTypes}}. Видаліть або замініть їх у Studio, потім спробуйте ще раз.",
- "unsupportedDslNodes.title": "Непідтримувані вузли",
- "unsupportedDslNodes.unknownType": "Невідомий тип",
- "versions.cancelCreate": "Скасувати",
- "versions.cancelDelete": "Скасувати",
- "versions.cancelEdit": "Скасувати",
"versions.checkingReleaseContent": "Перевірка вмісту релізу...",
- "versions.col.action": "Дія",
- "versions.col.author": "Створив",
- "versions.col.createdAt": "Створено",
- "versions.col.deployedTo": "Розгорнуто в",
- "versions.col.release": "Реліз",
- "versions.col.sourceApp": "Джерело",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Створити",
- "versions.createFailed": "Не вдалося створити реліз.",
- "versions.createRelease": "Створити Реліз",
- "versions.createReleaseDescription": "Створіть розгортаний реліз з Workflow програми або файлу Workflow DSL.",
- "versions.createSuccess": "Реліз \"{{name}}\" створено.",
- "versions.creating": "Створення...",
- "versions.currentOn": "Поточний Реліз у {{name}}",
- "versions.deleteConfirmDesc": "Реліз \"{{name}}\" буде назавжди видалено. Цю дію не можна скасувати.",
- "versions.deleteConfirmTitle": "Видалити реліз?",
- "versions.deleteFailed": "Не вдалося видалити реліз.",
- "versions.deleteRelease": "Видалити Реліз",
- "versions.deleteSuccess": "Реліз \"{{name}}\" видалено.",
- "versions.deployTo": "Розгорнути в {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Розгортається",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Очікує синхронізації",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Не вдалося",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Недійсний",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Запущено",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Не розгорнуто",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Скасування розгортання",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Невідомо",
- "versions.deployingTo": "{{name}} розгортається",
- "versions.disabledReason.checkDeploymentsFailed": "Не вдалося перевірити використання розгортання. Спробуйте пізніше.",
- "versions.disabledReason.checkingDeployments": "Перевірка використання розгортання",
- "versions.disabledReason.current": "Цей реліз уже запущено в {{name}}",
- "versions.disabledReason.deploying": "Дочекайтеся завершення активного розгортання",
- "versions.disabledReason.releaseInUse_one": "Скасуйте розгортання цього релізу з {{count}} Середовища перед його видаленням",
- "versions.disabledReason.releaseInUse_other": "Скасуйте розгортання цього релізу з {{count}} Середовищ перед його видаленням",
- "versions.dslReadFailed": "Не вдалося прочитати файл DSL. Виберіть інший файл і спробуйте ще раз.",
- "versions.dslReading": "Читання файлу DSL...",
- "versions.dslUnsupportedMode": "Для розгортань можна використовувати лише файли Workflow DSL.",
- "versions.editFailed": "Не вдалося оновити реліз.",
- "versions.editRelease": "Редагувати Реліз",
- "versions.editReleaseDescription": "Оновіть назву та опис цього релізу.",
- "versions.editSuccess": "Реліз \"{{name}}\" оновлено.",
- "versions.emptyDescription": "Створіть перший реліз перед розгортанням у Середовищі.",
- "versions.emptyTitle": "Поки що немає релізів",
- "versions.exportDsl": "Експортувати DSL",
- "versions.exportDslFailed": "Не вдалося експортувати DSL.",
- "versions.exportingDsl": "Експорт...",
- "versions.groupHeader.deploy": "Розгорнути",
- "versions.groupHeader.rollback": "Розгорнути попередню версію",
- "versions.groupHeader.unavailable": "Недоступно",
- "versions.manualDslOption": "Завантажити DSL",
- "versions.moreActions": "Більше дій",
- "versions.optional": "Необов'язково",
- "versions.releaseAlreadyExists": "Реліз з таким же вмістом уже існує: {{name}}.",
- "versions.releaseContentCheckFailed": "Не вдалося перевірити вміст релізу.",
- "versions.releaseDescriptionLabel": "Опис",
- "versions.releaseDescriptionPlaceholder": "Опишіть цей реліз",
- "versions.releaseNameConflict": "Реліз із такою назвою вже існує. Виберіть іншу назву.",
- "versions.releaseNameLabel": "Назва Релізу",
- "versions.releaseNamePlaceholder": "Назва Релізу",
- "versions.releaseNameRequired": "Введіть назву релізу.",
- "versions.releaseSourceLabel": "Джерело Релізу",
- "versions.rollbackTo": "Розгорнути в {{name}}",
- "versions.saveEdit": "Зберегти",
- "versions.sourceAppOption": "Workflow програма"
+ "versions.deployTo": "Розгорнути в {{name}}"
}
diff --git a/web/i18n/vi-VN/common.json b/web/i18n/vi-VN/common.json
index 30735ea7332..d203c77902f 100644
--- a/web/i18n/vi-VN/common.json
+++ b/web/i18n/vi-VN/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "Chi tiết ứng dụng",
"menus.apps": "Studio",
"menus.datasets": "Kiến thức",
- "menus.deployments": "Triển khai",
"menus.exploreMarketplace": "Khám phá Marketplace",
"menus.plugins": "Tích hợp",
"menus.status": "beta",
diff --git a/web/i18n/vi-VN/deployments.json b/web/i18n/vi-VN/deployments.json
index c40d22f62c0..879389b1969 100644
--- a/web/i18n/vi-VN/deployments.json
+++ b/web/i18n/vi-VN/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "Sao chép ví dụ cURL",
- "access.api.createFailed": "Không thể tạo API Token.",
- "access.api.createKey": "Tạo API Token",
- "access.api.createKeyTitle": "Tạo API Token mới",
- "access.api.curlExampleTitle": "Ví dụ cURL",
- "access.api.description": "Truy cập triển khai này qua HTTP. Mỗi API Token chỉ áp dụng cho một môi trường.",
- "access.api.developerTitle": "API Nhà phát triển",
- "access.api.disabled": "Truy cập API đã tắt cho triển khai này.",
- "access.api.disabledHint": "Bật truy cập API để tạo các token gắn với từng môi trường.",
- "access.api.docs": "Tài liệu API",
- "access.api.docsClose": "Đóng tài liệu API",
- "access.api.docsDescription": "Xem tài liệu tham khảo API Workflow cho triển khai này.",
- "access.api.docsTitle": "Tài liệu API Workflow",
- "access.api.empty": "Hãy triển khai đến một môi trường trước để bắt đầu phát hành API Token.",
- "access.api.emptyTitle": "Chưa có môi trường nào được triển khai",
- "access.api.endpoint": "URL yêu cầu",
- "access.api.keyList": "Danh sách API Token",
- "access.api.nameLabel": "Tên API Token",
- "access.api.namePlaceholder": "Nhập tên cho API Token",
- "access.api.nameRequired": "Tên API Token là bắt buộc.",
- "access.api.newKey": "Tạo API Token mới",
- "access.api.newTokenDescription": "API Token này chỉ hiển thị một lần. Hãy sao chép trước khi rời khỏi trang này.",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "Đã tạo API Token",
- "access.api.noKeys": "Chưa có API Token nào. Hãy tạo một token để bắt đầu gọi API.",
- "access.api.noKeysTitle": "Chưa có API Token",
- "access.api.revokeConfirmDescription": "API Token \"{{name}}\" sẽ ngừng hoạt động ngay lập tức. Hành động này không thể hoàn tác.",
- "access.api.revokeConfirmTitle": "Thu hồi API Token?",
- "access.api.revokeFailed": "Không thể thu hồi API Token.",
- "access.api.revokeSuccess": "Đã thu hồi API Token",
- "access.api.table.action": "Hành động",
- "access.api.table.environment": "Môi trường",
- "access.api.table.key": "API Token",
- "access.api.table.name": "Tên",
- "access.channels.disabled": "Các kênh truy cập đã tắt cho triển khai này.",
- "access.channels.disabledHint": "Bật các kênh truy cập để mở điểm truy cập WebApp và CLI.",
- "access.channels.title": "Kênh truy cập",
- "access.cli.description": "Gọi từ terminal bằng difyctl, phù hợp với script, quy trình tự động hoặc tích hợp Agent.",
- "access.cli.docs": "Hướng dẫn sử dụng",
- "access.cli.domain": "Tên miền",
- "access.cli.empty": "Chưa cấu hình điểm cuối CLI.",
- "access.cli.install": "Cài đặt CLI",
- "access.cli.title": "CLI",
- "access.copy": "Sao chép",
- "access.copyFailed": "Sao chép thất bại",
- "access.members.groupCount_one": "{{count}} nhóm",
- "access.members.groupCount_other": "{{count}} nhóm",
- "access.members.memberCount_one": "{{count}} thành viên",
- "access.members.memberCount_other": "{{count}} thành viên",
- "access.permission.anyone": "Bất kỳ ai có liên kết",
- "access.permission.organization": "Tất cả thành viên trong nền tảng",
- "access.permission.specific": "Thành viên cụ thể trong nền tảng",
- "access.permission.specificDesc": "Chọn nhóm hoặc thành viên cụ thể",
- "access.permission.updateFailed": "Không thể cập nhật chính sách truy cập.",
- "access.permissions.editAriaLabel": "Cấu hình truy cập cho {{environment}}",
- "access.permissions.editDescription": "Thiết lập quyền truy cập cho các điểm truy cập WebApp và CLI.",
- "access.permissions.editTitle": "Quyền truy cập",
- "access.permissions.title": "Quyền truy cập",
- "access.revoke": "Thu hồi",
- "access.runAccess.noEnvs": "Hãy triển khai đến một môi trường để cấu hình quyền truy cập.",
- "access.runAccess.noEnvsTitle": "Chưa có môi trường nào được triển khai",
- "access.runAccess.openWebapp": "Mở WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "Trang web được lưu trữ dành cho người dùng cuối.",
- "access.runAccess.webappEmpty": "Sắp ra mắt.",
- "backend.RUNTIME_BACKEND_EXTERNAL": "Bên ngoài",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "Không xác định",
- "card.access.api": "API Tokens",
- "card.access.cli": "CLI",
- "card.access.none": "Không có quyền truy cập",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "Tạo bản phát hành đầu tiên",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "Xóa triển khai",
- "card.menu.deploy": "Triển khai đến môi trường",
- "card.menu.editInfo": "Chỉnh sửa thông tin",
- "card.moreActions": "Thêm thao tác",
- "card.noDescription": "Không có mô tả.",
"card.notDeployed": "Chưa triển khai",
- "card.tooltip.createdAt": "Đã tạo",
- "card.tooltip.deployed": "Đã triển khai",
- "card.tooltip.deploymentStatus": "Triển khai",
- "card.tooltip.notDeployedShort": "Chưa triển khai",
- "card.tooltip.releaseName": "Tên bản phát hành",
- "card.tooltip.source": "Nguồn",
"common.loadFailed": "Không thể tải. Vui lòng thử lại sau.",
- "createGuide.actions.back": "Quay lại",
- "createGuide.actions.createAndDeploy": "Tạo & Triển khai",
- "createGuide.actions.creating": "Đang tạo...",
- "createGuide.actions.deploying": "Đang tạo & triển khai...",
- "createGuide.actions.next": "Tiếp theo",
- "createGuide.actions.skipDeploy": "Bỏ qua, triển khai sau",
- "createGuide.dsl.defaultAppName": "Ứng dụng DSL đã nhập",
- "createGuide.dsl.description": "Tải lên gói Workflow DSL để tạo triển khai, bản phát hành đầu tiên và triển khai đến môi trường tùy chọn.",
- "createGuide.dsl.dropDescription": "Tải lên gói Workflow YAML DSL. Các tùy chọn triển khai được xác định từ tệp này trước khi triển khai.",
- "createGuide.dsl.dropTitle": "Tải lên gói Workflow DSL",
- "createGuide.dsl.readFailed": "Không thể đọc tệp DSL. Vui lòng chọn tệp khác và thử lại.",
- "createGuide.dsl.reading": "Đang đọc tệp DSL...",
- "createGuide.dsl.title": "Nhập DSL",
- "createGuide.dsl.unsupportedMode": "Chỉ tệp Workflow DSL có thể được sử dụng cho triển khai.",
- "createGuide.errors.createReleaseFailed": "Không thể tạo triển khai hoặc bản phát hành.",
- "createGuide.errors.deployFailed": "Không thể triển khai đến môi trường.",
- "createGuide.method.description": "Chọn nguồn được sử dụng để tạo bản phát hành đầu tiên.",
- "createGuide.methods.bindApp.description": "Sử dụng một Workflow App hiện có trong Studio làm nguồn phát hành.",
- "createGuide.methods.bindApp.title": "Liên kết Workflow App hiện có",
- "createGuide.methods.importDsl.description": "Tải lên gói Workflow YAML DSL và tiếp tục qua giao diện triển khai.",
- "createGuide.methods.importDsl.title": "Nhập DSL",
- "createGuide.nav.back": "Triển khai",
- "createGuide.release.defaultName": "bản phát hành ban đầu",
- "createGuide.release.deployInfo": "Thông tin triển khai",
- "createGuide.release.description": "Điền thông tin triển khai và chi tiết bản phát hành đầu tiên.",
- "createGuide.release.firstVersion": "Bản phát hành đầu tiên",
- "createGuide.release.instanceDescription": "Mô tả triển khai",
- "createGuide.release.instanceDescriptionPlaceholder": "Mô tả mục đích sử dụng của triển khai này",
- "createGuide.release.instanceName": "Tên triển khai",
- "createGuide.release.instanceNameConflict": "Đã tồn tại một triển khai với tên này. Vui lòng chọn tên khác.",
- "createGuide.release.releaseDescription": "Mô tả bản phát hành",
- "createGuide.release.releaseDescriptionPlaceholder": "Mô tả bản phát hành này",
- "createGuide.release.releaseName": "Tên bản phát hành",
- "createGuide.release.title": "Thông tin cơ bản",
- "createGuide.source.clearSearch": "Xóa tìm kiếm ứng dụng",
- "createGuide.source.description": "Chọn nguồn được sử dụng để tạo bản phát hành đầu tiên.",
- "createGuide.source.empty": "Không tìm thấy Workflow App nào.",
- "createGuide.source.searchPlaceholder": "Tìm kiếm ứng dụng",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "Nguồn phát hành",
- "createGuide.steps.method": "Nguồn phát hành",
- "createGuide.steps.release": "Thông tin cơ bản",
- "createGuide.steps.source": "Nguồn phát hành",
- "createGuide.steps.target": "Triển khai đến môi trường",
- "createGuide.target.bindingCount_one": "{{count}} liên kết",
- "createGuide.target.bindingCount_other": "{{count}} liên kết",
- "createGuide.target.bindingHint": "Chọn thông tin xác thực được sử dụng bởi bản phát hành này.",
- "createGuide.target.bindings": "Thông tin xác thực",
- "createGuide.target.description": "Chọn môi trường đích và cung cấp các thiết lập runtime mà bản phát hành này cần ở đó. Bước này có thể bỏ qua.",
- "createGuide.target.envVarCount_one": "{{count}} biến",
- "createGuide.target.envVarCount_other": "{{count}} biến",
- "createGuide.target.envVarHint": "Với mỗi biến môi trường mà bản phát hành này cần, hãy nhập giá trị tùy chỉnh hoặc sử dụng giá trị được định nghĩa trong ứng dụng.",
- "createGuide.target.envVarPlaceholder": "Nhập giá trị",
- "createGuide.target.envVarSource.ariaLabel": "Chọn nguồn giá trị biến cho {{key}}",
- "createGuide.target.envVarSource.default": "Giá trị ứng dụng",
- "createGuide.target.envVarSource.lastDeployment": "Giá trị triển khai gần nhất",
- "createGuide.target.envVarSource.literal": "Giá trị tùy chỉnh",
- "createGuide.target.envVarType.number": "Số",
- "createGuide.target.envVarType.secret": "Bí mật",
- "createGuide.target.envVarType.string": "Chuỗi",
- "createGuide.target.envVars": "Biến môi trường",
- "createGuide.target.environment": "Môi trường đích",
- "createGuide.target.loadBindingsFailed": "Không thể tải thông tin xác thực.",
- "createGuide.target.loadEnvironmentsFailed": "Không thể tải các môi trường triển khai.",
- "createGuide.target.missingRequiredBinding": "Chọn thông tin xác thực cho liên kết bắt buộc này.",
- "createGuide.target.noBindingRequired": "Không yêu cầu thông tin xác thực.",
- "createGuide.target.noCredentialCandidates": "Không có thông tin xác thực khả dụng.",
- "createGuide.target.noEnvironmentOptions": "Không có môi trường triển khai khả dụng.",
- "createGuide.target.selectCredential": "Chọn thông tin xác thực",
- "createGuide.target.title": "Triển khai đến môi trường",
- "createGuide.title": "Triển khai mới",
- "createModal.appPickerPlaceholder": "Chọn một Workflow App",
- "createModal.appSearchEmpty": "Không có Workflow App nào phù hợp",
- "createModal.appSearchPlaceholder": "Tìm kiếm Workflow Apps…",
- "createModal.cancel": "Hủy",
- "createModal.loadingApps": "Đang tải ứng dụng…",
- "deployDrawer.bindingCount_one": "{{count}} liên kết",
- "deployDrawer.bindingCount_other": "{{count}} liên kết",
"deployDrawer.bindingOptionsFailed": "Không thể tải các tùy chọn thông tin xác thực.",
"deployDrawer.bindingSelectionHint": "Chọn thông tin xác thực được sử dụng bởi triển khai này.",
- "deployDrawer.cancel": "Hủy",
- "deployDrawer.close": "Đóng ngăn triển khai",
- "deployDrawer.defaultSelect": "Chọn...",
- "deployDrawer.deploy": "Triển khai đến môi trường",
- "deployDrawer.deployFailed": "Không thể bắt đầu triển khai.",
"deployDrawer.deploying": "Đang triển khai...",
- "deployDrawer.description": "Chọn một bản phát hành và môi trường đích để triển khai.",
- "deployDrawer.envVarCount_one": "{{count}} biến",
- "deployDrawer.envVarCount_other": "{{count}} biến",
- "deployDrawer.envVarHint": "Với mỗi biến môi trường mà bản phát hành này cần, hãy nhập giá trị tùy chỉnh hoặc sử dụng giá trị được định nghĩa trong ứng dụng.",
- "deployDrawer.envVarPlaceholder": "Nhập giá trị",
"deployDrawer.envVarSource.ariaLabel": "Chọn nguồn giá trị biến cho {{key}}",
- "deployDrawer.envVarSource.default": "Giá trị ứng dụng",
"deployDrawer.envVarSource.lastDeployment": "Giá trị triển khai gần nhất",
"deployDrawer.envVarSource.literal": "Giá trị tùy chỉnh",
"deployDrawer.envVarType.number": "Số",
"deployDrawer.envVarType.secret": "Bí mật",
"deployDrawer.envVarType.string": "Chuỗi",
"deployDrawer.envVars": "Biến môi trường",
- "deployDrawer.existingReleaseHint": "Bản phát hành này sẽ được triển khai nguyên trạng. Không có bản phát hành mới nào được tạo.",
- "deployDrawer.lockedHint": "Đã khóa với môi trường hiện tại",
- "deployDrawer.missingRequiredBinding": "Chọn thông tin xác thực cho liên kết bắt buộc này.",
- "deployDrawer.missingRequiredEnvVar": "Nhập giá trị cho biến môi trường bắt buộc này.",
- "deployDrawer.noBindingRequired": "Không bắt buộc",
"deployDrawer.noCredentialCandidates": "Không có thông tin xác thực khả dụng.",
"deployDrawer.noNewEnvironmentAvailable": "Tất cả các môi trường khả dụng đã có triển khai.",
- "deployDrawer.noOtherReleaseAvailable": "Không có bản phát hành nào khác khả dụng cho môi trường này.",
- "deployDrawer.noReleaseAvailable": "Tạo một bản phát hành trước khi triển khai đến môi trường.",
- "deployDrawer.notFound": "Không tìm thấy triển khai.",
- "deployDrawer.releaseLabel": "Bản phát hành",
"deployDrawer.runtimeCredentials": "Thông tin xác thực",
"deployDrawer.selectCredential": "Chọn thông tin xác thực",
- "deployDrawer.selectEnv": "Chọn một môi trường",
- "deployDrawer.selectRelease": "Chọn một bản phát hành",
- "deployDrawer.targetEnv": "Môi trường đích",
- "deployDrawer.title": "Triển khai đến môi trường",
- "deployTab.closeError": "Đóng",
"deployTab.col.actions": "Thao tác",
- "deployTab.col.currentRelease": "Bản phát hành hiện tại",
"deployTab.col.environment": "Môi trường",
"deployTab.col.status": "Trạng thái",
"deployTab.confirmUndeploy": "Hủy triển khai",
- "deployTab.deployOtherVersion": "Triển khai bản phát hành khác",
- "deployTab.emptyDescription": "Chọn một bản phát hành và môi trường đích để cung cấp triển khai này cho người dùng.",
- "deployTab.emptyTitle": "Chưa có môi trường nào đang chạy",
- "deployTab.errorCode": "Mã",
- "deployTab.errorDialogDesc": "Xem lại triển khai thất bại gần nhất trước khi thử lại hoặc triển khai bản phát hành khác.",
- "deployTab.errorDialogTitle": "Lỗi triển khai ở {{name}}",
- "deployTab.errorMessage": "Thông báo",
- "deployTab.errorPhase": "Giai đoạn",
"deployTab.moreActions": "Thêm thao tác",
- "deployTab.newDeployment": "Triển khai đến môi trường mới",
- "deployTab.panel.unknownError": "Triển khai thất bại.",
"deployTab.redeploy": "Triển khai lại",
- "deployTab.retry": "Thử lại",
- "deployTab.status.deployFailed": "Triển khai thất bại",
- "deployTab.status.deployingRelease": "Đang triển khai ({{release}})",
- "deployTab.status.runningOutOfSync": "Đang chạy (đang chờ đồng bộ)",
- "deployTab.status.runningWithFailed": "Đang chạy (triển khai gần nhất thất bại)",
"deployTab.undeploy": "Hủy triển khai",
- "deployTab.undeployConfirmDesc": "Điểm cuối của môi trường sẽ không còn khả dụng, nhưng phiên bản sẽ không bị xóa.",
- "deployTab.undeployConfirmTitle": "Hủy triển khai {{name}}?",
"deployTab.undeployConfirmWarning": "Sau khi xác nhận, môi trường này sẽ chuyển sang trạng thái đang hủy triển khai và các thao tác sẽ tạm thời bị vô hiệu hóa.",
- "deployTab.viewError": "Xem lỗi",
- "detail.mobileTabs": "Các mục triển khai",
- "detail.notFound": "Không tìm thấy triển khai",
- "documentTitle.create": "Triển khai mới · Triển khai",
- "documentTitle.detail": "Triển khai · Triển khai",
- "documentTitle.list": "Triển khai",
- "filter.allEnvs": "Tất cả môi trường",
- "filter.searchPlaceholder": "Tìm kiếm triển khai",
- "health.ENVIRONMENT_STATUS_ADMISSION": "Đang chấp nhận",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "Đang khởi động",
- "health.ENVIRONMENT_STATUS_DELETING": "Đang xóa",
"health.ENVIRONMENT_STATUS_FAILED": "Không khả dụng",
- "health.ENVIRONMENT_STATUS_READY": "Khả dụng",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "Không xác định",
- "list.clearFilters": "Xóa bộ lọc",
- "list.clearSearch": "Xóa tìm kiếm triển khai",
- "list.createDeployment": "Mới",
- "list.emptyDescription": "Tạo một triển khai từ Workflow App hoặc gói Workflow DSL để quản lý các bản phát hành, môi trường và quyền truy cập.",
- "list.emptyFilteredDescription": "Không có triển khai nào khớp với tìm kiếm hoặc bộ lọc môi trường hiện tại.",
- "list.emptyFilteredTitle": "Không có triển khai phù hợp",
"list.emptyTitle": "Chưa có triển khai nào",
- "mode.ENVIRONMENT_MODE_ISOLATED": "Cô lập",
- "mode.ENVIRONMENT_MODE_SHARED": "Chia sẻ",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "Không xác định",
- "overview.accessMeta.apiTokens": "Quản lý API Tokens",
- "overview.accessMeta.cli": "Xem truy cập CLI",
- "overview.accessMeta.webApp": "Quản lý truy cập WebApp",
- "overview.accessStatus": "Truy cập",
- "overview.api": "API Tokens",
- "overview.apiKeysCount_one": "{{count}} API Token",
- "overview.apiKeysCount_other": "{{count}} API Tokens",
- "overview.apiTokenSummary.environments_one": "{{count}} môi trường đã triển khai",
- "overview.apiTokenSummary.environments_other": "{{count}} môi trường đã triển khai",
- "overview.cardAction.deployLatest": "Triển khai bản phát hành mới nhất",
- "overview.cardAction.redeploy": "Triển khai lại",
- "overview.cardAction.viewProgress": "Xem triển khai",
- "overview.chip.behindTooltip_one": "Trễ 1 bản phát hành so với mới nhất. Hãy triển khai bản phát hành mới nhất để cập nhật.",
- "overview.chip.behindTooltip_other": "Trễ {{count}} bản phát hành so với mới nhất. Hãy triển khai bản phát hành mới nhất để cập nhật.",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "đang triển khai",
- "overview.chip.deployingTooltip": "Triển khai đang được thực hiện.",
- "overview.chip.empty": "trống",
- "overview.chip.emptyTooltip": "Chưa có bản phát hành nào được triển khai đến môi trường này.",
- "overview.chip.failed": "thất bại",
- "overview.chip.failedTooltip": "Lần thử triển khai gần nhất đã thất bại.",
"overview.chip.latest": "mới nhất",
- "overview.chip.latestTooltip": "Môi trường này đang chạy bản phát hành mới nhất.",
- "overview.chip.needsReleaseFirst": "Tạo một bản phát hành trước",
- "overview.chip.olderRelease": "cũ hơn",
- "overview.chip.olderReleaseTooltip": "Môi trường này đang chạy bản phát hành cũ hơn.",
- "overview.chip.openInDeployTab": "Xem tiến trình triển khai",
- "overview.disabled": "Đã tắt",
- "overview.enabled": "Đã bật",
- "overview.hero.byName": "bởi {{name}}",
- "overview.hero.empty": "Chưa có bản phát hành nào",
- "overview.hero.emptyDescription": "Hãy tạo một bản phát hành từ nguồn hiện tại trước khi triển khai.",
- "overview.latestRelease.releaseCount_one": "{{count}} bản phát hành",
- "overview.latestRelease.releaseCount_other": "{{count}} bản phát hành",
- "overview.latestReleaseTitle": "Bản phát hành mới nhất",
- "overview.previousReleases.viewAll": "Xem tất cả",
- "overview.strip.deployToNewEnvironment": "Triển khai đến môi trường mới",
- "overview.strip.emptyDeployableDescription": "Triển khai bản phát hành mới nhất đến một môi trường khi bạn đã sẵn sàng.",
- "overview.strip.emptyDescription": "Tạo một bản phát hành trước khi triển khai đến môi trường.",
- "overview.strip.emptyTitle": "Chưa có phiên bản nào",
- "overview.strip.title": "Phiên bản",
- "settings.delete": "Xóa triển khai",
- "settings.deleteConfirmDesc": "Xóa {{name}}? Mọi phiên bản sẽ ngừng chạy và bị xóa khỏi tất cả môi trường. Hành động này không thể hoàn tác.",
- "settings.deleteConfirmTitle": "Xóa triển khai",
- "settings.deleteFailed": "Không thể xóa triển khai.",
- "settings.deleted": "Đã xóa triển khai",
- "settings.description": "Mô tả",
- "settings.name": "Tên triển khai",
- "settings.save": "Lưu thay đổi",
- "settings.updateFailed": "Không thể cập nhật triển khai.",
- "settings.updated": "Đã cập nhật triển khai",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Đang triển khai",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "Đang chờ đồng bộ",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "Triển khai thất bại",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "Không hợp lệ",
"status.RUNTIME_INSTANCE_STATUS_READY": "Đang chạy",
@@ -370,87 +89,6 @@
"studio.versionValue": "Giá trị phiên bản",
"studio.versionsBehind_one": "Chậm {{count}} phiên bản",
"studio.versionsBehind_other": "Chậm {{count}} phiên bản",
- "tabs.access.description": "Quản lý các kênh truy cập và quyền truy cập.",
- "tabs.access.name": "Truy cập",
- "tabs.api-tokens.description": "Quản lý API Tokens và gọi các phiên bản qua HTTP.",
- "tabs.api-tokens.name": "API Tokens",
- "tabs.instances.description": "Xem và quản lý các phiên bản trong các môi trường đã triển khai.",
- "tabs.instances.name": "Phiên bản",
- "tabs.overview.description": "Xem trạng thái triển khai trên các môi trường.",
- "tabs.overview.name": "Tổng quan",
- "tabs.releases.description": "Tạo, triển khai và quản lý các bản phát hành.",
- "tabs.releases.name": "Bản phát hành",
- "unsupportedDslNodes.description": "Bản phát hành này chứa các node mà runtime triển khai chưa hỗ trợ. Hãy xóa hoặc thay thế chúng trong Studio, sau đó thử lại.",
- "unsupportedDslNodes.descriptionWithTypes": "Bản phát hành này chứa các node mà runtime triển khai chưa hỗ trợ: {{nodeTypes}}. Hãy xóa hoặc thay thế chúng trong Studio, sau đó thử lại.",
- "unsupportedDslNodes.title": "Các node không được hỗ trợ",
- "unsupportedDslNodes.unknownType": "Loại không xác định",
- "versions.cancelCreate": "Hủy",
- "versions.cancelDelete": "Hủy",
- "versions.cancelEdit": "Hủy",
"versions.checkingReleaseContent": "Đang kiểm tra nội dung bản phát hành...",
- "versions.col.action": "Hành động",
- "versions.col.author": "Người tạo",
- "versions.col.createdAt": "Tạo lúc",
- "versions.col.deployedTo": "Đã triển khai đến",
- "versions.col.release": "Bản phát hành",
- "versions.col.sourceApp": "Nguồn",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "Tạo",
- "versions.createFailed": "Không thể tạo bản phát hành.",
- "versions.createRelease": "Tạo bản phát hành",
- "versions.createReleaseDescription": "Tạo một bản phát hành có thể triển khai từ Workflow App hoặc tệp Workflow DSL.",
- "versions.createSuccess": "Đã tạo bản phát hành \"{{name}}\".",
- "versions.creating": "Đang tạo...",
- "versions.currentOn": "Bản phát hành hiện tại trên {{name}}",
- "versions.deleteConfirmDesc": "Bản phát hành \"{{name}}\" sẽ bị xóa vĩnh viễn. Hành động này không thể hoàn tác.",
- "versions.deleteConfirmTitle": "Xóa bản phát hành?",
- "versions.deleteFailed": "Không thể xóa bản phát hành.",
- "versions.deleteRelease": "Xóa bản phát hành",
- "versions.deleteSuccess": "Đã xóa bản phát hành \"{{name}}\".",
- "versions.deployTo": "Triển khai đến {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "Đang triển khai",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "Đang chờ đồng bộ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "Thất bại",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "Không hợp lệ",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "Đang chạy",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "Chưa triển khai",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "Đang hủy triển khai",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "Không xác định",
- "versions.deployingTo": "{{name}} đang được triển khai",
- "versions.disabledReason.checkDeploymentsFailed": "Không thể xác minh việc sử dụng triển khai. Vui lòng thử lại sau.",
- "versions.disabledReason.checkingDeployments": "Đang kiểm tra việc sử dụng triển khai",
- "versions.disabledReason.current": "Bản phát hành này đã đang chạy trên {{name}}",
- "versions.disabledReason.deploying": "Vui lòng chờ triển khai hiện tại hoàn thành",
- "versions.disabledReason.releaseInUse_one": "Hãy hủy triển khai bản phát hành này khỏi {{count}} môi trường trước khi xóa",
- "versions.disabledReason.releaseInUse_other": "Hãy hủy triển khai bản phát hành này khỏi {{count}} môi trường trước khi xóa",
- "versions.dslReadFailed": "Không thể đọc tệp DSL. Vui lòng chọn tệp khác và thử lại.",
- "versions.dslReading": "Đang đọc tệp DSL...",
- "versions.dslUnsupportedMode": "Chỉ tệp Workflow DSL có thể được sử dụng cho triển khai.",
- "versions.editFailed": "Không thể cập nhật bản phát hành.",
- "versions.editRelease": "Chỉnh sửa bản phát hành",
- "versions.editReleaseDescription": "Cập nhật tên và mô tả của bản phát hành này.",
- "versions.editSuccess": "Đã cập nhật bản phát hành \"{{name}}\".",
- "versions.emptyDescription": "Tạo bản phát hành đầu tiên trước khi triển khai đến môi trường.",
- "versions.emptyTitle": "Chưa có bản phát hành nào",
- "versions.exportDsl": "Xuất DSL",
- "versions.exportDslFailed": "Không thể xuất DSL.",
- "versions.exportingDsl": "Đang xuất...",
- "versions.groupHeader.deploy": "Triển khai",
- "versions.groupHeader.rollback": "Triển khai phiên bản trước",
- "versions.groupHeader.unavailable": "Không khả dụng",
- "versions.manualDslOption": "Tải lên DSL",
- "versions.moreActions": "Thêm thao tác",
- "versions.optional": "Tùy chọn",
- "versions.releaseAlreadyExists": "Một bản phát hành với cùng nội dung đã tồn tại: {{name}}.",
- "versions.releaseContentCheckFailed": "Không thể kiểm tra nội dung bản phát hành.",
- "versions.releaseDescriptionLabel": "Mô tả",
- "versions.releaseDescriptionPlaceholder": "Mô tả bản phát hành này",
- "versions.releaseNameConflict": "Tên bản phát hành này đã tồn tại. Hãy chọn tên khác.",
- "versions.releaseNameLabel": "Tên bản phát hành",
- "versions.releaseNamePlaceholder": "Tên bản phát hành",
- "versions.releaseNameRequired": "Vui lòng nhập tên bản phát hành.",
- "versions.releaseSourceLabel": "Nguồn bản phát hành",
- "versions.rollbackTo": "Triển khai đến {{name}}",
- "versions.saveEdit": "Lưu",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "Triển khai đến {{name}}"
}
diff --git a/web/i18n/zh-Hans/common.json b/web/i18n/zh-Hans/common.json
index fe70ac5985c..c246c4c9024 100644
--- a/web/i18n/zh-Hans/common.json
+++ b/web/i18n/zh-Hans/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "应用详情",
"menus.apps": "工作室",
"menus.datasets": "知识库",
- "menus.deployments": "部署",
"menus.exploreMarketplace": "探索 Marketplace",
"menus.plugins": "集成",
"menus.status": "beta",
diff --git a/web/i18n/zh-Hans/deployments.json b/web/i18n/zh-Hans/deployments.json
index 2c8c1ee60e5..900f98b8962 100644
--- a/web/i18n/zh-Hans/deployments.json
+++ b/web/i18n/zh-Hans/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "复制 cURL 示例",
- "access.api.createFailed": "生成 API 令牌失败。",
- "access.api.createKey": "生成 API 令牌",
- "access.api.createKeyTitle": "生成新 API 令牌",
- "access.api.curlExampleTitle": "cURL 示例",
- "access.api.description": "通过 HTTP 调用该部署。每个 API 令牌仅在一个环境中生效。",
- "access.api.developerTitle": "开发者 API",
- "access.api.disabled": "该部署的 API 接入已关闭。",
- "access.api.disabledHint": "开启 API 接入后即可生成绑定环境的令牌。",
- "access.api.docs": "API 文档",
- "access.api.docsClose": "关闭 API 文档",
- "access.api.docsDescription": "查看该部署的工作流 API 参考。",
- "access.api.docsTitle": "工作流 API 文档",
- "access.api.empty": "请先部署到环境后再签发 API 令牌。",
- "access.api.emptyTitle": "暂无已部署环境",
- "access.api.endpoint": "请求地址",
- "access.api.keyList": "API 令牌列表",
- "access.api.nameLabel": "API 令牌名称",
- "access.api.namePlaceholder": "输入 API 令牌名称",
- "access.api.nameRequired": "请输入 API 令牌名称。",
- "access.api.newKey": "生成新 API 令牌",
- "access.api.newTokenDescription": "该明文 API 令牌仅本次显示,请在离开页面前复制保存。",
- "access.api.newTokenLabel": "API 令牌",
- "access.api.newTokenTitle": "API 令牌已生成",
- "access.api.noKeys": "尚无 API 令牌,生成一个即可调用 API。",
- "access.api.noKeysTitle": "暂无 API 令牌",
- "access.api.revokeConfirmDescription": "API 令牌「{{name}}」将立即失效,此操作无法撤销。",
- "access.api.revokeConfirmTitle": "撤销 API 令牌?",
- "access.api.revokeFailed": "撤销 API 令牌失败。",
- "access.api.revokeSuccess": "API 令牌已撤销",
- "access.api.table.action": "操作",
- "access.api.table.environment": "环境",
- "access.api.table.key": "API 令牌",
- "access.api.table.name": "名称",
- "access.channels.disabled": "该部署的接入渠道已关闭。",
- "access.channels.disabledHint": "开启接入渠道后即可开放 WebApp 和 CLI 入口。",
- "access.channels.title": "接入渠道",
- "access.cli.description": "通过 difyctl 在终端中调用,适合脚本、自动化流程或 Agent 集成",
- "access.cli.docs": "使用说明",
- "access.cli.domain": "域名",
- "access.cli.empty": "尚未配置 CLI 接入地址。",
- "access.cli.install": "安装 CLI",
- "access.cli.title": "CLI",
- "access.copy": "复制",
- "access.copyFailed": "复制失败",
- "access.members.groupCount_one": "{{count}} 个分组",
- "access.members.groupCount_other": "{{count}} 个分组",
- "access.members.memberCount_one": "{{count}} 位成员",
- "access.members.memberCount_other": "{{count}} 位成员",
- "access.permission.anyone": "任何人",
- "access.permission.organization": "平台内所有成员",
- "access.permission.specific": "平台内指定成员",
- "access.permission.specificDesc": "选择指定的分组或成员",
- "access.permission.updateFailed": "更新访问策略失败。",
- "access.permissions.editAriaLabel": "配置 {{environment}} 的访问权限",
- "access.permissions.editDescription": "设置 WebApp 与 CLI 入口的访问权限。",
- "access.permissions.editTitle": "访问权限",
- "access.permissions.title": "访问权限",
- "access.revoke": "撤销",
- "access.runAccess.noEnvs": "请先部署到环境后再配置访问权限。",
- "access.runAccess.noEnvsTitle": "暂无已部署环境",
- "access.runAccess.openWebapp": "打开 WebApp",
- "access.runAccess.urlLabel": "访问地址",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "面向终端用户的托管 Web 页面。",
- "access.runAccess.webappEmpty": "即将支持。",
- "backend.RUNTIME_BACKEND_EXTERNAL": "外部",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "未知",
- "card.access.api": "API 令牌",
- "card.access.cli": "CLI",
- "card.access.none": "未开启接入",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "创建首个版本",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "删除部署",
- "card.menu.deploy": "部署到环境",
- "card.menu.editInfo": "编辑信息",
- "card.moreActions": "更多操作",
- "card.noDescription": "暂无描述",
"card.notDeployed": "未部署",
- "card.tooltip.createdAt": "创建时间",
- "card.tooltip.deployed": "已部署",
- "card.tooltip.deploymentStatus": "部署状态",
- "card.tooltip.notDeployedShort": "未部署",
- "card.tooltip.releaseName": "版本名称",
- "card.tooltip.source": "来源",
"common.loadFailed": "加载失败,请稍后再试。",
- "createGuide.actions.back": "返回",
- "createGuide.actions.createAndDeploy": "创建并部署",
- "createGuide.actions.creating": "创建中…",
- "createGuide.actions.deploying": "创建并部署中…",
- "createGuide.actions.next": "下一步",
- "createGuide.actions.skipDeploy": "跳过,稍后部署",
- "createGuide.dsl.defaultAppName": "导入的 DSL 应用",
- "createGuide.dsl.description": "上传工作流 DSL 包来新建部署、首个版本,并可部署到环境。",
- "createGuide.dsl.dropDescription": "上传工作流 YAML DSL 包。部署前会根据该文件解析部署选项。",
- "createGuide.dsl.dropTitle": "上传工作流 DSL 包",
- "createGuide.dsl.readFailed": "读取 DSL 文件失败。请选择其他文件后重试。",
- "createGuide.dsl.reading": "正在读取 DSL 文件…",
- "createGuide.dsl.title": "导入 DSL",
- "createGuide.dsl.unsupportedMode": "仅支持使用工作流 DSL 新建部署。",
- "createGuide.errors.createReleaseFailed": "新建部署或版本失败。",
- "createGuide.errors.deployFailed": "部署到环境失败。",
- "createGuide.method.description": "选择用于生成首个版本的来源。",
- "createGuide.methods.bindApp.description": "使用 Studio 中已有的工作流应用作为版本来源。",
- "createGuide.methods.bindApp.title": "绑定已有工作流应用",
- "createGuide.methods.importDsl.description": "上传工作流 YAML DSL 包,并继续完成部署配置。",
- "createGuide.methods.importDsl.title": "导入 DSL",
- "createGuide.nav.back": "部署",
- "createGuide.release.defaultName": "初始版本",
- "createGuide.release.deployInfo": "部署信息",
- "createGuide.release.description": "填写部署信息和首个版本信息。",
- "createGuide.release.firstVersion": "首个版本",
- "createGuide.release.instanceDescription": "部署描述",
- "createGuide.release.instanceDescriptionPlaceholder": "描述该部署的用途",
- "createGuide.release.instanceName": "部署名称",
- "createGuide.release.instanceNameConflict": "该部署名称已存在,请换一个名称。",
- "createGuide.release.releaseDescription": "版本描述",
- "createGuide.release.releaseDescriptionPlaceholder": "描述这个版本",
- "createGuide.release.releaseName": "版本名称",
- "createGuide.release.title": "基本信息",
- "createGuide.source.clearSearch": "清空应用搜索",
- "createGuide.source.description": "选择用于生成首个版本的来源。",
- "createGuide.source.empty": "未找到工作流应用。",
- "createGuide.source.searchPlaceholder": "搜索应用",
- "createGuide.source.sourceApp": "工作流应用",
- "createGuide.source.title": "版本来源",
- "createGuide.steps.method": "版本来源",
- "createGuide.steps.release": "基本信息",
- "createGuide.steps.source": "版本来源",
- "createGuide.steps.target": "部署到环境",
- "createGuide.target.bindingCount_one": "{{count}} 项",
- "createGuide.target.bindingCount_other": "{{count}} 项",
- "createGuide.target.bindingHint": "选择该版本使用的凭据。",
- "createGuide.target.bindings": "凭据",
- "createGuide.target.description": "选择目标环境,并提供此版本在该环境中所需的运行时设置。此步骤可跳过。",
- "createGuide.target.envVarCount_one": "{{count}} 项",
- "createGuide.target.envVarCount_other": "{{count}} 项",
- "createGuide.target.envVarHint": "为该版本需要的每个环境变量输入自定义值,或使用应用中定义的值。",
- "createGuide.target.envVarPlaceholder": "输入变量值",
- "createGuide.target.envVarSource.ariaLabel": "选择 {{key}} 的变量值来源",
- "createGuide.target.envVarSource.default": "应用中的值",
- "createGuide.target.envVarSource.lastDeployment": "上次部署值",
- "createGuide.target.envVarSource.literal": "自定义值",
- "createGuide.target.envVarType.number": "数字",
- "createGuide.target.envVarType.secret": "密钥",
- "createGuide.target.envVarType.string": "字符串",
- "createGuide.target.envVars": "环境变量",
- "createGuide.target.environment": "目标环境",
- "createGuide.target.loadBindingsFailed": "加载凭据失败。",
- "createGuide.target.loadEnvironmentsFailed": "加载部署环境失败。",
- "createGuide.target.missingRequiredBinding": "请选择该必填绑定使用的凭据。",
- "createGuide.target.noBindingRequired": "无需凭据。",
- "createGuide.target.noCredentialCandidates": "没有可用凭据。",
- "createGuide.target.noEnvironmentOptions": "没有可用部署环境。",
- "createGuide.target.selectCredential": "选择凭据",
- "createGuide.target.title": "部署到环境",
- "createGuide.title": "新建部署",
- "createModal.appPickerPlaceholder": "选择工作流应用",
- "createModal.appSearchEmpty": "没有匹配的工作流应用",
- "createModal.appSearchPlaceholder": "搜索工作流应用…",
- "createModal.cancel": "取消",
- "createModal.loadingApps": "正在加载应用…",
- "deployDrawer.bindingCount_one": "{{count}} 项",
- "deployDrawer.bindingCount_other": "{{count}} 项",
"deployDrawer.bindingOptionsFailed": "加载凭据选项失败。",
"deployDrawer.bindingSelectionHint": "选择本次部署要使用的凭据。",
- "deployDrawer.cancel": "取消",
- "deployDrawer.close": "关闭部署抽屉",
- "deployDrawer.defaultSelect": "选择…",
- "deployDrawer.deploy": "部署到环境",
- "deployDrawer.deployFailed": "启动部署失败。",
"deployDrawer.deploying": "部署中…",
- "deployDrawer.description": "选择版本和目标环境,完成部署。",
- "deployDrawer.envVarCount_one": "{{count}} 项",
- "deployDrawer.envVarCount_other": "{{count}} 项",
- "deployDrawer.envVarHint": "为该版本需要的每个环境变量输入自定义值,或使用应用中定义的值。",
- "deployDrawer.envVarPlaceholder": "输入变量值",
"deployDrawer.envVarSource.ariaLabel": "选择 {{key}} 的变量值来源",
- "deployDrawer.envVarSource.default": "应用中的值",
"deployDrawer.envVarSource.lastDeployment": "上次部署值",
"deployDrawer.envVarSource.literal": "自定义值",
"deployDrawer.envVarType.number": "数字",
"deployDrawer.envVarType.secret": "密钥",
"deployDrawer.envVarType.string": "字符串",
"deployDrawer.envVars": "环境变量",
- "deployDrawer.existingReleaseHint": "将直接部署该版本,不会创建新版本。",
- "deployDrawer.lockedHint": "已锁定至当前环境",
- "deployDrawer.missingRequiredBinding": "请选择该必填绑定使用的凭据。",
- "deployDrawer.missingRequiredEnvVar": "请填写该必填环境变量。",
- "deployDrawer.noBindingRequired": "无需配置",
"deployDrawer.noCredentialCandidates": "没有可用凭据。",
"deployDrawer.noNewEnvironmentAvailable": "所有可用环境都已有部署。",
- "deployDrawer.noOtherReleaseAvailable": "此环境没有其他可用版本。",
- "deployDrawer.noReleaseAvailable": "请先创建版本,再部署到环境。",
- "deployDrawer.notFound": "未找到部署。",
- "deployDrawer.releaseLabel": "版本",
"deployDrawer.runtimeCredentials": "凭据",
"deployDrawer.selectCredential": "选择凭据",
- "deployDrawer.selectEnv": "选择一个环境",
- "deployDrawer.selectRelease": "选择一个版本",
- "deployDrawer.targetEnv": "目标环境",
- "deployDrawer.title": "部署到环境",
- "deployTab.closeError": "关闭",
"deployTab.col.actions": "操作",
- "deployTab.col.currentRelease": "当前版本",
"deployTab.col.environment": "环境",
"deployTab.col.status": "状态",
"deployTab.confirmUndeploy": "下线",
- "deployTab.deployOtherVersion": "部署其他版本",
- "deployTab.emptyDescription": "选择版本和目标环境,让该部署可以被用户访问。",
- "deployTab.emptyTitle": "暂无运行中的环境",
- "deployTab.errorCode": "代码",
- "deployTab.errorDialogDesc": "重试或部署其他版本前,先查看上一次失败的部署原因。",
- "deployTab.errorDialogTitle": "{{name}} 的部署错误",
- "deployTab.errorMessage": "消息",
- "deployTab.errorPhase": "阶段",
"deployTab.moreActions": "更多操作",
- "deployTab.newDeployment": "部署到新环境",
- "deployTab.panel.unknownError": "部署失败。",
"deployTab.redeploy": "重新部署",
- "deployTab.retry": "重试",
- "deployTab.status.deployFailed": "部署失败",
- "deployTab.status.deployingRelease": "部署中({{release}})",
- "deployTab.status.runningOutOfSync": "运行中(待同步)",
- "deployTab.status.runningWithFailed": "运行中(上次部署失败)",
"deployTab.undeploy": "下线",
- "deployTab.undeployConfirmDesc": "环境端点将无法访问,但版本不会被删除。",
- "deployTab.undeployConfirmTitle": "下线 {{name}}?",
"deployTab.undeployConfirmWarning": "确认后,此环境将进入下线中状态,相关操作将暂时禁用。",
- "deployTab.viewError": "查看错误",
- "detail.mobileTabs": "部署页面",
- "detail.notFound": "未找到部署",
- "documentTitle.create": "新建部署 · 部署",
- "documentTitle.detail": "部署 · 部署",
- "documentTitle.list": "部署",
- "filter.allEnvs": "全部环境",
- "filter.searchPlaceholder": "搜索部署",
- "health.ENVIRONMENT_STATUS_ADMISSION": "准入中",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "启动中",
- "health.ENVIRONMENT_STATUS_DELETING": "删除中",
"health.ENVIRONMENT_STATUS_FAILED": "不可用",
- "health.ENVIRONMENT_STATUS_READY": "可用",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "未知",
- "list.clearFilters": "清空筛选",
- "list.clearSearch": "清空部署搜索",
- "list.createDeployment": "新建",
- "list.emptyDescription": "从工作流应用或工作流 DSL 包新建部署后,即可管理版本、环境和访问方式。",
- "list.emptyFilteredDescription": "当前搜索或环境筛选下没有匹配的部署。",
- "list.emptyFilteredTitle": "没有匹配的部署",
"list.emptyTitle": "暂无部署",
- "mode.ENVIRONMENT_MODE_ISOLATED": "独立",
- "mode.ENVIRONMENT_MODE_SHARED": "共享",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "未知",
- "overview.accessMeta.apiTokens": "管理 API 访问令牌",
- "overview.accessMeta.cli": "查看 CLI 接入方式",
- "overview.accessMeta.webApp": "管理 WebApp 接入",
- "overview.accessStatus": "接入方式",
- "overview.api": "API 令牌",
- "overview.apiKeysCount_one": "{{count}} 个 API 令牌",
- "overview.apiKeysCount_other": "{{count}} 个 API 令牌",
- "overview.apiTokenSummary.environments_one": "{{count}} 个已部署环境",
- "overview.apiTokenSummary.environments_other": "{{count}} 个已部署环境",
- "overview.cardAction.deployLatest": "部署最新版本",
- "overview.cardAction.redeploy": "重新部署",
- "overview.cardAction.viewProgress": "查看部署",
- "overview.chip.behindTooltip_one": "落后最新版本 1 个,可部署最新版本更新。",
- "overview.chip.behindTooltip_other": "落后最新版本 {{count}} 个,可部署最新版本更新。",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "部署中",
- "overview.chip.deployingTooltip": "部署正在进行中。",
- "overview.chip.empty": "空",
- "overview.chip.emptyTooltip": "此环境尚未部署任何版本。",
- "overview.chip.failed": "失败",
- "overview.chip.failedTooltip": "最近一次部署失败。",
"overview.chip.latest": "最新",
- "overview.chip.latestTooltip": "此环境正在运行最新版本。",
- "overview.chip.needsReleaseFirst": "请先创建版本",
- "overview.chip.olderRelease": "较旧",
- "overview.chip.olderReleaseTooltip": "此环境正在运行较早的版本。",
- "overview.chip.openInDeployTab": "查看部署进度",
- "overview.disabled": "未启用",
- "overview.enabled": "已启用",
- "overview.hero.byName": "由 {{name}} 创建",
- "overview.hero.empty": "尚无版本",
- "overview.hero.emptyDescription": "先从当前来源创建版本,再部署到环境。",
- "overview.latestRelease.releaseCount_one": "共 {{count}} 个版本",
- "overview.latestRelease.releaseCount_other": "共 {{count}} 个版本",
- "overview.latestReleaseTitle": "最新版本",
- "overview.previousReleases.viewAll": "查看全部",
- "overview.strip.deployToNewEnvironment": "部署到新环境",
- "overview.strip.emptyDeployableDescription": "已有版本后,可选择环境进行部署。",
- "overview.strip.emptyDescription": "请先创建版本,再部署到环境。",
- "overview.strip.emptyTitle": "暂无实例",
- "overview.strip.title": "实例",
- "settings.delete": "删除部署",
- "settings.deleteConfirmDesc": "确定删除 {{name}}?所有实例都将停止运行,并从所有环境中移除。此操作无法撤销。",
- "settings.deleteConfirmTitle": "删除部署",
- "settings.deleteFailed": "删除部署失败。",
- "settings.deleted": "部署已删除",
- "settings.description": "描述",
- "settings.name": "部署名称",
- "settings.save": "保存修改",
- "settings.updateFailed": "更新部署失败。",
- "settings.updated": "部署已更新",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "部署中",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "待同步",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "部署失败",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "异常",
"status.RUNTIME_INSTANCE_STATUS_READY": "运行中",
@@ -370,87 +89,6 @@
"studio.versionValue": "版本值",
"studio.versionsBehind_one": "落后 {{count}} 个版本",
"studio.versionsBehind_other": "落后 {{count}} 个版本",
- "tabs.access.description": "管理接入渠道与访问权限。",
- "tabs.access.name": "接入方式",
- "tabs.api-tokens.description": "管理 API 令牌,通过 HTTP 调用各环境中的实例。",
- "tabs.api-tokens.name": "API 令牌",
- "tabs.instances.description": "查看和管理各环境中的实例。",
- "tabs.instances.name": "实例",
- "tabs.overview.description": "查看此部署在各环境中的状态。",
- "tabs.overview.name": "概览",
- "tabs.releases.description": "创建、部署和管理版本。",
- "tabs.releases.name": "版本",
- "unsupportedDslNodes.description": "该版本包含当前部署运行时尚不支持的节点。请在 Studio 中移除或替换这些节点后重试。",
- "unsupportedDslNodes.descriptionWithTypes": "该版本包含当前部署运行时尚不支持的节点:{{nodeTypes}}。请在 Studio 中移除或替换后重试。",
- "unsupportedDslNodes.title": "不支持的节点",
- "unsupportedDslNodes.unknownType": "未知类型",
- "versions.cancelCreate": "取消",
- "versions.cancelDelete": "取消",
- "versions.cancelEdit": "取消",
"versions.checkingReleaseContent": "正在检查版本内容…",
- "versions.col.action": "操作",
- "versions.col.author": "创建者",
- "versions.col.createdAt": "创建时间",
- "versions.col.deployedTo": "已部署到",
- "versions.col.release": "版本",
- "versions.col.sourceApp": "来源",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "创建",
- "versions.createFailed": "创建版本失败。",
- "versions.createRelease": "创建版本",
- "versions.createReleaseDescription": "从工作流应用或工作流 DSL 文件创建可部署版本。",
- "versions.createSuccess": "版本 \"{{name}}\" 已创建。",
- "versions.creating": "创建中…",
- "versions.currentOn": "{{name}} 当前版本",
- "versions.deleteConfirmDesc": "版本 \"{{name}}\" 将被永久删除,此操作无法撤销。",
- "versions.deleteConfirmTitle": "删除版本?",
- "versions.deleteFailed": "删除版本失败。",
- "versions.deleteRelease": "删除版本",
- "versions.deleteSuccess": "版本 \"{{name}}\" 已删除。",
- "versions.deployTo": "部署到 {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "部署中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "待同步",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "失败",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "异常",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "运行中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "未部署",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "下线中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "未知",
- "versions.deployingTo": "{{name}} 正在部署",
- "versions.disabledReason.checkDeploymentsFailed": "无法确认部署使用情况,请稍后重试。",
- "versions.disabledReason.checkingDeployments": "正在检查部署使用情况",
- "versions.disabledReason.current": "{{name}} 已运行此版本",
- "versions.disabledReason.deploying": "请等待当前部署完成",
- "versions.disabledReason.releaseInUse_one": "请先从 {{count}} 个环境中取消部署此版本,再删除它",
- "versions.disabledReason.releaseInUse_other": "请先从 {{count}} 个环境中取消部署此版本,再删除它",
- "versions.dslReadFailed": "读取 DSL 文件失败。请选择其他文件后重试。",
- "versions.dslReading": "正在读取 DSL 文件…",
- "versions.dslUnsupportedMode": "仅支持使用工作流 DSL 创建部署版本。",
- "versions.editFailed": "更新版本失败。",
- "versions.editRelease": "编辑版本",
- "versions.editReleaseDescription": "更新此版本的名称和描述。",
- "versions.editSuccess": "版本 \"{{name}}\" 已更新。",
- "versions.emptyDescription": "先创建第一个版本,再部署到目标环境。",
- "versions.emptyTitle": "暂无版本",
- "versions.exportDsl": "导出 DSL",
- "versions.exportDslFailed": "导出 DSL 失败。",
- "versions.exportingDsl": "正在导出…",
- "versions.groupHeader.deploy": "部署",
- "versions.groupHeader.rollback": "部署历史版本",
- "versions.groupHeader.unavailable": "不可用",
- "versions.manualDslOption": "上传 DSL",
- "versions.moreActions": "更多操作",
- "versions.optional": "可选",
- "versions.releaseAlreadyExists": "相同内容的版本已存在:{{name}}。",
- "versions.releaseContentCheckFailed": "检查版本内容失败。",
- "versions.releaseDescriptionLabel": "描述",
- "versions.releaseDescriptionPlaceholder": "描述这个版本",
- "versions.releaseNameConflict": "此版本名称已存在,请选择其他名称。",
- "versions.releaseNameLabel": "版本名称",
- "versions.releaseNamePlaceholder": "版本名称",
- "versions.releaseNameRequired": "请输入版本名称。",
- "versions.releaseSourceLabel": "版本来源",
- "versions.rollbackTo": "部署到 {{name}}",
- "versions.saveEdit": "保存",
- "versions.sourceAppOption": "工作流应用"
+ "versions.deployTo": "部署到 {{name}}"
}
diff --git a/web/i18n/zh-Hant/common.json b/web/i18n/zh-Hant/common.json
index 29e455e99d6..08ca64bd61f 100644
--- a/web/i18n/zh-Hant/common.json
+++ b/web/i18n/zh-Hant/common.json
@@ -300,7 +300,6 @@
"menus.appDetail": "應用詳情",
"menus.apps": "工作室",
"menus.datasets": "知識庫",
- "menus.deployments": "部署",
"menus.exploreMarketplace": "探索 Marketplace",
"menus.plugins": "集成",
"menus.status": "beta",
diff --git a/web/i18n/zh-Hant/deployments.json b/web/i18n/zh-Hant/deployments.json
index a583e692690..dc7aef53ef8 100644
--- a/web/i18n/zh-Hant/deployments.json
+++ b/web/i18n/zh-Hant/deployments.json
@@ -1,313 +1,32 @@
{
- "access.api.copyCurlExample": "複製 cURL 範例",
- "access.api.createFailed": "產生 API Token 失敗。",
- "access.api.createKey": "產生 API Token",
- "access.api.createKeyTitle": "產生新的 API Token",
- "access.api.curlExampleTitle": "cURL 範例",
- "access.api.description": "透過 HTTP 呼叫此部署。每個 API Token 僅對單一環境生效。",
- "access.api.developerTitle": "開發者 API",
- "access.api.disabled": "此部署的 API 存取已關閉。",
- "access.api.disabledHint": "啟用 API 存取後即可產生繫結環境的 Token。",
- "access.api.docs": "API 文件",
- "access.api.docsClose": "關閉 API 文件",
- "access.api.docsDescription": "檢視此部署的 Workflow API 參考文件。",
- "access.api.docsTitle": "Workflow API 文件",
- "access.api.empty": "請先部署到環境,再簽發 API Token。",
- "access.api.emptyTitle": "尚無已部署環境",
- "access.api.endpoint": "請求 URL",
- "access.api.keyList": "API Token 清單",
- "access.api.nameLabel": "API Token 名稱",
- "access.api.namePlaceholder": "請輸入 API Token 名稱",
- "access.api.nameRequired": "請輸入 API Token 名稱。",
- "access.api.newKey": "產生新的 API Token",
- "access.api.newTokenDescription": "此 API Token 僅顯示一次,請在離開此頁面前複製保存。",
- "access.api.newTokenLabel": "API Token",
- "access.api.newTokenTitle": "API Token 已產生",
- "access.api.noKeys": "尚無 API Token,請產生一個以開始呼叫 API。",
- "access.api.noKeysTitle": "尚無 API Token",
- "access.api.revokeConfirmDescription": "API Token「{{name}}」將立即失效,此操作無法復原。",
- "access.api.revokeConfirmTitle": "撤銷 API Token?",
- "access.api.revokeFailed": "撤銷 API Token 失敗。",
- "access.api.revokeSuccess": "API Token 已撤銷",
- "access.api.table.action": "操作",
- "access.api.table.environment": "環境",
- "access.api.table.key": "API Token",
- "access.api.table.name": "名稱",
- "access.channels.disabled": "此部署的存取通道已關閉。",
- "access.channels.disabledHint": "啟用存取通道後即可開放 WebApp 與 CLI 進入點。",
- "access.channels.title": "存取通道",
- "access.cli.description": "透過 difyctl 在終端機呼叫,適用於腳本、自動化流程或 Agent 整合。",
- "access.cli.docs": "使用說明",
- "access.cli.domain": "網域",
- "access.cli.empty": "尚未設定 CLI 進入點。",
- "access.cli.install": "安裝 CLI",
- "access.cli.title": "CLI",
- "access.copy": "複製",
- "access.copyFailed": "複製失敗",
- "access.members.groupCount_one": "{{count}} 個群組",
- "access.members.groupCount_other": "{{count}} 個群組",
- "access.members.memberCount_one": "{{count}} 位成員",
- "access.members.memberCount_other": "{{count}} 位成員",
- "access.permission.anyone": "擁有連結的任何人",
- "access.permission.organization": "平台內所有成員",
- "access.permission.specific": "平台內指定成員",
- "access.permission.specificDesc": "選擇指定的群組或成員",
- "access.permission.updateFailed": "更新存取策略失敗。",
- "access.permissions.editAriaLabel": "設定 {{environment}} 的存取權限",
- "access.permissions.editDescription": "設定 WebApp 與 CLI 進入點的存取權限。",
- "access.permissions.editTitle": "存取權限",
- "access.permissions.title": "存取權限",
- "access.revoke": "撤銷",
- "access.runAccess.noEnvs": "請先部署到環境後再設定存取權限。",
- "access.runAccess.noEnvsTitle": "尚無已部署環境",
- "access.runAccess.openWebapp": "開啟 WebApp",
- "access.runAccess.urlLabel": "URL",
- "access.runAccess.webapp": "WebApp",
- "access.runAccess.webappDesc": "面向終端使用者的託管網頁。",
- "access.runAccess.webappEmpty": "即將推出。",
- "backend.RUNTIME_BACKEND_EXTERNAL": "外部",
- "backend.RUNTIME_BACKEND_K8S": "K8S",
- "backend.RUNTIME_BACKEND_UNSPECIFIED": "未知",
- "card.access.api": "API Token",
- "card.access.cli": "CLI",
- "card.access.none": "未開啟存取",
- "card.access.webApp": "WebApp",
- "card.createFirstRelease": "建立首個版本",
- "card.envOverflow": "+ {{count}}",
- "card.menu.delete": "刪除部署",
- "card.menu.deploy": "部署到環境",
- "card.menu.editInfo": "編輯資訊",
- "card.moreActions": "更多操作",
- "card.noDescription": "未提供描述。",
"card.notDeployed": "未部署",
- "card.tooltip.createdAt": "建立時間",
- "card.tooltip.deployed": "已部署",
- "card.tooltip.deploymentStatus": "部署狀態",
- "card.tooltip.notDeployedShort": "未部署",
- "card.tooltip.releaseName": "版本名稱",
- "card.tooltip.source": "來源",
"common.loadFailed": "載入失敗,請稍後再試。",
- "createGuide.actions.back": "返回",
- "createGuide.actions.createAndDeploy": "建立並部署",
- "createGuide.actions.creating": "建立中…",
- "createGuide.actions.deploying": "建立並部署中…",
- "createGuide.actions.next": "下一步",
- "createGuide.actions.skipDeploy": "跳過,稍後再部署",
- "createGuide.dsl.defaultAppName": "匯入的 DSL 應用",
- "createGuide.dsl.description": "上傳 Workflow DSL 套件以建立部署、首個版本,以及選擇性地部署到環境。",
- "createGuide.dsl.dropDescription": "上傳 Workflow YAML DSL 套件。部署前會從該檔案解析部署選項。",
- "createGuide.dsl.dropTitle": "上傳 Workflow DSL 套件",
- "createGuide.dsl.readFailed": "讀取 DSL 檔案失敗。請選擇其他檔案後重試。",
- "createGuide.dsl.reading": "正在讀取 DSL 檔案…",
- "createGuide.dsl.title": "匯入 DSL",
- "createGuide.dsl.unsupportedMode": "僅支援使用 Workflow DSL 檔案建立部署。",
- "createGuide.errors.createReleaseFailed": "建立部署或版本失敗。",
- "createGuide.errors.deployFailed": "部署到環境失敗。",
- "createGuide.method.description": "選擇用於建立首個版本的來源。",
- "createGuide.methods.bindApp.description": "使用 Studio 中現有的 Workflow App 作為版本來源。",
- "createGuide.methods.bindApp.title": "繫結現有的 Workflow App",
- "createGuide.methods.importDsl.description": "上傳 Workflow YAML DSL 套件並繼續完成部署流程。",
- "createGuide.methods.importDsl.title": "匯入 DSL",
- "createGuide.nav.back": "部署",
- "createGuide.release.defaultName": "初始版本",
- "createGuide.release.deployInfo": "部署資訊",
- "createGuide.release.description": "填寫部署資訊及首個版本詳細資料。",
- "createGuide.release.firstVersion": "首個版本",
- "createGuide.release.instanceDescription": "部署描述",
- "createGuide.release.instanceDescriptionPlaceholder": "描述此部署的用途",
- "createGuide.release.instanceName": "部署名稱",
- "createGuide.release.instanceNameConflict": "此部署名稱已存在,請另選名稱。",
- "createGuide.release.releaseDescription": "版本描述",
- "createGuide.release.releaseDescriptionPlaceholder": "描述此版本",
- "createGuide.release.releaseName": "版本名稱",
- "createGuide.release.title": "基本資訊",
- "createGuide.source.clearSearch": "清除應用搜尋",
- "createGuide.source.description": "選擇用於建立首個版本的來源。",
- "createGuide.source.empty": "找不到 Workflow App。",
- "createGuide.source.searchPlaceholder": "搜尋應用",
- "createGuide.source.sourceApp": "Workflow App",
- "createGuide.source.title": "版本來源",
- "createGuide.steps.method": "版本來源",
- "createGuide.steps.release": "基本資訊",
- "createGuide.steps.source": "版本來源",
- "createGuide.steps.target": "部署到環境",
- "createGuide.target.bindingCount_one": "{{count}} 項繫結",
- "createGuide.target.bindingCount_other": "{{count}} 項繫結",
- "createGuide.target.bindingHint": "選擇此版本要使用的憑證。",
- "createGuide.target.bindings": "憑證",
- "createGuide.target.description": "選擇目標環境,並提供此版本在該環境所需的執行階段設定。此步驟可跳過。",
- "createGuide.target.envVarCount_one": "{{count}} 項變數",
- "createGuide.target.envVarCount_other": "{{count}} 項變數",
- "createGuide.target.envVarHint": "為此版本所需的每個環境變數輸入自訂值,或使用應用中定義的值。",
- "createGuide.target.envVarPlaceholder": "輸入值",
- "createGuide.target.envVarSource.ariaLabel": "選擇 {{key}} 的變數值來源",
- "createGuide.target.envVarSource.default": "應用中的值",
- "createGuide.target.envVarSource.lastDeployment": "上次部署值",
- "createGuide.target.envVarSource.literal": "自訂值",
- "createGuide.target.envVarType.number": "數字",
- "createGuide.target.envVarType.secret": "機密",
- "createGuide.target.envVarType.string": "字串",
- "createGuide.target.envVars": "環境變數",
- "createGuide.target.environment": "目標環境",
- "createGuide.target.loadBindingsFailed": "載入憑證失敗。",
- "createGuide.target.loadEnvironmentsFailed": "載入部署環境失敗。",
- "createGuide.target.missingRequiredBinding": "請為此必要繫結選擇憑證。",
- "createGuide.target.noBindingRequired": "無需憑證。",
- "createGuide.target.noCredentialCandidates": "沒有可用的憑證。",
- "createGuide.target.noEnvironmentOptions": "沒有可用的部署環境。",
- "createGuide.target.selectCredential": "選擇憑證",
- "createGuide.target.title": "部署到環境",
- "createGuide.title": "新建部署",
- "createModal.appPickerPlaceholder": "選擇 Workflow App",
- "createModal.appSearchEmpty": "沒有符合的 Workflow App",
- "createModal.appSearchPlaceholder": "搜尋 Workflow App…",
- "createModal.cancel": "取消",
- "createModal.loadingApps": "正在載入應用…",
- "deployDrawer.bindingCount_one": "{{count}} 項繫結",
- "deployDrawer.bindingCount_other": "{{count}} 項繫結",
"deployDrawer.bindingOptionsFailed": "載入憑證選項失敗。",
"deployDrawer.bindingSelectionHint": "選擇此次部署要使用的憑證。",
- "deployDrawer.cancel": "取消",
- "deployDrawer.close": "關閉部署抽屜",
- "deployDrawer.defaultSelect": "選擇…",
- "deployDrawer.deploy": "部署到環境",
- "deployDrawer.deployFailed": "啟動部署失敗。",
"deployDrawer.deploying": "部署中…",
- "deployDrawer.description": "選擇版本和目標環境以完成部署。",
- "deployDrawer.envVarCount_one": "{{count}} 項變數",
- "deployDrawer.envVarCount_other": "{{count}} 項變數",
- "deployDrawer.envVarHint": "為此版本所需的每個環境變數輸入自訂值,或使用應用中定義的值。",
- "deployDrawer.envVarPlaceholder": "輸入值",
"deployDrawer.envVarSource.ariaLabel": "選擇 {{key}} 的變數值來源",
- "deployDrawer.envVarSource.default": "應用中的值",
"deployDrawer.envVarSource.lastDeployment": "上次部署值",
"deployDrawer.envVarSource.literal": "自訂值",
"deployDrawer.envVarType.number": "數字",
"deployDrawer.envVarType.secret": "機密",
"deployDrawer.envVarType.string": "字串",
"deployDrawer.envVars": "環境變數",
- "deployDrawer.existingReleaseHint": "此版本將原樣部署,不會建立新版本。",
- "deployDrawer.lockedHint": "已鎖定至目前環境",
- "deployDrawer.missingRequiredBinding": "請為此必要繫結選擇憑證。",
- "deployDrawer.missingRequiredEnvVar": "請為此必填環境變數輸入值。",
- "deployDrawer.noBindingRequired": "非必要",
"deployDrawer.noCredentialCandidates": "沒有可用的憑證。",
"deployDrawer.noNewEnvironmentAvailable": "所有可用的環境都已有部署。",
- "deployDrawer.noOtherReleaseAvailable": "此環境沒有其他可用的版本。",
- "deployDrawer.noReleaseAvailable": "請先建立版本,再部署到環境。",
- "deployDrawer.notFound": "找不到部署。",
- "deployDrawer.releaseLabel": "版本",
"deployDrawer.runtimeCredentials": "憑證",
"deployDrawer.selectCredential": "選擇憑證",
- "deployDrawer.selectEnv": "選擇一個環境",
- "deployDrawer.selectRelease": "選擇一個版本",
- "deployDrawer.targetEnv": "目標環境",
- "deployDrawer.title": "部署到環境",
- "deployTab.closeError": "關閉",
"deployTab.col.actions": "操作",
- "deployTab.col.currentRelease": "目前版本",
"deployTab.col.environment": "環境",
"deployTab.col.status": "狀態",
"deployTab.confirmUndeploy": "下線",
- "deployTab.deployOtherVersion": "部署其他版本",
- "deployTab.emptyDescription": "選擇版本和目標環境,讓使用者可以使用此部署。",
- "deployTab.emptyTitle": "尚無執行中的環境",
- "deployTab.errorCode": "錯誤碼",
- "deployTab.errorDialogDesc": "重試或部署其他版本前,請先檢視上次失敗的部署原因。",
- "deployTab.errorDialogTitle": "{{name}} 的部署錯誤",
- "deployTab.errorMessage": "訊息",
- "deployTab.errorPhase": "階段",
"deployTab.moreActions": "更多操作",
- "deployTab.newDeployment": "部署到新環境",
- "deployTab.panel.unknownError": "部署失敗。",
"deployTab.redeploy": "重新部署",
- "deployTab.retry": "重試",
- "deployTab.status.deployFailed": "部署失敗",
- "deployTab.status.deployingRelease": "部署中({{release}})",
- "deployTab.status.runningOutOfSync": "執行中(待同步)",
- "deployTab.status.runningWithFailed": "執行中(上次部署失敗)",
"deployTab.undeploy": "下線",
- "deployTab.undeployConfirmDesc": "環境端點將無法存取,但版本不會被刪除。",
- "deployTab.undeployConfirmTitle": "下線 {{name}}?",
"deployTab.undeployConfirmWarning": "確認後,此環境將進入下線中狀態,相關操作將暫時停用。",
- "deployTab.viewError": "檢視錯誤",
- "detail.mobileTabs": "部署頁面",
- "detail.notFound": "找不到部署",
- "documentTitle.create": "新建部署 · 部署",
- "documentTitle.detail": "部署 · 部署",
- "documentTitle.list": "部署",
- "filter.allEnvs": "所有環境",
- "filter.searchPlaceholder": "搜尋部署",
- "health.ENVIRONMENT_STATUS_ADMISSION": "准入中",
- "health.ENVIRONMENT_STATUS_BOOTSTRAPPING": "啟動中",
- "health.ENVIRONMENT_STATUS_DELETING": "刪除中",
"health.ENVIRONMENT_STATUS_FAILED": "不可用",
- "health.ENVIRONMENT_STATUS_READY": "可用",
- "health.ENVIRONMENT_STATUS_UNSPECIFIED": "未知",
- "list.clearFilters": "清除篩選",
- "list.clearSearch": "清除部署搜尋",
- "list.createDeployment": "新建",
- "list.emptyDescription": "從 Workflow App 或 Workflow DSL 套件建立部署後,即可管理版本、環境與存取權限。",
- "list.emptyFilteredDescription": "目前的搜尋或環境篩選下沒有符合的部署。",
- "list.emptyFilteredTitle": "沒有符合的部署",
"list.emptyTitle": "尚無部署",
- "mode.ENVIRONMENT_MODE_ISOLATED": "獨立",
- "mode.ENVIRONMENT_MODE_SHARED": "共用",
- "mode.ENVIRONMENT_MODE_UNSPECIFIED": "未知",
- "overview.accessMeta.apiTokens": "管理 API Token",
- "overview.accessMeta.cli": "檢視 CLI 存取方式",
- "overview.accessMeta.webApp": "管理 WebApp 存取",
- "overview.accessStatus": "存取",
- "overview.api": "API Token",
- "overview.apiKeysCount_one": "{{count}} 個 API Token",
- "overview.apiKeysCount_other": "{{count}} 個 API Token",
- "overview.apiTokenSummary.environments_one": "{{count}} 個已部署環境",
- "overview.apiTokenSummary.environments_other": "{{count}} 個已部署環境",
- "overview.cardAction.deployLatest": "部署最新版本",
- "overview.cardAction.redeploy": "重新部署",
- "overview.cardAction.viewProgress": "檢視部署",
- "overview.chip.behindTooltip_one": "落後最新版本 1 個,請部署最新版本以更新。",
- "overview.chip.behindTooltip_other": "落後最新版本 {{count}} 個,請部署最新版本以更新。",
- "overview.chip.behind_one": "↑ 1",
- "overview.chip.behind_other": "↑ {{count}}",
- "overview.chip.deploying": "部署中",
- "overview.chip.deployingTooltip": "部署正在進行中。",
- "overview.chip.empty": "空",
- "overview.chip.emptyTooltip": "此環境尚未部署任何版本。",
- "overview.chip.failed": "失敗",
- "overview.chip.failedTooltip": "最近一次部署嘗試失敗。",
"overview.chip.latest": "最新",
- "overview.chip.latestTooltip": "此環境正在執行最新版本。",
- "overview.chip.needsReleaseFirst": "請先建立版本",
- "overview.chip.olderRelease": "較舊",
- "overview.chip.olderReleaseTooltip": "此環境正在執行較舊的版本。",
- "overview.chip.openInDeployTab": "檢視部署進度",
- "overview.disabled": "已停用",
- "overview.enabled": "已啟用",
- "overview.hero.byName": "由 {{name}} 建立",
- "overview.hero.empty": "尚無版本",
- "overview.hero.emptyDescription": "請先從目前來源建立版本,再進行部署。",
- "overview.latestRelease.releaseCount_one": "共 {{count}} 個版本",
- "overview.latestRelease.releaseCount_other": "共 {{count}} 個版本",
- "overview.latestReleaseTitle": "最新版本",
- "overview.previousReleases.viewAll": "檢視全部",
- "overview.strip.deployToNewEnvironment": "部署到新環境",
- "overview.strip.emptyDeployableDescription": "準備好之後,可將最新版本部署到環境。",
- "overview.strip.emptyDescription": "請先建立版本,再部署到環境。",
- "overview.strip.emptyTitle": "尚無實例",
- "overview.strip.title": "實例",
- "settings.delete": "刪除部署",
- "settings.deleteConfirmDesc": "確定刪除 {{name}}?所有實例將停止執行,並從所有環境中移除。此操作無法復原。",
- "settings.deleteConfirmTitle": "刪除部署",
- "settings.deleteFailed": "刪除部署失敗。",
- "settings.deleted": "部署已刪除",
- "settings.description": "描述",
- "settings.name": "部署名稱",
- "settings.save": "儲存變更",
- "settings.updateFailed": "更新部署失敗。",
- "settings.updated": "部署已更新",
"status.RUNTIME_INSTANCE_STATUS_DEPLOYING": "部署中",
- "status.RUNTIME_INSTANCE_STATUS_DRIFTED": "待同步",
"status.RUNTIME_INSTANCE_STATUS_FAILED": "部署失敗",
"status.RUNTIME_INSTANCE_STATUS_INVALID": "異常",
"status.RUNTIME_INSTANCE_STATUS_READY": "執行中",
@@ -370,87 +89,6 @@
"studio.versionValue": "版本值",
"studio.versionsBehind_one": "落後 {{count}} 個版本",
"studio.versionsBehind_other": "落後 {{count}} 個版本",
- "tabs.access.description": "管理存取通道與存取權限。",
- "tabs.access.name": "存取",
- "tabs.api-tokens.description": "管理 API Token,並透過 HTTP 呼叫各環境中的實例。",
- "tabs.api-tokens.name": "API Token",
- "tabs.instances.description": "檢視並管理各環境中的實例。",
- "tabs.instances.name": "實例",
- "tabs.overview.description": "檢視此部署在各環境中的狀態。",
- "tabs.overview.name": "總覽",
- "tabs.releases.description": "建立、部署與管理版本。",
- "tabs.releases.name": "版本",
- "unsupportedDslNodes.description": "此版本包含部署執行階段尚未支援的節點。請在 Studio 中移除或替換後重試。",
- "unsupportedDslNodes.descriptionWithTypes": "此版本包含部署執行階段尚未支援的節點:{{nodeTypes}}。請在 Studio 中移除或替換後重試。",
- "unsupportedDslNodes.title": "不支援的節點",
- "unsupportedDslNodes.unknownType": "未知類型",
- "versions.cancelCreate": "取消",
- "versions.cancelDelete": "取消",
- "versions.cancelEdit": "取消",
"versions.checkingReleaseContent": "正在檢查版本內容…",
- "versions.col.action": "操作",
- "versions.col.author": "建立者",
- "versions.col.createdAt": "建立時間",
- "versions.col.deployedTo": "已部署到",
- "versions.col.release": "版本",
- "versions.col.sourceApp": "來源",
- "versions.commitTooltip": "Commit {{commit}}",
- "versions.create": "建立",
- "versions.createFailed": "建立版本失敗。",
- "versions.createRelease": "建立版本",
- "versions.createReleaseDescription": "從 Workflow App 或 Workflow DSL 檔案建立可部署的版本。",
- "versions.createSuccess": "版本「{{name}}」已建立。",
- "versions.creating": "建立中…",
- "versions.currentOn": "{{name}} 的目前版本",
- "versions.deleteConfirmDesc": "版本「{{name}}」將被永久刪除,此操作無法復原。",
- "versions.deleteConfirmTitle": "刪除版本?",
- "versions.deleteFailed": "刪除版本失敗。",
- "versions.deleteRelease": "刪除版本",
- "versions.deleteSuccess": "版本「{{name}}」已刪除。",
- "versions.deployTo": "部署到 {{name}}",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DEPLOYING": "部署中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_DRIFTED": "待同步",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_FAILED": "失敗",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_INVALID": "異常",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_READY": "執行中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYED": "未部署",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNDEPLOYING": "下線中",
- "versions.deployedStatus.RUNTIME_INSTANCE_STATUS_UNSPECIFIED": "未知",
- "versions.deployingTo": "{{name}} 正在部署中",
- "versions.disabledReason.checkDeploymentsFailed": "無法確認部署使用情況,請稍後再試。",
- "versions.disabledReason.checkingDeployments": "正在檢查部署使用情況",
- "versions.disabledReason.current": "此版本已在 {{name}} 上執行",
- "versions.disabledReason.deploying": "請等待目前部署完成",
- "versions.disabledReason.releaseInUse_one": "請先從 {{count}} 個環境中取消部署此版本,再進行刪除",
- "versions.disabledReason.releaseInUse_other": "請先從 {{count}} 個環境中取消部署此版本,再進行刪除",
- "versions.dslReadFailed": "讀取 DSL 檔案失敗。請選擇其他檔案後重試。",
- "versions.dslReading": "正在讀取 DSL 檔案…",
- "versions.dslUnsupportedMode": "僅支援使用 Workflow DSL 檔案建立部署。",
- "versions.editFailed": "更新版本失敗。",
- "versions.editRelease": "編輯版本",
- "versions.editReleaseDescription": "更新此版本的名稱與描述。",
- "versions.editSuccess": "版本「{{name}}」已更新。",
- "versions.emptyDescription": "請先建立第一個版本,再部署到環境。",
- "versions.emptyTitle": "尚無版本",
- "versions.exportDsl": "匯出 DSL",
- "versions.exportDslFailed": "匯出 DSL 失敗。",
- "versions.exportingDsl": "正在匯出…",
- "versions.groupHeader.deploy": "部署",
- "versions.groupHeader.rollback": "部署歷史版本",
- "versions.groupHeader.unavailable": "不可用",
- "versions.manualDslOption": "上傳 DSL",
- "versions.moreActions": "更多操作",
- "versions.optional": "選填",
- "versions.releaseAlreadyExists": "相同內容的版本已存在:{{name}}。",
- "versions.releaseContentCheckFailed": "檢查版本內容失敗。",
- "versions.releaseDescriptionLabel": "描述",
- "versions.releaseDescriptionPlaceholder": "描述此版本",
- "versions.releaseNameConflict": "此版本名稱已存在,請選擇其他名稱。",
- "versions.releaseNameLabel": "版本名稱",
- "versions.releaseNamePlaceholder": "版本名稱",
- "versions.releaseNameRequired": "請輸入版本名稱。",
- "versions.releaseSourceLabel": "版本來源",
- "versions.rollbackTo": "部署到 {{name}}",
- "versions.saveEdit": "儲存",
- "versions.sourceAppOption": "Workflow App"
+ "versions.deployTo": "部署到 {{name}}"
}
diff --git a/web/package.json b/web/package.json
index a416e30acfb..74827b86870 100644
--- a/web/package.json
+++ b/web/package.json
@@ -62,7 +62,6 @@
"@svgdotjs/svg.js": "catalog:",
"@t3-oss/env-nextjs": "catalog:",
"@tailwindcss/typography": "catalog:",
- "@tanstack/form-core": "catalog:",
"@tanstack/query-core": "catalog:",
"@tanstack/react-form": "catalog:",
"@tanstack/react-hotkeys": "catalog:",
@@ -95,7 +94,6 @@
"immer": "catalog:",
"jotai": "catalog:",
"jotai-scope": "catalog:",
- "jotai-tanstack-form": "workspace:*",
"jotai-tanstack-query": "catalog:",
"js-cookie": "catalog:",
"js-yaml": "catalog:",
diff --git a/web/service/access-control/use-access-subjects.ts b/web/service/access-control/use-access-subjects.ts
deleted file mode 100644
index f5fc9b4ae3c..00000000000
--- a/web/service/access-control/use-access-subjects.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import type { AccessControlGroup, Subject } from '@/models/access-control'
-import { useInfiniteQuery } from '@tanstack/react-query'
-import { consoleClient } from '../client'
-
-const NAME_SPACE = 'access-control'
-
-type SearchAccessSubjectsResult = {
- currPage: number
- totalPages: number
- subjects: Subject[]
- hasMore: boolean
-}
-
-export type SearchAccessSubjectsQuery = {
- keyword?: string
- groupId?: AccessControlGroup['id']
- resultsPerPage?: number
-}
-
-export const useSearchAccessSubjects = (query: SearchAccessSubjectsQuery, enabled: boolean) => {
- const { keyword, groupId, resultsPerPage } = query
-
- return useInfiniteQuery({
- queryKey: [NAME_SPACE, 'access-subject-candidates', keyword, groupId, resultsPerPage],
- queryFn: async ({ pageParam }) => {
- const response = await consoleClient.enterprise.webAppAuth.searchForWhilteListCandidates({
- query: {
- ...(keyword ? { keyword } : {}),
- ...(groupId ? { groupId } : {}),
- ...(resultsPerPage ? { resultsPerPage } : {}),
- pageNumber: pageParam as number,
- },
- })
-
- return {
- currPage: response.currPage ?? (pageParam as number),
- totalPages: 0,
- subjects: (response.subjects ?? []) as Subject[],
- hasMore: response.hasMore ?? false,
- } satisfies SearchAccessSubjectsResult
- },
- initialPageParam: 1,
- getNextPageParam: (lastPage) => {
- if (lastPage.hasMore) return lastPage.currPage + 1
- return undefined
- },
- gcTime: 0,
- staleTime: 0,
- enabled,
- })
-}