Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Browse files Browse the repository at this point in the history
…/approval-policy
  • Loading branch information
eshankvaish committed Dec 24, 2024
2 parents b492486 + de77078 commit 4e9a833
Show file tree
Hide file tree
Showing 77 changed files with 1,176 additions and 816 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,6 @@ FEATURE_PROMO_EMBEDDED_IFRAME_URL=
FEATURE_RB_SYNC_CLUSTER_ENABLE=false
FEATURE_BULK_RESTART_WORKLOADS_FROM_RB=deployment,rollout,daemonset,statefulset
FEATURE_DEFAULT_MERGE_STRATEGY=
FEATURE_CLUSTER_MAP_ENABLE=false
FEATURE_CLUSTER_MAP_ENABLE=true
FEATURE_DEFAULT_LANDING_RB_ENABLE=false
FEATURE_ACTION_AUDIOS_ENABLE=true
2 changes: 0 additions & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ src/components/app/Overview/utils.tsx
src/components/app/ResourceTreeNodes.tsx
src/components/app/ResponsiveDrawer.tsx
src/components/app/WebWorker.ts
src/components/app/appLabelCommon.tsx
src/components/app/create/CreateApp.tsx
src/components/app/create/validationRules.ts
src/components/app/details/AboutAppInfoModal.tsx
Expand Down Expand Up @@ -247,7 +246,6 @@ src/components/common/DatePickers/DayPickerRangeController.tsx
src/components/common/DeprecatedUpdateWarn.tsx
src/components/common/Description/GenericDescription.tsx
src/components/common/DynamicTabs/__tests__/DynamicTabs.test.tsx
src/components/common/ExportToCsv/ExportToCsv.tsx
src/components/common/FloatingVariablesSuggestions/FloatingVariablesSuggestions.tsx
src/components/common/FloatingVariablesSuggestions/SuggestionItem.tsx
src/components/common/FloatingVariablesSuggestions/Suggestions.tsx
Expand Down
1 change: 1 addition & 0 deletions config.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@
| TRIGGER_API_TIMEOUT | 60000 | Default timeout for all API requests for Trigger calls (Deploy artifacts, charts) in DASHBOARD |
| FEATURE_STEP_WISE_LOGS_ENABLE | true | Would segregate logs into tasks |
| 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 |

# DASHBOARD CONFIG SECRET
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "dashboard",
"version": "1.2.0",
"version": "1.3.0",
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "1.3.0-beta-4",
"@devtron-labs/devtron-fe-common-lib": "1.3.5",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand Down
113 changes: 71 additions & 42 deletions src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ import {
AppType,
ErrorScreenManager,
IndexStore,
useAsync,
useMainContext,
noop,
DeploymentAppTypes,
Progressing,
showError,
ResponseType,
noop,
ERROR_STATUS_CODE,
} from '@devtron-labs/devtron-fe-common-lib'
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
Expand All @@ -37,62 +38,90 @@ let initTimer = null

