From a281a577f9cfe4d21fa3d632a8c761046908a699 Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Wed, 2 Apr 2025 16:31:48 +0530 Subject: [PATCH 01/78] feat: add support for skipping hibernated apps in bulk deploy --- .../ApplicationGroup/AppGroup.types.ts | 2 +- .../Details/TriggerView/BulkCDTrigger.tsx | 49 ++++++++++++++----- .../Details/TriggerView/EnvTriggerView.tsx | 11 +++-- .../app/details/triggerView/cdMaterial.tsx | 1 + .../common/navigation/NavigationRoutes.tsx | 15 +++++- 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/components/ApplicationGroup/AppGroup.types.ts b/src/components/ApplicationGroup/AppGroup.types.ts index e0e0a3cbad..355e1831ef 100644 --- a/src/components/ApplicationGroup/AppGroup.types.ts +++ b/src/components/ApplicationGroup/AppGroup.types.ts @@ -133,7 +133,7 @@ export interface BulkCDTriggerType extends BulkRuntimeParamsType { appList: BulkCDDetailType[] closePopup: (e) => void updateBulkInputMaterial: (materialList: Record) => void - onClickTriggerBulkCD: (appsToRetry?: Record) => void + onClickTriggerBulkCD: (skipIfHibernated: boolean, appsToRetry?: Record) => void changeTab?: ( materrialId: string | number, artifactId: number, diff --git a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx index 6de4241b14..bbfee46953 100644 --- a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx +++ b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx @@ -19,7 +19,6 @@ import { CDMaterialResponseType, DeploymentNodeType, Drawer, - Progressing, ReleaseTag, ImageComment, showError, @@ -48,9 +47,12 @@ import { Button, ComponentSizeType, AnimatedDeployButton, + ButtonVariantType, + Icon, + ButtonStyleType, + useMainContext, } from '@devtron-labs/devtron-fe-common-lib' import { useHistory, useLocation } from 'react-router-dom' -import { ReactComponent as Close } from '@Icons/ic-cross.svg' import { ReactComponent as DeployIcon } from '@Icons/ic-nav-rocket.svg' import { ReactComponent as PlayIcon } from '@Icons/ic-play-outline.svg' import { ReactComponent as Error } from '@Icons/ic-warning.svg' @@ -89,6 +91,7 @@ const validateRuntimeParameters = importComponentFromFELibrary( () => ({ isValid: true, cellError: {} }), 'function', ) +const SkipHibernatedCheckbox = importComponentFromFELibrary('SkipHibernatedCheckbox', null, 'function') // TODO: Fix release tags selection export default function BulkCDTrigger({ @@ -109,6 +112,7 @@ export default function BulkCDTrigger({ runtimeParamsErrorState, setRuntimeParamsErrorState, }: BulkCDTriggerType) { + const { isScoopConfigured } = useMainContext() const [selectedApp, setSelectedApp] = useState( appList.find((app) => !app.warningMessage) || appList[0], ) @@ -125,6 +129,7 @@ export default function BulkCDTrigger({ const [isPartialActionAllowed, setIsPartialActionAllowed] = useState(false) const [showResistanceBox, setShowResistanceBox] = useState(false) const [currentSidebarTab, setCurrentSidebarTab] = useState(CDMaterialSidebarType.IMAGE) + const [skipHibernated, setSkipHibernated] = useState(false) const location = useLocation() const history = useHistory() @@ -351,15 +356,18 @@ export default function BulkCDTrigger({ const renderHeaderSection = (): JSX.Element => { return (
-

Deploy to {appList[0].envName}

- + size={ComponentSizeType.xs} + icon={} + ariaLabel="close bulk cd trigger modal" + showAriaLabelInTippy={false} + style={ButtonStyleType.negativeGrey} + variant={ButtonVariantType.borderLess} + />
) } @@ -829,13 +837,15 @@ export default function BulkCDTrigger({ setShowResistanceBox(false) } + const triggerBulkCD = () => onClickTriggerBulkCD(skipHibernated) + const onClickStartDeploy = (e): void => { if (isPartialActionAllowed && BulkDeployResistanceTippy && !showResistanceBox) { setShowResistanceBox(true) } else { isBulkDeploymentTriggered.current = true stopPropagation(e) - onClickTriggerBulkCD() + triggerBulkCD() setShowResistanceBox(false) } } @@ -848,8 +858,21 @@ export default function BulkCDTrigger({ const renderFooterSection = (): JSX.Element => { const isDeployButtonDisabled: boolean = isDeployDisabled() + const showSkipHibernatedCheckbox = stage === DeploymentNodeType.CD && !!SkipHibernatedCheckbox return ( -
+
+ {showSkipHibernatedCheckbox && ( + app.appId)} + skipHibernated={skipHibernated} + setSkipHibernated={setSkipHibernated} + /> + )}
{!isDeployButtonDisabled && stage === DeploymentNodeType.CD && !isLoading ? ( @@ -874,7 +897,7 @@ export default function BulkCDTrigger({ return (
-
+
{renderHeaderSection()} {responseListLength ? ( ) : ( renderFooterSection() diff --git a/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx b/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx index 87945322bf..082ab27a3c 100644 --- a/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx +++ b/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx @@ -1429,7 +1429,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou return true } - const onClickTriggerBulkCD = (appsToRetry?: Record) => { + const onClickTriggerBulkCD = (skipIfHibernated: boolean, appsToRetry?: Record) => { if (isCDLoading || !validateBulkRuntimeParams()) { return } @@ -1482,6 +1482,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou ...(getRuntimeParamsPayload ? { runtimeParamsPayload: getRuntimeParamsPayload(runtimeParams[currentAppId] ?? []) } : {}), + skipIfHibernated: skipIfHibernated, }), ) } else { @@ -1941,7 +1942,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou } if (!filteredWorkflows.length) { return ( -
+
) @@ -2099,7 +2100,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou ) } - const renderBulkSourchChange = (): JSX.Element | null => { + const renderBulkSourceChange = (): JSX.Element | null => { if (!showBulkSourceChangeModal) { return null } @@ -2452,12 +2453,12 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou {renderBulkCDMaterial()} {renderBulkCIMaterial()} {renderApprovalMaterial()} - {renderBulkSourchChange()} + {renderBulkSourceChange()}
{!!selectedAppList.length && ( -
+
{renderSelectedApps()} {renderBulkTriggerActionButtons()}
diff --git a/src/components/app/details/triggerView/cdMaterial.tsx b/src/components/app/details/triggerView/cdMaterial.tsx index 3614571a1e..38d8c0b21d 100644 --- a/src/components/app/details/triggerView/cdMaterial.tsx +++ b/src/components/app/details/triggerView/cdMaterial.tsx @@ -894,6 +894,7 @@ const CDMaterial = ({ ...(getRuntimeParamsPayload ? { runtimeParamsPayload: getRuntimeParamsPayload(runtimeParamsList ?? []) } : {}), + skipIfHibernated: false, }) .then((response: any) => { if (response.result) { diff --git a/src/components/common/navigation/NavigationRoutes.tsx b/src/components/common/navigation/NavigationRoutes.tsx index ea43038ded..f39c9a1e5c 100644 --- a/src/components/common/navigation/NavigationRoutes.tsx +++ b/src/components/common/navigation/NavigationRoutes.tsx @@ -155,13 +155,18 @@ export default function NavigationRoutes() { const [environmentDataState, setEnvironmentDataState] = useState< Pick< MainContext, - 'isAirgapped' | 'isManifestScanningEnabled' | 'canOnlyViewPermittedEnvOrgLevel' | 'featureGitOpsFlags' + | 'isAirgapped' + | 'isManifestScanningEnabled' + | 'canOnlyViewPermittedEnvOrgLevel' + | 'featureGitOpsFlags' + | 'isScoopConfigured' > >({ isAirgapped: false, isManifestScanningEnabled: false, canOnlyViewPermittedEnvOrgLevel: false, featureGitOpsFlags: structuredClone(DEFAULT_GIT_OPS_FEATURE_FLAGS), + isScoopConfigured: false, }) const [userPreferences, setUserPreferences] = useState(null) const [userPreferencesError, setUserPreferencesError] = useState(null) @@ -342,6 +347,7 @@ export default function NavigationRoutes() { isManifestScanningEnabled: false, canOnlyViewPermittedEnvOrgLevel: false, featureGitOpsFlags: structuredClone(DEFAULT_GIT_OPS_FEATURE_FLAGS), + isScoopConfigured: false, } if (!getEnvironmentData) { @@ -361,6 +367,7 @@ export default function NavigationRoutes() { isManifestScanningEnabled: result.isManifestScanningEnabled, canOnlyViewPermittedEnvOrgLevel: result.canOnlyViewPermittedEnvOrgLevel, featureGitOpsFlags: parsedFeatureGitOpsFlags, + isScoopConfigured: result.isScoopConfigured ?? false, } } catch { return fallbackResponse @@ -408,6 +415,7 @@ export default function NavigationRoutes() { isManifestScanningEnabled: environmentDataResponse.isManifestScanningEnabled, canOnlyViewPermittedEnvOrgLevel: environmentDataResponse.canOnlyViewPermittedEnvOrgLevel, featureGitOpsFlags: environmentDataResponse.featureGitOpsFlags, + isScoopConfigured: environmentDataResponse.isScoopConfigured, }) setServerMode(serverModeResponse) @@ -484,7 +492,9 @@ export default function NavigationRoutes() { } const _isOnboardingPage = isOnboardingPage() - const handleOpenLicenseInfoDialog = (initialDialogTab?: LicenseInfoDialogType.ABOUT | LicenseInfoDialogType.LICENSE) => { + const handleOpenLicenseInfoDialog = ( + initialDialogTab?: LicenseInfoDialogType.ABOUT | LicenseInfoDialogType.LICENSE, + ) => { setLicenseInfoDialogType(initialDialogTab || LicenseInfoDialogType.ABOUT) } @@ -526,6 +536,7 @@ export default function NavigationRoutes() { handleOpenLicenseInfoDialog, licenseData, setLicenseData, + isScoopConfigured: environmentDataState.isScoopConfigured, }} >
From 802b722a0e9a2a256e0d96eefa5319e38a4f84b2 Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Wed, 2 Apr 2025 16:40:51 +0530 Subject: [PATCH 02/78] chore: add check for scoop on skip checkbox --- .../ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx index bbfee46953..916fedd999 100644 --- a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx +++ b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx @@ -858,7 +858,7 @@ export default function BulkCDTrigger({ const renderFooterSection = (): JSX.Element => { const isDeployButtonDisabled: boolean = isDeployDisabled() - const showSkipHibernatedCheckbox = stage === DeploymentNodeType.CD && !!SkipHibernatedCheckbox + const showSkipHibernatedCheckbox = stage === DeploymentNodeType.CD && !!SkipHibernatedCheckbox && isScoopConfigured return (
Date: Thu, 3 Apr 2025 15:28:39 +0530 Subject: [PATCH 03/78] chore: update yarn.lock --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0fdc506f0a..c3093e794b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,10 +1126,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@devtron-labs/devtron-fe-common-lib@1.10.6": - version "1.10.6" - resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.10.6.tgz#bc3792c519cb9a00204ef29487b5c17809289f15" - integrity sha512-ZVZTfUpnEiqo2t+n+4n5cirGWkZeafSOJWxbmSVBHD5oqpt8yrD+UBrvDxy1viTwOCrjwol6dkVllNEZeA3V3A== +"@devtron-labs/devtron-fe-common-lib@1.10.11": + version "1.10.11" + resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.10.11.tgz#3d26a29373cb36d2bec35389d7a67f6a3ca3ee42" + integrity sha512-7Pts9Su3jigWtDARNn3JvznS7RZbiBae9nB8FQdI9vgKT1sWLfbapkcgz5A0iXaF72qOmrqVnMEjnnVYh8a8Rw== dependencies: "@codemirror/lang-json" "6.0.1" "@codemirror/lang-yaml" "6.1.2" From bdc83314b602a4c36b4c0083d62f7edaf04891b5 Mon Sep 17 00:00:00 2001 From: Neha Sharma Date: Sun, 6 Apr 2025 23:13:23 +0530 Subject: [PATCH 04/78] update the configfile --- config.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config.md b/config.md index 647ae15a40..007363fd10 100644 --- a/config.md +++ b/config.md @@ -48,5 +48,10 @@ | TRIGGER_API_TIMEOUT | 60000 | Default timeout for all API requests for Trigger calls (Deploy artifacts, charts) in DASHBOARD | | FEATURE_HIDE_USER_DIRECT_PERMISSIONS_FOR_NON_SUPER_ADMINS | "true" | Would hide the user direct permissions for non-super admin users in User Permissions | | FEATURE_ACTION_AUDIOS_ENABLE | true | Would enable audios in dashboard | +| k8s_client | false | To pass the kubelink URL | +| FEATURE_EXTERNAL_FLUX_CD_ENABLE | false | To enable flux cd option in app list page | +| FEATURE_BULK_RESTART_WORKLOADS_FROM_RB | deployment,rollout,daemonset,statefulset | To enable bulk restart workload option in resource browser | +| FEATURE_USER_DEFINED_GITOPS_REPO_ENABLE | false | If enabled user can pass the manual gitops repo | +| SENTRY_RELEASE_VERSION | | Sentry release Version | # DASHBOARD CONFIG SECRET From 6abf455afb80d5c36c4193d24743af08705fedd3 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Tue, 8 Apr 2025 12:00:06 +0530 Subject: [PATCH 05/78] fix: improve import/export order across modules via eslint-plugin-simple-import-sort --- .eslintrc.js | 24 ++- package.json | 1 + .../App/CreateAppModal/AppToCloneSelector.tsx | 5 +- .../CreateAppModal/ApplicationInfoForm.tsx | 9 +- .../CreateAppModal.component.tsx | 28 ++-- .../App/CreateAppModal/HeaderSection.tsx | 2 + .../App/CreateAppModal/ProjectSelector.tsx | 2 + src/Pages/App/CreateAppModal/Sidebar.tsx | 2 + .../CreateAppModal/UpdateTemplateConfig.tsx | 4 +- .../App/CreateAppModal/Workflow/Workflow.tsx | 3 +- .../App/CreateAppModal/Workflow/index.ts | 2 +- .../App/CreateAppModal/Workflow/utils.tsx | 8 +- src/Pages/App/CreateAppModal/constants.ts | 1 + src/Pages/App/CreateAppModal/service.ts | 1 + src/Pages/App/CreateAppModal/types.ts | 7 +- src/Pages/App/CreateAppModal/utils.tsx | 6 +- .../ExternalFlux/ExternalFluxAppDetails.tsx | 22 +-- .../ExternalFluxAppDetailsRoute.tsx | 4 +- .../App/Details/ExternalFlux/service.tsx | 1 + .../AppConfigurations/AppConfig.service.ts | 5 +- .../Details/AppConfigurations/AppConfig.tsx | 48 +++--- .../AppConfigurations/AppConfig.types.ts | 10 +- .../AppConfigurations/AppConfig.utils.ts | 12 +- .../AppConfiguration.provider.tsx | 1 + .../MainContent/AppComposeRouter.tsx | 17 ++- .../BaseConfigurationNavigation.tsx | 1 + .../MainContent/CompareConfigView.tsx | 6 +- .../MainContent/ConfigDryRun.tsx | 11 +- .../MainContent/ConfigHeader.tsx | 2 + .../MainContent/ConfigToolbar.tsx | 23 +-- .../DeploymentConfigCompare.tsx | 48 +++--- .../DeploymentConfigCompare/service.utils.ts | 1 + .../DeploymentConfigCompare/types.ts | 3 +- .../DeploymentConfigCompare/utils.ts | 6 +- .../DeploymentTemplate/DTChartSelector.tsx | 19 ++- .../DeleteOverrideDialog.tsx | 5 +- .../DeploymentTemplate/DeploymentTemplate.tsx | 142 +++++++++--------- .../DeploymentTemplateCTA.tsx | 5 +- .../DeploymentTemplateForm.tsx | 9 +- .../DeploymentTemplateOptionsHeader.tsx | 5 +- .../GUIView/GUIView.component.tsx | 21 +-- .../DeploymentTemplate/GUIView/types.ts | 1 + .../deploymentTemplateReducer.ts | 2 + .../MainContent/DeploymentTemplate/service.ts | 8 +- .../MainContent/DeploymentTemplate/types.ts | 21 +-- .../MainContent/DeploymentTemplate/utils.tsx | 19 ++- .../MainContent/NoOverrideEmptyState.tsx | 6 +- .../NoPublishedVersionEmptyState.tsx | 1 + .../MainContent/SelectMergeStrategy.tsx | 10 +- .../MainContent/constants.tsx | 3 +- .../AppConfigurations/MainContent/index.ts | 11 +- .../AppConfigurations/MainContent/types.ts | 8 +- .../AppConfigurations/MainContent/utils.tsx | 6 +- .../Navigation/AppNavigation.tsx | 13 +- .../Navigation/EnvConfigurationsNav.tsx | 16 +- .../Navigation/EnvironmentOverrideRouter.tsx | 33 ++-- .../Navigation/Navigation.helper.tsx | 4 +- .../AppConfigurations/Navigation/constants.ts | 7 +- src/Pages/Applications/DevtronApps/service.ts | 10 +- .../Applications/DevtronApps/service.types.ts | 1 + .../Authorization/APITokens/APITokenList.tsx | 13 +- .../APITokens/ApiTokens.component.tsx | 16 +- .../APITokens/CreateAPIToken.tsx | 30 ++-- .../APITokens/DeleteAPITokenModal.tsx | 7 +- .../Authorization/APITokens/EditAPIToken.tsx | 44 +++--- .../APITokens/ExpirationDate.tsx | 8 +- .../APITokens/GenerateActionButton.tsx | 1 + .../Authorization/APITokens/GenerateModal.tsx | 6 +- .../APITokens/RegenerateModal.tsx | 12 +- .../Authorization/APITokens/service.ts | 3 +- .../Authorization/Authorization.component.tsx | 2 + .../Authorization/AuthorizationProvider.tsx | 1 + .../PermissionGroupAddEdit.component.tsx | 6 +- .../AddEdit/PermissionGroupForm.tsx | 28 ++-- .../List/ExportPermissionGroupsToCsv.tsx | 4 +- .../List/NoPermissionGroups.tsx | 5 +- .../List/PermissionGroupContainer.tsx | 12 +- .../List/PermissionGroupList.component.tsx | 18 ++- .../List/PermissionGroupListHeader.tsx | 17 ++- .../List/PermissionGroupRow.tsx | 9 +- .../List/PermissionGroupTable.tsx | 1 + .../PermissionGroups/List/types.ts | 1 + .../SSOLoginServices/SSOLogin.component.tsx | 49 +++--- .../Authorization/SSOLoginServices/index.ts | 2 +- .../Authorization/SSOLoginServices/service.ts | 3 +- .../SSOLoginServices/ssoConfig.types.tsx | 3 +- .../AppPermissions/AppOrJobSelector.tsx | 15 +- .../AppPermissions/AppPermissionDetail.tsx | 5 +- .../AppPermissions.component.tsx | 39 ++--- .../AppPermissions/DirectPermission.tsx | 28 ++-- .../AppPermissions/EnvironmentSelector.tsx | 4 +- .../AppPermissions/JobRoleSelector.tsx | 1 + .../AppPermissions/RoleSelector.tsx | 26 ++-- .../AppPermissions/WorkflowSelector.tsx | 3 +- .../components/AppPermissions/constants.ts | 3 +- .../AppPermissions/roleSelectorHelpers.tsx | 7 +- .../Shared/components/AppPermissions/types.ts | 12 +- .../Shared/components/AppPermissions/utils.ts | 13 +- .../BulkSelection/BulkDeleteModal.tsx | 6 +- .../BulkSelectionActionWidget.tsx | 9 +- .../BulkSelectionClearConfirmationModal.tsx | 1 + .../BulkSelection/BulkSelectionModal.tsx | 5 +- .../Shared/components/BulkSelection/index.ts | 4 +- .../Shared/components/BulkSelection/types.ts | 4 +- .../useAuthorizationBulkSelection.tsx | 1 + .../ChartPermission.component.tsx | 12 +- .../K8sObjectPermissions/K8sListItemCard.tsx | 41 ++--- .../K8sPermissionModal.tsx | 8 +- .../K8sObjectPermissions/K8sPermissionRow.tsx | 7 +- .../K8sPermissions.component.tsx | 9 +- .../components/K8sObjectPermissions/types.ts | 1 + .../components/K8sObjectPermissions/utils.tsx | 5 +- .../PermissionConfigurationForm.component.tsx | 4 +- .../PermissionConfigurationFormProvider.tsx | 4 +- .../PermissionConfigurationForm/types.ts | 1 + ...UserPermissionGroupsSelector.component.tsx | 15 +- .../Authorization/UserAndGroupPermissions.tsx | 14 +- .../UserPermissions/AddEdit/UserForm.tsx | 40 ++--- .../UserPermissionAddEdit.component.tsx | 12 +- .../UserPermissions/DeleteUserPermission.tsx | 6 +- .../List/ExportUserPermissionsToCsv.tsx | 7 +- .../UserPermissions/List/NoUsers.tsx | 5 +- .../List/UserPermissionContainer.tsx | 18 ++- .../List/UserPermissionList.component.tsx | 19 +-- .../List/UserPermissionListHeader.tsx | 17 ++- .../List/UserPermissionRow.tsx | 36 ++--- .../List/UserPermissionTable.tsx | 1 + .../UserPermissions/List/constants.ts | 3 +- .../UserPermissions/List/types.tsx | 4 +- .../UserPermissions/SSONotConfiguredState.tsx | 3 +- .../UserPermissions.component.tsx | 8 +- .../Authorization/UserPermissions/utils.ts | 1 + .../Authorization/authorization.service.ts | 38 ++--- .../Authorization/constants.ts | 7 +- .../Authorization/libUtils.ts | 3 +- .../Authorization/types.ts | 28 ++-- .../Authorization/utils.ts | 44 +++--- .../BuildInfra/BuildInfra.tsx | 6 +- .../BuildInfra/BuildInfraCMCSForm.tsx | 1 + .../BuildInfra/BuildInfraUtiltityProvider.tsx | 2 + .../BuildInfra/ProfileForm.tsx | 10 +- .../ClusterEnvironmentDrawer.tsx | 32 ++-- .../EnvironmentDeleteComponent.tsx | 4 +- .../DeploymentChartsRouter.component.tsx | 5 +- .../List/DeploymentChartsList.component.tsx | 36 +++-- .../List/DeploymentChartsListHeader.tsx | 6 +- .../List/DownloadChartButton.tsx | 3 + .../DeploymentCharts/List/UploadButton.tsx | 4 +- .../List/UploadChartModal.tsx | 15 +- .../DeploymentCharts/List/service.tsx | 14 +- .../DeploymentCharts/List/utils.tsx | 1 + .../DeploymentCharts/types.ts | 2 +- .../OfflinePipelineModalAppView.tsx | 3 + src/Pages/GlobalConfigurations/index.ts | 2 +- .../Detail/Configurations/Configurations.tsx | 12 +- .../ConfigMapSecret.service.ts | 39 ++--- .../ConfigMapSecret.wrapper.tsx | 7 +- .../ConfigMapSecretContainer.tsx | 65 ++++---- .../ConfigMapSecret/ConfigMapSecretData.tsx | 22 +-- .../ConfigMapSecretDeleteModal.tsx | 9 +- .../ConfigMapSecret/ConfigMapSecretDryRun.tsx | 17 +-- .../ConfigMapSecret/ConfigMapSecretForm.tsx | 22 +-- .../ConfigMapSecretNullState.tsx | 4 +- .../ConfigMapSecretProtected.tsx | 18 +-- src/Pages/Shared/ConfigMapSecret/constants.ts | 1 + src/Pages/Shared/ConfigMapSecret/helpers.tsx | 4 +- src/Pages/Shared/ConfigMapSecret/index.ts | 1 - src/Pages/Shared/ConfigMapSecret/types.ts | 18 +-- src/Pages/Shared/ConfigMapSecret/utils.ts | 30 ++-- .../EnvironmentOverride.tsx | 13 +- .../EnvironmentOverrides.types.ts | 7 +- .../EnvironmentOverviewTable.component.tsx | 19 +-- .../EnvironmentOverviewTable.types.ts | 1 + .../Shared/EnvironmentOverviewTable/index.ts | 2 +- .../LinkedCIDetailsModal/LinkedCIAppList.tsx | 6 +- .../LinkedCIDetailsModal/LinkedCIDetail.tsx | 6 +- .../LinkedCIDetailsModal.tsx | 37 ++--- .../Shared/LinkedCIDetailsModal/constants.ts | 3 +- .../Shared/LinkedCIDetailsModal/service.ts | 5 +- .../Shared/LinkedCIDetailsModal/types.ts | 5 +- .../OrganizationFrame.component.tsx | 2 + .../SwitchThemeDialog.component.tsx | 9 +- src/Pages/index.ts | 2 +- src/components/AppSelector/AppSelector.tsx | 16 +- .../AppSelector/AppSelector.types.ts | 6 +- .../AppSelector/AppSelectorUtil.tsx | 1 + .../__mock__/EnvCDDetails.mock.ts | 1 + .../__mock__/EnvCIDetails.mock.ts | 1 + .../EnvironmentConfig/ApplicationRoutes.tsx | 3 +- .../Details/EnvironmentConfig/EnvConfig.tsx | 12 +- .../RestartStatusListDrawer.tsx | 16 +- .../RestartWorkloadModal.tsx | 35 +++-- .../__mock__/EnvironmentOverview.mock.ts | 1 + .../Details/EnvironmentOverview/service.ts | 7 +- .../Details/TriggerView/BulkSourceChange.tsx | 4 +- .../TriggerView/SourceUpdateResponseModal.tsx | 1 + .../TriggerView/TriggerModalTableRow.tsx | 9 +- .../TriggerView/TriggerResponseModal.tsx | 2 + .../ApplicationGroup/EnvEmptyStates.tsx | 1 + .../ApplicationGroup/EnvSelector.tsx | 6 +- .../List/EnvironmentListView.tsx | 12 +- .../List/EnvironmentsList.tsx | 24 +-- .../LoadingShimmer/LoadingShimmerList.tsx | 3 +- .../CreatePluginFormContent.tsx | 11 +- .../CreatePluginFormField.tsx | 2 + .../CreatePluginInputVariableContainer.tsx | 2 + .../CreatePluginModal.component.tsx | 28 ++-- .../CIPipelineN/CreatePluginModal/service.tsx | 2 + .../CIPipelineN/CreatePluginModal/utils.tsx | 13 +- .../CIPipelineN/CustomImageTag.type.ts | 2 + src/components/CIPipelineN/CustomScript.tsx | 8 +- .../CIPipelineN/CustomScriptCard.tsx | 2 + src/components/CIPipelineN/DockerArgs.tsx | 4 +- src/components/CIPipelineN/MountFromHost.tsx | 6 +- .../PluginDetailHeader/CreatePluginButton.tsx | 7 +- .../PluginDetailHeader.component.tsx | 21 +-- .../PluginVersionSelect.tsx | 5 +- .../CIPipelineN/TaskFieldTippyDescription.tsx | 1 + src/components/CIPipelineN/TaskTitle.tsx | 7 +- .../VariableDataTable/ValueConfigOverlay.tsx | 4 +- .../VariableDataTable.component.tsx | 5 +- .../VariableDataTablePopupMenu.tsx | 2 +- .../VariableDataTable/constants.ts | 2 +- .../CIPipelineN/VariableDataTable/types.ts | 5 +- .../CIPipelineN/VariableDataTable/utils.tsx | 8 +- .../VariableDataTable/validations.ts | 4 +- src/components/CIPipelineN/types.ts | 6 +- .../ClusterNodes/ClusterMapInitialStatus.tsx | 6 +- .../ClusterNodes/ClusterSelectionList.tsx | 38 ++--- .../ClusterNodes/ClusterTerminal.tsx | 52 ++++--- .../NodeActions/CordonNodeModal.tsx | 16 +- .../NodeActions/DeleteNodeModal.tsx | 7 +- .../NodeActions/DrainNodeModal.tsx | 18 ++- .../ClusterNodes/clusterNodes.service.tsx | 17 ++- src/components/ClusterNodes/types.ts | 14 +- src/components/ClusterNodes/utils.tsx | 1 + .../Jobs/JobList/JobListContainer.tsx | 13 +- .../Jobs/JobList/JobListFilters.tsx | 4 +- src/components/Jobs/JobList/JobsList.tsx | 16 +- src/components/Jobs/Types.ts | 2 + src/components/ResourceBrowser/Constants.ts | 4 +- .../ResourceBrowser/PageHeader.buttons.tsx | 4 +- .../ResourceBrowser.service.tsx | 14 +- .../ResourceBrowser/ResourceBrowser.tsx | 15 +- .../ResourceBrowser/ResourceBrowserRouter.tsx | 4 + .../ResourceList/AdminTerminal.tsx | 10 +- .../ResourceList/BaseResourceList.tsx | 61 ++++---- .../ResourceList/ClusterSelector.tsx | 8 +- .../ClusterUpgradeCompatibilityInfo.tsx | 8 +- .../ResourceList/ColumnSelector.tsx | 4 +- .../ResourceList/ConnectingToClusterState.tsx | 9 +- .../ResourceList/CreateResource.tsx | 24 +-- .../ResourceList/DeleteResourcePopup.tsx | 10 +- .../ResourceList/EventList.tsx | 3 + .../ResourceList/K8SResourceList.tsx | 17 ++- .../ResourceList/K8SResourceTabComponent.tsx | 10 +- .../ResourceList/NodeActionsMenu.tsx | 23 +-- .../ResourceList/NodeListSearchFilter.tsx | 15 +- .../ResourceBrowserActionMenu.tsx | 30 ++-- .../ResourceList/ResourceFilterOptions.tsx | 21 +-- .../ResourceList/ResourceList.component.tsx | 9 +- .../ResourceList/ResourceList.tsx | 63 ++++---- .../ResourceList/ResourceListEmptyState.tsx | 3 +- .../ResourceBrowser/ResourceList/Sidebar.tsx | 18 ++- .../ResourceBrowser/ResourceList/types.ts | 9 +- .../ResourceBrowser/ResourceList/utils.tsx | 5 +- src/components/ResourceBrowser/Types.ts | 17 ++- src/components/ResourceBrowser/Utils.tsx | 12 +- src/components/app/Overview/constants.ts | 1 + src/components/app/details/AppHeader.tsx | 23 +-- .../app/details/appDetails/AppDetails.tsx | 91 +++++------ .../details/appDetails/AppDetailsCDButton.tsx | 16 +- .../app/details/appDetails/AppSecurity.tsx | 3 +- .../details/appDetails/DeployedCommitCard.tsx | 4 +- .../appDetails/DeploymentStatusCard.tsx | 7 +- .../app/details/appDetails/HibernateModal.tsx | 2 + .../details/appDetails/IssuesListingModal.tsx | 6 +- .../details/appDetails/LastUpdatedCard.tsx | 5 +- .../appDetails/SecurityVulnerabilityCard.tsx | 6 +- .../details/appDetails/appDetails.service.ts | 5 +- .../app/details/appDetails/appDetails.type.ts | 4 +- .../app/details/appDetails/types.ts | 1 + .../app/details/cdDetails/cd.type.ts | 3 +- .../metrics/deploymentMetrics.types.ts | 2 +- .../details/triggerView/BranchRegexModal.tsx | 20 +-- .../details/triggerView/CIMaterialModal.tsx | 6 +- .../triggerView/CiWebhookDebuggingModal.tsx | 28 ++-- .../usePipelineDeploymentConfig.ts | 18 +-- .../triggerView/PipelineConfigDiff/utils.tsx | 2 +- .../details/triggerView/TriggerView.utils.tsx | 1 + .../WebhookReceivedPayloadModal.tsx | 11 +- .../triggerView/__mocks__/workflow.mock.ts | 1 + .../details/triggerView/cdMaterials.utils.ts | 3 +- .../app/details/triggerView/types.ts | 41 ++--- src/components/app/details/utils.tsx | 4 +- src/components/app/list-new/AppList.tsx | 60 ++++---- .../app/list-new/AppListComponents.tsx | 4 +- .../app/list-new/AppListFilters.tsx | 11 +- src/components/app/list-new/AppListType.ts | 4 +- src/components/app/list-new/Constants.ts | 2 + src/components/app/list-new/list.utils.ts | 5 +- .../app/list/DevtronAppListContainer.tsx | 30 ++-- src/components/app/list/types.tsx | 4 +- src/components/bulkEdits/bulkEdits.type.tsx | 2 + .../bulkEdits/bulkedits.service.tsx | 1 + src/components/cdPipeline/DeleteCDNode.tsx | 3 +- .../MigrateToDevtron/ClusterSelect.tsx | 1 + .../MigrateToDevtron.component.tsx | 19 ++- .../MigrateToDevtronValidationFactory.tsx | 22 +-- .../cdPipeline/MigrateToDevtron/service.tsx | 18 ++- .../cdPipeline/MigrateToDevtron/types.ts | 2 + .../cdPipeline/MigrateToDevtron/utils.tsx | 7 +- .../cdPipeline/PullImageDigestToggle.tsx | 6 +- .../cdPipeline/TriggerTypeRadio.tsx | 1 + src/components/cdPipeline/cdPipeline.types.ts | 9 +- src/components/cdPipeline/constants.ts | 3 +- src/components/cdPipeline/types.ts | 6 +- src/components/charts/charts.helper.ts | 1 + src/components/charts/charts.types.tsx | 1 + src/components/charts/list/AddChartSource.tsx | 1 + src/components/ciConfig/BuildContext.tsx | 10 +- .../ciConfig/CISelfDockerBuildOption.tsx | 2 + .../CreateDockerFileLanguageOptions.tsx | 5 +- src/components/ciConfig/ciConfigConstant.ts | 3 +- src/components/ciConfig/types.tsx | 19 ++- src/components/ciConfig/utils.tsx | 1 + src/components/ciPipeline/Webhook/types.ts | 1 + src/components/ciPipeline/types.ts | 27 ++-- src/components/cluster/cluster.type.ts | 4 +- .../ClusterMetaDataBar/ClusterMetaDataBar.tsx | 11 +- .../ClusterNotReachableDialog.tsx | 1 + src/components/common/Contexts/AppContext.tsx | 3 +- .../DeploymentTypeIcon/DeploymentTypeIcon.tsx | 3 +- .../common/DynamicTabs/DynamicTabs.timer.tsx | 6 +- .../common/DynamicTabs/DynamicTabs.tsx | 18 ++- .../common/DynamicTabs/DynamicTabsSelect.tsx | 5 +- src/components/common/DynamicTabs/types.ts | 2 + src/components/common/DynamicTabs/useTabs.ts | 6 +- src/components/common/DynamicTabs/utils.ts | 3 +- .../ExportToCsv/ExportConfiguration.tsx | 2 + .../common/ExportToCsv/ExportToCsv.tsx | 19 ++- .../common/GitTabs/GitProviderTab.tsx | 11 +- .../common/GitTabs/GitProviderTabIcons.tsx | 7 +- src/components/common/LazyImage/LazyImage.tsx | 1 + .../TLSConnectionForm.component.tsx | 1 + .../TLSConnectionForm/TLSInputField.tsx | 3 + .../common/TLSConnectionForm/index.ts | 2 +- .../common/emptyState/ChartEmptyState.tsx | 1 + .../common/formFields/Widgets/Widgets.tsx | 2 + .../GitInfoMaterialCard/GitInfoMaterial.tsx | 35 +++-- .../ReceivedWebhookRedirectButton.tsx | 7 +- .../helpers/GitInfoMaterialCard/types.ts | 6 +- .../InteractiveCellText.tsx | 1 + src/components/common/helpers/types.ts | 6 +- src/components/common/index.ts | 30 ++-- src/components/common/navigation/types.ts | 5 +- src/components/dockerRegistry/dockerType.tsx | 1 + .../externalLinks/AddLinkButton.tsx | 2 + .../externalLinks/ExternalLinkFilter.tsx | 5 +- .../externalLinks/ExternalLinkList.tsx | 13 +- .../externalLinks/ExternalLinks.service.ts | 1 + .../externalLinks/ExternalLinks.tsx | 31 ++-- .../externalLinks/ExternalLinks.type.ts | 6 +- .../externalLinks/ExternalLinks.utils.tsx | 11 +- .../gitOps/UpdateConfirmationDialog.tsx | 10 +- src/components/gitOps/constants.ts | 3 +- src/components/gitProvider/types.ts | 1 + src/components/globalConfigurations/types.ts | 3 +- src/components/hostURL/hosturl.service.ts | 1 + src/components/hostURL/hosturl.type.ts | 1 + src/components/login/Login.tsx | 34 +++-- src/components/login/LoginForm.tsx | 21 +-- src/components/login/login.service.ts | 1 + src/components/material/material.service.ts | 3 +- .../notifications/AddConfigurationButton.tsx | 5 +- .../ConfigTableRowActionButton.tsx | 6 +- .../ConfigurationDrawerModal.tsx | 4 +- .../notifications/ConfigurationTab.tsx | 21 +-- .../notifications/ConfigurationTables.tsx | 19 ++- .../ConfigurationTabsSwitcher.tsx | 6 +- .../notifications/DefaultCheckbox.tsx | 1 + .../notifications/EmptyConfigurationView.tsx | 3 +- .../notifications/SESConfigModal.tsx | 26 ++-- .../notifications/SESConfigurationTable.tsx | 12 +- .../notifications/SMTPConfigModal.tsx | 18 ++- .../notifications/SMTPConfigurationTable.tsx | 11 +- .../notifications/SlackConfigModal.tsx | 22 +-- .../notifications/SlackConfigurationTable.tsx | 11 +- .../WebhookConfigDynamicDataTable.tsx | 2 + .../notifications/WebhookConfigModal.tsx | 23 +-- .../WebhookConfigurationTable.tsx | 11 +- src/components/notifications/types.tsx | 11 +- src/components/project/service.ts | 1 + .../scopedVariables/DescriptionTab.tsx | 2 +- .../scopedVariables/SavedVariablesContent.tsx | 22 +-- src/components/scopedVariables/constants.tsx | 1 + src/components/scopedVariables/service.ts | 3 +- src/components/scopedVariables/types.tsx | 3 +- .../security/AddCVEPolicy/ExposureList.tsx | 1 + .../AddCVEPolicy/VulnerabilityExposure.tsx | 20 +-- .../SecurityScansTab/SecurityScansTab.tsx | 37 ++--- .../security/SecurityScansTab/utils.tsx | 1 + .../v2/HelmAppOverview/HelmAppOverview.tsx | 7 +- .../v2/appDetails/AppDetails.component.tsx | 28 ++-- .../appDetails/NodeDetailComponentWrapper.tsx | 5 +- .../v2/appDetails/NodeTreeDetailTab.tsx | 18 ++- .../v2/appDetails/appDetails.store.ts | 3 +- src/components/v2/appDetails/index.store.ts | 6 +- .../k8Resource/K8Resource.component.tsx | 18 ++- .../nodeDetail/DeleteEphemeralButton.tsx | 8 +- .../nodeDetail/NodeDetail.component.tsx | 56 +++---- .../nodeDetail/NodeDetailTabs/CopyToast.tsx | 2 + .../NodeDetailTabs/Events.component.tsx | 10 +- .../nodeDetail/NodeDetailTabs/EventsTable.tsx | 4 +- .../NodeDetailTabs/LogViewer.component.tsx | 9 +- .../NodeDetailTabs/Logs.component.tsx | 54 ++++--- .../NodeDetailTabs/Manifest.component.tsx | 69 +++++---- .../nodeDetail/NodeDetailTabs/node.type.ts | 2 + .../NodeDetailTabs/terminal/Terminal.tsx | 20 ++- .../__mocks__/terminalWrapper.mock.tsx | 6 +- .../terminal/terminal.utils.tsx | 33 ++-- .../k8Resource/nodeDetail/nodeDetail.type.ts | 8 +- .../k8Resource/nodeType/Node.component.tsx | 34 +++-- .../nodeType/NodeDelete.component.tsx | 36 +++-- .../nodeType/PodHeader.component.tsx | 7 +- .../k8Resource/nodeType/PodPopup.tsx | 7 +- .../appDetails/k8Resource/nodeType/types.ts | 4 +- .../v2/appDetails/k8Resource/utils.tsx | 1 + .../logAnalyzer/LogAnalyzer.component.tsx | 1 + .../appDetails/sourceInfo/environment.type.ts | 4 +- .../environmentStatus/ChartUsedCard.tsx | 9 +- .../HelmAppConfigApplyStatusCard.tsx | 4 +- .../rotatePods/rotatePodsModal.service.ts | 1 + .../rotatePods/rotatePodsModal.type.ts | 7 +- .../scaleWorkloadsModal.service.ts | 3 +- .../DockerImageDetails.tsx | 3 +- .../RollbackConfirmationDialog.tsx | 8 +- src/components/v2/common/message.ui.tsx | 8 +- .../DevtronStackManager.type.ts | 4 +- .../chartValuesDiff/ChartValuesGUIView.tsx | 15 +- .../chartValuesDiff/ChartValuesView.type.ts | 6 +- .../chartValuesDiff/ChartValuesView.utils.ts | 8 +- .../chartValuesDiff/DeleteChartDialog.tsx | 4 +- .../ConfigureGitopsInfoBlock.tsx | 3 +- .../workflowEditor/ToggleCDSelectButton.tsx | 1 + src/components/workflowEditor/service.ts | 3 +- src/components/workflowEditor/types.ts | 24 +-- src/stories/ActionMenu.stories.tsx | 2 +- src/stories/Button.stories.tsx | 6 +- src/stories/ConfirmationModal.stories.tsx | 3 +- src/stories/InfoBlock.stories.tsx | 3 +- src/stories/PasswordField.stories.tsx | 3 +- src/stories/SegmentedControl.stories.tsx | 4 +- src/stories/SelectPicker.stories.tsx | 4 +- src/stories/TextField.stories.tsx | 4 +- src/stories/Textarea.stories.tsx | 5 +- src/stories/ToastManager.stories.tsx | 4 +- src/stories/useForm.stories.tsx | 2 +- tsconfig.json | 27 +--- yarn.lock | 5 + 460 files changed, 2909 insertions(+), 2095 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index a052fdc9b4..400fd19ca5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,9 +14,11 @@ * limitations under the License. */ +const tsconfigPath = require('./tsconfig.json') + module.exports = { parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'react', 'prettier', 'import'], + plugins: ['@typescript-eslint', 'react', 'prettier', 'import', 'simple-import-sort'], env: { browser: true, es2021: true, @@ -112,6 +114,26 @@ module.exports = { 'import/named': 'off', 'no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': 'error', + 'simple-import-sort/imports': [ + 'error', + { + groups: [ + // Packages `react` related packages and external packages. + ['^react', '^@?\\w'], + // Devtron packages + ['^@devtron-labs'], + // Internal packages. + [...Object.keys(tsconfigPath.compilerOptions.paths).map((alias) => alias.replace('/*', ''))], + // Side effect imports. + ['^\\u0000'], + // Put same-folder imports, `..` and `.` last. Other relative imports. + ['^\\.\\.(?!/?$)', '^\\.\\./?$', '^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$',], + // Style imports. + [ '^.+\\.?(css|scss)$'], + ], + }, + ], + 'simple-import-sort/exports': 'error', }, overrides: [ { diff --git a/package.json b/package.json index b6366c1088..10adf87755 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "eslint-plugin-prettier": "^5.1.2", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-storybook": "^0.8.0", "husky": "^7.0.4", "jest-extended": "^2.0.0", diff --git a/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx b/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx index 2051120982..1d99162b7d 100644 --- a/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx +++ b/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx @@ -14,6 +14,8 @@ * limitations under the License. */ +import { useState } from 'react' + import { AppSelectorNoOptionsMessage as appSelectorNoOptionsMessage, ComponentSizeType, @@ -21,8 +23,9 @@ import { SelectPicker, SelectPickerProps, } from '@devtron-labs/devtron-fe-common-lib' + import { appListOptions } from '@Components/AppSelector/AppSelectorUtil' -import { useState } from 'react' + import { AppToCloneSelectorProps } from './types' const AppToCloneSelector = ({ isJobView, error, handleCloneIdChange }: AppToCloneSelectorProps) => { diff --git a/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx b/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx index d8744d7472..9c94c47315 100644 --- a/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx +++ b/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx @@ -14,12 +14,16 @@ * limitations under the License. */ +import { ChangeEvent } from 'react' + import { CustomInput, TagsContainer, Textarea } from '@devtron-labs/devtron-fe-common-lib' -import { ReactComponent as ICDevtronApp } from '@Icons/ic-devtron-app.svg' + import { ReactComponent as ICCaretLeftSmall } from '@Icons/ic-caret-left-small.svg' -import { ChangeEvent } from 'react' +import { ReactComponent as ICDevtronApp } from '@Icons/ic-devtron-app.svg' import { importComponentFromFELibrary } from '@Components/common' import { APP_TYPE } from '@Config/constants' + +import AppToCloneSelector from './AppToCloneSelector' import ProjectSelector from './ProjectSelector' import { ApplicationInfoFormProps, @@ -29,7 +33,6 @@ import { HandleFormStateChangeParamsType, ProjectSelectorProps, } from './types' -import AppToCloneSelector from './AppToCloneSelector' const MandatoryTagsContainer = importComponentFromFELibrary('MandatoryTagsContainer', null, 'function') diff --git a/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx b/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx index 1652d5e0eb..51b56c057a 100644 --- a/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx +++ b/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx @@ -14,6 +14,9 @@ * limitations under the License. */ +import { useEffect, useMemo, useState } from 'react' +import { useHistory } from 'react-router-dom' + import { Button, ButtonStyleType, @@ -28,17 +31,21 @@ import { validateTagKeyValue, validateTagValue, } from '@devtron-labs/devtron-fe-common-lib' -import { useEffect, useMemo, useState } from 'react' -import { getHostURLConfiguration } from '@Services/service' + +import { ReactComponent as ICAppTemplate } from '@Icons/ic-app-template.svg' +import { ReactComponent as ICBack } from '@Icons/ic-caret-left-small.svg' +import { importComponentFromFELibrary } from '@Components/common' import { saveHostURLConfiguration } from '@Components/hostURL/hosturl.service' import { createJob } from '@Components/Jobs/Service' -import { APP_COMPOSE_STAGE, getAppComposeURL, URLS } from '@Config/routes' -import { useHistory } from 'react-router-dom' import { REQUIRED_FIELDS_MISSING } from '@Config/constants' -import { importComponentFromFELibrary } from '@Components/common' -import { ReactComponent as ICBack } from '@Icons/ic-caret-left-small.svg' -import { ReactComponent as ICAppTemplate } from '@Icons/ic-app-template.svg' +import { APP_COMPOSE_STAGE, getAppComposeURL, URLS } from '@Config/routes' +import { getHostURLConfiguration } from '@Services/service' +import ApplicationInfoForm from './ApplicationInfoForm' +import { createAppInitialFormErrorState, createAppInitialFormState } from './constants' +import HeaderSection from './HeaderSection' +import { createApp } from './service' +import Sidebar from './Sidebar' import { ApplicationInfoFormProps, CreateAppFormErrorStateType, @@ -47,13 +54,8 @@ import { CreateAppModalProps, CreationMethodType, } from './types' -import { createAppInitialFormErrorState, createAppInitialFormState } from './constants' -import { getCreateMethodConfig, validateAppName, validateCloneApp, validateProject } from './utils' -import { createApp } from './service' -import ApplicationInfoForm from './ApplicationInfoForm' -import HeaderSection from './HeaderSection' -import Sidebar from './Sidebar' import UpdateTemplateConfig from './UpdateTemplateConfig' +import { getCreateMethodConfig, validateAppName, validateCloneApp, validateProject } from './utils' import './styles.scss' diff --git a/src/Pages/App/CreateAppModal/HeaderSection.tsx b/src/Pages/App/CreateAppModal/HeaderSection.tsx index fa16aeb4f2..81449efed5 100644 --- a/src/Pages/App/CreateAppModal/HeaderSection.tsx +++ b/src/Pages/App/CreateAppModal/HeaderSection.tsx @@ -15,7 +15,9 @@ */ import { Button, ButtonStyleType, ButtonVariantType, ComponentSizeType } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as ICClose } from '@Icons/ic-close.svg' + import { HeaderSectionProps } from './types' const HeaderSection = ({ isJobView, handleClose, isCloseDisabled }: HeaderSectionProps) => ( diff --git a/src/Pages/App/CreateAppModal/ProjectSelector.tsx b/src/Pages/App/CreateAppModal/ProjectSelector.tsx index 3dea0dfc4b..88942b12c6 100644 --- a/src/Pages/App/CreateAppModal/ProjectSelector.tsx +++ b/src/Pages/App/CreateAppModal/ProjectSelector.tsx @@ -21,7 +21,9 @@ import { SelectPickerProps, useGetResourceKindsOptions, } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as ICFolderColor } from '@Icons/ic-folder-color.svg' + import { CreateAppFormStateType, ProjectSelectorProps } from './types' const ProjectSelector = ({ selectedProjectId, handleProjectIdChange, error }: ProjectSelectorProps) => { diff --git a/src/Pages/App/CreateAppModal/Sidebar.tsx b/src/Pages/App/CreateAppModal/Sidebar.tsx index c9d6204c98..7d1cf69c09 100644 --- a/src/Pages/App/CreateAppModal/Sidebar.tsx +++ b/src/Pages/App/CreateAppModal/Sidebar.tsx @@ -15,7 +15,9 @@ */ import { ModalSidebarPanel } from '@devtron-labs/devtron-fe-common-lib' + import { DOCUMENTATION } from '@Config/constants' + import { CreationMethodType, SidebarProps } from './types' const Sidebar = ({ diff --git a/src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx b/src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx index 5d80a5fcc6..fd274fda9f 100644 --- a/src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx +++ b/src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx @@ -16,14 +16,14 @@ import { noop } from '@devtron-labs/devtron-fe-common-lib' -import MaterialList from '@Components/material/MaterialList' import CIConfig from '@Components/ciConfig/CIConfig' import { CIConfigProps } from '@Components/ciConfig/types' import { DockerConfigOverrideKeys } from '@Components/ciPipeline/types' import { MaterialListProps } from '@Components/material/material.types' +import MaterialList from '@Components/material/MaterialList' -import { Workflow, WorkflowProps } from './Workflow' import { CreateAppFormStateActionType, UpdateTemplateConfigProps } from './types' +import { Workflow, WorkflowProps } from './Workflow' const parentState: CIConfigProps['parentState'] = { loadingState: null, diff --git a/src/Pages/App/CreateAppModal/Workflow/Workflow.tsx b/src/Pages/App/CreateAppModal/Workflow/Workflow.tsx index 17b98437ce..7eff40a6e7 100644 --- a/src/Pages/App/CreateAppModal/Workflow/Workflow.tsx +++ b/src/Pages/App/CreateAppModal/Workflow/Workflow.tsx @@ -15,6 +15,7 @@ */ import { useEffect, useState } from 'react' + import { APIResponseHandler, GenericEmptyState, @@ -29,6 +30,7 @@ import { import { getCreateWorkflows } from '@Components/app/details/triggerView/workflow.service' import { getEnvironmentListMin } from '@Services/service' +import { HandleNodeUpdateActionProps, NodeUpdateActionType, WorkflowProps } from './types' import { getCDNodeIcon, getPipelineIdFromNodeId, @@ -37,7 +39,6 @@ import { getWorkflowGraphVisualizerNodes, getWorkflowLinkedCDNodes, } from './utils' -import { HandleNodeUpdateActionProps, NodeUpdateActionType, WorkflowProps } from './types' export const Workflow = ({ templateId, onChange, workflowIdToErrorMessageMap }: WorkflowProps) => { // STATES diff --git a/src/Pages/App/CreateAppModal/Workflow/index.ts b/src/Pages/App/CreateAppModal/Workflow/index.ts index e3d6dba9d2..e19381f415 100644 --- a/src/Pages/App/CreateAppModal/Workflow/index.ts +++ b/src/Pages/App/CreateAppModal/Workflow/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export * from './Workflow' export type { WorkflowProps } from './types' +export * from './Workflow' diff --git a/src/Pages/App/CreateAppModal/Workflow/utils.tsx b/src/Pages/App/CreateAppModal/Workflow/utils.tsx index 7f62f31b04..131e3b561e 100644 --- a/src/Pages/App/CreateAppModal/Workflow/utils.tsx +++ b/src/Pages/App/CreateAppModal/Workflow/utils.tsx @@ -26,15 +26,15 @@ import { WorkflowType, } from '@devtron-labs/devtron-fe-common-lib' -import { ReactComponent as ICCi } from '@Icons/ic-CI.svg' import { ReactComponent as ICCD } from '@Icons/ic-CD.svg' +import { ReactComponent as ICCi } from '@Icons/ic-CI.svg' import { ReactComponent as ICCIWebhook } from '@Icons/ic-CIWebhook.svg' -import { ReactComponent as ICNodeBuildLinked } from '@Icons/ic-node-build-linked.svg' -import { ReactComponent as ICWarning } from '@Icons/ic-warning.svg' +import { ReactComponent as ICError } from '@Icons/ic-error.svg' import { ReactComponent as ICJobNode } from '@Icons/ic-job-node.svg' import { ReactComponent as ICLinkedCD } from '@Icons/ic-linked-cd.svg' +import { ReactComponent as ICNodeBuildLinked } from '@Icons/ic-node-build-linked.svg' import { ReactComponent as ICPaperRocket } from '@Icons/ic-paper-rocket.svg' -import { ReactComponent as ICError } from '@Icons/ic-error.svg' +import { ReactComponent as ICWarning } from '@Icons/ic-warning.svg' import { createClusterEnvGroup } from '@Components/common' import { diff --git a/src/Pages/App/CreateAppModal/constants.ts b/src/Pages/App/CreateAppModal/constants.ts index 6a8f52e1b9..0396d0c3ed 100644 --- a/src/Pages/App/CreateAppModal/constants.ts +++ b/src/Pages/App/CreateAppModal/constants.ts @@ -15,6 +15,7 @@ */ import { getEmptyTagTableRow } from '@devtron-labs/devtron-fe-common-lib' + import { CreateAppFormErrorStateType, CreateAppFormStateType } from './types' export const createAppInitialFormState: CreateAppFormStateType = { diff --git a/src/Pages/App/CreateAppModal/service.ts b/src/Pages/App/CreateAppModal/service.ts index 739fcd10f1..61ce62c2af 100644 --- a/src/Pages/App/CreateAppModal/service.ts +++ b/src/Pages/App/CreateAppModal/service.ts @@ -15,6 +15,7 @@ */ import { post } from '@devtron-labs/devtron-fe-common-lib' + import { Routes } from '@Config/constants' export const createApp = (request) => post(Routes.APP, request) diff --git a/src/Pages/App/CreateAppModal/types.ts b/src/Pages/App/CreateAppModal/types.ts index f7e320d699..cb1c0db04a 100644 --- a/src/Pages/App/CreateAppModal/types.ts +++ b/src/Pages/App/CreateAppModal/types.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { SyntheticEvent } from 'react' + import { ButtonProps, DynamicDataTableCellErrorType, @@ -21,9 +23,10 @@ import { SelectPickerProps, TagsTableColumnsType, } from '@devtron-labs/devtron-fe-common-lib' -import { SyntheticEvent } from 'react' -import { GitMaterialType } from '@Components/material/material.types' + import { CIConfigProps } from '@Components/ciConfig/types' +import { GitMaterialType } from '@Components/material/material.types' + import { getCreateMethodConfig } from './utils' interface CreateAppWorkflowConfigType { diff --git a/src/Pages/App/CreateAppModal/utils.tsx b/src/Pages/App/CreateAppModal/utils.tsx index b713b8e891..d03620d569 100644 --- a/src/Pages/App/CreateAppModal/utils.tsx +++ b/src/Pages/App/CreateAppModal/utils.tsx @@ -14,10 +14,12 @@ * limitations under the License. */ -import { MAX_LENGTH_30 } from '@Config/constantMessaging' -import { PATTERNS } from '@Config/constants' import { Icon, IconsProps, SelectPickerOptionType, ValidationResponseType } from '@devtron-labs/devtron-fe-common-lib' + import { importComponentFromFELibrary } from '@Components/common' +import { MAX_LENGTH_30 } from '@Config/constantMessaging' +import { PATTERNS } from '@Config/constants' + import { CreateAppFormStateType, CreateAppModalProps, CreationMethodType } from './types' const isFELibAvailable: boolean = importComponentFromFELibrary('isFELibAvailable', null, 'function') diff --git a/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx b/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx index 66dcc5ebf8..2017e9360f 100644 --- a/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx +++ b/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx @@ -14,25 +14,27 @@ * limitations under the License. */ +import { useEffect, useState } from 'react' +import { useParams } from 'react-router-dom' + import { AppType, + DeploymentAppTypes, + ERROR_STATUS_CODE, ErrorScreenManager, IndexStore, - useMainContext, - DeploymentAppTypes, - showError, - ResponseType, noop, - ERROR_STATUS_CODE, + ResponseType, + showError, + useMainContext, } from '@devtron-labs/devtron-fe-common-lib' -import { useEffect, useState } from 'react' -import { useParams } from 'react-router-dom' -import { ExternalFluxAppDetailParams } from './types' -import { getExternalFluxCDAppDetails } from './service' + import { FluxCDTemplateType } from '../../../../components/app/list-new/AppListType' import AppDetailsComponent from '../../../../components/v2/appDetails/AppDetails.component' -import { getAppStatus } from './utils' import { AppDetails } from '../../../../components/v2/appDetails/appDetails.type' +import { getExternalFluxCDAppDetails } from './service' +import { ExternalFluxAppDetailParams } from './types' +import { getAppStatus } from './utils' let initTimer = null diff --git a/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetailsRoute.tsx b/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetailsRoute.tsx index ce248a5d2d..9d8eb3efba 100644 --- a/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetailsRoute.tsx +++ b/src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetailsRoute.tsx @@ -15,8 +15,10 @@ */ import { lazy, Suspense } from 'react' -import { AppListConstants, Progressing, URLS } from '@devtron-labs/devtron-fe-common-lib' import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom' + +import { AppListConstants, Progressing, URLS } from '@devtron-labs/devtron-fe-common-lib' + import EAHeaderComponent from '../../../../components/v2/headers/EAHeader.component' const ExternalFluxAppDetails = lazy(() => import('./ExternalFluxAppDetails')) diff --git a/src/Pages/App/Details/ExternalFlux/service.tsx b/src/Pages/App/Details/ExternalFlux/service.tsx index 9ded6e1974..936f6382f2 100644 --- a/src/Pages/App/Details/ExternalFlux/service.tsx +++ b/src/Pages/App/Details/ExternalFlux/service.tsx @@ -15,6 +15,7 @@ */ import { get, getUrlWithSearchParams } from '@devtron-labs/devtron-fe-common-lib' + import { Routes } from '../../../../config' export const getExternalFluxCDAppDetails = (clusterId, namespace, appName, isKustomization) => { diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.service.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.service.ts index 6f835680ec..a7d4ad6079 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.service.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.service.ts @@ -17,10 +17,11 @@ import { AppConfigProps, get, - trash, - ROUTES as CommonRoutes, getUrlWithSearchParams, + ROUTES as CommonRoutes, + trash, } from '@devtron-labs/devtron-fe-common-lib' + import { Routes } from '../../../../../config' export const getGitProviderMin = () => { diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.tsx index 9b74529a66..c09672253e 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.tsx @@ -14,46 +14,50 @@ * limitations under the License. */ -import { useState, useEffect } from 'react' -import { useParams, useLocation, useRouteMatch, useHistory } from 'react-router-dom' +import { useEffect, useState } from 'react' +import { useHistory, useLocation, useParams, useRouteMatch } from 'react-router-dom' + import { - showError, - Progressing, - ErrorScreenManager, - useAsync, - ResourceKindType, - ToastManager, - ToastVariantType, - ResourceIdToResourceApprovalPolicyConfigMapType, AppConfigProps, ConfirmationModal, ConfirmationModalVariantType, + ErrorScreenManager, noop, + Progressing, + ResourceIdToResourceApprovalPolicyConfigMapType, + ResourceKindType, + showError, + ToastManager, + ToastVariantType, URLS as CommonUrls, + useAsync, } from '@devtron-labs/devtron-fe-common-lib' + import { DeleteComponentsName } from '@Config/constantMessaging' import { ApplicationDeletionInfo } from '@Pages/Shared/ApplicationDeletionInfo/ApplicationDeletionInfo' -import { URLS, getAppComposeURL, APP_COMPOSE_STAGE, ViewType } from '../../../../../config' + import { importComponentFromFELibrary } from '../../../../../components/common' +import { APP_COMPOSE_STAGE, getAppComposeURL, URLS, ViewType } from '../../../../../config' import { getAppOtherEnvironmentMin, getJobOtherEnvironmentMin, getWorkflowList } from '../../../../../services/service' -import './appConfig.scss' +import { getUserRole } from '../../../../GlobalConfigurations/Authorization/authorization.service' +import { UserRoleType } from '../../../../GlobalConfigurations/Authorization/constants' +import { getAppConfigStatus, getEnvConfig } from '../../service' +import { AppConfigStatusItemType } from '../../service.types' +import AppComposeRouter from './MainContent/AppComposeRouter' +import { AppNavigation } from './Navigation/AppNavigation' +import { ENV_CONFIG_PATH_REG } from './AppConfig.constants' +import { deleteApp } from './AppConfig.service' import { AppConfigState, AppStageUnlockedType, - STAGE_NAME, DEFAULT_LANDING_STAGE, EnvConfigType, + STAGE_NAME, } from './AppConfig.types' -import { getUserRole } from '../../../../GlobalConfigurations/Authorization/authorization.service' -import { isCIPipelineCreated, isCDPipelineCreated, getNavItems, isUnlocked } from './AppConfig.utils' -import AppComposeRouter from './MainContent/AppComposeRouter' -import { UserRoleType } from '../../../../GlobalConfigurations/Authorization/constants' -import { AppNavigation } from './Navigation/AppNavigation' -import { AppConfigStatusItemType } from '../../service.types' -import { getAppConfigStatus, getEnvConfig } from '../../service' -import { deleteApp } from './AppConfig.service' +import { getNavItems, isCDPipelineCreated, isCIPipelineCreated, isUnlocked } from './AppConfig.utils' import { AppConfigurationProvider } from './AppConfiguration.provider' -import { ENV_CONFIG_PATH_REG } from './AppConfig.constants' + +import './appConfig.scss' const getApprovalPolicyConfigForApp: (appId: number) => Promise = importComponentFromFELibrary('getApprovalPolicyConfigForApp', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.types.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.types.ts index 210b32ace5..8bd9dd514e 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.types.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.types.ts @@ -15,17 +15,17 @@ */ import { - ResourceKindType, - CollapsibleListItem, + AppConfigProps, AppEnvDeploymentConfigType, - EnvResourceType, AppEnvironment, + CollapsibleListItem, + EnvResourceType, ResourceIdToResourceApprovalPolicyConfigMapType, - AppConfigProps, + ResourceKindType, } from '@devtron-labs/devtron-fe-common-lib' -import { ViewType } from '@Config/constants' import { WorkflowResult } from '@Components/app/details/triggerView/types' +import { ViewType } from '@Config/constants' import { UserRoleType } from '@Pages/GlobalConfigurations/Authorization/constants' import { ResourceConfig, ResourceConfigState } from '../../service.types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.utils.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.utils.ts index c8344c161d..b5e0e645c0 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.utils.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfig.utils.ts @@ -14,17 +14,19 @@ * limitations under the License. */ +import { generatePath } from 'react-router-dom' + import { + AppConfigProps, + BASE_CONFIGURATION_ENV_ID, + ConfigResourceType, ResourceKindType, stringComparatorBySortOrder, - ConfigResourceType, - BASE_CONFIGURATION_ENV_ID, URLS as CommonURLS, - AppConfigProps, } from '@devtron-labs/devtron-fe-common-lib' -import { generatePath } from 'react-router-dom' -import { URLS, DOCUMENTATION, getAppComposeURL, APP_COMPOSE_STAGE } from '@Config/index' +import { APP_COMPOSE_STAGE, DOCUMENTATION, getAppComposeURL, URLS } from '@Config/index' + import { AppConfigStatusItemType, EnvConfigDTO } from '../../service.types' import { AppConfigState, AppStageUnlockedType, CustomNavItemsType, EnvConfigType, STAGE_NAME } from './AppConfig.types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfiguration.provider.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfiguration.provider.tsx index 5841d5e899..5defe04947 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfiguration.provider.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/AppConfiguration.provider.tsx @@ -17,6 +17,7 @@ import React, { useMemo, useState } from 'react' import { ResourceKindType } from '@devtron-labs/devtron-fe-common-lib' + import { AppConfigurationContextType, AppConfigurationProviderProps } from './AppConfig.types' export const AppConfigurationContext = React.createContext(null) diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/AppComposeRouter.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/AppComposeRouter.tsx index 9a70e5d701..63a82ca803 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/AppComposeRouter.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/AppComposeRouter.tsx @@ -15,28 +15,29 @@ */ import React, { lazy, Suspense } from 'react' -import { useRouteMatch, useHistory, Route, Switch, Redirect, useLocation, generatePath } from 'react-router-dom' +import { generatePath, Redirect, Route, Switch, useHistory, useLocation, useRouteMatch } from 'react-router-dom' + import { - Progressing, - EnvResourceType, - BASE_CONFIGURATION_ENV_ID, ApprovalConfigDataKindType, - getIsApprovalPolicyConfigured, - CMSecretComponentType, + BASE_CONFIGURATION_ENV_ID, Button, + CMSecretComponentType, + EnvResourceType, + getIsApprovalPolicyConfigured, + Progressing, } from '@devtron-labs/devtron-fe-common-lib' import { ReactComponent as Next } from '@Icons/ic-arrow-forward.svg' -import { DEPLOYMENT_CONFIGURATION_RESOURCE_TYPE_ROUTE, URLS } from '@Config/index' import { ErrorBoundary, useAppContext } from '@Components/common' import ExternalLinks from '@Components/externalLinks/ExternalLinks' +import { DEPLOYMENT_CONFIGURATION_RESOURCE_TYPE_ROUTE, URLS } from '@Config/index' import { ConfigMapSecretWrapper } from '@Pages/Shared/ConfigMapSecret/ConfigMapSecret.wrapper' import { NextButtonProps, STAGE_NAME } from '../AppConfig.types' import { useAppConfigurationContext } from '../AppConfiguration.provider' +import { DeploymentConfigCompare } from './DeploymentConfigCompare' import '../appConfig.scss' -import { DeploymentConfigCompare } from './DeploymentConfigCompare' const MaterialList = lazy(() => import('@Components/material/MaterialList')) const CIConfig = lazy(() => import('@Components/ciConfig/CIConfig')) diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/BaseConfigurationNavigation.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/BaseConfigurationNavigation.tsx index 0226ea347b..da3012bf9a 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/BaseConfigurationNavigation.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/BaseConfigurationNavigation.tsx @@ -21,6 +21,7 @@ import { ButtonVariantType, ComponentSizeType, } from '@devtron-labs/devtron-fe-common-lib' + import { BaseConfigurationNavigationProps } from './types' const BaseConfigurationNavigation = ({ baseConfigurationURL }: BaseConfigurationNavigationProps) => ( diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/CompareConfigView.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/CompareConfigView.tsx index b557c51aa8..b65439a127 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/CompareConfigView.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/CompareConfigView.tsx @@ -14,9 +14,11 @@ * limitations under the License. */ -import { importComponentFromFELibrary } from '@Components/common' -import { ReactComponent as ICFileEdit } from '@Icons/ic-file-edit.svg' import { DeploymentHistoryDiffView, ErrorScreenManager } from '@devtron-labs/devtron-fe-common-lib' + +import { ReactComponent as ICFileEdit } from '@Icons/ic-file-edit.svg' +import { importComponentFromFELibrary } from '@Components/common' + import { CompareConfigViewProps } from './types' import { getCompareViewHistoryDiffConfigProps } from './utils' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigDryRun.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigDryRun.tsx index 2e5e9b0fbf..2d65779aa4 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigDryRun.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigDryRun.tsx @@ -15,6 +15,7 @@ */ import { useParams } from 'react-router-dom' + import { abortPreviousRequests, APIResponseHandler, @@ -25,15 +26,17 @@ import { getDeploymentManifest, getIsRequestAborted, MODES, - useAsync, ToggleResolveScopedVariables, + useAsync, } from '@devtron-labs/devtron-fe-common-lib' -import { importComponentFromFELibrary } from '@Components/common' -import { ReactComponent as ICFilePlay } from '@Icons/ic-file-play.svg' + // FIXME: Placeholder icon since no sense of git merge icon as of now import { ReactComponent as ICFileCode } from '@Icons/ic-file-code.svg' -import SelectMergeStrategy from './SelectMergeStrategy' +import { ReactComponent as ICFilePlay } from '@Icons/ic-file-play.svg' +import { importComponentFromFELibrary } from '@Components/common' + import NoPublishedVersionEmptyState from './NoPublishedVersionEmptyState' +import SelectMergeStrategy from './SelectMergeStrategy' import { ConfigDryRunProps } from './types' const DryRunEditorModeSelect = importComponentFromFELibrary('DryRunEditorModeSelect', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigHeader.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigHeader.tsx index b8d77300e9..7c6ce60bf8 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigHeader.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigHeader.tsx @@ -20,7 +20,9 @@ import { ConfigHeaderTabType, InvalidYAMLTippyWrapper, } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as ICErrorExclamation } from '@Icons/ic-error-exclamation.svg' + import { ConfigHeaderProps, ConfigHeaderTabProps } from './types' import { getConfigHeaderTabConfig } from './utils' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigToolbar.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigToolbar.tsx index 84e7935d9d..3ef556302d 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigToolbar.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/ConfigToolbar.tsx @@ -16,28 +16,31 @@ import { Fragment } from 'react' import ReactGA from 'react-ga4' +import { useParams } from 'react-router-dom' + import { + BaseURLParams, Button, ButtonStyleType, ButtonVariantType, - ConfigHeaderTabType, - ProtectConfigTabsType, - PopupMenu, - BaseURLParams, ComponentSizeType, + ConfigHeaderTabType, + Icon, InvalidYAMLTippyWrapper, + PopupMenu, + ProtectConfigTabsType, ToggleResolveScopedVariables, - Icon, } from '@devtron-labs/devtron-fe-common-lib' -import { useParams } from 'react-router-dom' -import { importComponentFromFELibrary } from '@Components/common' -import { ReactComponent as ICMore } from '@Icons/ic-more-option.svg' + import { ReactComponent as ICBookOpen } from '@Icons/ic-book-open.svg' import { ReactComponent as ICInfoOutlineGrey } from '@Icons/ic-info-outline-grey.svg' +import { ReactComponent as ICMore } from '@Icons/ic-more-option.svg' +import { importComponentFromFELibrary } from '@Components/common' + import BaseConfigurationNavigation from './BaseConfigurationNavigation' -import { PopupMenuItem } from './utils' -import { ConfigToolbarProps } from './types' import SelectMergeStrategy from './SelectMergeStrategy' +import { ConfigToolbarProps } from './types' +import { PopupMenuItem } from './utils' const ProtectionViewTabGroup = importComponentFromFELibrary('ProtectionViewTabGroup', null, 'function') const MergePatchWithTemplateCheckbox = importComponentFromFELibrary('MergePatchWithTemplateCheckbox', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/DeploymentConfigCompare.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/DeploymentConfigCompare.tsx index f4356388dc..fdcad751a1 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/DeploymentConfigCompare.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/DeploymentConfigCompare.tsx @@ -18,26 +18,26 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { generatePath, useHistory, useLocation, useRouteMatch } from 'react-router-dom' import { - useUrlFilters, - SelectPickerOptionType, - SelectPickerVariantType, - useAsync, + AppEnvDeploymentConfigType, + BASE_CONFIGURATION_ENV_ID, + DEPLOYMENT_CONFIG_DIFF_SORT_KEY, DeploymentConfigDiff, DeploymentConfigDiffProps, - AppEnvDeploymentConfigType, - getDefaultVersionAndPreviousDeploymentOptions, - getAppEnvDeploymentConfigList, - getSelectPickerOptionByValue, EnvResourceType, - BASE_CONFIGURATION_ENV_ID, - useMainContext, - getCompareSecretsData, getAppEnvDeploymentConfig, - DEPLOYMENT_CONFIG_DIFF_SORT_KEY, + getAppEnvDeploymentConfigList, + getCompareSecretsData, + getDefaultVersionAndPreviousDeploymentOptions, + getSelectPickerOptionByValue, + SelectPickerOptionType, + SelectPickerVariantType, SortingOrder, + useAsync, + useMainContext, + useUrlFilters, } from '@devtron-labs/devtron-fe-common-lib' -import { getTemplateOptions, getChartReferencesForAppAndEnv } from '@Services/service' +import { getChartReferencesForAppAndEnv, getTemplateOptions } from '@Services/service' import { BASE_CONFIGURATIONS } from '../../AppConfig.constants' import { @@ -46,24 +46,24 @@ import { DeploymentConfigCompareProps, DeploymentConfigParams, } from '../../AppConfig.types' +import { getDeploymentTemplateData, getManifestData } from './service.utils' +import { DeploymentConfigComparisonDataType } from './types' import { + deploymentConfigDiffTabs, + getAppAndEnvIds, + getAppEnvDeploymentConfigPayload, getCompareEnvironmentSelectorOptions, - getPreviousDeploymentOptionValue, - getPreviousDeploymentValue, - parseCompareWithSearchParams, - getEnvironmentConfigTypeOptions, getConfigChartRefId, - getManifestRequestValues, - deploymentConfigDiffTabs, getDeploymentConfigDiffTabs, - getAppAndEnvIds, + getEnvironmentConfigTypeOptions, + getIdentifierIdBasedOnConfiguration, + getManifestRequestValues, + getPreviousDeploymentOptionValue, + getPreviousDeploymentValue, isConfigTypeNonDraftOrPublished, isConfigTypePublished, - getAppEnvDeploymentConfigPayload, - getIdentifierIdBasedOnConfiguration, + parseCompareWithSearchParams, } from './utils' -import { getDeploymentTemplateData, getManifestData } from './service.utils' -import { DeploymentConfigComparisonDataType } from './types' export const DeploymentConfigCompare = ({ environments, diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/service.utils.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/service.utils.ts index 956a33c806..cf2c23e595 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/service.utils.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/service.utils.ts @@ -24,6 +24,7 @@ import { ResponseType, TemplateListType, } from '@devtron-labs/devtron-fe-common-lib' + import { GetDeploymentTemplateDataProps, GetManifestDataProps } from '../../AppConfig.types' import { getAppAndEnvIds } from './utils' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/types.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/types.ts index bc002ff1c4..219a65c88b 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/types.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/types.ts @@ -15,8 +15,9 @@ */ import { getAppEnvDeploymentConfig, TemplateListDTO } from '@devtron-labs/devtron-fe-common-lib' -import { getManifestData } from './service.utils' + import { AppEnvDeploymentConfigQueryParamsType } from '../../AppConfig.types' +import { getManifestData } from './service.utils' type ManifestComparisonDataType = { isManifestComparison: true diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/utils.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/utils.ts index d7a1469390..d78f2c7297 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/utils.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentConfigCompare/utils.ts @@ -28,14 +28,14 @@ import { import { Moment12HourFormat } from '@Config/constants' +import { BASE_CONFIGURATIONS } from '../../AppConfig.constants' import { - AppEnvDeploymentConfigQueryParamsType, - EnvironmentOptionType, AppEnvDeploymentConfigQueryParams, + AppEnvDeploymentConfigQueryParamsType, DeploymentConfigCompareProps, + EnvironmentOptionType, GetAppEnvDeploymentConfigProps, } from '../../AppConfig.types' -import { BASE_CONFIGURATIONS } from '../../AppConfig.constants' import { SetIdentifierIdBasedOnConfigurationProps } from './types' export const getPreviousDeploymentOptionValue = (identifierId: number, pipelineId?: number, chartRefId?: number) => { diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DTChartSelector.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DTChartSelector.tsx index a314519e51..8fc9754b57 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DTChartSelector.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DTChartSelector.tsx @@ -15,24 +15,27 @@ */ import { useState } from 'react' + import { - PopupMenu, - stopPropagation, - StyledRadioGroup as RadioGroup, + ComponentSizeType, DeploymentChartVersionType, + InvalidYAMLTippyWrapper, + PipelineMigratedFromType, + PopupMenu, SelectPicker, SelectPickerOptionType, SelectPickerVariantType, + stopPropagation, + StyledRadioGroup as RadioGroup, versionComparatorBySortOrder, - InvalidYAMLTippyWrapper, - ComponentSizeType, - PipelineMigratedFromType, } from '@devtron-labs/devtron-fe-common-lib' + +import { ReactComponent as Dropdown } from '@Icons/ic-chevron-down.svg' import { sortObjectArrayAlphabetically } from '@Components/common' import { DEPLOYMENT } from '@Config/constants' -import { ReactComponent as Dropdown } from '@Icons/ic-chevron-down.svg' + +import { CHART_DOCUMENTATION_LINK, CHART_TYPE_TAB, CHART_TYPE_TAB_KEYS } from './constants' import { ChartSelectorDropdownProps, DTChartSelectorProps } from './types' -import { CHART_TYPE_TAB_KEYS, CHART_TYPE_TAB, CHART_DOCUMENTATION_LINK } from './constants' const LoadingShimmer = () =>
diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeleteOverrideDialog.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeleteOverrideDialog.tsx index 8be3ee8376..cb1969b1dd 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeleteOverrideDialog.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeleteOverrideDialog.tsx @@ -15,6 +15,7 @@ */ import { useParams } from 'react-router-dom' + import { API_STATUS_CODES, BaseURLParams, @@ -22,9 +23,11 @@ import { ServerError, showError, } from '@devtron-labs/devtron-fe-common-lib' + import { DeleteComponentsName } from '@Config/constantMessaging' -import { DeleteOverrideDialogProps } from './types' + import { deleteOverrideDeploymentTemplate } from './service' +import { DeleteOverrideDialogProps } from './types' const DeleteOverrideDialog = ({ environmentConfigId, diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplate.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplate.tsx index 4759526e09..ad2d1ccb25 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplate.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplate.tsx @@ -14,63 +14,96 @@ * limitations under the License. */ -import { useEffect, SyntheticEvent, useMemo, useReducer, Reducer, useRef } from 'react' +import { Reducer, SyntheticEvent, useEffect, useMemo, useReducer, useRef } from 'react' import ReactGA from 'react-ga4' +import { Prompt, useLocation, useParams } from 'react-router-dom' +import YAML from 'yaml' + import { + abortPreviousRequests, + API_STATUS_CODES, + AppConfigProps, BASE_CONFIGURATION_ENV_ID, BaseURLParams, + Button, + ButtonStyleType, + ButtonVariantType, + checkIfPathIsMatching, + CompareFromApprovalOptionsValuesType, + ComponentSizeType, + ConfigHeaderTabType, + ConfigResourceType, ConfigurationType, + DEFAULT_LOCKED_KEYS_CONFIG, DeploymentChartVersionType, - DraftState, - showError, - useMainContext, - YAMLStringify, DeploymentTemplateConfigState, - Progressing, + DraftAction, + DraftState, + DryRunEditorMode, ErrorScreenManager, + FloatingVariablesSuggestions, + GenericEmptyState, + GET_RESOLVED_DEPLOYMENT_TEMPLATE_EMPTY_RESPONSE, + getIsRequestAborted, getResolvedDeploymentTemplate, - ModuleStatus, - useAsync, + logExceptionToSentry, ModuleNameMap, - ToastManager, - ToastVariantType, - SelectPickerOptionType, - ValuesAndManifestFlagDTO, - CompareFromApprovalOptionsValuesType, + ModuleStatus, noop, - logExceptionToSentry, - ConfigHeaderTabType, + OverrideMergeStrategyType, + Progressing, ProtectConfigTabsType, - Button, - ComponentSizeType, - ButtonStyleType, - ButtonVariantType, - DryRunEditorMode, - usePrompt, - DEFAULT_LOCKED_KEYS_CONFIG, - GenericEmptyState, - GET_RESOLVED_DEPLOYMENT_TEMPLATE_EMPTY_RESPONSE, ResponseType, - API_STATUS_CODES, - OverrideMergeStrategyType, - useUrlFilters, - ConfigResourceType, - abortPreviousRequests, - getIsRequestAborted, - DraftAction, - checkIfPathIsMatching, - FloatingVariablesSuggestions, + SelectPickerOptionType, + showError, + ToastManager, + ToastVariantType, + useAsync, + useMainContext, useOneTimePrompt, - AppConfigProps, + usePrompt, + useUrlFilters, + ValuesAndManifestFlagDTO, + YAMLStringify, } from '@devtron-labs/devtron-fe-common-lib' -import { Prompt, useLocation, useParams } from 'react-router-dom' -import YAML from 'yaml' -import { importComponentFromFELibrary } from '@Components/common' -import { getModuleInfo } from '@Components/v2/devtronStackManager/DevtronStackManager.service' -import { APP_COMPOSE_STAGE, getAppComposeURL } from '@Config/routes' + import { ReactComponent as ICClose } from '@Icons/ic-close.svg' import { ReactComponent as ICInfoOutlineGrey } from '@Icons/ic-info-outline-grey.svg' import deleteOverrideEmptyStateImage from '@Images/no-artifact.webp' +import { importComponentFromFELibrary } from '@Components/common' +import { getModuleInfo } from '@Components/v2/devtronStackManager/DevtronStackManager.service' +import { APP_COMPOSE_STAGE, getAppComposeURL } from '@Config/routes' + +import BaseConfigurationNavigation from '../BaseConfigurationNavigation' +import CompareConfigView from '../CompareConfigView' +import ConfigDryRun from '../ConfigDryRun' +import ConfigHeader from '../ConfigHeader' +import ConfigToolbar from '../ConfigToolbar' +import NoOverrideEmptyState from '../NoOverrideEmptyState' +import NoPublishedVersionEmptyState from '../NoPublishedVersionEmptyState' +import { ConfigToolbarProps, DeploymentTemplateComponentType } from '../types' +import { getConfigToolbarPopupConfig } from '../utils' +import { NO_SCOPED_VARIABLES_MESSAGE } from './constants' +import DeleteOverrideDialog from './DeleteOverrideDialog' +import DeploymentTemplateCTA from './DeploymentTemplateCTA' +import DeploymentTemplateForm from './DeploymentTemplateForm' +import DeploymentTemplateOptionsHeader from './DeploymentTemplateOptionsHeader' +import { + DeploymentTemplateActionState, + DeploymentTemplateActionType, + deploymentTemplateReducer, + getDeploymentTemplateInitialState, +} from './deploymentTemplateReducer' +import { + createBaseDeploymentTemplate, + createEnvDeploymentTemplate, + deleteOverrideDeploymentTemplate, + getBaseDeploymentTemplate, + getChartList, + getEnvOverrideDeploymentTemplate, + updateBaseDeploymentTemplate, + updateEnvDeploymentTemplate, +} from './service' import { ConfigEditorStatesType, DeploymentTemplateEditorDataStateType, @@ -85,10 +118,6 @@ import { UpdateBaseDTPayloadType, UpdateEnvironmentDTPayloadType, } from './types' -import { NO_SCOPED_VARIABLES_MESSAGE } from './constants' -import DeploymentTemplateOptionsHeader from './DeploymentTemplateOptionsHeader' -import DeploymentTemplateForm from './DeploymentTemplateForm' -import DeploymentTemplateCTA from './DeploymentTemplateCTA' import { getAreTemplateChangesPresent, getCompareFromEditorConfig, @@ -106,33 +135,8 @@ import { handleInitializeDraftData, parseDeploymentTemplateParams, } from './utils' -import DeleteOverrideDialog from './DeleteOverrideDialog' -import { - updateBaseDeploymentTemplate, - createBaseDeploymentTemplate, - updateEnvDeploymentTemplate, - createEnvDeploymentTemplate, - getEnvOverrideDeploymentTemplate, - getBaseDeploymentTemplate, - getChartList, - deleteOverrideDeploymentTemplate, -} from './service' -import ConfigHeader from '../ConfigHeader' + import './DeploymentTemplate.scss' -import ConfigToolbar from '../ConfigToolbar' -import { ConfigToolbarProps, DeploymentTemplateComponentType } from '../types' -import { getConfigToolbarPopupConfig } from '../utils' -import ConfigDryRun from '../ConfigDryRun' -import NoOverrideEmptyState from '../NoOverrideEmptyState' -import CompareConfigView from '../CompareConfigView' -import NoPublishedVersionEmptyState from '../NoPublishedVersionEmptyState' -import BaseConfigurationNavigation from '../BaseConfigurationNavigation' -import { - DeploymentTemplateActionState, - DeploymentTemplateActionType, - deploymentTemplateReducer, - getDeploymentTemplateInitialState, -} from './deploymentTemplateReducer' const getDraftByResourceName = importComponentFromFELibrary('getDraftByResourceName', null, 'function') const getJsonPath = importComponentFromFELibrary('getJsonPath', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateCTA.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateCTA.tsx index 43269575dd..a2d1854a43 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateCTA.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateCTA.tsx @@ -14,6 +14,8 @@ * limitations under the License. */ +import { useParams } from 'react-router-dom' + import { BaseURLParams, Button, @@ -21,8 +23,9 @@ import { DTApplicationMetricsFormField, InvalidYAMLTippyWrapper, } from '@devtron-labs/devtron-fe-common-lib' -import { useParams } from 'react-router-dom' + import { ReactComponent as ICArrowRight } from '@Icons/ic-arrow-right.svg' + import { DeploymentTemplateCTAProps } from './types' // For protect we will have a separate component diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateForm.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateForm.tsx index d84c2a52f3..6035740a7d 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateForm.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateForm.tsx @@ -15,6 +15,7 @@ */ import { useMemo } from 'react' + import { CodeEditor, ConfigurationType, @@ -24,14 +25,16 @@ import { OverrideMergeStrategyType, SelectPickerOptionType, } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as ICBookOpen } from '@Icons/ic-book-open.svg' import { ReactComponent as ICPencil } from '@Icons/ic-pencil.svg' import { importComponentFromFELibrary } from '@Components/common' -import { DeploymentTemplateFormProps } from './types' -import { GUIView as DeploymentTemplateGUIView } from './GUIView' + +import { MERGE_STRATEGY_OPTIONS } from '../constants' import { APPLICATION_METRICS_DROPDOWN_OPTIONS, DEPLOYMENT_TEMPLATE_LABELS_KEYS } from './constants' +import { GUIView as DeploymentTemplateGUIView } from './GUIView' +import { DeploymentTemplateFormProps } from './types' import { getEditorSchemaURIFromChartNameAndVersion } from './utils' -import { MERGE_STRATEGY_OPTIONS } from '../constants' const ExpressEditDiffEditor = importComponentFromFELibrary('ExpressEditDiffEditor', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateOptionsHeader.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateOptionsHeader.tsx index f18166a881..9780b22981 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateOptionsHeader.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/DeploymentTemplateOptionsHeader.tsx @@ -15,13 +15,14 @@ */ import { + ComponentSizeType, + CONFIGURATION_TYPE_OPTIONS, ConfigurationType, InvalidYAMLTippyWrapper, SegmentedControl, - CONFIGURATION_TYPE_OPTIONS, SegmentedControlProps, - ComponentSizeType, } from '@devtron-labs/devtron-fe-common-lib' + import DTChartSelector from './DTChartSelector' import { DeploymentTemplateOptionsHeaderProps } from './types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/GUIView.component.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/GUIView.component.tsx index 947cb209f9..7fe62dead5 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/GUIView.component.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/GUIView.component.tsx @@ -15,28 +15,31 @@ */ import { useEffect, useMemo, useRef, useState } from 'react' +import { JSONPath } from 'jsonpath-plus' import YAML from 'yaml' + import { - InfoColourBar, - RJSFForm, + flatMapOfJSONPaths, FormProps, GenericEmptyState, - joinObjects, - flatMapOfJSONPaths, + GUIViewError, HIDE_SUBMIT_BUTTON_UI_SCHEMA, + InfoColourBar, + joinObjects, OverrideMergeStrategyType, - GUIViewError, + RJSFForm, ToastManager, ToastVariantType, } from '@devtron-labs/devtron-fe-common-lib' -import { JSONPath } from 'jsonpath-plus' -import EmptyFolderImage from '@Images/empty-folder.webp' + +import { ReactComponent as ICArrow } from '@Icons/ic-arrow-forward.svg' import { ReactComponent as Help } from '@Icons/ic-help.svg' import { ReactComponent as ICWarningY5 } from '@Icons/ic-warning-y5.svg' -import { ReactComponent as ICArrow } from '@Icons/ic-arrow-forward.svg' +import EmptyFolderImage from '@Images/empty-folder.webp' import { importComponentFromFELibrary } from '@Components/common' + +import { DEPLOYMENT_TEMPLATE_LABELS_KEYS, GUI_VIEW_TEXTS } from '../constants' import { GUIViewProps, GUIViewState } from './types' -import { GUI_VIEW_TEXTS, DEPLOYMENT_TEMPLATE_LABELS_KEYS } from '../constants' import { getRenderActionButton } from './utils' const makeObjectFromJsonPathArray = importComponentFromFELibrary('makeObjectFromJsonPathArray', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/types.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/types.ts index cd54acb3c5..cd0f85c02c 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/types.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/GUIView/types.ts @@ -15,6 +15,7 @@ */ import { DeploymentChartVersionType, GUIViewError } from '@devtron-labs/devtron-fe-common-lib' + import { DeploymentTemplateFormProps } from '../types' export interface GUIViewProps diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/deploymentTemplateReducer.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/deploymentTemplateReducer.ts index 13dc96d7bb..e7abb9ec37 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/deploymentTemplateReducer.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/deploymentTemplateReducer.ts @@ -15,6 +15,7 @@ */ import YAML from 'yaml' + import { CompareFromApprovalOptionsValuesType, ConfigToolbarPopupNodeType, @@ -30,6 +31,7 @@ import { ToastVariantType, YAMLStringify, } from '@devtron-labs/devtron-fe-common-lib' + import { ConfigEditorStatesType, DeploymentTemplateEditorDataStateType, diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/service.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/service.ts index dc058713e2..6eb257eed3 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/service.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/service.ts @@ -14,21 +14,23 @@ * limitations under the License. */ -import { Routes } from '@Config/constants' import { AppConfigProps, BaseURLParams, get, + getTemplateAPIRoute, GetTemplateAPIRouteType, + getUrlWithSearchParams, post, put, ResponseType, trash, - getTemplateAPIRoute, - getUrlWithSearchParams, versionComparatorBySortOrder, } from '@devtron-labs/devtron-fe-common-lib' + +import { Routes } from '@Config/constants' import { getChartReferencesForAppAndEnv } from '@Services/service' + import { DeploymentTemplateConfigDTO, EnvironmentOverrideDeploymentTemplateDTO, diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/types.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/types.ts index 2e9fac4f38..6fd2879b02 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/types.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/types.ts @@ -16,23 +16,24 @@ import { SyntheticEvent } from 'react' import { Operation } from 'fast-json-patch' + import { - ConfigKeysWithLockType, - DeploymentChartVersionType, + AppConfigProps, ChartMetadataType, - DeploymentTemplateConfigState, - SelectedChartDetailsType, CompareFromApprovalOptionsValuesType, - ConfigurationType, - ServerErrors, - ConfigToolbarPopupNodeType, - DryRunEditorMode, ConfigHeaderTabType, - ProtectConfigTabsType, + ConfigKeysWithLockType, + ConfigToolbarPopupNodeType, + ConfigurationType, + DeploymentChartVersionType, + DeploymentTemplateConfigState, DraftMetadataDTO, + DryRunEditorMode, OverrideMergeStrategyType, - AppConfigProps, PipelineMigratedFromType, + ProtectConfigTabsType, + SelectedChartDetailsType, + ServerErrors, } from '@devtron-labs/devtron-fe-common-lib' import { ConfigToolbarProps } from '../types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/utils.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/utils.tsx index 9e76732887..33c296c568 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/utils.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/DeploymentTemplate/utils.tsx @@ -14,19 +14,25 @@ * limitations under the License. */ +import YAML from 'yaml' + import { applyCompareDiffOnUneditedDocument, + CONFIG_HEADER_TAB_VALUES, + ConfigHeaderTabType, + DeploymentTemplateConfigState, DryRunEditorMode, getGuiSchemaFromChartName, + OverrideMergeStrategyType, ResponseType, YAMLStringify, - DeploymentTemplateConfigState, - OverrideMergeStrategyType, - ConfigHeaderTabType, - CONFIG_HEADER_TAB_VALUES, } from '@devtron-labs/devtron-fe-common-lib' + import { importComponentFromFELibrary } from '@Components/common' -import YAML from 'yaml' + +import { DEFAULT_MERGE_STRATEGY } from '../constants' +import { CompareConfigViewProps, EnvOverrideEditorCommonStateType } from '../types' +import { CHART_NAME_TO_DOC_SEGMENT, PROTECT_BASE_DEPLOYMENT_TEMPLATE_IDENTIFIER_DTO } from './constants' import { BaseDeploymentTemplateParsedDraftDTO, ConfigEditorStatesType, @@ -44,9 +50,6 @@ import { UpdateBaseDTPayloadType, UpdateEnvironmentDTPayloadType, } from './types' -import { CHART_NAME_TO_DOC_SEGMENT, PROTECT_BASE_DEPLOYMENT_TEMPLATE_IDENTIFIER_DTO } from './constants' -import { DEFAULT_MERGE_STRATEGY } from '../constants' -import { CompareConfigViewProps, EnvOverrideEditorCommonStateType } from '../types' const removeLockedKeysFromYaml = importComponentFromFELibrary('removeLockedKeysFromYaml', null, 'function') const reapplyRemovedLockedKeysToYaml = importComponentFromFELibrary('reapplyRemovedLockedKeysToYaml', null, 'function') diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoOverrideEmptyState.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoOverrideEmptyState.tsx index 1bb63a6b7c..8a9234869e 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoOverrideEmptyState.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoOverrideEmptyState.tsx @@ -17,13 +17,15 @@ import { Button, ButtonVariantType, + CMSecretComponentType, ComponentSizeType, GenericEmptyState, ImageType, - CMSecretComponentType, } from '@devtron-labs/devtron-fe-common-lib' -import cmCsEmptyState from '@Images/cm-cs-empty-state.png' + import { ReactComponent as ICAdd } from '@Icons/ic-add.svg' +import cmCsEmptyState from '@Images/cm-cs-empty-state.png' + import { NoOverrideEmptyStateProps } from './types' import './NoOverrideEmptyState.scss' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoPublishedVersionEmptyState.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoPublishedVersionEmptyState.tsx index 70eeb96579..2196b8737e 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoPublishedVersionEmptyState.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/NoPublishedVersionEmptyState.tsx @@ -15,6 +15,7 @@ */ import { Button, ButtonVariantType, GenericEmptyState, Icon } from '@devtron-labs/devtron-fe-common-lib' + import noArtifact from '@Images/no-artifact.webp' import { NoPublishedVersionEmptyStateProps } from './types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/SelectMergeStrategy.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/SelectMergeStrategy.tsx index eadd4549ab..0cfb4ad4b3 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/SelectMergeStrategy.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/SelectMergeStrategy.tsx @@ -15,18 +15,20 @@ */ import { + ComponentSizeType, + DOCUMENTATION_HOME_PAGE, + getSelectPickerOptionByValue, InfoIconTippy, + noop, OverrideMergeStrategyType, OverrideStrategyTippyContent, SelectPicker, SelectPickerOptionType, SelectPickerVariantType, - DOCUMENTATION_HOME_PAGE, - ComponentSizeType, - noop, - getSelectPickerOptionByValue, } from '@devtron-labs/devtron-fe-common-lib' + import { importComponentFromFELibrary } from '@Components/common' + import { MERGE_STRATEGY_OPTIONS } from './constants' import { SelectMergeStrategyProps } from './types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/constants.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/constants.tsx index f32e6cf570..327f0fe409 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/constants.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/constants.tsx @@ -14,9 +14,10 @@ * limitations under the License. */ -import { importComponentFromFELibrary } from '@Components/common' import { EnterpriseTag, OverrideMergeStrategyType, SelectPickerOptionType } from '@devtron-labs/devtron-fe-common-lib' +import { importComponentFromFELibrary } from '@Components/common' + const isFELibAvailable = importComponentFromFELibrary('isFELibAvailable', false, 'function') const IS_ENV_MERGE_STRATEGY_VALID = diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/index.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/index.ts index 3c883fc22a..c3d0303c8c 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/index.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/index.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -export * from './DeploymentTemplate' +export { default as CompareConfigView } from './CompareConfigView' export { default as ConfigDryRun } from './ConfigDryRun' +export { default as ConfigHeader } from './ConfigHeader' export { default as ConfigToolbar } from './ConfigToolbar' +export * from './DeploymentConfigCompare' +export * from './DeploymentTemplate' export { default as NoOverrideEmptyState } from './NoOverrideEmptyState' -export { default as ConfigHeader } from './ConfigHeader' export { default as NoPublishedVersionEmptyState } from './NoPublishedVersionEmptyState' -export { default as CompareConfigView } from './CompareConfigView' -export * from './DeploymentConfigCompare' export { default as SelectMergeStrategy } from './SelectMergeStrategy' - -export type { ConfigToolbarProps, CompareConfigViewProps } from './types' +export type { CompareConfigViewProps, ConfigToolbarProps } from './types' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/types.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/types.ts index af9f659e18..e717d83aac 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/types.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/types.ts @@ -14,7 +14,10 @@ * limitations under the License. */ +import { FunctionComponent, MutableRefObject, ReactNode } from 'react' + import { + CMSecretComponentType, CompareFromApprovalOptionsValuesType, ConfigHeaderTabType, ConfigToolbarPopupMenuConfigType, @@ -23,13 +26,12 @@ import { DeploymentTemplateConfigState, DraftMetadataDTO, OverrideMergeStrategyType, + PipelineMigratedFromType, ProtectConfigTabsType, SelectPickerOptionType, ServerErrors, - CMSecretComponentType, - PipelineMigratedFromType, } from '@devtron-labs/devtron-fe-common-lib' -import { FunctionComponent, MutableRefObject, ReactNode } from 'react' + import { DeploymentTemplateStateType } from './DeploymentTemplate/types' export interface ConfigHeaderProps { diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/utils.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/utils.tsx index 919ef21c7b..e099278f77 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/utils.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/MainContent/utils.tsx @@ -21,11 +21,13 @@ import { PipelineMigratedFromType, Tooltip, } from '@devtron-labs/devtron-fe-common-lib' -import { ReactComponent as ICFilePlay } from '@Icons/ic-file-play.svg' -import { ReactComponent as ICFileCode } from '@Icons/ic-file-code.svg' + import { ReactComponent as ICArrowSquareIn } from '@Icons/ic-arrow-square-in.svg' import { ReactComponent as ICDeleteInteractive } from '@Icons/ic-delete-interactive.svg' +import { ReactComponent as ICFileCode } from '@Icons/ic-file-code.svg' +import { ReactComponent as ICFilePlay } from '@Icons/ic-file-play.svg' import { importComponentFromFELibrary } from '@Components/common' + import { CompareConfigViewEditorConfigType, ConfigHeaderTabConfigType, diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/AppNavigation.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/AppNavigation.tsx index 04c2d37769..bd1e7a6566 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/AppNavigation.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/AppNavigation.tsx @@ -33,6 +33,7 @@ import { ReactNode } from 'react' import { Route, Switch, useLocation, useRouteMatch } from 'react-router-dom' + import { Button, ButtonStyleType, @@ -42,16 +43,16 @@ import { TippyCustomized, TippyTheme, } from '@devtron-labs/devtron-fe-common-lib' -import { DEVTRON_APPS_STEPS, STAGE_NAME } from '../AppConfig.types' + +import DockerFileInUse from '../../../../../../assets/img/ic-dockerfile-in-use.png' import { DEPLOYMENT_CONFIGURATION_RESOURCE_TYPE_ROUTE, URLS } from '../../../../../../config' -import AppConfigurationCheckBox from './AppConfigurationCheckBox' import { GIT_MATERIAL_IN_USE_MESSAGE } from '../../../../../../config/constantMessaging' -import DockerFileInUse from '../../../../../../assets/img/ic-dockerfile-in-use.png' - -import EnvironmentOverrideRouter from './EnvironmentOverrideRouter' +import { DEVTRON_APPS_STEPS, STAGE_NAME } from '../AppConfig.types' import { useAppConfigurationContext } from '../AppConfiguration.provider' -import { renderNavItem } from './Navigation.helper' +import AppConfigurationCheckBox from './AppConfigurationCheckBox' import { EnvConfigurationsNav } from './EnvConfigurationsNav' +import EnvironmentOverrideRouter from './EnvironmentOverrideRouter' +import { renderNavItem } from './Navigation.helper' export const AppNavigation = () => { // HOOKS diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvConfigurationsNav.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvConfigurationsNav.tsx index 1552918af2..9b6ba81625 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvConfigurationsNav.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvConfigurationsNav.tsx @@ -15,9 +15,10 @@ */ import { Dispatch, MouseEvent, useEffect, useMemo, useState } from 'react' -import { useRouteMatch, useLocation, NavLink, useHistory, generatePath } from 'react-router-dom' -import Tippy from '@tippyjs/react' +import ReactGA from 'react-ga4' +import { generatePath, NavLink, useHistory, useLocation, useRouteMatch } from 'react-router-dom' import { GroupBase, OptionsOrGroups } from 'react-select' +import Tippy from '@tippyjs/react' import { BASE_CONFIGURATION_ENV_ID, @@ -36,18 +37,17 @@ import { useMainContext, } from '@devtron-labs/devtron-fe-common-lib' -import { ReactComponent as ICBack } from '@Icons/ic-caret-left-small.svg' -import { ReactComponent as ICArrowsLeftRight } from '@Icons/ic-arrows-left-right.svg' import { ReactComponent as ICAdd } from '@Icons/ic-add.svg' -import { ReactComponent as ICLocked } from '@Icons/ic-locked.svg' +import { ReactComponent as ICArrowsLeftRight } from '@Icons/ic-arrows-left-right.svg' +import { ReactComponent as ICBack } from '@Icons/ic-caret-left-small.svg' import { ReactComponent as ICFileCode } from '@Icons/ic-file-code.svg' +import { ReactComponent as ICLocked } from '@Icons/ic-locked.svg' +import { DEPLOYMENT_CONFIGURATION_RESOURCE_TYPE_ROUTE } from '@Config/constants' import { URLS } from '@Config/routes' import { ResourceConfigState } from '@Pages/Applications/DevtronApps/service.types' -import { DEPLOYMENT_CONFIGURATION_RESOURCE_TYPE_ROUTE } from '@Config/constants' -import ReactGA from 'react-ga4' import { BASE_CONFIGURATIONS } from '../AppConfig.constants' -import { EnvConfigRouteParams, EnvConfigurationsNavProps, EnvConfigObjectKey, EnvConfigType } from '../AppConfig.types' +import { EnvConfigObjectKey, EnvConfigRouteParams, EnvConfigType, EnvConfigurationsNavProps } from '../AppConfig.types' import { getEnvConfiguration, getNavigationPath, getUnnamedIconConfig } from './Navigation.helper' // LOADING SHIMMER diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvironmentOverrideRouter.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvironmentOverrideRouter.tsx index bab787a61c..441735e5ea 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvironmentOverrideRouter.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/EnvironmentOverrideRouter.tsx @@ -14,34 +14,37 @@ * limitations under the License. */ -import { useState, useEffect, Fragment } from 'react' -import { useParams, useLocation, useRouteMatch, NavLink, Link } from 'react-router-dom' +import { Fragment, useEffect, useState } from 'react' +import { Link, NavLink, useLocation, useParams, useRouteMatch } from 'react-router-dom' + import { - showError, ConfirmationDialog, + DeleteConfirmationModal, + EnvResourceType, + getEnvironmentListMinPublic, InfoColourBar, PopupMenu, Progressing, - getEnvironmentListMinPublic, - ToastVariantType, - ToastManager, SelectPicker, - DeleteConfirmationModal, - EnvResourceType, + showError, + ToastManager, + ToastVariantType, } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as ICStamp } from '@Icons/ic-stamp.svg' -import { URLS, DOCUMENTATION } from '../../../../../../config' -import { usePrevious, createClusterEnvGroup } from '../../../../../../components/common' -import { addJobEnvironment, deleteJobEnvironment, getCIConfig } from '../../../../../../services/service' -import { ReactComponent as Help } from '../../../../../../assets/icons/ic-help.svg' + import { ReactComponent as Add } from '../../../../../../assets/icons/ic-add.svg' -import { ReactComponent as More } from '../../../../../../assets/icons/ic-more-option.svg' import { ReactComponent as DeleteIcon } from '../../../../../../assets/icons/ic-delete-interactive.svg' +import { ReactComponent as Help } from '../../../../../../assets/icons/ic-help.svg' +import { ReactComponent as More } from '../../../../../../assets/icons/ic-more-option.svg' import warn from '../../../../../../assets/icons/ic-warning.svg' -import { AppConfigState, JobEnvOverrideRouteProps } from '../AppConfig.types' +import { createClusterEnvGroup, usePrevious } from '../../../../../../components/common' import { RESOURCE_ACTION_MENU } from '../../../../../../components/ResourceBrowser/Constants' -import { renderNavItem } from './Navigation.helper' +import { DOCUMENTATION, URLS } from '../../../../../../config' +import { addJobEnvironment, deleteJobEnvironment, getCIConfig } from '../../../../../../services/service' +import { AppConfigState, JobEnvOverrideRouteProps } from '../AppConfig.types' import { useAppConfigurationContext } from '../AppConfiguration.provider' +import { renderNavItem } from './Navigation.helper' const EnvOverridesHelpNote = () => (
diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/Navigation.helper.tsx b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/Navigation.helper.tsx index 523f227d85..9bc7fe1c63 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/Navigation.helper.tsx +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/Navigation.helper.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { NavLink, generatePath } from 'react-router-dom' +import { generatePath, NavLink } from 'react-router-dom' import { ApprovalConfigDataKindType, @@ -31,10 +31,10 @@ import { ResourceConfigStage, ResourceConfigState } from '@Pages/Applications/De import { CustomNavItemsType, + EnvConfigObjectKey, EnvConfigRouteParams, EnvConfigType, ExtendedCollapsibleListItem, - EnvConfigObjectKey, } from '../AppConfig.types' import { RESOURCE_CONFIG_STATE_TO_ICON_CONFIG_MAP } from './constants' diff --git a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/constants.ts b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/constants.ts index f607a078e2..1c25781558 100644 --- a/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/constants.ts +++ b/src/Pages/Applications/DevtronApps/Details/AppConfigurations/Navigation/constants.ts @@ -15,10 +15,11 @@ */ import { CollapsibleListItem } from '@devtron-labs/devtron-fe-common-lib' -import { ResourceConfigState } from '@Pages/Applications/DevtronApps/service.types' -import { ReactComponent as ICStamp } from '@Icons/ic-stamp.svg' -import { ReactComponent as ICFileEdit } from '@Icons/ic-file-edit.svg' + import { ReactComponent as ICCheckCircleDots } from '@Icons/ic-check-circle-dots.svg' +import { ReactComponent as ICFileEdit } from '@Icons/ic-file-edit.svg' +import { ReactComponent as ICStamp } from '@Icons/ic-stamp.svg' +import { ResourceConfigState } from '@Pages/Applications/DevtronApps/service.types' export const RESOURCE_CONFIG_STATE_TO_ICON_CONFIG_MAP: Record< ResourceConfigState, diff --git a/src/Pages/Applications/DevtronApps/service.ts b/src/Pages/Applications/DevtronApps/service.ts index 59a6f69a54..62bd6d2792 100644 --- a/src/Pages/Applications/DevtronApps/service.ts +++ b/src/Pages/Applications/DevtronApps/service.ts @@ -33,21 +33,21 @@ import { AppConfigProps, - GetTemplateAPIRouteType, - ResourceKindType, - ResponseType, get, + getTemplateAPIRoute, + GetTemplateAPIRouteType, getUrlWithSearchParams, noop, + ResourceKindType, + ResponseType, showError, - getTemplateAPIRoute, } from '@devtron-labs/devtron-fe-common-lib' import { Routes } from '@Config/constants' -import { AppConfigStatusItemType } from './service.types' import { DEFAULT_LANDING_STAGE, EnvConfigType } from './Details/AppConfigurations/AppConfig.types' import { transformEnvConfig } from './Details/AppConfigurations/AppConfig.utils' +import { AppConfigStatusItemType } from './service.types' export const getAppConfigStatus = ( appId: number, diff --git a/src/Pages/Applications/DevtronApps/service.types.ts b/src/Pages/Applications/DevtronApps/service.types.ts index 4674e7d2b8..5c0c6e9e79 100644 --- a/src/Pages/Applications/DevtronApps/service.types.ts +++ b/src/Pages/Applications/DevtronApps/service.types.ts @@ -32,6 +32,7 @@ */ import { ConfigResourceType } from '@devtron-labs/devtron-fe-common-lib' + import { STAGE_NAME } from './Details/AppConfigurations/AppConfig.types' export interface AppConfigStatusItemType { diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/APITokenList.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/APITokenList.tsx index c72304b24e..a852a6b498 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/APITokenList.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/APITokenList.tsx @@ -14,24 +14,27 @@ * limitations under the License. */ -import moment from 'moment' import { useState } from 'react' import { useHistory } from 'react-router-dom' +import moment from 'moment' + import { - GenericFilterEmptyState, - FeatureTitleWithInfo, Button, ButtonStyleType, ButtonVariantType, ComponentSizeType, + FeatureTitleWithInfo, + GenericFilterEmptyState, } from '@devtron-labs/devtron-fe-common-lib' -import { HEADER_TEXT, MomentDateFormat } from '../../../../config' + +import { ReactComponent as Trash } from '../../../../assets/icons/ic-delete-interactive.svg' import { ReactComponent as Key } from '../../../../assets/icons/ic-key-bulb.svg' import { ReactComponent as Edit } from '../../../../assets/icons/ic-pencil.svg' -import { ReactComponent as Trash } from '../../../../assets/icons/ic-delete-interactive.svg' +import { HEADER_TEXT, MomentDateFormat } from '../../../../config' import { APITokenListType, TokenListType } from './apiToken.type' import { isTokenExpired } from './apiToken.utils' import DeleteAPITokenModal from './DeleteAPITokenModal' + import './apiToken.scss' const APITokenList = ({ tokenList, renderSearchToken, reload }: APITokenListType) => { diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/ApiTokens.component.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/ApiTokens.component.tsx index e3457b9dd3..3888215b37 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/ApiTokens.component.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/ApiTokens.component.tsx @@ -15,22 +15,26 @@ */ import { useEffect, useState } from 'react' -import './apiToken.scss' +import { Redirect, Route, Switch, useHistory, useLocation, useRouteMatch } from 'react-router-dom' + import { - showError, - Progressing, ErrorScreenManager, GenericEmptyState, + Progressing, SearchBar, + showError, } from '@devtron-labs/devtron-fe-common-lib' -import { Redirect, Route, Switch, useHistory, useLocation, useRouteMatch } from 'react-router-dom' + import emptyGeneratToken from '@Images/ic-empty-generate-token.png' import { EMPTY_STATE_STATUS } from '@Config/constantMessaging' -import { getGeneratedAPITokenList } from './service' + +import { TokenListType, TokenResponseType } from './apiToken.type' import APITokenList from './APITokenList' import CreateAPIToken from './CreateAPIToken' import EditAPIToken from './EditAPIToken' -import { TokenListType, TokenResponseType } from './apiToken.type' +import { getGeneratedAPITokenList } from './service' + +import './apiToken.scss' const ApiTokens = () => { const { path } = useRouteMatch() diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/CreateAPIToken.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/CreateAPIToken.tsx index 33355735f7..6f7ff3641b 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/CreateAPIToken.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/CreateAPIToken.tsx @@ -19,35 +19,37 @@ import { useEffect, useState } from 'react' import { useHistory, useRouteMatch } from 'react-router-dom' import { Moment } from 'moment' + import { - ServerErrors, - showError, CustomInput, InfoIconTippy, - useMainContext, - ToastVariantType, - ToastManager, + ServerErrors, + showError, Textarea, + ToastManager, + ToastVariantType, + useMainContext, } from '@devtron-labs/devtron-fe-common-lib' -import { FormType, GenerateTokenType } from './apiToken.type' -import { createGeneratedAPIToken } from './service' -import GenerateModal from './GenerateModal' -import { getDateInMilliseconds } from './apiToken.utils' -import GenerateActionButton from './GenerateActionButton' -import { ValidationRules } from './validationRules' + import { ReactComponent as Error } from '../../../../assets/icons/ic-warning.svg' -import ExpirationDate from './ExpirationDate' +import { importComponentFromFELibrary } from '../../../../components/common' import { DOCUMENTATION, REQUIRED_FIELDS_MISSING } from '../../../../config' import { API_COMPONENTS } from '../../../../config/constantMessaging' import { createOrUpdateUser } from '../authorization.service' +import { getDefaultUserStatusAndTimeout } from '../libUtils' import { PermissionConfigurationForm, PermissionConfigurationFormProvider, usePermissionConfiguration, } from '../Shared/components/PermissionConfigurationForm' import { createUserPermissionPayload, validateDirectPermissionForm } from '../utils' -import { getDefaultUserStatusAndTimeout } from '../libUtils' -import { importComponentFromFELibrary } from '../../../../components/common' +import { FormType, GenerateTokenType } from './apiToken.type' +import { getDateInMilliseconds } from './apiToken.utils' +import ExpirationDate from './ExpirationDate' +import GenerateActionButton from './GenerateActionButton' +import GenerateModal from './GenerateModal' +import { createGeneratedAPIToken } from './service' +import { ValidationRules } from './validationRules' const showStatus = !!importComponentFromFELibrary('StatusHeaderCell', null, 'function') diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/DeleteAPITokenModal.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/DeleteAPITokenModal.tsx index bc651799fd..894fb962c9 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/DeleteAPITokenModal.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/DeleteAPITokenModal.tsx @@ -15,10 +15,13 @@ */ import { useHistory, useRouteMatch } from 'react-router-dom' -import { DeleteComponentsName } from '@Config/constantMessaging' + import { DeleteConfirmationModal } from '@devtron-labs/devtron-fe-common-lib' -import { deleteGeneratedAPIToken } from './service' + +import { DeleteComponentsName } from '@Config/constantMessaging' + import { DeleteAPITokenModalProps } from './apiToken.type' +import { deleteGeneratedAPIToken } from './service' const DeleteAPITokenModal = ({ isEditView, tokenData, reload, setDeleteConfirmation }: DeleteAPITokenModalProps) => { const match = useRouteMatch() diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/EditAPIToken.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/EditAPIToken.tsx index 6242644859..2cc59a4d6e 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/EditAPIToken.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/EditAPIToken.tsx @@ -16,42 +16,44 @@ /* eslint-disable jsx-a11y/label-has-associated-control */ import React, { useEffect, useState } from 'react' +import { useHistory, useParams, useRouteMatch } from 'react-router-dom' +import moment from 'moment' + import { - showError, - Progressing, - InfoColourBar, + ButtonWithLoader, + ClipboardButton, CustomInput, + InfoColourBar, noop, - ClipboardButton, - useMainContext, - ButtonWithLoader, - ToastVariantType, - ToastManager, + Progressing, + showError, Textarea, + ToastManager, + ToastVariantType, + useMainContext, } from '@devtron-labs/devtron-fe-common-lib' -import { useHistory, useRouteMatch, useParams } from 'react-router-dom' -import moment from 'moment' -import { ReactComponent as InfoIcon } from '../../../../assets/icons/info-filled.svg' -import RegeneratedModal from './RegenerateModal' -import { EditDataType, EditTokenType } from './apiToken.type' -import { isTokenExpired } from './apiToken.utils' + import { ReactComponent as Delete } from '../../../../assets/icons/ic-delete-interactive.svg' -import GenerateActionButton from './GenerateActionButton' -import { MomentDateFormat } from '../../../../config' +import { ReactComponent as InfoIcon } from '../../../../assets/icons/info-filled.svg' import { importComponentFromFELibrary } from '../../../../components/common' -import { updateGeneratedAPIToken } from './service' -import DeleteAPITokenModal from './DeleteAPITokenModal' +import { MomentDateFormat } from '../../../../config' import { API_COMPONENTS } from '../../../../config/constantMessaging' -import { renderQuestionwithTippy } from './CreateAPIToken' import { createOrUpdateUser, getUserById } from '../authorization.service' -import { User } from '../types' +import { getDefaultUserStatusAndTimeout } from '../libUtils' import { PermissionConfigurationForm, PermissionConfigurationFormProvider, usePermissionConfiguration, } from '../Shared/components/PermissionConfigurationForm' +import { User } from '../types' import { createUserPermissionPayload, validateDirectPermissionForm } from '../utils' -import { getDefaultUserStatusAndTimeout } from '../libUtils' +import { EditDataType, EditTokenType } from './apiToken.type' +import { isTokenExpired } from './apiToken.utils' +import { renderQuestionwithTippy } from './CreateAPIToken' +import DeleteAPITokenModal from './DeleteAPITokenModal' +import GenerateActionButton from './GenerateActionButton' +import RegeneratedModal from './RegenerateModal' +import { updateGeneratedAPIToken } from './service' const showStatus = !!importComponentFromFELibrary('StatusHeaderCell', null, 'function') diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/ExpirationDate.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/ExpirationDate.tsx index 408158cfca..8fe9d078e4 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/ExpirationDate.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/ExpirationDate.tsx @@ -16,11 +16,13 @@ /* eslint-disable react/prop-types */ import moment from 'moment' + import { InfoColourBar, SelectPicker } from '@devtron-labs/devtron-fe-common-lib' -import { MomentDateFormat } from '../../../../config' -import { SingleDatePickerComponent } from '../../../../components/common' -import { getOptions, getDateInMilliseconds } from './apiToken.utils' + import { ReactComponent as Warn } from '../../../../assets/icons/ic-warning.svg' +import { SingleDatePickerComponent } from '../../../../components/common' +import { MomentDateFormat } from '../../../../config' +import { getDateInMilliseconds, getOptions } from './apiToken.utils' const ExpirationDate = ({ selectedExpirationDate, onChangeSelectFormData, handleDatesChange, customDate }) => (
diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateActionButton.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateActionButton.tsx index c85169addf..b102e07c3c 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateActionButton.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateActionButton.tsx @@ -15,6 +15,7 @@ */ import { ButtonWithLoader } from '@devtron-labs/devtron-fe-common-lib' + import { GenerateActionButtonType } from './apiToken.type' const GenerateActionButton = ({ diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateModal.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateModal.tsx index 4f359b5e2e..9607f8f3c8 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateModal.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateModal.tsx @@ -15,17 +15,19 @@ */ import { useState } from 'react' + import { Button, ButtonVariantType, ClipboardButton, ComponentSizeType, - VisibleModal, copyToClipboard, + VisibleModal, } from '@devtron-labs/devtron-fe-common-lib' -import { ReactComponent as Success } from '../../../../assets/icons/ic-success-outline.svg' + import { ReactComponent as Close } from '../../../../assets/icons/ic-close.svg' import { ReactComponent as Key } from '../../../../assets/icons/ic-key-bulb.svg' +import { ReactComponent as Success } from '../../../../assets/icons/ic-success-outline.svg' import { GenerateTokenModalType } from './apiToken.type' const GenerateModal = ({ close, token, reload, redirectToTokenList, isRegenerationModal }: GenerateTokenModalType) => { diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/RegenerateModal.tsx b/src/Pages/GlobalConfigurations/Authorization/APITokens/RegenerateModal.tsx index 9c5ac78018..d6231307b9 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/RegenerateModal.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/RegenerateModal.tsx @@ -15,15 +15,17 @@ */ import { useState } from 'react' -import { showError, Progressing, VisibleModal, InfoColourBar } from '@devtron-labs/devtron-fe-common-lib' + +import { InfoColourBar, Progressing, showError, VisibleModal } from '@devtron-labs/devtron-fe-common-lib' + import { ReactComponent as Close } from '../../../../assets/icons/ic-close.svg' import { ReactComponent as Warn } from '../../../../assets/icons/ic-warning.svg' -import GenerateActionButton from './GenerateActionButton' -import { getDateInMilliseconds } from './apiToken.utils' import { RegenerateModalType, TokenResponseType } from './apiToken.type' -import { updateGeneratedAPIToken } from './service' -import GenerateModal from './GenerateModal' +import { getDateInMilliseconds } from './apiToken.utils' import ExpirationDate from './ExpirationDate' +import GenerateActionButton from './GenerateActionButton' +import GenerateModal from './GenerateModal' +import { updateGeneratedAPIToken } from './service' const RegeneratedModal = ({ close, diff --git a/src/Pages/GlobalConfigurations/Authorization/APITokens/service.ts b/src/Pages/GlobalConfigurations/Authorization/APITokens/service.ts index eccd716cad..e5656ef653 100644 --- a/src/Pages/GlobalConfigurations/Authorization/APITokens/service.ts +++ b/src/Pages/GlobalConfigurations/Authorization/APITokens/service.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { get, post, put, trash, ResponseType } from '@devtron-labs/devtron-fe-common-lib' +import { get, post, put, ResponseType, trash } from '@devtron-labs/devtron-fe-common-lib' + import { Routes } from '../../../../config' export function getGeneratedAPITokenList(): Promise { diff --git a/src/Pages/GlobalConfigurations/Authorization/Authorization.component.tsx b/src/Pages/GlobalConfigurations/Authorization/Authorization.component.tsx index b79883c04d..31743ee2fb 100644 --- a/src/Pages/GlobalConfigurations/Authorization/Authorization.component.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/Authorization.component.tsx @@ -16,7 +16,9 @@ import { lazy } from 'react' import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom' + import { Routes } from '../../../config' + import './authorization.scss' const UserAndGroupPermissions = lazy(() => import('./UserAndGroupPermissions')) diff --git a/src/Pages/GlobalConfigurations/Authorization/AuthorizationProvider.tsx b/src/Pages/GlobalConfigurations/Authorization/AuthorizationProvider.tsx index 2962d5e406..2aa74a950b 100644 --- a/src/Pages/GlobalConfigurations/Authorization/AuthorizationProvider.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/AuthorizationProvider.tsx @@ -15,6 +15,7 @@ */ import { createContext, useContext } from 'react' + import { AuthorizationContextProps, AuthorizationProviderProps } from './types' const AuthorizationContext = createContext({ diff --git a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupAddEdit.component.tsx b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupAddEdit.component.tsx index 96274a963a..70a2e50d27 100644 --- a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupAddEdit.component.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupAddEdit.component.tsx @@ -14,16 +14,18 @@ * limitations under the License. */ +import { Link, useParams } from 'react-router-dom' + import { - ErrorScreenNotAuthorized, ERROR_EMPTY_SCREEN, + ErrorScreenNotAuthorized, GenericEmptyState, Progressing, Reload, TOAST_ACCESS_DENIED, useAsync, } from '@devtron-labs/devtron-fe-common-lib' -import { Link, useParams } from 'react-router-dom' + import { API_STATUS_CODES, URLS } from '../../../../../config' import { getPermissionGroupById } from '../../authorization.service' import { PermissionConfigurationFormProvider } from '../../Shared/components/PermissionConfigurationForm' diff --git a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupForm.tsx b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupForm.tsx index c8a650f7e8..b2a9225cb2 100644 --- a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupForm.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/AddEdit/PermissionGroupForm.tsx @@ -14,35 +14,37 @@ * limitations under the License. */ -import { useState, useEffect } from 'react' +import { useEffect, useState } from 'react' +import { Link, useHistory } from 'react-router-dom' + import { - showError, - CustomInput, - useMainContext, - ToastVariantType, - ToastManager, + Button, ButtonComponentType, + ButtonStyleType, ButtonVariantType, ComponentSizeType, - ButtonStyleType, - Button, + CustomInput, + showError, Textarea, + ToastManager, + ToastVariantType, + useMainContext, } from '@devtron-labs/devtron-fe-common-lib' -import { Link, useHistory } from 'react-router-dom' + import { ReactComponent as ICDeleteInteractive } from '@Icons/ic-delete-interactive.svg' import { ReactComponent as ICWarning } from '@Icons/ic-warning.svg' -import { deepEqual } from '../../../../../components/common' +import { deepEqual } from '../../../../../components/common' import { URLS } from '../../../../../config' -import { PermissionGroup, PermissionGroupCreateOrUpdatePayload } from '../../types' import { createOrUpdatePermissionGroup, deletePermissionGroup } from '../../authorization.service' +import { excludeKeyAndClusterValue } from '../../Shared/components/K8sObjectPermissions/utils' import { PermissionConfigurationForm, usePermissionConfiguration, } from '../../Shared/components/PermissionConfigurationForm' -import { getIsSuperAdminPermission, getRolesAndAccessRoles, validateDirectPermissionForm } from '../../utils' -import { excludeKeyAndClusterValue } from '../../Shared/components/K8sObjectPermissions/utils' +import { PermissionGroup, PermissionGroupCreateOrUpdatePayload } from '../../types' import { DeleteUserPermission } from '../../UserPermissions/DeleteUserPermission' +import { getIsSuperAdminPermission, getRolesAndAccessRoles, validateDirectPermissionForm } from '../../utils' const PermissionGroupForm = ({ isAddMode }: { isAddMode: boolean }) => { const { serverMode } = useMainContext() diff --git a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/ExportPermissionGroupsToCsv.tsx b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/ExportPermissionGroupsToCsv.tsx index 34ada23150..7ef385691b 100644 --- a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/ExportPermissionGroupsToCsv.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/ExportPermissionGroupsToCsv.tsx @@ -14,11 +14,11 @@ * limitations under the License. */ -import { PermissionGroupListHeaderProps } from './types' -import ExportToCsv from '../../../../../components/common/ExportToCsv/ExportToCsv' import { FILE_NAMES, GROUP_EXPORT_HEADER_ROW } from '../../../../../components/common/ExportToCsv/constants' +import ExportToCsv from '../../../../../components/common/ExportToCsv/ExportToCsv' import { useAuthorizationContext } from '../../AuthorizationProvider' import { getRoleFiltersToExport } from '../../utils' +import { PermissionGroupListHeaderProps } from './types' const ExportPermissionGroupsToCsv = ({ disabled, diff --git a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx index e0074b792d..7676640262 100644 --- a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx +++ b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx @@ -15,10 +15,11 @@ */ import { Button, ButtonComponentType, ComponentSizeType, GenericEmptyState } from '@devtron-labs/devtron-fe-common-lib' -import nullStateImage from '../../../../../assets/img/empty-applist@2x.png' + import { ReactComponent as AddIcon } from '../../../../../assets/icons/ic-add.svg' -import { EMPTY_STATE_STATUS } from '../../../../../config/constantMessaging' +import nullStateImage from '../../../../../assets/img/empty-applist@2x.png' import { URLS } from '../../../../../config' +import { EMPTY_STATE_STATUS } from '../../../../../config/constantMessaging' const renderAddGroupButton = () => (
+ +) diff --git a/src/components/ClusterNodes/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterListRow.tsx new file mode 100644 index 0000000000..2f9e1986e1 --- /dev/null +++ b/src/components/ClusterNodes/ClusterListRow.tsx @@ -0,0 +1,162 @@ +import { SIDEBAR_KEYS, K8S_EMPTY_GROUP } from '@Components/ResourceBrowser/Constants' +import { + ALL_NAMESPACE_OPTION, + BulkSelectionEvents, + BulkSelectionIdentifiersType, + Checkbox, + CHECKBOX_VALUE, + ClusterDetail, + ClusterStatusType, + Icon, + Tooltip, + URLS, + useBulkSelection, +} from '@devtron-labs/devtron-fe-common-lib' +import { Link, useHistory, useLocation } from 'react-router-dom' +import { ReactComponent as Error } from '@Icons/ic-error-exclamation.svg' +import { ReactComponent as TerminalIcon } from '@Icons/ic-terminal-fill.svg' +import { importComponentFromFELibrary } from '@Components/common' +import { AppDetailsTabs } from '@Components/v2/appDetails/appDetails.store' +import { CLUSTER_PROD_TYPE } from './constants' +import { ClusterMapInitialStatus } from './ClusterMapInitialStatus' +import { ClusterListRowTypes } from './types' +import { KubeConfigButton } from './KubeConfigButton' + +export const ClusterListRow = ({ clusterData, index, clusterListLoader }: ClusterListRowTypes) => { + // const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') + const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') + const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') + + const { + selectedIdentifiers: bulkSelectionState, + isBulkSelectionApplied, + handleBulkSelection, + } = useBulkSelection>() + const errorCount = clusterData.nodeErrors ? Object.keys(clusterData.nodeErrors).length : 0 + const history = useHistory() + const location = useLocation() + + const handleSelection = () => { + const { name } = clusterData + if (isBulkSelectionApplied) { + handleBulkSelection({ + action: BulkSelectionEvents.CLEAR_IDENTIFIERS_AFTER_ACROSS_SELECTION, + data: { + identifierIds: [name], + }, + }) + } else if (bulkSelectionState[name]) { + handleBulkSelection({ + action: BulkSelectionEvents.CLEAR_IDENTIFIERS, + data: { + identifierIds: [name], + }, + }) + } else { + handleBulkSelection({ + action: BulkSelectionEvents.SELECT_IDENTIFIER, + data: { + identifierObject: { + ...bulkSelectionState, + [name]: clusterData, + }, + }, + }) + } + } + + const getOpenTerminalHandler = () => () => + history.push(`${location.pathname}/${clusterData.id}/all/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}`) + + const hideDataOnLoad = (value) => { + if (clusterListLoader) { + return null + } + return value + } + + const renderClusterStatus = ({ errorInNodeListing, status }: ClusterDetail) => { + if (ClusterStatusCell && status) { + return + } + + return + } + const isIdentifierSelected = !!bulkSelectionState[clusterData.name] || isBulkSelectionApplied + + return ( +
+ + {!isIdentifierSelected && ( +
+ +
+ )} +
+ + {clusterData.name} + + {/* NOTE: visible-hover plays with display prop; therefore need to set display: flex on a new div */} +
+
+ {!!clusterData.nodeCount && !clusterListLoader && ( + +
+ +
+
+ )} + {CompareClusterButton && clusterData.status !== ClusterStatusType.CONNECTION_FAILED && ( + + )} + {/* {KubeConfigButton && } */} + +
+
+
+ + {renderClusterStatus(clusterData)} + +
+ {hideDataOnLoad(clusterData.isProd ? CLUSTER_PROD_TYPE.PRODUCTION : CLUSTER_PROD_TYPE.NON_PRODUCTION)} +
+
{hideDataOnLoad(clusterData.nodeCount)}
+
+ {errorCount > 0 && + hideDataOnLoad( + <> + + {errorCount} + , + )} +
+
+ {hideDataOnLoad( + + {clusterData.serverVersion} + , + )} +
+
{hideDataOnLoad(clusterData.cpu?.capacity)}
+
{hideDataOnLoad(clusterData.memory?.capacity)}
+
+ ) +} diff --git a/src/components/ClusterNodes/ClusterSelectionList.tsx b/src/components/ClusterNodes/ClusterSelectionList.tsx index b5aa39a0d8..bbfde46ec5 100644 --- a/src/components/ClusterNodes/ClusterSelectionList.tsx +++ b/src/components/ClusterNodes/ClusterSelectionList.tsx @@ -14,46 +14,38 @@ * limitations under the License. */ -import React, { useState, useMemo } from 'react' -import { useHistory, useLocation, Link } from 'react-router-dom' +import React, { useState, useMemo, useEffect } from 'react' import { GenericEmptyState, SearchBar, useUrlFilters, - Tooltip, ClusterFiltersType, - ALL_NAMESPACE_OPTION, SortableTableHeaderCell, ClusterDetail, - ClusterStatusType, + BulkSelection, + BulkSelectionIdentifiersType, + useBulkSelection, + BulkSelectionEvents, + BulkSelectionProvider, + SelectAllDialogStatus, } from '@devtron-labs/devtron-fe-common-lib' import dayjs, { Dayjs } from 'dayjs' import { importComponentFromFELibrary } from '@Components/common' import Timer from '@Components/common/DynamicTabs/DynamicTabs.timer' import NoClusterEmptyState from '@Images/no-cluster-empty-state.png' import { AddClusterButton } from '@Components/ResourceBrowser/PageHeader.buttons' -import { ReactComponent as Error } from '@Icons/ic-error-exclamation.svg' -import { ReactComponent as TerminalIcon } from '@Icons/ic-terminal-fill.svg' + import ClusterNodeEmptyState from './ClusterNodeEmptyStates' import { ClusterSelectionType } from '../ResourceBrowser/Types' -import { AppDetailsTabs } from '../v2/appDetails/appDetails.store' -import { K8S_EMPTY_GROUP, SIDEBAR_KEYS } from '../ResourceBrowser/Constants' -import { URLS } from '../../config' -import { - CLUSTER_PROD_TYPE, - ClusterMapListSortableKeys, - ClusterMapListSortableTitle, - ClusterStatusByFilter, -} from './constants' + +import { ClusterMapListSortableKeys, ClusterMapListSortableTitle, ClusterStatusByFilter } from './constants' import './clusterNodes.scss' -import { ClusterMapInitialStatus } from './ClusterMapInitialStatus' import { getSortedClusterList } from './utils' +import { ClusterBulkSelectionActionWidget } from './ClusterBulkSelectionActionWidget' +import { ClusterListRow } from './ClusterListRow' -const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') -const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') -const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') -const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') const ClusterMap = importComponentFromFELibrary('ClusterMap', null, 'function') +const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') const parseSearchParams = (searchParams: URLSearchParams) => ({ clusterFilter: (searchParams.get('clusterFilter') as ClusterFiltersType) || ClusterFiltersType.ALL_CLUSTERS, @@ -64,9 +56,8 @@ const ClusterSelectionList: React.FC = ({ clusterListLoader, initialLoading, refreshData, + parentRef, }) => { - const location = useLocation() - const history = useHistory() const [lastSyncTime, setLastSyncTime] = useState(dayjs()) const { @@ -83,6 +74,19 @@ const ClusterSelectionList: React.FC = ({ initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, }) + const { handleBulkSelection, setIdentifiers, isBulkSelectionApplied, getSelectedIdentifiersCount } = + useBulkSelection>() + + useEffect(() => { + if (clusterOptions.length) { + const clusterIdentifier: BulkSelectionIdentifiersType = {} + clusterOptions.forEach((cluster) => { + clusterIdentifier[cluster.name] = cluster + }) + setIdentifiers(clusterIdentifier) + } + }, [clusterOptions]) + const filteredList: ClusterDetail[] = useMemo(() => { const loweredSearchKey = searchKey.toLowerCase() const updatedClusterOptions = [...clusterOptions] @@ -113,93 +117,6 @@ const ClusterSelectionList: React.FC = ({ updateSearchParams({ clusterFilter: _clusterFilter }) } - const getOpenTerminalHandler = (clusterData) => () => - history.push(`${location.pathname}/${clusterData.id}/all/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}`) - - const hideDataOnLoad = (value) => { - if (clusterListLoader) { - return null - } - return value - } - - const renderClusterStatus = ({ errorInNodeListing, status }: ClusterDetail) => { - if (ClusterStatusCell && status) { - return - } - - return - } - - const renderClusterRow = (clusterData: ClusterDetail): JSX.Element => { - const errorCount = clusterData.nodeErrors ? Object.keys(clusterData.nodeErrors).length : 0 - return ( -
-
- - {clusterData.name} - - {/* NOTE: visible-hover plays with display prop; therefore need to set display: flex on a new div */} -
-
- {!!clusterData.nodeCount && !clusterListLoader && ( - -
- -
-
- )} - - {CompareClusterButton && clusterData.status !== ClusterStatusType.CONNECTION_FAILED && ( - - )} - - {KubeConfigButton && } -
-
-
- - {renderClusterStatus(clusterData)} - -
- {hideDataOnLoad( - clusterData.isProd ? CLUSTER_PROD_TYPE.PRODUCTION : CLUSTER_PROD_TYPE.NON_PRODUCTION, - )} -
-
{hideDataOnLoad(clusterData.nodeCount)}
-
- {errorCount > 0 && - hideDataOnLoad( - <> - - {errorCount} - , - )} -
-
- {hideDataOnLoad( - - {clusterData.serverVersion} - , - )} -
-
{hideDataOnLoad(clusterData.cpu?.capacity)}
-
{hideDataOnLoad(clusterData.memory?.capacity)}
-
- ) - } - if (!clusterOptions.length) { return ( = ({ ) } - const handleCellSorting = (cellToSort: ClusterMapListSortableKeys) => { + const handleCellSorting = (cellToSort: ClusterMapListSortableKeys) => () => { handleSorting(cellToSort) } - return ( + const renderClusterListContent = () => (
@@ -271,22 +188,76 @@ const ClusterSelectionList: React.FC = ({
{Object.entries(ClusterMapListSortableKeys).map(([cellName, cellKey]) => ( - handleCellSorting(cellKey)} - /> + <> + {cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( + + )} + + ))}
- {filteredList.map((clusterData) => renderClusterRow(clusterData))} + {filteredList.map((clusterData, index) => ( + + ))}
)}
) + + const handleClearBulkSelection = () => { + handleBulkSelection({ + action: BulkSelectionEvents.CLEAR_ALL_SELECTIONS, + }) + } + + const renderClusterBulkSelection = () => { + if (getSelectedIdentifiersCount() > 0 || isBulkSelectionApplied) { + return ( + + ) + } + return null + } + + return ( +
+ {renderClusterBulkSelection()} + {renderClusterListContent()} +
+ ) +} + +const BaseClusterList = (props: ClusterSelectionType) => { + const { clusterOptions } = props + const allOnThisPageIdentifiers = useMemo( + () => + clusterOptions?.reduce((acc, cluster) => { + acc[cluster.name] = cluster + return acc + }, {} as ClusterDetail) ?? {}, + [clusterOptions], + ) + + return ( + > + identifiers={allOnThisPageIdentifiers} + getSelectAllDialogStatus={() => SelectAllDialogStatus.CLOSED} + > + + + ) } -export default ClusterSelectionList +export default BaseClusterList diff --git a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx new file mode 100644 index 0000000000..d5ca862c78 --- /dev/null +++ b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +import { useState } from 'react' +import ReactGA from 'react-ga4' +import { + Button, + ButtonStyleType, + ButtonVariantType, + ComponentSizeType, + Icon, +} from '@devtron-labs/devtron-fe-common-lib' +import { KubeConfigButtonProps } from './types' +import KubeConfigModal from './KubeConfigModal' + +const KubeConfigButton = ({ clusterName, isPrimaryButton = false }: KubeConfigButtonProps) => { + const [openModal, setOpenModal] = useState(false) + + const handleOpenKubeConfigModal = () => { + setOpenModal(true) + ReactGA.event({ + category: 'Resource Browser', + action: 'Get kubeconfig button clicked', + }) + } + + const handleModalClose = () => { + setOpenModal(false) + } + + return ( + <> + {isPrimaryButton ? ( +
+ ) + + const onChange = (selectedClusters) => { + setSelectedClusterName(selectedClusters) + setKubeconfigCommand(getKubeConfigCommand(selectedClusters.value)) + ReactGA.event({ + category: 'Resource Browser', + action: 'Get kubeconfig set context', + label: selectedClusters.value, + }) + } + + const reachableClustersList = Object.values(bulkSelectionClusterList).filter( + (clusterData) => clusterData.status !== ClusterStatusType.CONNECTION_FAILED, + ) + console.log(reachableClustersList) + + const handleReachableClustersToggle = () => { + setToggleEnabled(!toggleEnabled) + if (toggleEnabled) { + setKubeconfigCommand(getDefaultConfig()) + } else { + setKubeconfigCommand(reachableClustersList.map((cluster) => getKubeConfigCommand(cluster.name)).join('\n')) + } + } + + const renderSelectiveClusters = () => ( +
+
+

+

Get access for reachable clusters only
+
+ {`${reachableClustersList.length}/${bulkSelectedClusterNames.length}`} selected clusters are + reachable +
+

+
+ +
+
+ + {reachableClustersList.length > 0 && ( +
+ Set cluster context + + +
+ )} +
+ ) + + const renderConfigCommand = () => ( +
+ {bulkSelectedClusterNames.length > 1 && renderSelectiveClusters()} + +
    1 ? 'border__secondary--top' : ''} pt-12 px-0`} + > +
  1. + + Prerequisites: +   + + kubectl + +  must be installed + +
  2. +
  3. +
    + + Run below command on terminal to get server URI & bearer token + +
    +                            {kubeconfigCommand}
    +                        
    +
    +
  4. +
+
+ ) + + const renderActionButtons = () => ( +
+ + View documentation + +
+ ) + + return ( + +
+ {renderHeader()} + {renderConfigCommand()} + {renderActionButtons()} +
+
+ ) +} + +export default KubeConfigModal diff --git a/src/components/ClusterNodes/KubeConfigButton/index.ts b/src/components/ClusterNodes/KubeConfigButton/index.ts new file mode 100644 index 0000000000..cfcc93819f --- /dev/null +++ b/src/components/ClusterNodes/KubeConfigButton/index.ts @@ -0,0 +1,5 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +export { default as KubeConfigButton } from './KubeConfigButton.component' diff --git a/src/components/ClusterNodes/KubeConfigButton/types.ts b/src/components/ClusterNodes/KubeConfigButton/types.ts new file mode 100644 index 0000000000..47339de98f --- /dev/null +++ b/src/components/ClusterNodes/KubeConfigButton/types.ts @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +export interface KubeConfigButtonProps { + isPrimaryButton?: boolean + clusterName?: string +} + +export interface KubeConfigTippyContentProps extends Pick { + handleModalClose: () => void +} diff --git a/src/components/ClusterNodes/KubeConfigButton/utils.ts b/src/components/ClusterNodes/KubeConfigButton/utils.ts new file mode 100644 index 0000000000..4d265af834 --- /dev/null +++ b/src/components/ClusterNodes/KubeConfigButton/utils.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +import { getCookie, TOKEN_COOKIE_NAME } from '@devtron-labs/devtron-fe-common-lib' + +export const getKubeConfigContextCommand = (clusterName: string) => `kubectl config use-context devtron-${clusterName}` + +export const getKubeConfigCommand = (clusterName: string) => { + const token = getCookie(TOKEN_COOKIE_NAME) + + // NOTE: please don't modify spacing in the following template string + return `kubectl config set-cluster devtron-${clusterName} --server=https://${window.location.host}/orchestrator/k8s/proxy/cluster/${clusterName} --insecure-skip-tls-verify +kubectl config set-credentials devtron-${clusterName} --token=${token} +kubectl config set-context devtron-${clusterName} --cluster=devtron-${clusterName} --user=devtron-${clusterName}` +} + +export const getKubeConfigCommandWithContext = (clusterNames: string[], context?: string) => + clusterNames + .map((clusterName) => `${getKubeConfigCommand(clusterName)}`) + .join(getKubeConfigContextCommand(context || '')) diff --git a/src/components/ClusterNodes/clusterNodes.scss b/src/components/ClusterNodes/clusterNodes.scss index 992291e2f0..5a4026c6fd 100644 --- a/src/components/ClusterNodes/clusterNodes.scss +++ b/src/components/ClusterNodes/clusterNodes.scss @@ -17,7 +17,7 @@ .cluster-list-main-container { .cluster-list-row { display: grid; - grid-template-columns: auto 150px 100px 60px 100px 100px 100px 130px; + grid-template-columns: 24px auto 150px 100px 60px 100px 100px 100px 130px; column-gap: 16px; .cluster-status { diff --git a/src/components/ClusterNodes/types.ts b/src/components/ClusterNodes/types.ts index 6db632899a..dfc6bcf206 100644 --- a/src/components/ClusterNodes/types.ts +++ b/src/components/ClusterNodes/types.ts @@ -291,3 +291,15 @@ export interface ClusterOverviewProps { export interface ClusterMapInitialStatusType { errorInNodeListing: string } + +export interface ClusterBulkSelectionActionWidgetProps { + parentRef: React.RefObject + count: number + handleClearBulkSelection: () => void +} + +export interface ClusterListRowTypes { + clusterData: ClusterDetail + index: number + clusterListLoader: boolean +} diff --git a/src/components/ResourceBrowser/ResourceBrowser.tsx b/src/components/ResourceBrowser/ResourceBrowser.tsx index 67244a7f0c..89a5e0f0b1 100644 --- a/src/components/ResourceBrowser/ResourceBrowser.tsx +++ b/src/components/ResourceBrowser/ResourceBrowser.tsx @@ -26,12 +26,13 @@ import { } from '@devtron-labs/devtron-fe-common-lib' import { DEFAULT_CLUSTER_ID } from '@Components/cluster/cluster.type' import { sortObjectArrayAlphabetically } from '../common' -import ClusterSelectionList from '../ClusterNodes/ClusterSelectionList' import { getClusterList, getClusterListMin } from '../ClusterNodes/clusterNodes.service' import { AddClusterButton } from './PageHeader.buttons' +import BaseClusterList from '../ClusterNodes/ClusterSelectionList' const ResourceBrowser: React.FC = () => { const abortControllerRef = useRef(new AbortController()) + const parentRef = useRef(null) const [detailClusterListLoading, detailClusterList, , reloadDetailClusterList] = useAsync(async () => { try { @@ -68,11 +69,12 @@ const ResourceBrowser: React.FC = () => { } return ( - ) } diff --git a/src/components/ResourceBrowser/Types.ts b/src/components/ResourceBrowser/Types.ts index 9747a05282..3e674b9923 100644 --- a/src/components/ResourceBrowser/Types.ts +++ b/src/components/ResourceBrowser/Types.ts @@ -76,6 +76,7 @@ export interface ClusterSelectionType { clusterListLoader: boolean initialLoading: boolean refreshData: () => void + parentRef: React.RefObject } export interface CreateResourceType { diff --git a/src/css/base.scss b/src/css/base.scss index 4092c4ed18..5cf83d98ad 100644 --- a/src/css/base.scss +++ b/src/css/base.scss @@ -3506,6 +3506,10 @@ button.anchor { max-height: 64px; } +.mxh-100 { + max-height: 100px; +} + .mxh-140 { max-height: 140px; } From b460dd765607bb90fa45a91573fb0a363c7608b4 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Wed, 9 Apr 2025 18:07:52 +0530 Subject: [PATCH 11/78] chore: unreachable cluster ui --- .../KubeConfigButton/KubeConfigModal.tsx | 110 ++++++++++-------- .../ClusterNodes/KubeConfigButton/utils.ts | 10 +- 2 files changed, 69 insertions(+), 51 deletions(-) diff --git a/src/components/ClusterNodes/KubeConfigButton/KubeConfigModal.tsx b/src/components/ClusterNodes/KubeConfigButton/KubeConfigModal.tsx index b3f96b24ab..25e9be7066 100644 --- a/src/components/ClusterNodes/KubeConfigButton/KubeConfigModal.tsx +++ b/src/components/ClusterNodes/KubeConfigButton/KubeConfigModal.tsx @@ -23,11 +23,11 @@ import { } from '@devtron-labs/devtron-fe-common-lib' import { GroupBase } from 'react-select' import { KubeConfigTippyContentProps } from './types' -import { getKubeConfigCommand } from './utils' +import { getKubeConfigCommand, getKubeConfigCommandWithContext } from './utils' const DefaultSelectPickerOptionType = { label: 'Do not set context', - value: 'Do not set context', + value: '', } const getOptions = ( @@ -48,10 +48,14 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte const [toggleEnabled, setToggleEnabled] = useState(false) const { selectedIdentifiers: bulkSelectionClusterList } = useBulkSelection>() - const [selectedClusterName, setSelectedClusterName] = + const [selectedClusterContext, setSelectedClusterContext] = useState>(DefaultSelectPickerOptionType) const bulkSelectedClusterNames = Object.keys(bulkSelectionClusterList) + const reachableClustersList = Object.values(bulkSelectionClusterList).filter( + (clusterData) => clusterData.status !== ClusterStatusType.CONNECTION_FAILED, + ) + const reachableClusters = reachableClustersList.map((cluster) => cluster.name) const getDefaultConfig = () => { const command = () => @@ -61,14 +65,14 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte return (command() as string[]).join('\n') } - const [kubeconfigCommand, setKubeconfigCommand] = useState(getDefaultConfig) + const [kubeConfigCommand, setKubeConfigCommand] = useState(getDefaultConfig) const handleCopyButtonClick = () => { ReactGA.event({ category: 'Resource Browser', action: 'Get kubeconfig copy button clicked', }) - setCopyToClipboardPromise(copyToClipboard(kubeconfigCommand)) + setCopyToClipboardPromise(copyToClipboard(kubeConfigCommand)) } const renderHeader = () => ( @@ -86,27 +90,27 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte
) - const onChange = (selectedClusters) => { - setSelectedClusterName(selectedClusters) - setKubeconfigCommand(getKubeConfigCommand(selectedClusters.value)) + const handleContextChange = (context) => { + setSelectedClusterContext(context) + setKubeConfigCommand( + getKubeConfigCommandWithContext( + toggleEnabled ? reachableClusters : bulkSelectedClusterNames, + context.value, + ), + ) ReactGA.event({ category: 'Resource Browser', action: 'Get kubeconfig set context', - label: selectedClusters.value, + label: context.value, }) } - const reachableClustersList = Object.values(bulkSelectionClusterList).filter( - (clusterData) => clusterData.status !== ClusterStatusType.CONNECTION_FAILED, - ) - console.log(reachableClustersList) - const handleReachableClustersToggle = () => { setToggleEnabled(!toggleEnabled) if (toggleEnabled) { - setKubeconfigCommand(getDefaultConfig()) + setKubeConfigCommand(getDefaultConfig()) } else { - setKubeconfigCommand(reachableClustersList.map((cluster) => getKubeConfigCommand(cluster.name)).join('\n')) + setKubeConfigCommand(reachableClustersList.map((cluster) => getKubeConfigCommand(cluster.name)).join('\n')) } } @@ -138,47 +142,59 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte inputId="cluster-kube-config" options={getOptions(bulkSelectedClusterNames)} size={ComponentSizeType.medium} - onChange={onChange} - value={selectedClusterName} + onChange={handleContextChange} + value={selectedClusterContext} />
)}
) + const renderNoClusterReachable = () => ( +
+ +
+ None of the selected clusters are reachable. +
+
+ ) + const renderConfigCommand = () => (
{bulkSelectedClusterNames.length > 1 && renderSelectiveClusters()} - -
    1 ? 'border__secondary--top' : ''} pt-12 px-0`} - > -
  1. - - Prerequisites: -   - - kubectl - -  must be installed - -
  2. -
  3. -
    + {!reachableClustersList.length && toggleEnabled ? ( + renderNoClusterReachable() + ) : ( +
      1 ? 'border__secondary--top' : ''} pt-12 px-0`} + > +
    1. - Run below command on terminal to get server URI & bearer token + Prerequisites: +   + + kubectl + +  must be installed -
      -                            {kubeconfigCommand}
      -                        
      -
    -
  4. -
+ +
  • +
    + + Run below command on terminal to get server URI & bearer token + +
    +                                {kubeConfigCommand}
    +                            
    +
    +
  • + + )}
    ) @@ -197,7 +213,7 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte size={ComponentSizeType.medium} onClick={handleCopyButtonClick} startIcon={ - + } text="Copy command" /> diff --git a/src/components/ClusterNodes/KubeConfigButton/utils.ts b/src/components/ClusterNodes/KubeConfigButton/utils.ts index 4d265af834..0e721ec998 100644 --- a/src/components/ClusterNodes/KubeConfigButton/utils.ts +++ b/src/components/ClusterNodes/KubeConfigButton/utils.ts @@ -15,7 +15,9 @@ kubectl config set-credentials devtron-${clusterName} --token=${token} kubectl config set-context devtron-${clusterName} --cluster=devtron-${clusterName} --user=devtron-${clusterName}` } -export const getKubeConfigCommandWithContext = (clusterNames: string[], context?: string) => - clusterNames - .map((clusterName) => `${getKubeConfigCommand(clusterName)}`) - .join(getKubeConfigContextCommand(context || '')) +export const getKubeConfigCommandWithContext = (clusterNames: string[], context?: string) => { + const commands = clusterNames.map((clusterName) => `${getKubeConfigCommand(clusterName)}`) + const contextCommand = context ? getKubeConfigContextCommand(context) : null + + return [...commands, contextCommand].join('\n') +} From 540a1f964a30adb8dd3f93699b87b1a7628c20a6 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Thu, 10 Apr 2025 13:12:21 +0530 Subject: [PATCH 12/78] chore: GA event added for kube config modal --- .../ClusterBulkSelectionActionWidget.tsx | 9 +- .../ClusterNodes/ClusterListRow.tsx | 43 +++++---- .../ClusterNodes/ClusterSelectionList.tsx | 13 +-- .../KubeConfigButton.component.tsx | 16 ++-- .../KubeConfigButton/KubeConfigModal.tsx | 93 +++++++++---------- .../KubeConfigButton/constants.ts | 35 +++++++ .../ClusterNodes/KubeConfigButton/utils.ts | 23 ----- .../ClusterNodes/KubeConfigButton/utils.tsx | 43 +++++++++ 8 files changed, 167 insertions(+), 108 deletions(-) create mode 100644 src/components/ClusterNodes/KubeConfigButton/constants.ts delete mode 100644 src/components/ClusterNodes/KubeConfigButton/utils.ts create mode 100644 src/components/ClusterNodes/KubeConfigButton/utils.tsx diff --git a/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx b/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx index d565971279..840628d713 100644 --- a/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx +++ b/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx @@ -1,16 +1,17 @@ import { - DraggableWrapper, - DraggablePositionVariant, - DraggableButton, Button, ButtonComponentType, ButtonStyleType, ButtonVariantType, ComponentSizeType, + DraggableButton, + DraggablePositionVariant, + DraggableWrapper, Icon, } from '@devtron-labs/devtron-fe-common-lib' -import { ClusterBulkSelectionActionWidgetProps } from './types' + import { KubeConfigButton } from './KubeConfigButton' +import { ClusterBulkSelectionActionWidgetProps } from './types' // const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') diff --git a/src/components/ClusterNodes/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterListRow.tsx index 2f9e1986e1..a2df56b357 100644 --- a/src/components/ClusterNodes/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterListRow.tsx @@ -1,26 +1,33 @@ -import { SIDEBAR_KEYS, K8S_EMPTY_GROUP } from '@Components/ResourceBrowser/Constants' +import { Link } from 'react-router-dom' + import { ALL_NAMESPACE_OPTION, BulkSelectionEvents, BulkSelectionIdentifiersType, + Button, + ButtonComponentType, + ButtonStyleType, + ButtonVariantType, Checkbox, CHECKBOX_VALUE, ClusterDetail, ClusterStatusType, + ComponentSizeType, Icon, Tooltip, URLS, useBulkSelection, } from '@devtron-labs/devtron-fe-common-lib' -import { Link, useHistory, useLocation } from 'react-router-dom' + import { ReactComponent as Error } from '@Icons/ic-error-exclamation.svg' -import { ReactComponent as TerminalIcon } from '@Icons/ic-terminal-fill.svg' import { importComponentFromFELibrary } from '@Components/common' +import { K8S_EMPTY_GROUP, SIDEBAR_KEYS } from '@Components/ResourceBrowser/Constants' import { AppDetailsTabs } from '@Components/v2/appDetails/appDetails.store' -import { CLUSTER_PROD_TYPE } from './constants' + import { ClusterMapInitialStatus } from './ClusterMapInitialStatus' -import { ClusterListRowTypes } from './types' +import { CLUSTER_PROD_TYPE } from './constants' import { KubeConfigButton } from './KubeConfigButton' +import { ClusterListRowTypes } from './types' export const ClusterListRow = ({ clusterData, index, clusterListLoader }: ClusterListRowTypes) => { // const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') @@ -33,8 +40,6 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste handleBulkSelection, } = useBulkSelection>() const errorCount = clusterData.nodeErrors ? Object.keys(clusterData.nodeErrors).length : 0 - const history = useHistory() - const location = useLocation() const handleSelection = () => { const { name } = clusterData @@ -65,8 +70,7 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste } } - const getOpenTerminalHandler = () => () => - history.push(`${location.pathname}/${clusterData.id}/all/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}`) + const terminalURL = `${URLS.RESOURCE_BROWSER}/${clusterData.id}/all}/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}` const hideDataOnLoad = (value) => { if (clusterListLoader) { @@ -114,15 +118,18 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste
    {!!clusterData.nodeCount && !clusterListLoader && ( - -
    - -
    -
    +
    ) - const handleClearBulkSelection = () => { - handleBulkSelection({ - action: BulkSelectionEvents.CLEAR_ALL_SELECTIONS, - }) - } - const renderClusterBulkSelection = () => { if (getSelectedIdentifiersCount() > 0 || isBulkSelectionApplied) { return ( diff --git a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx index d5ca862c78..6cfb89c9ab 100644 --- a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx +++ b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx @@ -4,6 +4,7 @@ import { useState } from 'react' import ReactGA from 'react-ga4' + import { Button, ButtonStyleType, @@ -11,18 +12,21 @@ import { ComponentSizeType, Icon, } from '@devtron-labs/devtron-fe-common-lib' -import { KubeConfigButtonProps } from './types' + +import { RB_KUBE_CONFIG_GA_EVENTS } from './constants' import KubeConfigModal from './KubeConfigModal' +import { KubeConfigButtonProps } from './types' const KubeConfigButton = ({ clusterName, isPrimaryButton = false }: KubeConfigButtonProps) => { const [openModal, setOpenModal] = useState(false) const handleOpenKubeConfigModal = () => { setOpenModal(true) - ReactGA.event({ - category: 'Resource Browser', - action: 'Get kubeconfig button clicked', - }) + ReactGA.event( + isPrimaryButton + ? RB_KUBE_CONFIG_GA_EVENTS.BulkSelectionWidgetClicked + : RB_KUBE_CONFIG_GA_EVENTS.IndividualKubeConfig, + ) } const handleModalClose = () => { @@ -40,7 +44,7 @@ const KubeConfigButton = ({ clusterName, isPrimaryButton = false }: KubeConfigBu /> ) : (
    ) - const handleContextChange = (context) => { - setSelectedClusterContext(context) + const onChangeContextSelect = (selectedContext: SelectPickerOptionType) => { + setSelectedClusterContext(selectedContext) setKubeConfigCommand( getKubeConfigCommandWithContext( toggleEnabled ? reachableClusters : bulkSelectedClusterNames, - context.value, - ), + selectedContext.value, + ) as string, + ) + ReactGA.event( + selectedContext.value === DefaultSelectPickerOptionType.value + ? RB_KUBE_CONFIG_GA_EVENTS.DoNotSetContextSelect + : RB_KUBE_CONFIG_GA_EVENTS.SetContextSelect, ) - ReactGA.event({ - category: 'Resource Browser', - action: 'Get kubeconfig set context', - label: context.value, - }) } const handleReachableClustersToggle = () => { setToggleEnabled(!toggleEnabled) if (toggleEnabled) { - setKubeConfigCommand(getDefaultConfig()) + setKubeConfigCommand(getDefaultConfig(selectedClusterContext.value)) + ReactGA.event(RB_KUBE_CONFIG_GA_EVENTS.ReachableClusterToggleDisabled) } else { - setKubeConfigCommand(reachableClustersList.map((cluster) => getKubeConfigCommand(cluster.name)).join('\n')) + setKubeConfigCommand( + reachableClustersList + .map((cluster) => getKubeConfigCommand(cluster.name, selectedClusterContext.value)) + .join('\n'), + ) + ReactGA.event(RB_KUBE_CONFIG_GA_EVENTS.ReachableClusterToggleEnabled) } } @@ -134,15 +120,15 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte
    - {reachableClustersList.length > 0 && ( + {reachableClustersList.length > 1 && (
    Set cluster context
    @@ -151,7 +137,7 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte ) const renderNoClusterReachable = () => ( -
    +
    None of the selected clusters are reachable. @@ -166,7 +152,7 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte renderNoClusterReachable() ) : (
      1 ? 'border__secondary--top' : ''} pt-12 px-0`} + className={`steps-with-trail--normal ${bulkSelectedClusterNames.length > 1 ? 'border__secondary--top pt-12' : ''} px-0`} >
    1. @@ -200,14 +186,19 @@ const KubeConfigModal = ({ clusterName, handleModalClose }: KubeConfigTippyConte const renderActionButtons = () => (
      - - View documentation - +
      - {reachableClustersList.length > 1 && ( + {reachableClustersList.length > 0 && (
      Set cluster context From 59edc9d878ca98cca1cc20e25ba2a2c327c50345 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Thu, 10 Apr 2025 15:29:13 +0530 Subject: [PATCH 15/78] chore: kubeconfig modal update --- .../KubeConfigButton/KubeConfigButton.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx index 6cfb89c9ab..ee71df9c67 100644 --- a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx +++ b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx @@ -49,7 +49,7 @@ const KubeConfigButton = ({ clusterName, isPrimaryButton = false }: KubeConfigBu dataTestId="rb-cluster-bulk-selection-kube-config" variant={ButtonVariantType.borderLess} ariaLabel="Get kubeconfig" - size={ComponentSizeType.small} + size={ComponentSizeType.xs} style={ButtonStyleType.neutral} /> )} From dc706e34f7887d566e5cda287b550de73b4d494e Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Thu, 10 Apr 2025 16:17:01 +0530 Subject: [PATCH 16/78] fix: retry failed apps --- .../ApplicationGroup/AppGroup.types.ts | 17 +++++-- src/components/ApplicationGroup/Constants.ts | 6 ++- .../Details/TriggerView/BulkCDTrigger.tsx | 20 ++++---- .../Details/TriggerView/EnvTriggerView.tsx | 11 +++-- .../TriggerView/TriggerResponseModal.tsx | 9 +++- .../common/navigation/NavigationRoutes.tsx | 49 +++++++------------ src/components/common/navigation/constants.ts | 24 ++++++++- 7 files changed, 83 insertions(+), 53 deletions(-) diff --git a/src/components/ApplicationGroup/AppGroup.types.ts b/src/components/ApplicationGroup/AppGroup.types.ts index 355e1831ef..d18510e936 100644 --- a/src/components/ApplicationGroup/AppGroup.types.ts +++ b/src/components/ApplicationGroup/AppGroup.types.ts @@ -185,10 +185,21 @@ export interface TriggerResponseModalBodyProps { envName?: string } -export interface TriggerResponseModalFooterProps extends Pick { - onClickRetryBuild: (appsToRetry: Record) => void +type RetryFailedType = + | { + onClickRetryDeploy: BulkCDTriggerType['onClickTriggerBulkCD'] + skipHibernatedApps: boolean + onClickRetryBuild?: never + } + | { + onClickRetryDeploy?: never + skipHibernatedApps?: never + onClickRetryBuild: (appsToRetry: Record) => void + } + +export type TriggerResponseModalFooterProps = Pick & { closePopup: (e) => void -} +} & RetryFailedType export interface TriggerModalRowType { rowData: ResponseRowType diff --git a/src/components/ApplicationGroup/Constants.ts b/src/components/ApplicationGroup/Constants.ts index fd3e96ce62..3ccbbedfd9 100644 --- a/src/components/ApplicationGroup/Constants.ts +++ b/src/components/ApplicationGroup/Constants.ts @@ -69,24 +69,28 @@ export const BULK_VIRTUAL_RESPONSE_STATUS = { [BulkResponseStatus.PASS]: 'Succeeded', [BulkResponseStatus.FAIL]: 'Failed', [BulkResponseStatus.UNAUTHORIZE]: 'Not authorised', + [BulkResponseStatus.SKIP]: 'Skipped', } export const BULK_CI_RESPONSE_STATUS_TEXT = { [BulkResponseStatus.PASS]: 'Build triggered', [BulkResponseStatus.FAIL]: 'Build not triggered', [BulkResponseStatus.UNAUTHORIZE]: 'Not authorized', + [BulkResponseStatus.SKIP]: 'Skipped', } export const BULK_CD_RESPONSE_STATUS_TEXT = { [BulkResponseStatus.PASS]: 'Deployment triggered', [BulkResponseStatus.FAIL]: 'Deployment not triggered', [BulkResponseStatus.UNAUTHORIZE]: 'Not authorized', + [BulkResponseStatus.SKIP]: 'Skipped', } export const responseListOrder = { [BulkResponseStatus.FAIL]: 0, [BulkResponseStatus.UNAUTHORIZE]: 1, - [BulkResponseStatus.PASS]: 2, + [BulkResponseStatus.SKIP]: 2, + [BulkResponseStatus.PASS]: 3, } export const BULK_HIBERNATE_ERROR_MESSAGE = { diff --git a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx index abe954d804..2fbd12a47f 100644 --- a/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx +++ b/src/components/ApplicationGroup/Details/TriggerView/BulkCDTrigger.tsx @@ -112,7 +112,7 @@ export default function BulkCDTrigger({ runtimeParamsErrorState, setRuntimeParamsErrorState, }: BulkCDTriggerType) { - const { deployUnhibernatedAppOnly } = useMainContext() + const { fetchHelmAppStatus } = useMainContext() const [selectedApp, setSelectedApp] = useState( appList.find((app) => !app.warningMessage) || appList[0], ) @@ -129,7 +129,7 @@ export default function BulkCDTrigger({ const [isPartialActionAllowed, setIsPartialActionAllowed] = useState(false) const [showResistanceBox, setShowResistanceBox] = useState(false) const [currentSidebarTab, setCurrentSidebarTab] = useState(CDMaterialSidebarType.IMAGE) - const [skipHibernated, setSkipHibernated] = useState(false) + const [skipHibernatedApps, setSkipHibernatedApps] = useState(false) const location = useLocation() const history = useHistory() @@ -356,7 +356,7 @@ export default function BulkCDTrigger({ const renderHeaderSection = (): JSX.Element => { return (
      -

      Deploy to {appList[0].envName}

      +

      Deploy to {appList[0].envName}

    diff --git a/src/components/ClusterNodes/ClusterSelectionList.tsx b/src/components/ClusterNodes/ClusterSelectionList.tsx index 9669d85384..db5ffed0bb 100644 --- a/src/components/ClusterNodes/ClusterSelectionList.tsx +++ b/src/components/ClusterNodes/ClusterSelectionList.tsx @@ -38,7 +38,6 @@ import Timer from '@Components/common/DynamicTabs/DynamicTabs.timer' import { AddClusterButton } from '@Components/ResourceBrowser/PageHeader.buttons' import { ClusterSelectionType } from '../ResourceBrowser/Types' -import { ClusterBulkSelectionActionWidget } from './ClusterBulkSelectionActionWidget' import { ClusterListRow } from './ClusterListRow' import ClusterNodeEmptyState from './ClusterNodeEmptyStates' import { ClusterMapListSortableKeys, ClusterMapListSortableTitle, ClusterStatusByFilter } from './constants' @@ -48,6 +47,11 @@ import './clusterNodes.scss' const ClusterMap = importComponentFromFELibrary('ClusterMap', null, 'function') const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') +const ClusterBulkSelectionActionWidget = importComponentFromFELibrary( + 'ClusterBulkSelectionActionWidget', + null, + 'function', +) const parseSearchParams = (searchParams: URLSearchParams) => ({ clusterFilter: (searchParams.get('clusterFilter') as ClusterFiltersType) || ClusterFiltersType.ALL_CLUSTERS, diff --git a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx b/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx deleted file mode 100644 index ee71df9c67..0000000000 --- a/src/components/ClusterNodes/KubeConfigButton/KubeConfigButton.component.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024. Devtron Inc. - */ - -import { useState } from 'react' -import ReactGA from 'react-ga4' - -import { - Button, - ButtonStyleType, - ButtonVariantType, - ComponentSizeType, - Icon, -} from '@devtron-labs/devtron-fe-common-lib' - -import { RB_KUBE_CONFIG_GA_EVENTS } from './constants' -import KubeConfigModal from './KubeConfigModal' -import { KubeConfigButtonProps } from './types' - -const KubeConfigButton = ({ clusterName, isPrimaryButton = false }: KubeConfigButtonProps) => { - const [openModal, setOpenModal] = useState(false) - - const handleOpenKubeConfigModal = () => { - setOpenModal(true) - ReactGA.event( - isPrimaryButton - ? RB_KUBE_CONFIG_GA_EVENTS.BulkSelectionWidgetClicked - : RB_KUBE_CONFIG_GA_EVENTS.IndividualKubeConfig, - ) - } - - const handleModalClose = () => { - setOpenModal(false) - } - - return ( - <> - {isPrimaryButton ? ( -
    - ) - - const onChangeContextSelect = (selectedContext: SelectPickerOptionType) => { - setSelectedClusterContext(selectedContext) - setKubeConfigCommand( - getKubeConfigCommandWithContext( - toggleEnabled ? reachableClusters : bulkSelectedClusterNames, - selectedContext.value, - ) as string, - ) - ReactGA.event( - selectedContext.value === DefaultSelectPickerOptionType.value - ? RB_KUBE_CONFIG_GA_EVENTS.DoNotSetContextSelect - : RB_KUBE_CONFIG_GA_EVENTS.SetContextSelect, - ) - } - - const handleReachableClustersToggle = () => { - setToggleEnabled(!toggleEnabled) - if (toggleEnabled) { - setKubeConfigCommand(getDefaultConfig(selectedClusterContext.value)) - ReactGA.event(RB_KUBE_CONFIG_GA_EVENTS.ReachableClusterToggleDisabled) - } else { - setSelectedClusterContext( - reachableClusters.includes(selectedClusterContext.value) - ? selectedClusterContext - : DefaultSelectPickerOptionType, - ) - setKubeConfigCommand(getKubeConfigCommandWithContext(reachableClusters) as string) - ReactGA.event(RB_KUBE_CONFIG_GA_EVENTS.ReachableClusterToggleEnabled) - } - } - - const renderSelectiveClusters = () => ( -
    -
    -

    -

    Get access for reachable clusters only
    -
    - {`${reachableClusters.length}/${bulkSelectedClusterNames.length}`} selected clusters are - reachable -
    -

    -
    - -
    -
    - - {(reachableClusters.length > 1 || !toggleEnabled) && ( -
    - Set cluster context - - -
    - )} -
    - ) - - const renderNoClusterReachable = () => ( -
    - -
    - None of the selected clusters are reachable. -
    -
    - ) - - const renderConfigCommand = () => ( -
    - {bulkSelectedClusterNames.length > 1 && renderSelectiveClusters()} - {!reachableClusters.length && toggleEnabled ? ( - renderNoClusterReachable() - ) : ( -
      1 ? 'border__secondary--top pt-12' : ''} px-0`} - > -
    1. - - Prerequisites: -   - - kubectl - -  must be installed - -
    2. -
    3. -
      - - Run below command on terminal to get server URI & bearer token - -
      -                                {kubeConfigCommand}
      -                            
      -
      -
    4. -
    - )} -
    - ) - - const renderActionButtons = () => ( -
    -
    - ) - - return ( - -
    - {renderHeader()} - {renderConfigCommand()} - {renderActionButtons()} -
    -
    - ) -} - -export default KubeConfigModal diff --git a/src/components/ClusterNodes/KubeConfigButton/constants.ts b/src/components/ClusterNodes/KubeConfigButton/constants.ts deleted file mode 100644 index afea5abb79..0000000000 --- a/src/components/ClusterNodes/KubeConfigButton/constants.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const RB_KUBE_CONFIG_GA_EVENTS = { - BulkSelectionWidgetClicked: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_BULK_CLICKED', - }, - IndividualKubeConfig: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_INDIVIDUAL_CLICKED', - }, - CopyButton: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_COPYCOMMAND_CLICKED', - }, - ReachableClusterToggleEnabled: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_BULK_REACHABLE_CLUSTERS_ENABLED', - }, - ReachableClusterToggleDisabled: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_BULK_REACHABLE_CLUSTERS_DISABLED', - }, - DoNotSetContextSelect: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_BULK_SETCONTEXT_OPTION_DONOTSET_CHANGED', - }, - SetContextSelect: { - category: 'Resource Browser', - action: 'RESOURCE_BROWSER_GET_KUBECONFIG_BULK_SETCONTEXT_OPTION_SELECTED_CLUSTER_CHANGED', - }, -} - -export const DefaultSelectPickerOptionType = { - label: 'Do not set context', - value: '', -} diff --git a/src/components/ClusterNodes/KubeConfigButton/index.ts b/src/components/ClusterNodes/KubeConfigButton/index.ts deleted file mode 100644 index cfcc93819f..0000000000 --- a/src/components/ClusterNodes/KubeConfigButton/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2024. Devtron Inc. - */ - -export { default as KubeConfigButton } from './KubeConfigButton.component' diff --git a/src/components/ClusterNodes/KubeConfigButton/types.ts b/src/components/ClusterNodes/KubeConfigButton/types.ts deleted file mode 100644 index 47339de98f..0000000000 --- a/src/components/ClusterNodes/KubeConfigButton/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2024. Devtron Inc. - */ - -export interface KubeConfigButtonProps { - isPrimaryButton?: boolean - clusterName?: string -} - -export interface KubeConfigTippyContentProps extends Pick { - handleModalClose: () => void -} diff --git a/src/components/ClusterNodes/KubeConfigButton/utils.tsx b/src/components/ClusterNodes/KubeConfigButton/utils.tsx deleted file mode 100644 index 5ba33e3eed..0000000000 --- a/src/components/ClusterNodes/KubeConfigButton/utils.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2024. Devtron Inc. - */ - -import { GroupBase } from 'react-select' - -import { getCookie, SelectPickerOptionType, TOKEN_COOKIE_NAME } from '@devtron-labs/devtron-fe-common-lib' - -import { DefaultSelectPickerOptionType } from './constants' - -export const getKubeConfigUseContextCommand = (clusterName: string) => - `kubectl config use-context devtron-${clusterName}` - -export const getKubeConfigCommand = (clusterName: string, context: string) => { - const token = getCookie(TOKEN_COOKIE_NAME) - - // NOTE: please don't modify spacing in the following template string - return `kubectl config set-cluster devtron-${clusterName} --server=https://${window.location.host}/orchestrator/k8s/proxy/cluster/${clusterName} --insecure-skip-tls-verify -kubectl config set-credentials devtron-${clusterName} --token=${token} -kubectl config set-context devtron-${clusterName} --cluster=devtron-${clusterName} --user=devtron-${clusterName} -${context ? getKubeConfigUseContextCommand(context) : ''}` -} - -export const getKubeConfigCommandWithContext = (clusterNames: string[] | string, context?: string) => { - // for single selection of cluster, use context will save always by default as clusterName - const normalizedClusters = Array.isArray(clusterNames) ? clusterNames : [clusterNames] - return clusterNames.length === 1 - ? getKubeConfigCommand(normalizedClusters[0], context || normalizedClusters[0]) - : normalizedClusters.map((clusterName) => `${getKubeConfigCommand(clusterName, context)}`) -} - -export const getOptions = ( - clusterNames: string[], -): Array> | SelectPickerOptionType> => [ - DefaultSelectPickerOptionType, - { - label: 'Set Context of', - options: clusterNames?.map((_cluster) => ({ - label: _cluster, - value: _cluster, - })), - }, -] From f550273366182af23f45073fef6d8b4cd37c4320 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Thu, 10 Apr 2025 23:01:27 +0530 Subject: [PATCH 30/78] chore: unnecesssary component removed --- .../ClusterBulkSelectionActionWidget.tsx | 55 ------------------- src/components/ClusterNodes/types.ts | 6 -- 2 files changed, 61 deletions(-) delete mode 100644 src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx diff --git a/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx b/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx deleted file mode 100644 index 36b0d95f5a..0000000000 --- a/src/components/ClusterNodes/ClusterBulkSelectionActionWidget.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { - Button, - ButtonComponentType, - ButtonStyleType, - ButtonVariantType, - ComponentSizeType, - DraggableButton, - DraggablePositionVariant, - DraggableWrapper, - Icon, -} from '@devtron-labs/devtron-fe-common-lib' - -import { importComponentFromFELibrary } from '@Components/common' - -import { ClusterBulkSelectionActionWidgetProps } from './types' - -const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') - -export const ClusterBulkSelectionActionWidget = ({ - parentRef, - count, - handleClearBulkSelection, -}: ClusterBulkSelectionActionWidgetProps) => ( - -
    -
    - - -
    - {count} - Selected -
    -
    - - {KubeConfigButton && } - -
    -
    -) diff --git a/src/components/ClusterNodes/types.ts b/src/components/ClusterNodes/types.ts index 58cfa62cde..1dbe48adbf 100644 --- a/src/components/ClusterNodes/types.ts +++ b/src/components/ClusterNodes/types.ts @@ -294,12 +294,6 @@ export interface ClusterMapInitialStatusType { errorInNodeListing: string } -export interface ClusterBulkSelectionActionWidgetProps { - parentRef: React.RefObject - count: number - handleClearBulkSelection: () => void -} - export interface ClusterListRowTypes { clusterData: ClusterDetail index: number From d172b52a48f558a2c037c27df6958e7ec2f901b1 Mon Sep 17 00:00:00 2001 From: AbhishekA1509 Date: Sun, 13 Apr 2025 23:34:49 +0530 Subject: [PATCH 31/78] chore: add h-18--imp --- src/css/base.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/css/base.scss b/src/css/base.scss index 4092c4ed18..3ffc77f594 100644 --- a/src/css/base.scss +++ b/src/css/base.scss @@ -3254,6 +3254,10 @@ button.anchor { .h-18 { height: 18px; + + &--imp { + height: 18px !important; + } } .h-20 { From 2216f10a8e49865dccf0a28766f4af9dbada8e10 Mon Sep 17 00:00:00 2001 From: AbhishekA1509 Date: Sun, 13 Apr 2025 23:40:55 +0530 Subject: [PATCH 32/78] chore: move getTimeDifference params to obj --- src/components/common/helpers/time.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/helpers/time.ts b/src/components/common/helpers/time.ts index 45cfe1e64e..cc02f1866d 100644 --- a/src/components/common/helpers/time.ts +++ b/src/components/common/helpers/time.ts @@ -39,5 +39,5 @@ export function handleUTCTime(ts: string, isRelativeTime = false) { } export const getTimeElapsed = (start: Dayjs, now: Dayjs) => { - return getTimeDifference(start?.toISOString(), now?.toISOString()) + return getTimeDifference({ startTime: start?.toISOString(), endTime: now?.toISOString()}) } From 688c2cefdbee3b8644f92c5695c39dba600ea25a Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 02:19:29 +0530 Subject: [PATCH 33/78] chore: code refactoring --- src/components/ClusterNodes/ClusterList.tsx | 65 +++++++++++ .../ClusterNodes/ClusterListRow.tsx | 42 ++++---- .../ClusterNodes/ClusterOverview.tsx | 3 +- .../ClusterNodes/ClusterSelectionList.tsx | 101 +++++++----------- src/components/ClusterNodes/types.ts | 11 +- src/components/ClusterNodes/utils.tsx | 5 + 6 files changed, 140 insertions(+), 87 deletions(-) create mode 100644 src/components/ClusterNodes/ClusterList.tsx diff --git a/src/components/ClusterNodes/ClusterList.tsx b/src/components/ClusterNodes/ClusterList.tsx new file mode 100644 index 0000000000..ae2beb9dcf --- /dev/null +++ b/src/components/ClusterNodes/ClusterList.tsx @@ -0,0 +1,65 @@ +import React from 'react' + +import { + BulkSelection, + ClusterFiltersType, + SortableTableHeaderCell, + useUrlFilters, +} from '@devtron-labs/devtron-fe-common-lib' + +import { ClusterListRow } from './ClusterListRow' +import { ClusterMapListSortableKeys, ClusterMapListSortableTitle } from './constants' +import { ClusterListTypes } from './types' +import { parseSearchParams } from './utils' + +export const ClusterList = ({ + filteredList, + clusterListLoader, + showKubeConfigModal, + onChangeShowKubeConfigModal, + setSelectedClusterName, +}: ClusterListTypes) => { + const { sortBy, sortOrder, handleSorting } = useUrlFilters< + ClusterMapListSortableKeys, + { clusterFilter: ClusterFiltersType } + >({ + parseSearchParams, + initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, + }) + + const handleCellSorting = (cellToSort: ClusterMapListSortableKeys) => () => { + handleSorting(cellToSort) + } + + return ( +
    +
    + {Object.entries(ClusterMapListSortableKeys).map(([cellName, cellKey]) => ( + + {cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( + + )} + + + ))} +
    + {filteredList.map((clusterData) => ( + + ))} +
    + ) +} diff --git a/src/components/ClusterNodes/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterListRow.tsx index 2b0fa325f4..de6b1a9abd 100644 --- a/src/components/ClusterNodes/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterListRow.tsx @@ -28,15 +28,18 @@ import { ClusterMapInitialStatus } from './ClusterMapInitialStatus' import { CLUSTER_PROD_TYPE } from './constants' import { ClusterListRowTypes } from './types' +const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') +const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') -export const ClusterListRow = ({ clusterData, index, clusterListLoader }: ClusterListRowTypes) => { - const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') - const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') - +export const ClusterListRow = ({ + clusterData, + clusterListLoader, + onChangeShowKubeConfigModal, + setSelectedClusterName, +}: ClusterListRowTypes) => { const { selectedIdentifiers: bulkSelectionState, - isBulkSelectionApplied, handleBulkSelection, getSelectedIdentifiersCount, } = useBulkSelection>() @@ -44,14 +47,7 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste const handleSelection = () => { const { name } = clusterData - if (isBulkSelectionApplied) { - handleBulkSelection({ - action: BulkSelectionEvents.CLEAR_IDENTIFIERS_AFTER_ACROSS_SELECTION, - data: { - identifierIds: [name], - }, - }) - } else if (bulkSelectionState[name]) { + if (bulkSelectionState[name]) { handleBulkSelection({ action: BulkSelectionEvents.CLEAR_IDENTIFIERS, data: { @@ -69,10 +65,9 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste }, }) } + setSelectedClusterName('') } - const terminalURL = `${URLS.RESOURCE_BROWSER}/${clusterData.id}/all}/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}` - const hideDataOnLoad = (value) => { if (clusterListLoader) { return null @@ -87,7 +82,7 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste return } - const isIdentifierSelected = !!bulkSelectionState[clusterData.name] || isBulkSelectionApplied + const isIdentifierSelected = !!bulkSelectionState[clusterData.name] return (
    0 ? 'dc__visible' - : 'dc__visible-hover--child flexbox' + : 'dc__visible-hover--child flex left' } >
    {!isIdentifierSelected && getSelectedIdentifiersCount() === 0 && (
    - +
    )}
    @@ -137,14 +131,20 @@ export const ClusterListRow = ({ clusterData, index, clusterListLoader }: Cluste variant={ButtonVariantType.borderLess} component={ButtonComponentType.link} linkProps={{ - to: terminalURL, + to: `${URLS.RESOURCE_BROWSER}/${clusterData.id}/${ALL_NAMESPACE_OPTION.value}/${AppDetailsTabs.terminal}/${K8S_EMPTY_GROUP}`, }} /> )} {CompareClusterButton && clusterData.status !== ClusterStatusType.CONNECTION_FAILED && ( )} - {KubeConfigButton && } + {KubeConfigButton && ( + + )}
    diff --git a/src/components/ClusterNodes/ClusterOverview.tsx b/src/components/ClusterNodes/ClusterOverview.tsx index ab519cc205..ec1d3f1d7c 100644 --- a/src/components/ClusterNodes/ClusterOverview.tsx +++ b/src/components/ClusterNodes/ClusterOverview.tsx @@ -26,6 +26,7 @@ import { getUrlWithSearchParams, showError, ClusterCapacityType, + Icon, } from '@devtron-labs/devtron-fe-common-lib' import { ClusterErrorType, @@ -412,7 +413,7 @@ function ClusterOverview({ selectedCluster, addTab }: ClusterOverviewProps) {
    ) } + +export default ClusterList diff --git a/src/components/ClusterNodes/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx similarity index 97% rename from src/components/ClusterNodes/ClusterListRow.tsx rename to src/components/ClusterNodes/ClusterList/ClusterListRow.tsx index 83f854f8c2..9af839e361 100644 --- a/src/components/ClusterNodes/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx @@ -24,15 +24,15 @@ import { importComponentFromFELibrary } from '@Components/common' import { K8S_EMPTY_GROUP, SIDEBAR_KEYS } from '@Components/ResourceBrowser/Constants' import { AppDetailsTabs } from '@Components/v2/appDetails/appDetails.store' -import { ClusterMapInitialStatus } from './ClusterMapInitialStatus' -import { CLUSTER_PROD_TYPE } from './constants' +import { ClusterMapInitialStatus } from '../ClusterMapInitialStatus' +import { CLUSTER_PROD_TYPE } from '../constants' import { ClusterListRowTypes } from './types' const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') -export const ClusterListRow = ({ +const ClusterListRow = ({ clusterData, clusterListLoader, onChangeShowKubeConfigModal, @@ -175,3 +175,5 @@ export const ClusterListRow = ({
    ) } + +export default ClusterListRow diff --git a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx new file mode 100644 index 0000000000..2e23cf65f1 --- /dev/null +++ b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx @@ -0,0 +1,91 @@ +import { useMemo } from 'react' + +import { + BulkSelectionIdentifiersType, + BulkSelectionProvider, + ClusterDetail, + ClusterFiltersType, + SearchBar, + SelectAllDialogStatus, + useUrlFilters, +} from '@devtron-labs/devtron-fe-common-lib' + +import { importComponentFromFELibrary } from '@Components/common' + +import { ClusterMapListSortableKeys, ClusterStatusByFilter } from '../constants' +import { getSortedClusterList, parseSearchParams } from '../utils' +import ClusterSelectionBody from './ClusterSelectionBody' +import { ClusterViewType } from './types' + +const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') + +const ClusterListView = (props: ClusterViewType) => { + const { searchKey, clusterFilter, updateSearchParams, handleSearch, sortBy, sortOrder } = useUrlFilters< + ClusterMapListSortableKeys, + { clusterFilter: ClusterFiltersType } + >({ + parseSearchParams, + initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, + }) + const { clusterOptions, initialLoading } = props + + const setClusterFilter = (_clusterFilter: ClusterFiltersType) => { + updateSearchParams({ clusterFilter: _clusterFilter }) + } + + const filteredList: ClusterDetail[] = useMemo(() => { + const loweredSearchKey = searchKey.toLowerCase() + const updatedClusterOptions = [...clusterOptions] + // Sort the cluster list based on the selected sorting key + getSortedClusterList(updatedClusterOptions, sortBy, sortOrder) + + // Filter the cluster list based on the search key and cluster filter + return updatedClusterOptions.filter((option) => { + const filterCondition = + clusterFilter === ClusterFiltersType.ALL_CLUSTERS || + !option.status || + option.status === ClusterStatusByFilter[clusterFilter] + + return (!searchKey || option.name.toLowerCase().includes(loweredSearchKey)) && filterCondition + }) + }, [searchKey, clusterOptions, `${clusterFilter}`, sortBy, sortOrder]) + + const handleFilterKeyPress = (value: string) => { + handleSearch(value) + } + + const allOnThisPageIdentifiers = useMemo( + () => + filteredList?.reduce((acc, cluster) => { + acc[cluster.name] = cluster + return acc + }, {} as ClusterDetail) ?? {}, + [clusterOptions], + ) + + const getSelectAllDialogStatus = () => SelectAllDialogStatus.CLOSED + + return ( + > + identifiers={allOnThisPageIdentifiers} + getSelectAllDialogStatus={getSelectAllDialogStatus} + > +
    + + {ClusterFilters && } +
    + + + ) +} + +export default ClusterListView diff --git a/src/components/ClusterNodes/ClusterSelectionList.tsx b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx similarity index 62% rename from src/components/ClusterNodes/ClusterSelectionList.tsx rename to src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx index 9d17dbb5a4..2e7526adeb 100644 --- a/src/components/ClusterNodes/ClusterSelectionList.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx @@ -14,18 +14,15 @@ * limitations under the License. */ -import React, { useMemo, useRef, useState } from 'react' +import React, { useRef, useState } from 'react' import dayjs, { Dayjs } from 'dayjs' import { BulkSelectionEvents, BulkSelectionIdentifiersType, - BulkSelectionProvider, ClusterDetail, ClusterFiltersType, GenericEmptyState, - SearchBar, - SelectAllDialogStatus, useBulkSelection, useUrlFilters, } from '@devtron-labs/devtron-fe-common-lib' @@ -35,16 +32,15 @@ import { importComponentFromFELibrary } from '@Components/common' import Timer from '@Components/common/DynamicTabs/DynamicTabs.timer' import { AddClusterButton } from '@Components/ResourceBrowser/PageHeader.buttons' -import { ClusterSelectionType } from '../ResourceBrowser/Types' -import { ClusterList } from './ClusterList' -import ClusterNodeEmptyState from './ClusterNodeEmptyStates' -import { ClusterMapListSortableKeys, ClusterStatusByFilter } from './constants' -import { getSortedClusterList, parseSearchParams } from './utils' +import ClusterNodeEmptyState from '../ClusterNodeEmptyStates' +import { ClusterMapListSortableKeys } from '../constants' +import { parseSearchParams } from '../utils' +import ClusterList from './ClusterList' +import { ClusterSelectionBodyTypes } from './types' -import './clusterNodes.scss' +import '../clusterNodes.scss' const ClusterMap = importComponentFromFELibrary('ClusterMap', null, 'function') -const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') const ClusterBulkSelectionActionWidget = importComponentFromFELibrary( 'ClusterBulkSelectionActionWidget', null, @@ -52,11 +48,11 @@ const ClusterBulkSelectionActionWidget = importComponentFromFELibrary( ) const KubeConfigModal = importComponentFromFELibrary('KubeConfigModal', null, 'function') -const ClusterSelectionList: React.FC = ({ +const ClusterSelectionBody: React.FC = ({ clusterOptions, clusterListLoader, - initialLoading, refreshData, + filteredList, }) => { const parentRef = useRef(null) @@ -64,36 +60,14 @@ const ClusterSelectionList: React.FC = ({ const [showKubeConfigModal, setKubeConfigModal] = useState(false) const [selectedClusterName, setSelectedClusterName] = useState('') - const { searchKey, clusterFilter, updateSearchParams, handleSearch, clearFilters, sortBy, sortOrder } = - useUrlFilters({ - parseSearchParams, - initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, - }) + const { clearFilters } = useUrlFilters({ + parseSearchParams, + initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, + }) const { handleBulkSelection, isBulkSelectionApplied, getSelectedIdentifiersCount } = useBulkSelection>() - const filteredList: ClusterDetail[] = useMemo(() => { - const loweredSearchKey = searchKey.toLowerCase() - const updatedClusterOptions = [...clusterOptions] - // Sort the cluster list based on the selected sorting key - getSortedClusterList(updatedClusterOptions, sortBy, sortOrder) - - // Filter the cluster list based on the search key and cluster filter - return updatedClusterOptions.filter((option) => { - const filterCondition = - clusterFilter === ClusterFiltersType.ALL_CLUSTERS || - !option.status || - option.status === ClusterStatusByFilter[clusterFilter] - - return (!searchKey || option.name.toLowerCase().includes(loweredSearchKey)) && filterCondition - }) - }, [searchKey, clusterOptions, `${clusterFilter}`, sortBy, sortOrder]) - - const handleFilterKeyPress = (value: string) => { - handleSearch(value) - } - const handleClearBulkSelection = () => { handleBulkSelection({ action: BulkSelectionEvents.CLEAR_ALL_SELECTIONS, @@ -106,10 +80,6 @@ const ClusterSelectionList: React.FC = ({ handleClearBulkSelection() } - const setClusterFilter = (_clusterFilter: ClusterFiltersType) => { - updateSearchParams({ clusterFilter: _clusterFilter }) - } - if (!clusterOptions.length) { return ( = ({ const renderClusterList = () => (
    -
    - - {ClusterFilters && ( - - )} -
    {clusterListLoader ? ( Syncing @@ -177,7 +132,7 @@ const ClusterSelectionList: React.FC = ({ isProportional /> )} - {!filteredList.length ? ( + {!filteredList?.length ? (
    @@ -222,27 +177,4 @@ const ClusterSelectionList: React.FC = ({ ) } -const BaseClusterList = (props: ClusterSelectionType) => { - const { clusterOptions } = props - const allOnThisPageIdentifiers = useMemo( - () => - clusterOptions?.reduce((acc, cluster) => { - acc[cluster.name] = cluster - return acc - }, {} as ClusterDetail) ?? {}, - [clusterOptions], - ) - - const getSelectAllDialogStatus = () => SelectAllDialogStatus.CLOSED - - return ( - > - identifiers={allOnThisPageIdentifiers} - getSelectAllDialogStatus={getSelectAllDialogStatus} - > - - - ) -} - -export default BaseClusterList +export default ClusterSelectionBody diff --git a/src/components/ClusterNodes/ClusterList/index.ts b/src/components/ClusterNodes/ClusterList/index.ts new file mode 100644 index 0000000000..73c8c6e7df --- /dev/null +++ b/src/components/ClusterNodes/ClusterList/index.ts @@ -0,0 +1,4 @@ +export { default as ClusterList } from './ClusterList' +export { default as ClusterListRow } from './ClusterListRow' +export { default as ClusterListView } from './ClusterListView' +export { default as ClusterSelectionBody } from './ClusterSelectionBody' diff --git a/src/components/ClusterNodes/ClusterList/types.ts b/src/components/ClusterNodes/ClusterList/types.ts new file mode 100644 index 0000000000..0f1b274399 --- /dev/null +++ b/src/components/ClusterNodes/ClusterList/types.ts @@ -0,0 +1,23 @@ +import { ClusterDetail } from '@devtron-labs/devtron-fe-common-lib' + +export interface ClusterViewType { + clusterOptions: ClusterDetail[] + clusterListLoader: boolean + initialLoading: boolean + refreshData: () => void +} + +export interface ClusterListTypes { + filteredList: ClusterDetail[] + clusterListLoader: boolean + showKubeConfigModal: boolean + onChangeShowKubeConfigModal: () => void + setSelectedClusterName: React.Dispatch> +} +export interface ClusterListRowTypes extends Omit { + clusterData: ClusterDetail +} + +export interface ClusterSelectionBodyTypes extends ClusterViewType { + filteredList: ClusterDetail[] +} diff --git a/src/components/ClusterNodes/types.ts b/src/components/ClusterNodes/types.ts index a5de34c3ef..3ce6bf6173 100644 --- a/src/components/ClusterNodes/types.ts +++ b/src/components/ClusterNodes/types.ts @@ -293,14 +293,3 @@ export interface ClusterOverviewProps { export interface ClusterMapInitialStatusType { errorInNodeListing: string } - -export interface ClusterListTypes { - filteredList: ClusterDetail[] - clusterListLoader: boolean - showKubeConfigModal: boolean - onChangeShowKubeConfigModal: () => void - setSelectedClusterName: React.Dispatch> -} -export interface ClusterListRowTypes extends Omit { - clusterData: ClusterDetail -} diff --git a/src/components/ResourceBrowser/ResourceBrowser.tsx b/src/components/ResourceBrowser/ResourceBrowser.tsx index 99f38781c2..293c3ba32f 100644 --- a/src/components/ResourceBrowser/ResourceBrowser.tsx +++ b/src/components/ResourceBrowser/ResourceBrowser.tsx @@ -27,9 +27,9 @@ import { } from '@devtron-labs/devtron-fe-common-lib' import { DEFAULT_CLUSTER_ID } from '@Components/cluster/cluster.type' +import { ClusterListView } from '@Components/ClusterNodes/ClusterList' import { getClusterList, getClusterListMin } from '../ClusterNodes/clusterNodes.service' -import BaseClusterList from '../ClusterNodes/ClusterSelectionList' import { sortObjectArrayAlphabetically } from '../common' import { AddClusterButton } from './PageHeader.buttons' @@ -71,7 +71,7 @@ const ResourceBrowser: React.FC = () => { } return ( - void -} - export interface CreateResourceType { closePopup: (refreshData?: boolean) => void clusterId: string From 12a95ca593618eb141989bb7e92d512941300c05 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 13:25:44 +0530 Subject: [PATCH 39/78] chore: code refactoring --- src/components/ClusterNodes/ClusterList/ClusterListView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx index 2e23cf65f1..1922727766 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx @@ -19,6 +19,8 @@ import { ClusterViewType } from './types' const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'function') +const getSelectAllDialogStatus = () => SelectAllDialogStatus.CLOSED + const ClusterListView = (props: ClusterViewType) => { const { searchKey, clusterFilter, updateSearchParams, handleSearch, sortBy, sortOrder } = useUrlFilters< ClusterMapListSortableKeys, @@ -63,8 +65,6 @@ const ClusterListView = (props: ClusterViewType) => { [clusterOptions], ) - const getSelectAllDialogStatus = () => SelectAllDialogStatus.CLOSED - return ( > identifiers={allOnThisPageIdentifiers} From 49779e1f90e421ad387fc909142602f053113752 Mon Sep 17 00:00:00 2001 From: AbhishekA1509 Date: Mon, 14 Apr 2025 15:11:30 +0530 Subject: [PATCH 40/78] chore: update common-lib to 1.11.0-beta-4 --- package.json | 2 +- yarn.lock | 307 ++++++++++++++++++++++++++------------------------- 2 files changed, 157 insertions(+), 152 deletions(-) diff --git a/package.json b/package.json index 5f67f5176a..bfe6c61769 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "homepage": "/dashboard", "dependencies": { - "@devtron-labs/devtron-fe-common-lib": "1.11.0-beta-3", + "@devtron-labs/devtron-fe-common-lib": "1.11.0-beta-4", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@rjsf/core": "^5.13.3", "@rjsf/utils": "^5.13.3", diff --git a/yarn.lock b/yarn.lock index 08d02ca735..907f4c3898 100644 --- a/yarn.lock +++ b/yarn.lock @@ -985,9 +985,9 @@ "@lezer/common" "^1.0.0" "@codemirror/commands@^6.0.0", "@codemirror/commands@^6.1.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.0.tgz#92f200b66f852939bd6ebb90d48c2d9e9c813d64" - integrity sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ== + version "6.8.1" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.1.tgz#639f5559d2f33f2582a2429c58cb0c1b925c7a30" + integrity sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw== dependencies: "@codemirror/language" "^6.0.0" "@codemirror/state" "^6.4.0" @@ -1111,9 +1111,9 @@ "@lezer/highlight" "^1.0.0" "@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": - version "6.36.4" - resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.4.tgz#d47d38b92a22cc40647bfb9cc97944e13d44942d" - integrity sha512-ZQ0V5ovw/miKEXTvjgzRyjnrk9TwriUB1k4R5p7uNnHR9Hus+D1SXHGdJshijEzPFjU25xea/7nhIeSqYFKdbA== + version "6.36.5" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.5.tgz#bb99b971322b9a3f8c7013f0ef6c4a511c0d750a" + integrity sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg== dependencies: "@codemirror/state" "^6.5.0" style-mod "^4.1.0" @@ -1126,10 +1126,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@devtron-labs/devtron-fe-common-lib@1.11.0-beta-3": - version "1.11.0-beta-3" - resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.11.0-beta-3.tgz#7c2a82bfb7f12c26b0f46d7391acbdd4756accfa" - integrity sha512-AdE4clxlAV8WYsPaVf8+0Azav1grf8CAmho3HweS8CRXrmfck+nO2FCule+0//YpDUWeZS0z7GJTNaUV/9/7qA== +"@devtron-labs/devtron-fe-common-lib@1.11.0-beta-4": + version "1.11.0-beta-4" + resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.11.0-beta-4.tgz#81729d43ff0ff5b5518b4028869025a35e225cfa" + integrity sha512-BhEe/eY8h2fpo8XqOPQPeix1bh4A48YZ8epYrvJph/jkzyBqgbiASfuH7N9t28O9ii9GyoKGZYQujQqrt5UgFA== dependencies: "@codemirror/lang-json" "6.0.1" "@codemirror/lang-yaml" "6.1.2" @@ -1165,9 +1165,9 @@ tslib "2.7.0" "@emnapi/runtime@^1.2.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" - integrity sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.1.tgz#79e54e3cc7f1955b3080f6e1e0e111e06114e114" + integrity sha512-LMshMVP0ZhACNjQNYXiU1iZJ6QCcv0lUdPDPugqGvCGXt5xtRVBPdtA0qU12pEXZzpWAhWlZYptfdAFq10DOVQ== dependencies: tslib "^2.4.0" @@ -1935,112 +1935,112 @@ "@rollup/pluginutils@^5.1.0": version "5.1.4" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz" integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz#9bedc746a97fe707154086365f269ced92ff4aa9" - integrity sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ== - -"@rollup/rollup-android-arm64@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz#6edc6ffc8af8773e4bc28c72894dd5e846b8ee6c" - integrity sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA== - -"@rollup/rollup-darwin-arm64@4.37.0": - version "4.37.0" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz" - integrity sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA== - -"@rollup/rollup-darwin-x64@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz#a6a697bb685ca9462a7caeea5f22f6a686acff1f" - integrity sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ== - -"@rollup/rollup-freebsd-arm64@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz#18113e8e133ccb6de4b9dc9d3e09f7acff344cb7" - integrity sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA== - -"@rollup/rollup-freebsd-x64@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz#5e56ffd4a0d7ccfcbc86867c40b8f0e6a2c0c81e" - integrity sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA== - -"@rollup/rollup-linux-arm-gnueabihf@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz#5addf1a51e1495ae7ff28d26442a88adf629c980" - integrity sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w== - -"@rollup/rollup-linux-arm-musleabihf@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz#00cddb9ab51086c5f2cd33cd4738259e24be4e73" - integrity sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag== - -"@rollup/rollup-linux-arm64-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz#c3b4324496236b6fd9f31fda5701c6d6060b1512" - integrity sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA== - -"@rollup/rollup-linux-arm64-musl@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz#b5222180bb1a50e6e9bc8263efd771c1ce770b6f" - integrity sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz#5660181c1c1efb7b19c7a531d496e685236c5ce7" - integrity sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz#8273166495d2f5d3fbc556cf42a5a6e24b78bdab" - integrity sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ== - -"@rollup/rollup-linux-riscv64-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz#9677e39288ccc91ebcd707cdd794732d701cd174" - integrity sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw== - -"@rollup/rollup-linux-riscv64-musl@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz#71cc5ca7be1ed263357618bfe4f8f50c09725a7e" - integrity sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA== - -"@rollup/rollup-linux-s390x-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz#6b0b7df33eb32b0ee7423898b183acc1b5fee33e" - integrity sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A== - -"@rollup/rollup-linux-x64-gnu@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz#52c27717d3c4819d13b5ebc2373ddea099d2e71b" - integrity sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ== - -"@rollup/rollup-linux-x64-musl@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz#c134a22d30642345de8b799c816345674bf68019" - integrity sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w== - -"@rollup/rollup-win32-arm64-msvc@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz#8063d5f8195dd1845e056d069366fbe06a424d09" - integrity sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg== - -"@rollup/rollup-win32-ia32-msvc@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz#891d90e3b5517f9d290bb416afdfe2ebfb12139e" - integrity sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA== - -"@rollup/rollup-win32-x64-msvc@4.37.0": - version "4.37.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz#a54d7304c3bd45573d8bcd1270de89771f8195fe" - integrity sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA== +"@rollup/rollup-android-arm-eabi@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz#d964ee8ce4d18acf9358f96adc408689b6e27fe3" + integrity sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg== + +"@rollup/rollup-android-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz#9b5e130ecc32a5fc1e96c09ff371743ee71a62d3" + integrity sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w== + +"@rollup/rollup-darwin-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz" + integrity sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ== + +"@rollup/rollup-darwin-x64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz#d7380c1531ab0420ca3be16f17018ef72dd3d504" + integrity sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA== + +"@rollup/rollup-freebsd-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz#cbcbd7248823c6b430ce543c59906dd3c6df0936" + integrity sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg== + +"@rollup/rollup-freebsd-x64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz#96bf6ff875bab5219c3472c95fa6eb992586a93b" + integrity sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw== + +"@rollup/rollup-linux-arm-gnueabihf@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz#d80cd62ce6d40f8e611008d8dbf03b5e6bbf009c" + integrity sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA== + +"@rollup/rollup-linux-arm-musleabihf@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz#75440cfc1e8d0f87a239b4c31dfeaf4719b656b7" + integrity sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg== + +"@rollup/rollup-linux-arm64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz#ac527485ecbb619247fb08253ec8c551a0712e7c" + integrity sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg== + +"@rollup/rollup-linux-arm64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz#74d2b5cb11cf714cd7d1682e7c8b39140e908552" + integrity sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ== + +"@rollup/rollup-linux-loongarch64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz#a0a310e51da0b5fea0e944b0abd4be899819aef6" + integrity sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg== + +"@rollup/rollup-linux-powerpc64le-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz#4077e2862b0ac9f61916d6b474d988171bd43b83" + integrity sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw== + +"@rollup/rollup-linux-riscv64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz#5812a1a7a2f9581cbe12597307cc7ba3321cf2f3" + integrity sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA== + +"@rollup/rollup-linux-riscv64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz#973aaaf4adef4531375c36616de4e01647f90039" + integrity sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ== + +"@rollup/rollup-linux-s390x-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz#9bad59e907ba5bfcf3e9dbd0247dfe583112f70b" + integrity sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw== + +"@rollup/rollup-linux-x64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz#68b045a720bd9b4d905f462b997590c2190a6de0" + integrity sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ== + +"@rollup/rollup-linux-x64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz#8e703e2c2ad19ba7b2cb3d8c3a4ad11d4ee3a282" + integrity sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw== + +"@rollup/rollup-win32-arm64-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz#c5bee19fa670ff5da5f066be6a58b4568e9c650b" + integrity sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ== + +"@rollup/rollup-win32-ia32-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz#846e02c17044bd922f6f483a3b4d36aac6e2b921" + integrity sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA== + +"@rollup/rollup-win32-x64-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz#fd92d31a2931483c25677b9c6698106490cbbc76" + integrity sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ== "@sagold/json-pointer@^5.1.1", "@sagold/json-pointer@^5.1.2": version "5.1.2" @@ -2926,10 +2926,10 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/estree@1.0.6", "@types/estree@^1.0.0": - version "1.0.6" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/estree@1.0.7", "@types/estree@^1.0.0": + version "1.0.7" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz" + integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== "@types/glob@^7.1.3": version "7.2.0" @@ -5110,7 +5110,7 @@ eslint-plugin-react@^7.33.2: eslint-plugin-simple-import-sort@^12.1.1: version "12.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz#e64bfdaf91c5b98a298619aa634a9f7aa43b709e" + resolved "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz" integrity sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA== eslint-plugin-storybook@^0.8.0: @@ -7892,32 +7892,32 @@ rollup-pluginutils@^2.8.1: estree-walker "^0.6.1" rollup@^2.43.1, rollup@^4.20.0, rollup@^4.22.4: - version "4.37.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.37.0.tgz#e4172f8bdb6ea7df08a1b0acf99abeccb2250378" - integrity sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg== + version "4.40.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.0.tgz#13742a615f423ccba457554f006873d5a4de1920" + integrity sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w== dependencies: - "@types/estree" "1.0.6" + "@types/estree" "1.0.7" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.37.0" - "@rollup/rollup-android-arm64" "4.37.0" - "@rollup/rollup-darwin-arm64" "4.37.0" - "@rollup/rollup-darwin-x64" "4.37.0" - "@rollup/rollup-freebsd-arm64" "4.37.0" - "@rollup/rollup-freebsd-x64" "4.37.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.37.0" - "@rollup/rollup-linux-arm-musleabihf" "4.37.0" - "@rollup/rollup-linux-arm64-gnu" "4.37.0" - "@rollup/rollup-linux-arm64-musl" "4.37.0" - "@rollup/rollup-linux-loongarch64-gnu" "4.37.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.37.0" - "@rollup/rollup-linux-riscv64-gnu" "4.37.0" - "@rollup/rollup-linux-riscv64-musl" "4.37.0" - "@rollup/rollup-linux-s390x-gnu" "4.37.0" - "@rollup/rollup-linux-x64-gnu" "4.37.0" - "@rollup/rollup-linux-x64-musl" "4.37.0" - "@rollup/rollup-win32-arm64-msvc" "4.37.0" - "@rollup/rollup-win32-ia32-msvc" "4.37.0" - "@rollup/rollup-win32-x64-msvc" "4.37.0" + "@rollup/rollup-android-arm-eabi" "4.40.0" + "@rollup/rollup-android-arm64" "4.40.0" + "@rollup/rollup-darwin-arm64" "4.40.0" + "@rollup/rollup-darwin-x64" "4.40.0" + "@rollup/rollup-freebsd-arm64" "4.40.0" + "@rollup/rollup-freebsd-x64" "4.40.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.40.0" + "@rollup/rollup-linux-arm-musleabihf" "4.40.0" + "@rollup/rollup-linux-arm64-gnu" "4.40.0" + "@rollup/rollup-linux-arm64-musl" "4.40.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.40.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.40.0" + "@rollup/rollup-linux-riscv64-gnu" "4.40.0" + "@rollup/rollup-linux-riscv64-musl" "4.40.0" + "@rollup/rollup-linux-s390x-gnu" "4.40.0" + "@rollup/rollup-linux-x64-gnu" "4.40.0" + "@rollup/rollup-linux-x64-musl" "4.40.0" + "@rollup/rollup-win32-arm64-msvc" "4.40.0" + "@rollup/rollup-win32-ia32-msvc" "4.40.0" + "@rollup/rollup-win32-x64-msvc" "4.40.0" fsevents "~2.3.2" run-parallel@^1.1.9: @@ -8436,7 +8436,7 @@ tapable@^2.2.0: tar-mini@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/tar-mini/-/tar-mini-0.2.0.tgz#2b2cdc215f5b83b0ab8ce363dc9ded22de51849b" + resolved "https://registry.npmjs.org/tar-mini/-/tar-mini-0.2.0.tgz" integrity sha512-+qfUHz700DWnRutdUsxRRVZ38G1Qr27OetwaMYTdg8hcPxf46U0S1Zf76dQMWRBmusOt2ZCK5kbIaiLkoGO7WQ== temp-dir@^2.0.0: @@ -8615,7 +8615,7 @@ tsconfig-paths@^4.2.0: tslib@2.7.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.6.2: version "2.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== tslib@^1.8.1, tslib@^1.9.3: @@ -8846,9 +8846,9 @@ use-isomorphic-layout-effect@^1.1.2: integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== use-sync-external-store@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" - integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== + version "1.5.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== util@^0.12.5: version "0.12.5" @@ -8961,7 +8961,7 @@ victory-vendor@^36.6.8: vite-plugin-compression2@^1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/vite-plugin-compression2/-/vite-plugin-compression2-1.3.3.tgz#d33ddfb4000c914783f4760f81a44ba52fc21ed1" + resolved "https://registry.npmjs.org/vite-plugin-compression2/-/vite-plugin-compression2-1.3.3.tgz" integrity sha512-Mb+xi/C5b68awtF4fNwRBPtoZiyUHU3I0SaBOAGlerlR31kusq1si6qG31lsjJH8T7QNg/p3IJY2HY9O9SvsfQ== dependencies: "@rollup/pluginutils" "^5.1.0" @@ -9015,7 +9015,7 @@ vite-tsconfig-paths@5.0.1: vite@5.4.17: version "5.4.17" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.17.tgz#4bf61dd4cdbf64b0d6661f5dba76954cc81d5082" + resolved "https://registry.npmjs.org/vite/-/vite-5.4.17.tgz" integrity sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg== dependencies: esbuild "^0.21.3" @@ -9388,9 +9388,9 @@ yaml@^1.10.0, yaml@^1.10.2: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.0.0, yaml@^2.3.4: +yaml@^2.0.0: version "2.7.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz" integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== yaml@^2.2.2: @@ -9398,6 +9398,11 @@ yaml@^2.2.2: resolved "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz" integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== +yaml@^2.3.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.1.tgz#44a247d1b88523855679ac7fa7cda6ed7e135cf6" + integrity sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ== + yaml@^2.4.1: version "2.4.5" resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz" From 88b04710b548b834d7c7d7af80d216e16d62fd17 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 16:08:27 +0530 Subject: [PATCH 41/78] chore: checkboc logic moved to fe lib --- .../ClusterNodes/ClusterList/ClusterList.tsx | 23 ++++---- .../ClusterList/ClusterListRow.tsx | 53 +++---------------- .../ClusterList/ClusterSelectionBody.tsx | 10 ++-- 3 files changed, 25 insertions(+), 61 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterList.tsx b/src/components/ClusterNodes/ClusterList/ClusterList.tsx index 6b6fd14a56..9825754454 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterList.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterList.tsx @@ -7,11 +7,15 @@ import { useUrlFilters, } from '@devtron-labs/devtron-fe-common-lib' +import { importComponentFromFELibrary } from '@Components/common' + import { ClusterMapListSortableKeys, ClusterMapListSortableTitle } from '../constants' import { parseSearchParams } from '../utils' import ClusterListRow from './ClusterListRow' import { ClusterListTypes } from './types' +const KubeConfigRowCheckbox = importComponentFromFELibrary('KubeConfigRowCheckbox', null, 'function') + const ClusterList = ({ filteredList, clusterListLoader, @@ -36,7 +40,7 @@ const ClusterList = ({
    {Object.entries(ClusterMapListSortableKeys).map(([cellName, cellKey]) => ( - {cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( + {KubeConfigRowCheckbox && cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( )} {filteredList.map((clusterData) => ( - - - + ))}
    ) diff --git a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx index 9af839e361..26326d47c8 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx @@ -2,14 +2,11 @@ import { Link } from 'react-router-dom' import { ALL_NAMESPACE_OPTION, - BulkSelectionEvents, BulkSelectionIdentifiersType, Button, ButtonComponentType, ButtonStyleType, ButtonVariantType, - Checkbox, - CHECKBOX_VALUE, ClusterDetail, ClusterStatusType, ComponentSizeType, @@ -31,6 +28,7 @@ import { ClusterListRowTypes } from './types' const CompareClusterButton = importComponentFromFELibrary('CompareClusterButton', null, 'function') const ClusterStatusCell = importComponentFromFELibrary('ClusterStatus', null, 'function') const KubeConfigButton = importComponentFromFELibrary('KubeConfigButton', null, 'function') +const KubeConfigRowCheckbox = importComponentFromFELibrary('KubeConfigRowCheckbox', null, 'function') const ClusterListRow = ({ clusterData, @@ -38,35 +36,10 @@ const ClusterListRow = ({ onChangeShowKubeConfigModal, setSelectedClusterName, }: ClusterListRowTypes) => { - const { - selectedIdentifiers: bulkSelectionState, - handleBulkSelection, - getSelectedIdentifiersCount, - } = useBulkSelection>() + const { selectedIdentifiers: bulkSelectionState, getSelectedIdentifiersCount } = + useBulkSelection>() const errorCount = clusterData.nodeErrors ? Object.keys(clusterData.nodeErrors).length : 0 - - const handleSelection = () => { - const { name } = clusterData - if (bulkSelectionState[name]) { - handleBulkSelection({ - action: BulkSelectionEvents.CLEAR_IDENTIFIERS, - data: { - identifierIds: [name], - }, - }) - } else { - handleBulkSelection({ - action: BulkSelectionEvents.SELECT_IDENTIFIER, - data: { - identifierObject: { - ...bulkSelectionState, - [name]: clusterData, - }, - }, - }) - } - setSelectedClusterName('') - } + const identifierCount = getSelectedIdentifiersCount() const hideDataOnLoad = (value) => { if (clusterListLoader) { @@ -92,22 +65,8 @@ const ClusterListRow = ({ className={`cluster-list-row fw-4 cn-9 fs-13 dc__border-bottom-n1 pt-12 pb-12 pr-20 pl-20 hover-class dc__visible-hover dc__visible-hover--parent ${clusterListLoader ? 'show-shimmer-loading dc__align-items-center' : ''}`} > -
    0 - ? 'dc__visible' - : 'dc__visible-hover--child flex left' - } - > - -
    - {!isIdentifierSelected && getSelectedIdentifiersCount() === 0 && ( + {KubeConfigRowCheckbox && } + {!isIdentifierSelected && identifierCount === 0 && (
    diff --git a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx index 2e7526adeb..a6d1c1a64c 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx @@ -65,9 +65,11 @@ const ClusterSelectionBody: React.FC = ({ initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, }) - const { handleBulkSelection, isBulkSelectionApplied, getSelectedIdentifiersCount } = + const { handleBulkSelection, getSelectedIdentifiersCount } = useBulkSelection>() + const identifierCount = getSelectedIdentifiersCount() + const handleClearBulkSelection = () => { handleBulkSelection({ action: BulkSelectionEvents.CLEAR_ALL_SELECTIONS, @@ -149,11 +151,11 @@ const ClusterSelectionBody: React.FC = ({ ) const renderClusterBulkSelection = () => { - if (getSelectedIdentifiersCount() > 0 || isBulkSelectionApplied) { + if (identifierCount > 0) { return ( @@ -168,7 +170,7 @@ const ClusterSelectionBody: React.FC = ({ {renderClusterList()} {showKubeConfigModal && KubeConfigModal && ( From a5eb583386dd7126518c0db428fba38d326cdfb4 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 16:22:53 +0530 Subject: [PATCH 42/78] chore: selectedClusterName value reset on close --- .../ClusterNodes/ClusterList/ClusterSelectionBody.tsx | 7 ++++--- src/components/ClusterNodes/utils.tsx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx index a6d1c1a64c..3e34107814 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx @@ -57,7 +57,7 @@ const ClusterSelectionBody: React.FC = ({ const parentRef = useRef(null) const [lastSyncTime, setLastSyncTime] = useState(dayjs()) - const [showKubeConfigModal, setKubeConfigModal] = useState(false) + const [showKubeConfigModal, setShowKubeConfigModal] = useState(false) const [selectedClusterName, setSelectedClusterName] = useState('') const { clearFilters } = useUrlFilters({ @@ -94,11 +94,12 @@ const ClusterSelectionBody: React.FC = ({ } const onChangeShowKubeConfigModal = () => { - setKubeConfigModal(true) + setShowKubeConfigModal(true) } const onChangeCloseKubeConfigModal = () => { - setKubeConfigModal(false) + setShowKubeConfigModal(false) + setSelectedClusterName('') } const renderClusterList = () => ( diff --git a/src/components/ClusterNodes/utils.tsx b/src/components/ClusterNodes/utils.tsx index 5811b90d15..f218ae76c3 100644 --- a/src/components/ClusterNodes/utils.tsx +++ b/src/components/ClusterNodes/utils.tsx @@ -87,5 +87,5 @@ export const getSortedClusterList = ( } export const parseSearchParams = (searchParams: URLSearchParams) => ({ - clusterFilter: (searchParams.get('clusterFilter') as ClusterFiltersType) || ClusterFiltersType.ALL_CLUSTERS, + clusterFilter: (searchParams.get('clusterFilter') as ClusterFiltersType) ?? ClusterFiltersType.ALL_CLUSTERS, }) From 29ef069228f50188a8bf55ef569871a93e8184d4 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 16:38:02 +0530 Subject: [PATCH 43/78] chore: code refactoring --- .../ClusterList/ClusterListView.tsx | 72 +++++++++++++++---- .../ClusterList/ClusterSelectionBody.tsx | 33 --------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx index 1922727766..c8d9e4109c 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx @@ -1,16 +1,20 @@ -import { useMemo } from 'react' +import { useMemo, useState } from 'react' +import dayjs, { Dayjs } from 'dayjs' import { + BulkSelectionEvents, BulkSelectionIdentifiersType, BulkSelectionProvider, ClusterDetail, ClusterFiltersType, SearchBar, SelectAllDialogStatus, + useBulkSelection, useUrlFilters, } from '@devtron-labs/devtron-fe-common-lib' import { importComponentFromFELibrary } from '@Components/common' +import Timer from '@Components/common/DynamicTabs/DynamicTabs.timer' import { ClusterMapListSortableKeys, ClusterStatusByFilter } from '../constants' import { getSortedClusterList, parseSearchParams } from '../utils' @@ -22,6 +26,8 @@ const ClusterFilters = importComponentFromFELibrary('ClusterFilters', null, 'fun const getSelectAllDialogStatus = () => SelectAllDialogStatus.CLOSED const ClusterListView = (props: ClusterViewType) => { + const [lastSyncTime, setLastSyncTime] = useState(dayjs()) + const { searchKey, clusterFilter, updateSearchParams, handleSearch, sortBy, sortOrder } = useUrlFilters< ClusterMapListSortableKeys, { clusterFilter: ClusterFiltersType } @@ -29,7 +35,9 @@ const ClusterListView = (props: ClusterViewType) => { parseSearchParams, initialSortKey: ClusterMapListSortableKeys.CLUSTER_NAME, }) - const { clusterOptions, initialLoading } = props + const { handleBulkSelection } = useBulkSelection>() + + const { clusterOptions, initialLoading, clusterListLoader, refreshData } = props const setClusterFilter = (_clusterFilter: ClusterFiltersType) => { updateSearchParams({ clusterFilter: _clusterFilter }) @@ -65,24 +73,60 @@ const ClusterListView = (props: ClusterViewType) => { [clusterOptions], ) + const handleClearBulkSelection = () => { + handleBulkSelection({ + action: BulkSelectionEvents.CLEAR_ALL_SELECTIONS, + }) + } + + const handleRefresh = () => { + refreshData() + setLastSyncTime(dayjs()) + handleClearBulkSelection() + } + return ( > identifiers={allOnThisPageIdentifiers} getSelectAllDialogStatus={getSelectAllDialogStatus} > -
    - - {ClusterFilters && } +
    +
    + + {ClusterFilters && ( + + )} +
    + {clusterListLoader ? ( + Syncing + ) : ( +
    + + Last refreshed  + +  ago + + +
    + )}
    + ) diff --git a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx index 3e34107814..4a18e8ffcf 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterSelectionBody.tsx @@ -15,7 +15,6 @@ */ import React, { useRef, useState } from 'react' -import dayjs, { Dayjs } from 'dayjs' import { BulkSelectionEvents, @@ -29,7 +28,6 @@ import { import NoClusterEmptyState from '@Images/no-cluster-empty-state.png' import { importComponentFromFELibrary } from '@Components/common' -import Timer from '@Components/common/DynamicTabs/DynamicTabs.timer' import { AddClusterButton } from '@Components/ResourceBrowser/PageHeader.buttons' import ClusterNodeEmptyState from '../ClusterNodeEmptyStates' @@ -51,12 +49,10 @@ const KubeConfigModal = importComponentFromFELibrary('KubeConfigModal', null, 'f const ClusterSelectionBody: React.FC = ({ clusterOptions, clusterListLoader, - refreshData, filteredList, }) => { const parentRef = useRef(null) - const [lastSyncTime, setLastSyncTime] = useState(dayjs()) const [showKubeConfigModal, setShowKubeConfigModal] = useState(false) const [selectedClusterName, setSelectedClusterName] = useState('') @@ -76,12 +72,6 @@ const ClusterSelectionBody: React.FC = ({ }) } - const handleRefresh = () => { - refreshData() - setLastSyncTime(dayjs()) - handleClearBulkSelection() - } - if (!clusterOptions.length) { return ( = ({ const renderClusterList = () => (
    -
    -
    - {clusterListLoader ? ( - Syncing - ) : ( - <> - - Last refreshed  - -  ago - - - - )} -
    -
    {ClusterMap && window._env_.FEATURE_CLUSTER_MAP_ENABLE && ( Date: Mon, 14 Apr 2025 16:49:49 +0530 Subject: [PATCH 44/78] chore: replacement with generic button --- .../ClusterNodes/ClusterList/ClusterListRow.tsx | 2 +- .../ClusterNodes/ClusterList/ClusterListView.tsx | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx index 26326d47c8..20c7c67ff8 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx @@ -62,7 +62,7 @@ const ClusterListRow = ({ return (
    {KubeConfigRowCheckbox && } diff --git a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx index c8d9e4109c..b940bb5e35 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx @@ -5,6 +5,8 @@ import { BulkSelectionEvents, BulkSelectionIdentifiersType, BulkSelectionProvider, + Button, + ButtonVariantType, ClusterDetail, ClusterFiltersType, SearchBar, @@ -109,20 +111,18 @@ const ClusterListView = (props: ClusterViewType) => { {clusterListLoader ? ( Syncing ) : ( -
    +
    Last refreshed   ago - + variant={ButtonVariantType.text} + />
    )}
    From c905ef3d087203f85b6bf4fb58b30e775c11c67b Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 17:19:19 +0530 Subject: [PATCH 45/78] fix: identifier count for filtered list --- src/components/ClusterNodes/ClusterList/ClusterListView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx index b940bb5e35..ada7f19ce4 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListView.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListView.tsx @@ -72,7 +72,7 @@ const ClusterListView = (props: ClusterViewType) => { acc[cluster.name] = cluster return acc }, {} as ClusterDetail) ?? {}, - [clusterOptions], + [filteredList], ) const handleClearBulkSelection = () => { From 9d168f705b5bdbefe4f8f050ddf5673e4522af87 Mon Sep 17 00:00:00 2001 From: AbhishekA1509 Date: Mon, 14 Apr 2025 18:35:25 +0530 Subject: [PATCH 46/78] chore: update common version to 1.11.0-pre-2 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index bfe6c61769..73a32fdd9d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "homepage": "/dashboard", "dependencies": { - "@devtron-labs/devtron-fe-common-lib": "1.11.0-beta-4", + "@devtron-labs/devtron-fe-common-lib": "1.11.0-pre-2", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@rjsf/core": "^5.13.3", "@rjsf/utils": "^5.13.3", diff --git a/yarn.lock b/yarn.lock index 907f4c3898..cd0cac6dba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,10 +1126,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@devtron-labs/devtron-fe-common-lib@1.11.0-beta-4": - version "1.11.0-beta-4" - resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.11.0-beta-4.tgz#81729d43ff0ff5b5518b4028869025a35e225cfa" - integrity sha512-BhEe/eY8h2fpo8XqOPQPeix1bh4A48YZ8epYrvJph/jkzyBqgbiASfuH7N9t28O9ii9GyoKGZYQujQqrt5UgFA== +"@devtron-labs/devtron-fe-common-lib@1.11.0-pre-2": + version "1.11.0-pre-2" + resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.11.0-pre-2.tgz#411049b145d7ed7d0a97497c089761a28bbe8c15" + integrity sha512-00xUb1vlaITPr2UxU/yQrGPS0GUUavqMR/MqJLx8YSWIkgd00JgMhW7Eu1AO0qtN4z1p74xL0SpkOFsmIXSQtw== dependencies: "@codemirror/lang-json" "6.0.1" "@codemirror/lang-yaml" "6.1.2" @@ -8615,7 +8615,7 @@ tsconfig-paths@^4.2.0: tslib@2.7.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.6.2: version "2.7.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== tslib@^1.8.1, tslib@^1.9.3: From d18ea964c5caaba21ed7c738693e70b5e96e7774 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Mon, 14 Apr 2025 19:01:22 +0530 Subject: [PATCH 47/78] chore: button added for the redirection of env override --- .../app/details/appDetails/SourceInfo.tsx | 34 ++++++++++++++----- src/config/routes.ts | 1 + 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/components/app/details/appDetails/SourceInfo.tsx b/src/components/app/details/appDetails/SourceInfo.tsx index 118a830bad..25155ae0ba 100644 --- a/src/components/app/details/appDetails/SourceInfo.tsx +++ b/src/components/app/details/appDetails/SourceInfo.tsx @@ -15,7 +15,7 @@ */ import { useMemo, useState } from 'react' -import { Link, useParams } from 'react-router-dom' +import { Link, useHistory, useParams } from 'react-router-dom' import moment from 'moment' import { Button, @@ -26,6 +26,7 @@ import { DATE_TIME_FORMATS, DeploymentAppTypes, handleUTCTime, + Icon, Progressing, ReleaseMode, showError, @@ -93,6 +94,8 @@ export const SourceInfo = ({ appDetails?.releaseMode === ReleaseMode.MIGRATE_EXTERNAL_APPS && !appDetails?.isPipelineTriggered const isIsolatedEnv = isVirtualEnvironment && !!appDetails?.resourceTree + const history = useHistory() + if ( ['progressing', 'degraded'].includes(status?.toLowerCase()) && Array.isArray(conditions) && @@ -151,6 +154,10 @@ export const SourceInfo = ({ return
    {loadingCards}
    } + const onClickConfigButton = () => { + history.push(`${URLS.APP}/${params.appId}/edit/${URLS.APP_ENV_OVERRIDE_CONFIG}/${params.envId}`) + } + const renderDevtronAppsEnvironmentSelector = (environment) => { // If moving to a component then move getIsApprovalConfigured with it as well with memoization. const isApprovalConfigured = appDetails?.isApprovalPolicyApplicable ?? false @@ -278,6 +285,16 @@ export const SourceInfo = ({ }} /> )} +
    diff --git a/src/components/workflowEditor/nodes/WebhookNode.tsx b/src/components/workflowEditor/nodes/WebhookNode.tsx index 8b86872f9e..47e0eabe2d 100644 --- a/src/components/workflowEditor/nodes/WebhookNode.tsx +++ b/src/components/workflowEditor/nodes/WebhookNode.tsx @@ -15,13 +15,22 @@ */ import { ReactElement, useState } from 'react' -import { WorkflowNodeType, ConditionalWrap, TARGET_IDS, TippyTheme, TippyCustomized } from '@devtron-labs/devtron-fe-common-lib' +import { + WorkflowNodeType, + ConditionalWrap, + TARGET_IDS, + TippyTheme, + TippyCustomized, +} from '@devtron-labs/devtron-fe-common-lib' import { Link } from 'react-router-dom' import ToggleCDSelectButton from '../ToggleCDSelectButton' import { ReactComponent as Webhook } from '../../../assets/icons/ic-CIWebhook.svg' import { WebhookNodeProps } from '../types' import { ReactComponent as ICCIWebhook } from '@Icons/ic-CIWebhook.svg' import { DOCUMENTATION } from '@Config/constants' +import { importComponentFromFELibrary } from '@Components/common' + +const WebhookAddImageButton = importComponentFromFELibrary('WebhookAddImageButton', null, 'function') export const WebhookNode = ({ x, @@ -38,12 +47,15 @@ export const WebhookNode = ({ isLastNode, isReadonlyView = false, isTemplateView, + showAddImageButton = false, }: WebhookNodeProps) => { const [isWebhookTippyOpen, setIsWebhookTippyOpen] = useState(false) const selectedNodeKey = `${selectedNode?.nodeType}-${selectedNode?.id}` const currentNodeKey = `${WorkflowNodeType.WEBHOOK}-${id ?? ''}` + const showWebhookAddImageButton = WebhookAddImageButton && showAddImageButton + const addNewCD = (event): void => { event.preventDefault() event.stopPropagation() @@ -63,7 +75,7 @@ export const WebhookNode = ({ } const toggleIsWebhookTippyOpen = () => { - setIsWebhookTippyOpen(prev => !prev) + setIsWebhookTippyOpen((prev) => !prev) } const renderWrapWithLinkOrTippy = (children: ReactElement) => @@ -90,7 +102,7 @@ export const WebhookNode = ({ {children} ) - + const handleCardClick = () => { if (isTemplateView) { toggleIsWebhookTippyOpen() @@ -102,11 +114,16 @@ export const WebhookNode = ({ return ( -
    +
    -
    +
    Webhook -
    External source
    +
    External source
    @@ -121,6 +138,7 @@ export const WebhookNode = ({ /> )}
    + {showWebhookAddImageButton && {}} />}
    ) diff --git a/src/components/workflowEditor/types.ts b/src/components/workflowEditor/types.ts index fa20762330..48e8badea6 100644 --- a/src/components/workflowEditor/types.ts +++ b/src/components/workflowEditor/types.ts @@ -202,6 +202,7 @@ export interface WebhookNodeProps extends Required Date: Tue, 15 Apr 2025 16:14:40 +0530 Subject: [PATCH 55/78] fix: add check for starts with http in create material --- src/components/material/CreateMaterial.tsx | 4 ++-- src/components/material/UpdateMaterial.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/material/CreateMaterial.tsx b/src/components/material/CreateMaterial.tsx index 2b46c2ccc3..2bb7176f3c 100644 --- a/src/components/material/CreateMaterial.tsx +++ b/src/components/material/CreateMaterial.tsx @@ -119,8 +119,8 @@ export class CreateMaterial extends Component provider?.id == selectedId) || [] - if (res[0]?.authMode != 'SSH' && !url.startsWith('https')) { - return "Git Repo URL must start with 'http' or 'https:'" + if (res[0]?.authMode != 'SSH' && !url.startsWith('http')) { + return "Git Repo URL must start with 'http' or 'https'" } if (res[0]?.authMode === 'SSH' && !url.includes('@')) { diff --git a/src/components/material/UpdateMaterial.tsx b/src/components/material/UpdateMaterial.tsx index 8641fe212d..da2398cbde 100644 --- a/src/components/material/UpdateMaterial.tsx +++ b/src/components/material/UpdateMaterial.tsx @@ -128,7 +128,7 @@ export class UpdateMaterial extends Component provider?.id === selectedId) if (res[0]?.authMode != 'SSH' && !url.startsWith('http')) { - return "Git Repo URL must start with 'http' or 'https:'" + return "Git Repo URL must start with 'http' or 'https'" } if (res[0]?.authMode === 'SSH' && !url.includes('@')) { From 656c7a75397edbfdead25c7b07c97e26c2fae193 Mon Sep 17 00:00:00 2001 From: shivani170 Date: Tue, 15 Apr 2025 16:18:51 +0530 Subject: [PATCH 56/78] chore: text update --- src/components/ClusterNodes/ClusterList/ClusterList.tsx | 1 + .../ClusterNodes/ClusterList/ClusterListRow.tsx | 2 +- src/components/app/details/appDetails/SourceInfo.tsx | 9 +++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterList.tsx b/src/components/ClusterNodes/ClusterList/ClusterList.tsx index 9825754454..e6dcafb7e4 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterList.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterList.tsx @@ -38,6 +38,7 @@ const ClusterList = ({ return (
    + {KubeConfigRowCheckbox === null &&
    } {Object.entries(ClusterMapListSortableKeys).map(([cellName, cellKey]) => ( {KubeConfigRowCheckbox && cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( diff --git a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx index 20c7c67ff8..24c35a098c 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterListRow.tsx @@ -67,7 +67,7 @@ const ClusterListRow = ({ > {KubeConfigRowCheckbox && } {!isIdentifierSelected && identifierCount === 0 && ( -
    +
    )} diff --git a/src/components/app/details/appDetails/SourceInfo.tsx b/src/components/app/details/appDetails/SourceInfo.tsx index e26bc537ee..acd75ce185 100644 --- a/src/components/app/details/appDetails/SourceInfo.tsx +++ b/src/components/app/details/appDetails/SourceInfo.tsx @@ -266,7 +266,7 @@ export const SourceInfo = ({ showTooltip={isApprovalConfigured} tooltipProps={{ content: 'Application deployment requiring approval cannot be hibernated.', - placement: 'bottom-end', + placement: 'bottom', }} /> )} @@ -284,7 +284,7 @@ export const SourceInfo = ({ showTooltip={isApprovalConfigured} tooltipProps={{ content: 'Application deployment requiring approval cannot be hibernated.', - placement: 'bottom-end', + placement: 'bottom', }} /> )} @@ -297,6 +297,11 @@ export const SourceInfo = ({ component={ButtonComponentType.button} style={ButtonStyleType.neutral} ariaLabel="Go to Environment Configuration" + showTooltip + tooltipProps={{ + content: "Go to Environment Config", + placement: 'bottom', + }} /> {window._env_.FEATURE_SWAP_TRAFFIC_ENABLE && SwapTraffic && From f4cdeeb98e6589c6750c9b8c822e5a3624092f2c Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Tue, 15 Apr 2025 16:28:09 +0530 Subject: [PATCH 57/78] feat: add authentication type radio button --- src/components/dockerRegistry/Docker.tsx | 33 +++++++++++++++++++++-- src/components/dockerRegistry/service.tsx | 1 + src/config/constants.ts | 3 +++ src/services/service.ts | 3 +-- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/components/dockerRegistry/Docker.tsx b/src/components/dockerRegistry/Docker.tsx index 219a83ff98..5f0c9d5c18 100644 --- a/src/components/dockerRegistry/Docker.tsx +++ b/src/components/dockerRegistry/Docker.tsx @@ -53,6 +53,7 @@ import { RegistryIcon, ComponentSizeType, PasswordField, + OtherRegistryAuthenticationType, } from '@devtron-labs/devtron-fe-common-lib' import Tippy from '@tippyjs/react' import { useHistory, useParams, useRouteMatch } from 'react-router-dom' @@ -100,6 +101,7 @@ import { VALIDATION_STATUS, ValidateForm } from '../common/ValidateForm/Validate const RegistryHelmPushCheckbox = importComponentFromFELibrary('RegistryHelmPushCheckbox') const RemoteConnectionRadio = importComponentFromFELibrary('RemoteConnectionRadio') const getRemoteConnectionConfig = importComponentFromFELibrary('getRemoteConnectionConfig', noop, 'function') +const AuthenticationTypeRadio = importComponentFromFELibrary('AuthenticationTypeRadio', null, 'function') enum CERTTYPE { SECURE = 'secure', @@ -259,6 +261,7 @@ const CollapsedList = ({ repositoryList = [], disabledFields = [], ociRegistryConfig, + credentialsType, ...rest }) => { const [collapsed, toggleCollapse] = useState(true) @@ -338,6 +341,7 @@ const CollapsedList = ({ isPublic, disabledFields, ociRegistryConfig, + credentialsType, }} /> )} @@ -377,6 +381,7 @@ const DockerForm = ({ : { CONTAINER: OCIRegistryConfigConstants.PULL_PUSH, }, + credentialsType: authCredentialsType, ...rest }) => { const re = PATTERNS.APP_NAME @@ -539,6 +544,9 @@ const DockerForm = ({ const [registryStorageType, setRegistryStorageType] = useState( isPublic ? RegistryStorageType.OCI_PUBLIC : RegistryStorageType.OCI_PRIVATE, ) + const [authenticationType, setAuthenticationType] = useState( + id ? authCredentialsType : OtherRegistryAuthenticationType.USERNAME_PASSWORD, + ) const InitialValueOfIsContainerStore: boolean = ociRegistryConfig?.CONTAINER === OCIRegistryConfigConstants.PULL_PUSH @@ -712,6 +720,11 @@ const DockerForm = ({ } } + const handleChangeOtherRegistryAuthType = (e) => { + const updatedAuthType = e.target.value as OtherRegistryAuthenticationType + setAuthenticationType(updatedAuthType) + } + function fetchAWSRegion(): string { const pattern = registryStorageType === RegistryStorageType.OCI_PUBLIC @@ -839,6 +852,9 @@ const DockerForm = ({ customState.remoteConnectionConfig.connectionMethod.value, sshConnectionType, ), + ...(AuthenticationTypeRadio && selectedDockerRegistryType.value === RegistryType.OTHER + ? { credentialsType: authenticationType } + : {}), } } @@ -1003,6 +1019,7 @@ const DockerForm = ({ let error = false if ( registryStorageType === RegistryStorageType.OCI_PRIVATE && + authenticationType === OtherRegistryAuthenticationType.USERNAME_PASSWORD && (!customState.username.value || !(customState.password.value || id)) ) { setCustomState((st) => ({ @@ -1605,13 +1622,25 @@ const DockerForm = ({ ) } + + const isUserNamePasswordRequired = + selectedDockerRegistryType.value === RegistryType.OTHER + ? authenticationType === OtherRegistryAuthenticationType.USERNAME_PASSWORD + : true + return ( <> + {AuthenticationTypeRadio && selectedDockerRegistryType.value === RegistryType.OTHER && ( + + )}
    { const URL = `${Routes.DOCKER_REGISTRY_CONFIG}/${id}` return get(URL) diff --git a/src/config/constants.ts b/src/config/constants.ts index 402efa05f1..82f2c03a43 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -21,6 +21,7 @@ import { ToastManager, ROUTES as COMMON_ROUTES, EnvResourceType, + OtherRegistryAuthenticationType, } from '@devtron-labs/devtron-fe-common-lib' export const DEFAULT_STATUS = 'checking' export const DEFAULT_STATUS_TEXT = 'Checking Status' @@ -471,6 +472,7 @@ export type OCIRegistryStorageConfigType = { CONTAINER?: OCIRegistryStorageActionType CHART?: OCIRegistryStorageActionType } + export const OCIRegistryConfigConstants: Record = { PULL: 'PULL', PUSH: 'PUSH', @@ -541,6 +543,7 @@ export interface RegistryPayloadType { sshAuthKey: string } } + credentialsType?: OtherRegistryAuthenticationType } export interface RegistryPayloadWithSelectType extends RegistryPayloadType, SelectPickerOptionType {} diff --git a/src/services/service.ts b/src/services/service.ts index 60c1028e69..6d00af6474 100644 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -250,8 +250,7 @@ export function getDockerRegistryStatus(isStorageActionPush?: boolean): Promise< } export function getDockerRegistryList(): Promise { - const URL = `${Routes.DOCKER_REGISTRY_CONFIG}` - return get(URL) + return get(Routes.DOCKER_REGISTRY_CONFIG) } export function getAppOtherEnvironmentMin( From 6a6df6a75fd1926f60352fd0a470b5ef19a3f2ae Mon Sep 17 00:00:00 2001 From: shivani170 Date: Tue, 15 Apr 2025 17:00:22 +0530 Subject: [PATCH 58/78] chore: fix --- src/components/ClusterNodes/ClusterList/ClusterList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ClusterNodes/ClusterList/ClusterList.tsx b/src/components/ClusterNodes/ClusterList/ClusterList.tsx index e6dcafb7e4..de312abc93 100644 --- a/src/components/ClusterNodes/ClusterList/ClusterList.tsx +++ b/src/components/ClusterNodes/ClusterList/ClusterList.tsx @@ -38,7 +38,7 @@ const ClusterList = ({ return (
    - {KubeConfigRowCheckbox === null &&
    } + {KubeConfigRowCheckbox === null ?
    : null} {Object.entries(ClusterMapListSortableKeys).map(([cellName, cellKey]) => ( {KubeConfigRowCheckbox && cellKey === ClusterMapListSortableKeys.CLUSTER_NAME && ( From 7971ec117002f6232a258c172766909715345994 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Tue, 15 Apr 2025 17:01:14 +0530 Subject: [PATCH 59/78] feat: TriggerView, EnvTriggerView - integrate webhook add image modal --- .../Details/TriggerView/EnvTriggerView.tsx | 22 +++++++++++++++- .../app/details/triggerView/TriggerView.tsx | 25 +++++++++++++++++-- .../app/details/triggerView/types.ts | 2 ++ .../details/triggerView/workflow/Workflow.tsx | 2 +- .../workflowEditor/nodes/WebhookNode.tsx | 10 +++++--- src/components/workflowEditor/types.ts | 5 +++- 6 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx b/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx index 87945322bf..5df22f01b3 100644 --- a/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx +++ b/src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx @@ -125,6 +125,7 @@ import { LinkedCIDetail } from '../../../../Pages/Shared/LinkedCIDetailsModal' import CIMaterialModal from '../../../app/details/triggerView/CIMaterialModal' import { RenderCDMaterialContentProps } from './types' import { WebhookReceivedPayloadModal } from '@Components/app/details/triggerView/WebhookReceivedPayloadModal' +import { getExternalCIConfig } from '@Components/ciPipeline/Webhook/webhook.service' const ApprovalMaterialModal = importComponentFromFELibrary('ApprovalMaterialModal') const getCIBlockState: (...props) => Promise = importComponentFromFELibrary( @@ -145,6 +146,7 @@ const validateRuntimeParameters = importComponentFromFELibrary( 'function', ) const ChangeImageSource = importComponentFromFELibrary('ChangeImageSource', null, 'function') +const WebhookAddImageModal = importComponentFromFELibrary('WebhookAddImageModal', null, 'function') // FIXME: IN CIMaterials we are sending isCDLoading while in CD materials we are sending isCILoading let inprogressStatusTimer @@ -192,6 +194,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou const [runtimeParams, setRuntimeParams] = useState>({}) const [runtimeParamsErrorState, setRuntimeParamsErrorState] = useState>({}) const [isBulkTriggerLoading, setIsBulkTriggerLoading] = useState(false) + const [selectedWebhookNode, setSelectedWebhookNode] = useState<{ appId: number; id: number }>(null) const selectedWorkflows = filteredWorkflows.filter((wf) => wf.isSelected) @@ -1941,7 +1944,7 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou } if (!filteredWorkflows.length) { return ( -
    +
    ) @@ -2381,6 +2384,16 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou history.push(match.url) } + const getWebhookDetails = () => getExternalCIConfig(selectedWebhookNode.appId, selectedWebhookNode.id, false) + + const handleWebhookAddImageClick = (appId: number) => (id: number) => { + setSelectedWebhookNode({ appId, id }) + } + + const handleWebhookAddImageModalClose = () => { + setSelectedWebhookNode(null) + } + const renderWorkflow = (): JSX.Element => { return ( <> @@ -2403,10 +2416,17 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou location={location} match={match} index={index} + handleWebhookAddImageClick={handleWebhookAddImageClick(workflow.appId)} /> ) })} + {WebhookAddImageModal && selectedWebhookNode && ( + + )} ) } diff --git a/src/components/app/details/triggerView/TriggerView.tsx b/src/components/app/details/triggerView/TriggerView.tsx index 08e140bc3a..688afc1ffc 100644 --- a/src/components/app/details/triggerView/TriggerView.tsx +++ b/src/components/app/details/triggerView/TriggerView.tsx @@ -95,6 +95,7 @@ import { CIPipelineBuildType } from '../../../ciPipeline/types' import { LinkedCIDetail } from '../../../../Pages/Shared/LinkedCIDetailsModal' import { CIMaterialModal } from './CIMaterialModal' import { WebhookReceivedPayloadModal } from './WebhookReceivedPayloadModal' +import { getExternalCIConfig } from '@Components/ciPipeline/Webhook/webhook.service' const ApprovalMaterialModal = importComponentFromFELibrary('ApprovalMaterialModal') const getCIBlockState: (...props) => Promise = importComponentFromFELibrary( @@ -103,6 +104,7 @@ const getCIBlockState: (...props) => Promise = importComponent 'function', ) const WorkflowActionRouter = importComponentFromFELibrary('WorkflowActionRouter', null, 'function') +const WebhookAddImageModal = importComponentFromFELibrary('WebhookAddImageModal', null, 'function') const getRuntimeParams = importComponentFromFELibrary('getRuntimeParams', null, 'function') const getRuntimeParamsPayload = importComponentFromFELibrary('getRuntimeParamsPayload', null, 'function') @@ -146,6 +148,7 @@ class TriggerView extends Component { searchImageTag: '', resourceFilters: [], runtimeParams: [], + selectedWebhookNodeId: null, } this.refreshMaterial = this.refreshMaterial.bind(this) this.onClickCIMaterial = this.onClickCIMaterial.bind(this) @@ -1141,6 +1144,17 @@ class TriggerView extends Component { this.setState({ selectedEnv: _selectedEnv }) } + getWebhookDetails = () => + getExternalCIConfig(this.props.match.params.appId, this.state.selectedWebhookNodeId, false) + + handleWebhookAddImageClick = (webhookId: number) => { + this.setState({ selectedWebhookNodeId: webhookId }) + } + + handleWebhookAddImageModalClose = () => { + this.setState({ selectedWebhookNodeId: null }) + } + getCINode = (): CommonNodeAttr => { let nd: CommonNodeAttr if (this.state.ciNodeId) { @@ -1314,7 +1328,7 @@ class TriggerView extends Component {
    -
    +
    @@ -1378,10 +1392,17 @@ class TriggerView extends Component { filteredCIPipelines={this.state.filteredCIPipelines} environmentLists={this.state.environmentLists} appId={+this.props.match.params.appId} + handleWebhookAddImageClick={this.handleWebhookAddImageClick} /> ) })} + {WebhookAddImageModal && this.state.selectedWebhookNodeId && ( + + )} ) } @@ -1425,7 +1446,7 @@ class TriggerView extends Component { } if (!this.state.workflows.length) { return ( -
    +
    {this.props.isJobView ? ( void } export interface TriggerViewContextType { @@ -403,6 +404,7 @@ export interface TriggerViewState { searchImageTag?: string resourceFilters?: FilterConditionsListType[] runtimeParams?: RuntimePluginVariables[] + selectedWebhookNodeId: number } export interface CIMaterialProps diff --git a/src/components/app/details/triggerView/workflow/Workflow.tsx b/src/components/app/details/triggerView/workflow/Workflow.tsx index ac4da263cc..bf3a0b4d31 100644 --- a/src/components/app/details/triggerView/workflow/Workflow.tsx +++ b/src/components/app/details/triggerView/workflow/Workflow.tsx @@ -124,7 +124,7 @@ export class Workflow extends Component { key={`webhook-${node.id}`} id={node.id} isTemplateView={false} - showAddImageButton + addImageButtonConfig={{ show: true, onClick: this.props.handleWebhookAddImageClick }} /> ) } diff --git a/src/components/workflowEditor/nodes/WebhookNode.tsx b/src/components/workflowEditor/nodes/WebhookNode.tsx index 47e0eabe2d..45ecb40978 100644 --- a/src/components/workflowEditor/nodes/WebhookNode.tsx +++ b/src/components/workflowEditor/nodes/WebhookNode.tsx @@ -47,14 +47,14 @@ export const WebhookNode = ({ isLastNode, isReadonlyView = false, isTemplateView, - showAddImageButton = false, + addImageButtonConfig, }: WebhookNodeProps) => { const [isWebhookTippyOpen, setIsWebhookTippyOpen] = useState(false) const selectedNodeKey = `${selectedNode?.nodeType}-${selectedNode?.id}` const currentNodeKey = `${WorkflowNodeType.WEBHOOK}-${id ?? ''}` - const showWebhookAddImageButton = WebhookAddImageButton && showAddImageButton + const showWebhookAddImageButton = WebhookAddImageButton && (addImageButtonConfig?.show || false) const addNewCD = (event): void => { event.preventDefault() @@ -78,6 +78,8 @@ export const WebhookNode = ({ setIsWebhookTippyOpen((prev) => !prev) } + const onWebhookAddImageClick = () => addImageButtonConfig?.onClick(id) + const renderWrapWithLinkOrTippy = (children: ReactElement) => isTemplateView ? ( )}
    - {showWebhookAddImageButton && {}} />} + {showWebhookAddImageButton && ( + + )}
    ) diff --git a/src/components/workflowEditor/types.ts b/src/components/workflowEditor/types.ts index 48e8badea6..13bd5bdcc7 100644 --- a/src/components/workflowEditor/types.ts +++ b/src/components/workflowEditor/types.ts @@ -202,7 +202,10 @@ export interface WebhookNodeProps extends Required void + } } export interface WebhookTippyType { From 71c1c365e367476abf529fbcb4479afa51f6f7dc Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Tue, 15 Apr 2025 17:22:45 +0530 Subject: [PATCH 60/78] chore: add fallback for credential type --- src/components/dockerRegistry/Docker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dockerRegistry/Docker.tsx b/src/components/dockerRegistry/Docker.tsx index 5f0c9d5c18..62f9cae54f 100644 --- a/src/components/dockerRegistry/Docker.tsx +++ b/src/components/dockerRegistry/Docker.tsx @@ -545,7 +545,7 @@ const DockerForm = ({ isPublic ? RegistryStorageType.OCI_PUBLIC : RegistryStorageType.OCI_PRIVATE, ) const [authenticationType, setAuthenticationType] = useState( - id ? authCredentialsType : OtherRegistryAuthenticationType.USERNAME_PASSWORD, + id && authCredentialsType ? authCredentialsType : OtherRegistryAuthenticationType.USERNAME_PASSWORD, ) const InitialValueOfIsContainerStore: boolean = From 74d49991676ffad0a82c561494afa18048752193 Mon Sep 17 00:00:00 2001 From: arunjaindev Date: Tue, 15 Apr 2025 17:49:38 +0530 Subject: [PATCH 61/78] feat: hide user name password for anonymous --- src/components/dockerRegistry/Docker.tsx | 70 ++++++++++++------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/components/dockerRegistry/Docker.tsx b/src/components/dockerRegistry/Docker.tsx index 62f9cae54f..67f89c1194 100644 --- a/src/components/dockerRegistry/Docker.tsx +++ b/src/components/dockerRegistry/Docker.tsx @@ -1636,45 +1636,47 @@ const DockerForm = ({ handleChangeOtherRegistryAuthType={handleChangeOtherRegistryAuthType} /> )} -
    -
    - -
    -
    - {(selectedDockerRegistryType.value === RegistryType.DOCKER_HUB || - selectedDockerRegistryType.value === RegistryType.ACR || - selectedDockerRegistryType.value === RegistryType.QUAY || - selectedDockerRegistryType.value === RegistryType.OTHER) && ( - +
    + - )} +
    +
    + {(selectedDockerRegistryType.value === RegistryType.DOCKER_HUB || + selectedDockerRegistryType.value === RegistryType.ACR || + selectedDockerRegistryType.value === RegistryType.QUAY || + selectedDockerRegistryType.value === RegistryType.OTHER) && ( + + )} +
    -
    + )} {isGCROrGCP && (