Skip to content

Commit 5d4b49f

Browse files
committed
Merge branch 'main' into approval-via-email
1 parent 3d344d8 commit 5d4b49f

File tree

59 files changed

+1537
-678
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1537
-678
lines changed

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ ANNOUNCEMENT_BANNER_MSG=
3838
LOGIN_PAGE_IMAGE=
3939
LOGIN_PAGE_IMAGE_BG=
4040
HIDE_DEFAULT_CLUSTER=false
41+
GLOBAL_API_TIMEOUT=60000
42+
TRIGGER_API_TIMEOUT=60000

config.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,7 @@
2828
| LOGIN_PAGE_IMAGE | "" | Login page image url |
2929
| LOGIN_PAGE_IMAGE_BG | "" | Login page image background color code |
3030
| DEFAULT_CI_TRIGGER_TYPE_MANUAL | "false" | Change default trigger behaviour of newly created ci-pipeline to manual |
31+
| GLOBAL_API_TIMEOUT | 60000 | Default timeout for all API requests in DASHBOARD |
32+
| TRIGGER_API_TIMEOUT | 60000 | Default timeout for all API requests for Trigger calls (Deploy artifacts, charts) in DASHBOARD |
3133

3234
# DASHBOARD CONFIG SECRET

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "0.0.51-beta-3-1",
7+
"@devtron-labs/devtron-fe-common-lib": "0.0.52-beta-2",
88
"@rjsf/core": "^5.13.3",
99
"@rjsf/utils": "^5.13.3",
1010
"@rjsf/validator-ajv8": "^5.13.3",

src/components/ApplicationGroup/Details/EnvironmentConfig/EnvConfig.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ export default function EnvConfig({ filteredAppIds, envName }: AppGroupDetailDef
7171
</div>
7272
</div>
7373
<div className="env-compose__main">
74-
<EnvironmentOverride appList={envAppList} environments={[]} reloadEnvironments={noop} envName={envName}/>
74+
<EnvironmentOverride
75+
appList={envAppList}
76+
environments={[]}
77+
reloadEnvironments={noop}
78+
envName={envName}
79+
/>
7580
</div>
7681
</div>
7782
)

