From 35717cad17a8361ba85ba846fdb12771b61b37a9 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Mon, 23 Dec 2024 11:24:23 +0200 Subject: [PATCH] feat: update hideFromReadData field to accept an array of strings and implement condition comparison logic --- destinations/data/elasticsearch.yaml | 4 ++- destinations/data/jaeger.yaml | 2 +- destinations/model.go | 2 +- frontend/endpoints/destinations.go | 2 +- frontend/graph/generated.go | 6 ++-- frontend/graph/model/models_gen.go | 2 +- frontend/graph/schema.graphqls | 2 +- .../destination-drawer/build-card.ts | 13 +++++-- .../dynamic-fields/index.tsx | 34 +------------------ frontend/webapp/types/destinations.ts | 2 +- .../resolvers/compare-condition/index.ts | 32 +++++++++++++++++ .../webapp/utils/functions/resolvers/index.ts | 1 + 12 files changed, 56 insertions(+), 46 deletions(-) create mode 100644 frontend/webapp/utils/functions/resolvers/compare-condition/index.ts diff --git a/destinations/data/elasticsearch.yaml b/destinations/data/elasticsearch.yaml index f2827eea8..089093c3d 100644 --- a/destinations/data/elasticsearch.yaml +++ b/destinations/data/elasticsearch.yaml @@ -57,6 +57,7 @@ spec: required: false tooltip: 'Username used for HTTP Basic Authentication' renderCondition: ['ELASTICSEARCH_BASIC_AUTH_ENABLED', '==', 'true'] + hideFromReadData: ['ELASTICSEARCH_BASIC_AUTH_ENABLED', '==', 'false'] - name: ELASTICSEARCH_PASSWORD displayName: Password componentType: input @@ -66,6 +67,7 @@ spec: tooltip: 'Password used for HTTP Basic Authentication' secret: true renderCondition: ['ELASTICSEARCH_BASIC_AUTH_ENABLED', '==', 'true'] + hideFromReadData: ['ELASTICSEARCH_BASIC_AUTH_ENABLED', '==', 'false'] - name: ELASTICSEARCH_TLS_ENABLED displayName: Enable TLS componentType: checkbox @@ -89,4 +91,4 @@ spec: placeholder: '-----BEGIN CERTIFICATE-----' tooltip: 'When using TLS, provide the CA certificate to verify the server. If empty uses system root CA' renderCondition: ['ELASTICSEARCH_TLS_ENABLED', '==', 'true'] - hideFromReadData: true + hideFromReadData: ['true'] diff --git a/destinations/data/jaeger.yaml b/destinations/data/jaeger.yaml index 0281a857b..a39e76b4b 100644 --- a/destinations/data/jaeger.yaml +++ b/destinations/data/jaeger.yaml @@ -43,5 +43,5 @@ spec: placeholder: '-----BEGIN CERTIFICATE-----' tooltip: 'When using TLS, provide the CA certificate to verify the server. If empty uses system root CA' renderCondition: ['JAEGER_TLS_ENABLED', '==', 'true'] - hideFromReadData: true + hideFromReadData: ['true'] testConnectionSupported: true diff --git a/destinations/model.go b/destinations/model.go index 778d0439e..790e5cbfe 100644 --- a/destinations/model.go +++ b/destinations/model.go @@ -46,6 +46,6 @@ type Field struct { Secret bool `yaml:"secret"` InitialValue string `yaml:"initialValue"` RenderCondition []string `yaml:"renderCondition"` - HideFromReadData bool `yaml:"hideFromReadData"` + HideFromReadData []string `yaml:"hideFromReadData"` CustomReadDataLabels []*CustomReadDataLabel `yaml:"customReadDataLabels"` } diff --git a/frontend/endpoints/destinations.go b/frontend/endpoints/destinations.go index edb65193f..5bb6d2ebf 100644 --- a/frontend/endpoints/destinations.go +++ b/frontend/endpoints/destinations.go @@ -115,7 +115,7 @@ type Field struct { Secret bool `json:"secret,omitempty"` InitialValue string `json:"initial_value,omitempty"` RenderCondition []string `json:"render_condition,omitempty"` - HideFromReadData bool `json:"hide_from_read_data,omitempty"` + HideFromReadData []string `json:"hide_from_read_data,omitempty"` CustomReadDataLabels []*CustomReadDataLabel `json:"custom_read_data_labels,omitempty"` } diff --git a/frontend/graph/generated.go b/frontend/graph/generated.go index d5b2663fe..e4a309309 100644 --- a/frontend/graph/generated.go +++ b/frontend/graph/generated.go @@ -7288,9 +7288,9 @@ func (ec *executionContext) _Field_hideFromReadData(ctx context.Context, field g } return graphql.Null } - res := resTmp.(bool) + res := resTmp.([]string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Field_hideFromReadData(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -7300,7 +7300,7 @@ func (ec *executionContext) fieldContext_Field_hideFromReadData(_ context.Contex IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil diff --git a/frontend/graph/model/models_gen.go b/frontend/graph/model/models_gen.go index 47c8ef539..8b79a6e3a 100644 --- a/frontend/graph/model/models_gen.go +++ b/frontend/graph/model/models_gen.go @@ -212,7 +212,7 @@ type Field struct { Secret bool `json:"secret"` InitialValue string `json:"initialValue"` RenderCondition []string `json:"renderCondition"` - HideFromReadData bool `json:"hideFromReadData"` + HideFromReadData []string `json:"hideFromReadData"` CustomReadDataLabels []*CustomReadDataLabel `json:"customReadDataLabels"` } diff --git a/frontend/graph/schema.graphqls b/frontend/graph/schema.graphqls index 243a93374..ba209da7e 100644 --- a/frontend/graph/schema.graphqls +++ b/frontend/graph/schema.graphqls @@ -273,7 +273,7 @@ type Field { secret: Boolean! initialValue: String! renderCondition: [String!]! - hideFromReadData: Boolean! + hideFromReadData: [String!]! customReadDataLabels: [CustomReadDataLabel!]! } diff --git a/frontend/webapp/containers/main/destinations/destination-drawer/build-card.ts b/frontend/webapp/containers/main/destinations/destination-drawer/build-card.ts index e7ca1bbeb..47929808e 100644 --- a/frontend/webapp/containers/main/destinations/destination-drawer/build-card.ts +++ b/frontend/webapp/containers/main/destinations/destination-drawer/build-card.ts @@ -1,4 +1,4 @@ -import { DISPLAY_TITLES, safeJsonParse } from '@/utils'; +import { compareCondition, DISPLAY_TITLES, safeJsonParse } from '@/utils'; import { DataCardRow, DataCardFieldTypes } from '@/reuseable-components'; import type { ActualDestination, DestinationDetailsResponse, ExportedSignals } from '@/types'; @@ -24,9 +24,16 @@ const buildCard = (destination: ActualDestination, destinationTypeDetails?: Dest sortedParsedFields.map(({ key, value }) => { const { displayName, secret, componentProperties, hideFromReadData, customReadDataLabels } = destinationTypeDetails?.fields?.find((field) => field.name === key) || {}; - if (!hideFromReadData) { + const shouldHide = !!hideFromReadData?.length + ? compareCondition( + hideFromReadData, + (destinationTypeDetails?.fields || []).map((field) => ({ name: field.name, value: parsedFields[field.name] ?? null })), + ) + : false; + + if (!shouldHide) { const { type } = safeJsonParse(componentProperties, { type: '' }); - const isSecret = secret || type === 'password' ? new Array(10).fill('•').join('') : ''; + const isSecret = (secret || type === 'password') && !!value.length ? new Array(10).fill('•').join('') : ''; if (!!customReadDataLabels?.length) { customReadDataLabels.forEach(({ condition, ...custom }) => { diff --git a/frontend/webapp/containers/main/destinations/destination-form-body/dynamic-fields/index.tsx b/frontend/webapp/containers/main/destinations/destination-form-body/dynamic-fields/index.tsx index 588e68f31..e99717fc1 100644 --- a/frontend/webapp/containers/main/destinations/destination-form-body/dynamic-fields/index.tsx +++ b/frontend/webapp/containers/main/destinations/destination-form-body/dynamic-fields/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { INPUT_TYPES } from '@/utils'; import type { DynamicField } from '@/types'; +import { compareCondition, INPUT_TYPES } from '@/utils'; import { Dropdown, Input, TextArea, InputList, KeyValueInputsList, Checkbox } from '@/reuseable-components'; interface Props { @@ -9,38 +9,6 @@ interface Props { formErrors: Record; } -const compareCondition = (renderCondition: DynamicField['renderCondition'], fields: DynamicField[]) => { - if (!renderCondition || !renderCondition.length) return true; - - const [key, cond, val] = renderCondition; - const field = fields.find((field) => field.name === key); - - if (!field) { - console.warn(`Field with name ${key} not found, render condition will be ignored`); - return true; - } - - switch (cond) { - case '===': - case '==': - return field.value === val; - case '!==': - case '!=': - return field.value !== val; - case '>': - return field.value > val; - case '<': - return field.value < val; - case '>=': - return field.value >= val; - case '<=': - return field.value <= val; - default: - console.warn(`Invalid condition ${cond}, render condition will be ignored`); - return true; - } -}; - export const DestinationDynamicFields: React.FC = ({ fields, onChange, formErrors }) => { return fields?.map((field) => { const { componentType, renderCondition, ...rest } = field; diff --git a/frontend/webapp/types/destinations.ts b/frontend/webapp/types/destinations.ts index 77943294c..ea8d84895 100644 --- a/frontend/webapp/types/destinations.ts +++ b/frontend/webapp/types/destinations.ts @@ -40,7 +40,7 @@ export interface DestinationDetailsField { secret: boolean; initialValue: string; renderCondition: string[]; - hideFromReadData: boolean; + hideFromReadData: string[]; customReadDataLabels: { condition: string; title: string; diff --git a/frontend/webapp/utils/functions/resolvers/compare-condition/index.ts b/frontend/webapp/utils/functions/resolvers/compare-condition/index.ts new file mode 100644 index 000000000..fff624f65 --- /dev/null +++ b/frontend/webapp/utils/functions/resolvers/compare-condition/index.ts @@ -0,0 +1,32 @@ +export const compareCondition = (renderCondition: string[], fields: { name: string; value: any }[]) => { + if (!renderCondition || !renderCondition.length) return true; + if (renderCondition.length === 1) return renderCondition[0] == 'true'; + + const [key, cond, val] = renderCondition; + const field = fields.find((field) => field.name === key); + + if (!field) { + console.warn(`Field with name ${key} not found, condition will be skipped`); + return true; + } + + switch (cond) { + case '===': + case '==': + return field.value === val; + case '!==': + case '!=': + return field.value !== val; + case '>': + return field.value > val; + case '<': + return field.value < val; + case '>=': + return field.value >= val; + case '<=': + return field.value <= val; + default: + console.warn(`Invalid condition ${cond}, condition will be skipped`); + return true; + } +}; diff --git a/frontend/webapp/utils/functions/resolvers/index.ts b/frontend/webapp/utils/functions/resolvers/index.ts index 5115af1ea..6c3ae5d3c 100644 --- a/frontend/webapp/utils/functions/resolvers/index.ts +++ b/frontend/webapp/utils/functions/resolvers/index.ts @@ -1 +1,2 @@ +export * from './compare-condition'; export * from './get-value-for-range';