Skip to content

Commit 60ae7f5

Browse files
committed
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-common-lib into feat/security-modal
2 parents 2ab53ad + 600429e commit 60ae7f5

File tree

25 files changed

+384
-366
lines changed

25 files changed

+384
-366
lines changed

package-lock.json

Lines changed: 20 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.3.9-beta-1",
3+
"version": "0.3.11-beta-1",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",
@@ -66,7 +66,7 @@
6666
"react-mde": "^11.5.0",
6767
"react-toastify": "9.1.3",
6868
"typescript": "5.5.4",
69-
"vite": "5.4.2",
69+
"vite": "5.4.6",
7070
"vite-plugin-dts": "4.0.3",
7171
"vite-plugin-lib-inject-css": "2.1.1",
7272
"vite-plugin-svgr": "^2.4.0",
@@ -110,7 +110,7 @@
110110
"monaco-editor": "0.44.0"
111111
},
112112
"vite-plugin-svgr": {
113-
"vite": "5.4.2"
113+
"vite": "5.4.6"
114114
}
115115
}
116116
}

src/Common/Drawer/Drawer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const Drawer = ({
4141
maxWidth,
4242
parentClassName,
4343
onEscape,
44+
onClose,
4445
}: drawerInterface) => {
4546
const drawerRef = useRef(null)
4647
useEffect(() => {
@@ -61,7 +62,7 @@ export const Drawer = ({
6162
style['--height'] = height
6263
}
6364
return (
64-
<VisibleModal className="drawer--container" parentClassName={parentClassName || ''} onEscape={onEscape}>
65+
<VisibleModal className="drawer--container" parentClassName={parentClassName || ''} onEscape={onEscape} close={onClose}>
6566
<aside style={style} ref={drawerRef} className={`drawer ${position}`}>
6667
{children}
6768
</aside>

src/Common/Helper.tsx

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,24 @@ import * as Sentry from '@sentry/browser'
2222
import moment from 'moment'
2323
import { useLocation } from 'react-router-dom'
2424
import YAML from 'yaml'
25-
import { ERROR_EMPTY_SCREEN, SortingOrder, EXCLUDED_FALSY_VALUES, DISCORD_LINK, ZERO_TIME_STRING, TOAST_ACCESS_DENIED } from './Constants'
25+
import { deepEquals } from '@rjsf/utils'
26+
import {
27+
ERROR_EMPTY_SCREEN,
28+
SortingOrder,
29+
EXCLUDED_FALSY_VALUES,
30+
DISCORD_LINK,
31+
ZERO_TIME_STRING,
32+
TOAST_ACCESS_DENIED,
33+
} from './Constants'
2634
import { ServerErrors } from './ServerError'
2735
import { AsyncOptions, AsyncState, UseSearchString } from './Types'
28-
import { scrollableInterface, DATE_TIME_FORMAT_STRING, ToastManager, ToastVariantType } from '../Shared'
36+
import {
37+
scrollableInterface,
38+
DATE_TIME_FORMAT_STRING,
39+
ToastManager,
40+
ToastVariantType,
41+
versionComparatorBySortOrder,
42+
} from '../Shared'
2943
import { ReactComponent as ArrowDown } from '../Assets/Icon/ic-chevron-down.svg'
3044

3145
export function showError(serverError, showToastOnUnknownError = true, hideAccessError = false) {
@@ -620,6 +634,7 @@ export const getFilteredChartVersions = (charts, selectedChartType) =>
620634
// Filter chart versions based on selected chart type
621635
charts
622636
.filter((item) => item?.chartType === selectedChartType.value)
637+
.sort((a, b) => versionComparatorBySortOrder(a?.chartVersion, b?.chartVersion))
623638
.map((item) => ({
624639
value: item?.chartVersion,
625640
label: item?.chartVersion,
@@ -818,28 +833,7 @@ export const compareObjectLength = (objA: any, objB: any): boolean => {
818833
* Return deep copy of the object
819834
*/
820835
export function deepEqual(configA: any, configB: any): boolean {
821-
try {
822-
if (configA === configB) {
823-
return true
824-
}
825-
if ((configA && !configB) || (!configA && configB) || !compareObjectLength(configA, configB)) {
826-
return false
827-
}
828-
let isEqual = true
829-
for (const idx in configA) {
830-
if (!isEqual) {
831-
break
832-
} else if (typeof configA[idx] === 'object' && typeof configB[idx] === 'object') {
833-
isEqual = deepEqual(configA[idx], configB[idx])
834-
} else if (configA[idx] !== configB[idx]) {
835-
isEqual = false
836-
}
837-
}
838-
return isEqual
839-
} catch (err) {
840-
showError(err)
841-
return true
842-
}
836+
return deepEquals(configA, configB)
843837
}
844838

845839
export function shallowEqual(objA, objB) {

src/Common/RJSF/Form.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const RJSFForm = (props: FormProps) => (
3939
...templates,
4040
...props.templates,
4141
}}
42+
formContext={props.formData}
4243
widgets={{ ...widgets, ...props.widgets }}
4344
translateString={translateString}
4445
/>

src/Common/RJSF/templates/ObjectFieldTemplate.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { ObjectFieldTemplateProps, canExpand, titleId } from '@rjsf/utils'
17+
import { ObjectFieldTemplateProps, canExpand, titleId, deepEquals } from '@rjsf/utils'
1818
import { JSONPath } from 'jsonpath-plus'
19+
import { convertJSONPointerToJSONPath } from '@Common/Helper'
1920
import { FieldRowWithLabel } from '../common/FieldRow'
2021
import { TitleField } from './TitleField'
2122
import { AddButton } from './ButtonTemplates'
2223
import { RJSFFormSchema } from '../types'
24+
import { parseSchemaHiddenType } from '../utils'
2325

2426
const Field = ({
2527
disabled,
@@ -33,6 +35,7 @@ const Field = ({
3335
schema,
3436
title,
3537
uiSchema,
38+
formContext,
3639
}: ObjectFieldTemplateProps<any, RJSFFormSchema, any>) => {
3740
const hasAdditionalProperties = !!schema.additionalProperties
3841

@@ -54,8 +57,19 @@ const Field = ({
5457
return true
5558
}
5659
try {
57-
const value = JSONPath({ path: hiddenSchemaProp.match, json: formData })?.[0]
58-
const isHidden = value === undefined || hiddenSchemaProp.condition === value
60+
const hiddenSchema = parseSchemaHiddenType(hiddenSchemaProp)
61+
if (!hiddenSchema.path) {
62+
throw new Error('Empty path property of hidden descriptor field')
63+
}
64+
if (!hiddenSchema.path.match(/^\/\w+(\/\w+)*$/g)) {
65+
throw new Error('Provided path is not a valid JSON pointer')
66+
}
67+
// NOTE: formContext is the formData passed to RJSFForm
68+
const value = JSONPath({
69+
path: convertJSONPointerToJSONPath(hiddenSchema.path),
70+
json: formContext,
71+
})?.[0]
72+
const isHidden = value === undefined || deepEquals(hiddenSchema.value, value)
5973
return !isHidden
6074
} catch {
6175
return true

src/Common/RJSF/types.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@ import { StrictRJSFSchema } from '@rjsf/utils'
2020

2121
export type FormProps = Omit<ComponentProps<typeof RJSFForm>, 'validator'>
2222

23-
interface Hidden {
24-
condition: boolean
25-
match: string
23+
export interface MetaHiddenType {
24+
value: any
25+
path: string
2626
}
2727

28+
export type HiddenType =
29+
| MetaHiddenType
30+
| {
31+
condition: any
32+
value: string
33+
}
34+
| string
35+
2836
export interface RJSFFormSchema extends StrictRJSFSchema {
2937
properties: {
3038
[key: string]: RJSFFormSchema
3139
}
32-
hidden: Hidden
40+
hidden: HiddenType
3341
}

src/Common/RJSF/utils.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { TranslatableString, englishStringTranslator } from '@rjsf/utils'
18+
import { HiddenType, MetaHiddenType } from './types'
1819

1920
/**
2021
* Override for the TranslatableString from RJSF
@@ -135,3 +136,59 @@ export const getInferredTypeFromValueType = (value) => {
135136
return 'null'
136137
}
137138
}
139+
140+
const conformPathToPointers = (path: string): string => {
141+
if (!path) {
142+
return ''
143+
}
144+
const trimmedPath = path.trim()
145+
const isSlashSeparatedPathMissingBeginSlash = trimmedPath.match(/^\w+(\/\w+)*$/g)
146+
if (isSlashSeparatedPathMissingBeginSlash) {
147+
return `/${trimmedPath}`
148+
}
149+
const isDotSeparatedPath = trimmedPath.match(/^\w+(\.\w+)*$/g)
150+
if (isDotSeparatedPath) {
151+
// NOTE: replacing dots with forward slash (/)
152+
return `/${trimmedPath.replaceAll(/\./g, '/')}`
153+
}
154+
return trimmedPath
155+
}
156+
157+
const emptyMetaHiddenTypeInstance: MetaHiddenType = {
158+
value: false,
159+
path: '',
160+
}
161+
162+
export const parseSchemaHiddenType = (hiddenSchema: HiddenType): MetaHiddenType => {
163+
if (!hiddenSchema) {
164+
return null
165+
}
166+
const clone = structuredClone(hiddenSchema)
167+
if (typeof clone === 'string') {
168+
return {
169+
value: false,
170+
path: conformPathToPointers(clone),
171+
}
172+
}
173+
if (typeof clone !== 'object') {
174+
return structuredClone(emptyMetaHiddenTypeInstance)
175+
}
176+
if (
177+
Object.hasOwn(clone, 'condition') &&
178+
'condition' in clone &&
179+
Object.hasOwn(clone, 'value') &&
180+
'value' in clone
181+
) {
182+
return {
183+
value: clone.condition,
184+
path: conformPathToPointers(clone.value),
185+
}
186+
}
187+
if (Object.hasOwn(clone, 'value') && 'value' in clone && Object.hasOwn(clone, 'path') && 'path' in clone) {
188+
return {
189+
value: clone.value,
190+
path: conformPathToPointers(clone.path),
191+
}
192+
}
193+
return structuredClone(emptyMetaHiddenTypeInstance)
194+
}

src/Common/Tooltip/constants.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const TOOLTIP_CONTENTS = {
2+
INVALID_INPUT: 'Valid input is required for all mandatory fields.',
3+
}

src/Common/Tooltip/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default as Tooltip } from './Tooltip'
2+
export { TOOLTIP_CONTENTS } from './constants'

src/Pages/GlobalConfigurations/DeploymentCharts/utils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { versionComparatorBySortOrder } from '@Shared/Helpers'
2-
import { SortingOrder } from '@Common/Constants'
32
import { DeploymentChartListDTO, DeploymentChartType, DEVTRON_DEPLOYMENT_CHART_NAMES } from './types'
43
import fallbackGuiSchema from './basicViewSchema.json'
54

@@ -31,7 +30,7 @@ export const convertDeploymentChartListToChartType = (data: DeploymentChartListD
3130
{} as Record<string, DeploymentChartType>,
3231
)
3332
const result = Object.values(chartMap).map((element) => {
34-
element.versions.sort((a, b) => versionComparatorBySortOrder(a, b, 'version', SortingOrder.DESC))
33+
element.versions.sort((a, b) => versionComparatorBySortOrder(a.version, b.version))
3534
return element
3635
})
3736
return result
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.gui-yaml-switch.status-filter-button {
2+
&.radio-group {
3+
.radio__item-label {
4+
padding: 2px 8px;
5+
display: flex;
6+
align-items: center;
7+
gap: 6px;
8+
}
9+
}
10+
11+
&.with-menu-button {
12+
border-top-right-radius: 0;
13+
border-bottom-right-radius: 0;
14+
15+
.radio:last-child > .radio__item-label {
16+
border-right: none;
17+
border-top-right-radius: 0 !important;
18+
border-bottom-right-radius: 0 !important;
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)