src/components/CodeEditor/CodeEditor.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useEffect, useCallback, useReducer, useRef } from 'react'
22
import MonacoEditor, { MonacoDiffEditor } from 'react-monaco-editor';
3-
import { useJsonYaml, Select, RadioGroup, useWindowSize } from '../common'
4-
import { Progressing, copyToClipboard } from '@devtron-labs/devtron-fe-common-lib'
3+
import { useJsonYaml, Select, RadioGroup } from '../common'
4+
import { Progressing, copyToClipboard, useWindowSize } from '@devtron-labs/devtron-fe-common-lib'
55
import { ReactComponent as ClipboardIcon } from '../../assets/icons/ic-copy.svg';
66
import { ReactComponent as Info } from '../../assets/icons/ic-info-filled.svg';
77
import { ReactComponent as ErrorIcon } from '../../assets/icons/ic-error-exclamation.svg';
@@ -48,7 +48,7 @@ interface CodeEditorInterface {
4848
onFocus?: () => void;
4949
children?: any;
5050
defaultValue?: string;
51-
mode?: 'json' | 'yaml' | 'shell' | 'dockerfile';
51+
mode?: 'json' | 'yaml' | 'shell' | 'dockerfile' | 'plaintext';
5252
tabSize?: number;
5353
readOnly?: boolean;
5454
noParsing?: boolean;
@@ -110,7 +110,7 @@ interface Action {
110110
}
111111

112112
interface CodeEditorState {
113-
mode: 'json' | 'yaml' | 'shell' | 'dockerfile';
113+
mode: 'json' | 'yaml' | 'shell' | 'dockerfile' | 'plaintext';
114114
diffMode: boolean;
115115
theme: 'vs' | 'vs-dark';
116116
code: string;

src/components/ConfigMapSecret/ConfigMapSecretForm.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ export const ConfigMapSecretForm = React.memo(
11011101
toggleModal={toggleDraftSaveModal}
11021102
latestDraft={latestDraftData}
11031103
reload={reloadData}
1104+
showAsModal={true}
11041105
/>
11051106
)}
11061107
</>

src/components/EnvironmentOverride/DeploymentTemplateOverride.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function DeploymentTemplateOverride({
3838
isProtected,
3939
reloadEnvironments,
4040
}: DeploymentTemplateOverrideProps) {
41-
const { currentServerInfo } = useContext(mainContext)
41+
const { currentServerInfo, isSuperAdmin } = useContext(mainContext)
4242
const { appId, envId } = useParams<{ appId; envId }>()
4343
const [, grafanaModuleStatus] = useAsync(() => getModuleInfo(ModuleNameMap.GRAFANA), [appId])
4444
const [state, dispatch] = useReducer<Reducer<DeploymentConfigStateWithDraft, DeploymentConfigStateAction>>(
@@ -501,6 +501,7 @@ export default function DeploymentTemplateOverride({
501501
setManifestDataRHS={setManifestDataRHSOverride}
502502
setManifestDataLHS={setManifestDataLHSOverride}
503503
convertVariablesOverride={state.convertVariablesOverride}
504+
isSuperAdmin={isSuperAdmin}
504505
/>
505506
)}
506507
</div>

src/components/EnvironmentOverride/DeploymentTemplateOverrideForm.tsx

Lines changed: 127 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import React, { useEffect, useMemo, useState } from 'react'
22
import { useParams } from 'react-router-dom'
33
import { toast } from 'react-toastify'
44
import YAML from 'yaml'
5-
import { Progressing } from '@devtron-labs/devtron-fe-common-lib'
5+
import { Progressing, getLockedJSON, getUnlockedJSON } from '@devtron-labs/devtron-fe-common-lib'
66
import { FloatingVariablesSuggestions, importComponentFromFELibrary, useJsonYaml } from '../common'
7-
import { DeploymentConfigStateActionTypes } from '../deploymentConfig/types'
7+
import { ConfigKeysWithLockType, DeploymentConfigStateActionTypes } from '../deploymentConfig/types'
88
import { EDITOR_VIEW } from '../deploymentConfig/constants'
99
import { DEPLOYMENT, ROLLOUT_DEPLOYMENT } from '../../config'
1010
import { createDeploymentTemplate, updateDeploymentTemplate } from './service'
@@ -14,6 +14,7 @@ import DeploymentTemplateOptionsTab from '../deploymentConfig/DeploymentTemplate
1414
import DeploymentTemplateEditorView from '../deploymentConfig/DeploymentTemplateView/DeploymentTemplateEditorView'
1515
import DeploymentConfigFormCTA from '../deploymentConfig/DeploymentTemplateView/DeploymentConfigFormCTA'
1616
import { DeploymentConfigContext } from '../deploymentConfig/DeploymentConfig'
17+
import { getDeploymentManisfest, getIfLockedConfigProtected } from '../deploymentConfig/service'
1718
import { DeleteOverrideDialog } from '../deploymentConfig/DeploymentTemplateView/DeploymentTemplateView.component'
1819
import DeploymentTemplateReadOnlyEditorView from '../deploymentConfig/DeploymentTemplateView/DeploymentTemplateReadOnlyEditorView'
1920
import DeploymentConfigToolbar from '../deploymentConfig/DeploymentTemplateView/DeploymentConfigToolbar'
@@ -25,12 +26,12 @@ import {
2526
updateTemplateFromBasicValue,
2627
validateBasicView,
2728
} from '../deploymentConfig/DeploymentConfig.utils'
28-
import { getDeploymentManisfest } from '../deploymentConfig/service'
29+
import CodeEditor from '../CodeEditor/CodeEditor'
2930

3031
const ConfigToolbar = importComponentFromFELibrary('ConfigToolbar', DeploymentConfigToolbar)
3132
const SaveChangesModal = importComponentFromFELibrary('SaveChangesModal')
3233
const DeleteOverrideDraftModal = importComponentFromFELibrary('DeleteOverrideDraftModal')
33-
34+
const DeploymentTemplateLockedDiff = importComponentFromFELibrary('DeploymentTemplateLockedDiff')
3435
export default function DeploymentTemplateOverrideForm({
3536
state,
3637
isConfigProtectionEnabled,
@@ -52,10 +53,19 @@ export default function DeploymentTemplateOverrideForm({
5253
setManifestDataRHS,
5354
setManifestDataLHS,
5455
convertVariablesOverride,
56+
isSuperAdmin,
5557
}) {
5658
const [obj, , , error] = useJsonYaml(state.tempFormData, 4, 'yaml', true)
5759
const { appId, envId } = useParams<{ appId; envId }>()
5860
const readOnlyPublishedMode = state.selectedTabIndex === 1 && isConfigProtectionEnabled && !!state.latestDraft
61+
const [saveEligibleChangesCb, setSaveEligibleChangesCb] = useState(false)
62+
const [showLockedDiffForApproval, setShowLockedDiffForApproval] = useState(false)
63+
const [lockedOverride, setLockedOverride] = useState({})
64+
const [lockedConfigKeysWithLockType, setLockedConfigKeysWithLockType] = useState<ConfigKeysWithLockType>({
65+
config: [],
66+
allowed: false,
67+
})
68+
const [disableSaveEligibleChanges, setDisableSaveEligibleChanges] = useState(false)
5969

6070
useEffect(() => {
6171
// Reset editor value on delete override action
@@ -94,14 +104,25 @@ export default function DeploymentTemplateOverrideForm({
94104
}
95105

96106
const prepareDataToSave = (envOverrideValuesWithBasic, includeInDraft?: boolean) => {
107+
let valuesOverride = envOverrideValuesWithBasic || obj || state.duplicate
108+
if (state.showLockedTemplateDiff) {
109+
// if locked keys
110+
if (!lockedConfigKeysWithLockType.allowed) {
111+
valuesOverride = getUnlockedJSON(lockedOverride, lockedConfigKeysWithLockType.config)
112+
} else {
113+
// if allowed keys
114+
valuesOverride = getLockedJSON(lockedOverride, lockedConfigKeysWithLockType.config)
115+
}
116+
}
97117
const payload = {
98118
environmentId: +envId,
99-
envOverrideValues: envOverrideValuesWithBasic || obj || state.duplicate,
119+
envOverrideValues: valuesOverride,
100120
chartRefId: state.selectedChartRefId,
101121
IsOverride: true,
102122
isAppMetricsEnabled: state.latestDraft ? state.isAppMetricsEnabled : state.data.appMetrics,
103123
currentViewEditor: state.isBasicLocked ? EDITOR_VIEW.ADVANCED : state.currentEditorView,
104124
isBasicLocked: state.isBasicLocked,
125+
saveEligibleChanges: saveEligibleChangesCb,
105126
...(state.data.environmentConfig.id > 0
106127
? {
107128
id: state.data.environmentConfig.id,
@@ -124,8 +145,20 @@ export default function DeploymentTemplateOverrideForm({
124145
return payload
125146
}
126147

127-
async function handleSubmit(e) {
128-
e.preventDefault()
148+
const closeLockedDiffDrawerWithChildModal = () => {
149+
state.showSaveChangesModal && toggleSaveChangesModal()
150+
handleLockedDiffDrawer(false)
151+
setSaveEligibleChangesCb(false)
152+
}
153+
154+
const handleLockedDiffDrawer = (value) => {
155+
dispatch({
156+
type: DeploymentConfigStateActionTypes.toggleShowLockedTemplateDiff,
157+
payload: value,
158+
})
159+
}
160+
161+
const checkForSaveAsDraft = () => {
129162
if (!obj && state.yamlMode) {
130163
toast.error(error)
131164
return
@@ -140,7 +173,35 @@ export default function DeploymentTemplateOverrideForm({
140173
toggleSaveChangesModal()
141174
return
142175
}
176+
}
143177

178+
const handleSaveChanges = (e) => {
179+
e.preventDefault()
180+
handleSubmit(false)
181+
}
182+
183+
const handleChangeCheckbox = () => {
184+
if (!saveEligibleChangesCb) {
185+
checkForSaveAsDraft()
186+
} else {
187+
state.showSaveChangesModal && toggleSaveChangesModal()
188+
}
189+
setSaveEligibleChangesCb(!saveEligibleChangesCb)
190+
}
191+
192+
const checkForProtectedLockedChanges = async () => {
193+
const data = prepareDataToSaveDraft()
194+
const action = data['id'] > 0 ? 2 : 1
195+
const requestPayload = {
196+
appId: Number(appId),
197+
envId: Number(envId),
198+
action,
199+
data: JSON.stringify(data),
200+
}
201+
return await getIfLockedConfigProtected(requestPayload)
202+
}
203+
204+
const handleSubmit = async (saveEligibleChanges: boolean = false) => {
144205
const api =
145206
state.data.environmentConfig && state.data.environmentConfig.id > 0
146207
? updateDeploymentTemplate
@@ -149,8 +210,26 @@ export default function DeploymentTemplateOverrideForm({
149210
!state.yamlMode && patchBasicData(obj || state.duplicate, state.basicFieldValues)
150211

151212
try {
152-
dispatch({ type: DeploymentConfigStateActionTypes.loading, payload: true })
153-
await api(+appId, +envId, prepareDataToSave(envOverrideValuesWithBasic))
213+
if (saveEligibleChanges) {
214+
dispatch({ type: DeploymentConfigStateActionTypes.loading, payload: true })
215+
} else {
216+
//loading state for checking locked changes
217+
dispatch({ type: DeploymentConfigStateActionTypes.lockChangesLoading, payload: true })
218+
}
219+
const deploymentTemplateResp = isConfigProtectionEnabled
220+
? await checkForProtectedLockedChanges()
221+
: await api(+appId, +envId, prepareDataToSave(envOverrideValuesWithBasic, false))
222+
if (deploymentTemplateResp.result.isLockConfigError && !saveEligibleChanges) {
223+
//checking if any locked changes and opening drawer to show eligible and locked ones
224+
setLockedOverride(deploymentTemplateResp.result?.lockedOverride)
225+
setDisableSaveEligibleChanges(deploymentTemplateResp.result?.disableSaveEligibleChanges)
226+
handleLockedDiffDrawer(true)
227+
return
228+
} else if (isConfigProtectionEnabled) {
229+
toggleSaveChangesModal()
230+
return
231+
}
232+
154233
if (envOverrideValuesWithBasic) {
155234
editorOnChange(YAML.stringify(envOverrideValuesWithBasic, { indent: 2 }), true)
156235
}
@@ -174,7 +253,17 @@ export default function DeploymentTemplateOverrideForm({
174253
} catch (err) {
175254
handleConfigProtectionError(2, err, dispatch, reloadEnvironments)
176255
} finally {
177-
dispatch({ type: DeploymentConfigStateActionTypes.loading, payload: false })
256+
if (saveEligibleChanges) {
257+
//closing drawer if selected save eligible changes
258+
handleLockedDiffDrawer(false)
259+
}
260+
dispatch({
261+
type: DeploymentConfigStateActionTypes.multipleOptions,
262+
payload: {
263+
loading: false,
264+
lockChangesLoading: false,
265+
},
266+
})
178267
}
179268
}
180269

@@ -532,7 +621,7 @@ export default function DeploymentTemplateOverrideForm({
532621
className={`deployment-template-override-form h-100 ${state.openComparison ? 'comparison-view' : ''} ${
533622
state.showReadme ? 'readme-view' : ''
534623
}`}
535-
onSubmit={handleSubmit}
624+
onSubmit={handleSaveChanges}
536625
>
537626
<div className="variables-widget-position">
538627
<FloatingVariablesSuggestions zIndex={1004} appId={appId} envId={envId} clusterId={clusterId} />
@@ -544,7 +633,7 @@ export default function DeploymentTemplateOverrideForm({
544633
/>
545634
{renderEditorComponent()}
546635
<DeploymentConfigFormCTA
547-
loading={state.loading || state.chartConfigLoading}
636+
loading={state.loading || state.chartConfigLoading || state.lockChangesLoading}
548637
isEnvOverride={true}
549638
disableButton={!state.duplicate}
550639
disableCheckbox={!state.duplicate}
@@ -565,6 +654,12 @@ export default function DeploymentTemplateOverrideForm({
565654
reload={reload}
566655
isValues={isValuesOverride}
567656
convertVariables={convertVariablesOverride}
657+
handleLockedDiffDrawer={handleLockedDiffDrawer}
658+
setShowLockedDiffForApproval={setShowLockedDiffForApproval}
659+
isSuperAdmin={isSuperAdmin}
660+
checkForProtectedLockedChanges={checkForProtectedLockedChanges}
661+
showLockedDiffForApproval={showLockedDiffForApproval}
662+
setLockedOverride={setLockedOverride}
568663
/>
569664
</form>
570665
)
@@ -603,11 +698,13 @@ export default function DeploymentTemplateOverrideForm({
603698
convertVariables={convertVariablesOverride}
604699
setConvertVariables={setConvertVariables}
605700
componentType={3}
701+
setShowLockedDiffForApproval={setShowLockedDiffForApproval}
702+
setLockedConfigKeysWithLockType={setLockedConfigKeysWithLockType}
606703
/>
607704
{state.selectedTabIndex !== 2 && !state.showReadme && renderOverrideInfoStrip()}
608705
{renderValuesView()}
609706
{state.dialog && <DeleteOverrideDialog appId={appId} envId={envId} initialise={initialise} />}
610-
{SaveChangesModal && state.showSaveChangsModal && (
707+
{SaveChangesModal && state.showSaveChangesModal && (
611708
<SaveChangesModal
612709
appId={Number(appId)}
613710
envId={Number(envId)}
@@ -617,6 +714,9 @@ export default function DeploymentTemplateOverrideForm({
617714
toggleModal={toggleSaveChangesModal}
618715
latestDraft={state.latestDraft}
619716
reload={reload}
717+
closeLockedDiffDrawerWithChildModal={closeLockedDiffDrawerWithChildModal}
718+
showAsModal={!state.showLockedTemplateDiff}
719+
saveEligibleChangesCb={saveEligibleChangesCb}
620720
/>
621721
)}
622722
{DeleteOverrideDraftModal && state.showDeleteOverrideDraftModal && (
@@ -631,6 +731,20 @@ export default function DeploymentTemplateOverrideForm({
631731
reload={reload}
632732
/>
633733
)}
734+
{DeploymentTemplateLockedDiff && state.showLockedTemplateDiff && (
735+
<DeploymentTemplateLockedDiff
736+
CodeEditor={CodeEditor}
737+
closeModal={closeLockedDiffDrawerWithChildModal}
738+
handleChangeCheckbox={handleChangeCheckbox}
739+
saveEligibleChangesCb={saveEligibleChangesCb}
740+
showLockedDiffForApproval={showLockedDiffForApproval}
741+
onSave={handleSubmit}
742+
lockedOverride={lockedOverride}
743+
lockedConfigKeysWithLockType={lockedConfigKeysWithLockType}
744+
disableSaveEligibleChanges={disableSaveEligibleChanges}
745+
setLockedConfigKeysWithLockType={setLockedConfigKeysWithLockType}
746+
/>
747+
)}
634748
</DeploymentConfigContext.Provider>
635749
)
636750
}

src/components/EnvironmentOverride/service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export function getDeploymentTemplate(appId, envId, chartId){
55
return get(`app/env/${appId}/${envId}/${chartId}`)
66
}
77

8+
89
export function updateDeploymentTemplate(appId, envId, payload){
910
return put(`app/env`, payload)
1011
}

src/components/ResourceBrowser/ResourceList/ResourceList.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ export default function ResourceList() {
310310
!isTerminal &&
311311
!isNodes
312312
) {
313-
getResourceListData()
313+
selectedResource.gvk.Kind !== SIDEBAR_KEYS.nodeGVK.Kind && getResourceListData()
314314
setSearchText('')
315315
setSearchApplied(false)
316316
} else if (isNodes) {
@@ -634,7 +634,6 @@ export default function ResourceList() {
634634
setResourceListLoader(true)
635635
setResourceList(null)
636636
setFilteredResourceList([])
637-
638637
const resourceListPayload: ResourceListPayloadType = {
639638
clusterId: Number(clusterId),
640639
k8sRequest: {

0 commit comments

Comments
 (0)