const ExternalFluxAppDetails = () => {
const { clusterId, appName, namespace, templateType } = useParams<ExternalFluxAppDetailParams>()
const [isPublishing, setIsPublishing] = useState<boolean>(true)
const { isSuperAdmin } = useMainContext()
const isKustomization = templateType === FluxCDTemplateType.KUSTOMIZATION
const [initialLoading, setInitialLoading] = useState(true)
const [isReloadResourceTreeInProgress, setIsReloadResourceTreeInProgress] = useState(true)
const [appDetailsError, setAppDetailsError] = useState(null)

const [isAppDetailsLoading, appDetailsResult, appDetailsError, reloadAppDetails] = useAsync(
() => getExternalFluxCDAppDetails(clusterId, namespace, appName, isKustomization),
[clusterId, appName, namespace, templateType],
isSuperAdmin,
{
resetOnChange: false,
},
)
const handleUpdateIndexStoreWithDetails = (response: ResponseType<any>) => {
const genericAppDetail: AppDetails = {
...response.result,
appStatus: getAppStatus(response.result.appStatus),
deploymentAppType: DeploymentAppTypes.FLUX,
fluxTemplateType: templateType,
}

useEffect(
() => () => {
IndexStore.clearAppDetails()
clearTimeout(initTimer)
},
[],
)
IndexStore.publishAppDetails(genericAppDetail, AppType.EXTERNAL_FLUX_APP)
setAppDetailsError(null)
}

useEffect(() => {
if (appDetailsResult && !appDetailsError) {
initTimer = setTimeout(reloadAppDetails, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
const genericAppDetail: AppDetails = {
...appDetailsResult.result,
appStatus: getAppStatus(appDetailsResult.result.appStatus),
deploymentAppType: DeploymentAppTypes.FLUX,
fluxTemplateType: templateType,
}
IndexStore.publishAppDetails(genericAppDetail, AppType.EXTERNAL_FLUX_APP)
setIsPublishing(false)
}
}, [appDetailsResult])
const handleFetchExternalFluxCDAppDetails = () =>
// NOTE: returning a promise so that we can trigger the next timeout after this api call completes
new Promise<void>((resolve) => {
setIsReloadResourceTreeInProgress(true)

getExternalFluxCDAppDetails(clusterId, namespace, appName, isKustomization)
.then(handleUpdateIndexStoreWithDetails)
.catch((error) => {
if (!initialLoading) {
showError(error)
} else {
setAppDetailsError(error)
}
})
.finally(() => {
setIsReloadResourceTreeInProgress(false)
setInitialLoading(false)
resolve()
})
})

if (!isSuperAdmin) {
return <ErrorScreenManager code={403} />
const initializePageDetails = () => {
handleFetchExternalFluxCDAppDetails()
.then(() => {
// NOTE: using timeouts instead of intervals since we want the next api call after the last one finishes
// https://stackoverflow.com/questions/729921/whats-the-difference-between-recursive-settimeout-versus-setinterval
initTimer = setTimeout(initializePageDetails, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
})
.catch(noop)
}

if (appDetailsError) {
return <ErrorScreenManager code={appDetailsError.code} reload={reloadAppDetails} />
const handleReloadResourceTree = async () => {
await handleFetchExternalFluxCDAppDetails()
}

// To show loader on first render only
const isLoadingOnMount = isAppDetailsLoading && !appDetailsResult
useEffect(() => {
if (isSuperAdmin) {
setInitialLoading(true)
initializePageDetails()
}

return () => {
IndexStore.clearAppDetails()
clearTimeout(initTimer)
}
}, [clusterId, appName, namespace, templateType, isSuperAdmin])

if (isLoadingOnMount || isPublishing) {
return <Progressing pageLoader />
if (appDetailsError || !isSuperAdmin) {
return (
<ErrorScreenManager
code={appDetailsError?.code ?? ERROR_STATUS_CODE.PERMISSION_DENIED}
reload={handleReloadResourceTree}
/>
)
}

return (
<AppDetailsComponent
isExternalApp
// NOTE: in case of DA & Helm Apps, when we delete that app _init is called
// since we can't delete flux app, sending in noop
_init={noop}
loadingDetails={isLoadingOnMount}
loadingResourceTree={isLoadingOnMount}
loadingDetails={initialLoading}
loadingResourceTree={initialLoading}
handleReloadResourceTree={handleReloadResourceTree}
isReloadResourceTreeInProgress={isReloadResourceTreeInProgress}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const ConfigToolbar = ({
if (configHeaderTab === ConfigHeaderTabType.INHERITED) {
return (
<div className="flexbox dc__align-items-center dc__gap-6">
<ICInfoOutlineGrey className="p-2 icon-dim-20 dc__no-shrink" />
<ICInfoOutlineGrey className="p-2 icon-dim-20 dc__no-shrink scn-6" />
<span className="cn-9 fs-12 fw-4 lh-20">Inherited from</span>
<BaseConfigurationNavigation baseConfigurationURL={baseConfigurationURL} />
</div>
Expand All @@ -158,7 +158,7 @@ const ConfigToolbar = ({
<>
{headerMessage && configHeaderTab === ConfigHeaderTabType.VALUES && !showProtectedTabs && (
<div className="flexbox dc__align-items-center dc__gap-6">
<ICInfoOutlineGrey className="p-2 icon-dim-20 dc__no-shrink" />
<ICInfoOutlineGrey className="p-2 icon-dim-20 dc__no-shrink scn-6" />
<span className="cn-9 fs-12 fw-4 lh-20">{headerMessage}</span>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,7 @@ const DeploymentTemplate = ({

return (
<div className="flexbox dc__gap-6 dc__align-items-center dc__border-top-n1 bc-n50 py-6 px-10">
<ICInfoOutlineGrey className="flex icon-dim-16 p-2 dc__no-shrink" />
<ICInfoOutlineGrey className="flex icon-dim-16 dc__no-shrink scn-6" />
<div className="flexbox">
<span className="cn-8 fs-12 fw-4 lh-20 dc__truncate">
Application metrics is {!baseDeploymentTemplateData?.isAppMetricsEnabled ? 'not' : ''} enabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* limitations under the License.
*/

import moment from 'moment'
import { Moment12HourExportFormat } from '../../../../../config'
import { getFormattedUTCTimeForExport, UserTypeToFetchType } from '@devtron-labs/devtron-fe-common-lib'
import { ExportToCsvProps } from '@Components/common/ExportToCsv/types'

import { UserPermissionListHeaderProps } from './types'
import ExportToCsv from '../../../../../components/common/ExportToCsv/ExportToCsv'
Expand All @@ -26,6 +26,11 @@ import { LAST_LOGIN_TIME_NULL_STATE } from '../constants'
import { importComponentFromFELibrary } from '../../../../../components/common'

const getStatusExportText = importComponentFromFELibrary('getStatusExportText', null, 'function')
const getUserExportToCsvConfiguration = importComponentFromFELibrary(
'getUserExportToCsvConfiguration',
null,
'function',
)
const showStatus = !!getStatusExportText

const ExportUserPermissionsToCsv = ({
Expand All @@ -37,8 +42,8 @@ const ExportUserPermissionsToCsv = ({
/**
* Returns the list of users which have permission to devtron applications
*/
const getUsersDataToExport = async () => {
const { users } = await getDataToExport()
const getUsersDataToExport: ExportToCsvProps<UserTypeToFetchType>['apiPromise'] = async (selectedConfig) => {
const { users } = await getDataToExport(selectedConfig)
const userList = users.reduce((_usersList, _user) => {
let isRowAdded = false

Expand All @@ -51,19 +56,25 @@ const ExportUserPermissionsToCsv = ({
isRowAdded = true
}

const updatedOn = getFormattedUTCTimeForExport(_user.updatedOn)

const _userData = {
emailId: _user.emailId,
userId: _user.id,
...(showStatus
? {
status: getStatusExportText(_user.userStatus, _user.timeToLive),
permissionStatus: '-',
createdOn: getFormattedUTCTimeForExport(_user.createdOn),
updatedOn,
deletedOn: _user.isDeleted ? updatedOn : '-',
isDeleted: _user.isDeleted,
}
: {}),
lastLoginTime:
_user.lastLoginTime === LAST_LOGIN_TIME_NULL_STATE
? _user.lastLoginTime
: `${moment.utc(_user.lastLoginTime).format(Moment12HourExportFormat)} (UTC)`,
: getFormattedUTCTimeForExport(_user.lastLoginTime),
superAdmin: _user.superAdmin,
group: '-',
project: '-',
Expand Down Expand Up @@ -106,6 +117,10 @@ const ExportUserPermissionsToCsv = ({
},
)
}

if (!isRowAdded) {
_pushToUserList(_userData)
}
}

return _usersList
Expand All @@ -115,7 +130,15 @@ const ExportUserPermissionsToCsv = ({
}

return (
<ExportToCsv disabled={disabled} apiPromise={getUsersDataToExport} fileName={FILE_NAMES.Users} showOnlyIcon />
<ExportToCsv
disabled={disabled}
apiPromise={getUsersDataToExport}
fileName={FILE_NAMES.Users}
showOnlyIcon
{...(getUserExportToCsvConfiguration && {
configuration: getUserExportToCsvConfiguration(),
})}
/>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ import { User } from '../../types'
import { getIsAdminOrSystemUser, parseSearchParams } from '../utils'
import UserPermissionContainer from './UserPermissionContainer'
import { BulkSelectionModalConfig, BulkSelectionModalTypes } from '../../Shared/components/BulkSelection'
import { UserListFilter } from './types'
import { UserListFilter, UserPermissionContainerProps } from './types'

const StatusHeaderCell = importComponentFromFELibrary('StatusHeaderCell', null, 'function')
const getUserTypeToFetchFromSelectedConfigOptions = importComponentFromFELibrary(
'getUserTypeToFetchFromSelectedConfigOptions',
null,
'function',
)

const showStatus = !!StatusHeaderCell

Expand Down Expand Up @@ -102,14 +107,17 @@ const UserPermissionList = () => {

const showLoadingState = isLoading || getIsRequestAborted(error)

const getUserDataForExport = () =>
const getUserDataForExport: UserPermissionContainerProps['getUserDataForExport'] = (selectedConfig) =>
getUserList({
...filterConfig,
showAll: true,
offset: null,
size: null,
sortBy: UserListSortableKeys.email,
sortOrder: SortingOrder.ASC,
...(getUserTypeToFetchFromSelectedConfigOptions && {
typeToFetch: getUserTypeToFetchFromSelectedConfigOptions(selectedConfig),
}),
})

const getSelectAllDialogStatus = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export const userListLoading: User[] = Array.from(Array(DEFAULT_SHIMMER_LOADING_
userRoleGroups: [],
userGroups: [],
superAdmin: false,
createdOn: '',
updatedOn: '',
isDeleted: false,
...getDefaultUserStatusAndTimeout(),
}))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import {
UserListSortableKeys,
UserStatus,
UseUrlFiltersReturnType,
UserTypeToFetchType,
} from '@devtron-labs/devtron-fe-common-lib'
import { ExportToCsvProps } from '@Components/common/ExportToCsv/types'
import { getUserList } from '../../authorization.service'
import { BulkSelectionActionWidgetProps, BulkSelectionModalConfig } from '../../Shared/components/BulkSelection'
import { User } from '../../types'
Expand All @@ -42,7 +44,9 @@ export interface UserPermissionListHeaderProps {
showStatus: boolean
handleSearch: SearchBarProps['handleEnter']
initialSearchText: SearchBarProps['initialSearchText']
getDataToExport: () => ReturnType<typeof getUserList>
getDataToExport: (
...params: Parameters<ExportToCsvProps<UserTypeToFetchType>['apiPromise']>
) => ReturnType<typeof getUserList>
status: UserStatus[]
handleStatusFilterChange: (status: UserStatus[]) => void
}
Expand Down
Loading

0 comments on commit 4e9a833

Please sign in to comment.