diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index 7a001b0d..b438fcff 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -82,6 +82,29 @@ export interface Field { dataFileId?: string; dataFileKey?: string; dataFileValue?: string; + + // When clause + when?: WhenClause; +} + +export enum WhenOperator { + equals = "eq", + notEquals = "neq", + contains = "contains", + notContains = "notContains", + startsWith = "startsWith", + endsWith = "endsWith", + greaterThan = "gt", + greaterThanOrEqual = "gte", + lessThan = "lt", + lessThanOrEqual = "lte", +} + +export interface WhenClause { + fieldRef: string; + operator: WhenOperator; + value: any; + caseSensitive?: boolean; } export interface DateInfo { diff --git a/src/panelWebView/components/Fields/WrapperField.tsx b/src/panelWebView/components/Fields/WrapperField.tsx index e666cdce..292e35bf 100644 --- a/src/panelWebView/components/Fields/WrapperField.tsx +++ b/src/panelWebView/components/Fields/WrapperField.tsx @@ -1,10 +1,8 @@ - - import { Messenger } from '@estruyf/vscode/dist/client'; import * as React from 'react'; import { useCallback, useEffect, useState } from 'react'; import { DateHelper } from '../../../helpers/DateHelper'; -import { BlockFieldData, Field, PanelSettings } from '../../../models'; +import { BlockFieldData, Field, PanelSettings, WhenOperator } from '../../../models'; import { Command } from '../../Command'; import { CommandToCode } from '../../CommandToCode'; import { TagType } from '../../TagType'; @@ -16,6 +14,7 @@ import { JsonField } from '../JsonField'; import { IMetadata } from '../Metadata'; import { TagPicker } from '../TagPicker'; import { ChoiceField, DataFileField, DateTimeField, DraftField, FieldTitle, FileField, ListField, Toggle, TextField, SlugField, PreviewImageField, PreviewImageValue, NumberField } from '.'; +import { fieldWhenClause } from '../../../utils/fieldWhenClause'; export interface IWrapperFieldProps { field: Field; @@ -111,6 +110,16 @@ export const WrapperField: React.FunctionComponent = ({ return null; } + // Conditional fields + if (typeof field.when !== "undefined") { + const shouldRender = fieldWhenClause(field, parent); + + if (!shouldRender) { + return null; + } + } + + if (field.type === 'divider') { return (
diff --git a/src/utils/fieldWhenClause.ts b/src/utils/fieldWhenClause.ts new file mode 100644 index 00000000..f20c539c --- /dev/null +++ b/src/utils/fieldWhenClause.ts @@ -0,0 +1,126 @@ +import { WhenClause } from './../models/PanelSettings'; +import { Field, WhenOperator } from "../models"; +import { IMetadata } from "../panelWebView/components/Metadata"; + +/** + * Validate the field its "when" clause + * @param field + * @param parent + * @returns + */ +export const fieldWhenClause = (field: Field, parent: IMetadata): boolean => { + const when = field.when; + if (!when) { + return true; + } + + let whenValue = parent[when.fieldRef]; + if (when.caseSensitive || typeof when.caseSensitive === "undefined") { + return caseSensitive(when, field, whenValue); + } else { + return caseInsensitive(when, field, whenValue); + } +} + +/** + * Case sensitive checks + * @param when + * @param field + * @param whenValue + * @returns + */ +const caseInsensitive = (when: WhenClause, field: Field, whenValue: string | IMetadata | string[] | null) => { + whenValue = lowerValue(whenValue); + + const whenClone = Object.assign({}, when); + whenClone.value = lowerValue(whenClone.value); + + return caseSensitive(whenClone, field, whenValue); +} + +/** + * Case insensitive checks + * @param when + * @param field + * @param whenValue + * @returns + */ +const caseSensitive = (when: WhenClause, field: Field, whenValue: string | IMetadata | string[] | null) => { + switch (when.operator) { + case WhenOperator.equals: + if (whenValue !== when.value) { + return false; + } + break; + case WhenOperator.notEquals: + if (whenValue === when.value) { + return false; + } + break; + case WhenOperator.contains: + if ((typeof whenValue === "string" || whenValue instanceof Array) && !whenValue.includes(when.value)) { + return false; + } + break; + case WhenOperator.notContains: + if ((typeof whenValue === "string" || whenValue instanceof Array) && whenValue.includes(when.value)) { + return false; + } + break; + case WhenOperator.startsWith: + if (typeof whenValue === "string" && !whenValue.startsWith(when.value)) { + return false; + } + break; + case WhenOperator.endsWith: + if (typeof whenValue === "string" && !whenValue.endsWith(when.value)) { + return false; + } + break; + case WhenOperator.greaterThan: + if (typeof whenValue === "number" && whenValue <= when.value) { + return false; + } + break; + case WhenOperator.greaterThanOrEqual: + if (typeof whenValue === "number" && whenValue < when.value) { + return false; + } + break; + case WhenOperator.lessThan: + if (typeof whenValue === "number" && whenValue >= when.value) { + return false; + } + break; + case WhenOperator.lessThanOrEqual: + if (typeof whenValue === "number" && whenValue > when.value) { + return false; + } + break; + default: + break; + } + + return true; +} + +/** + * Lower the value(s) + * @param value + * @returns + */ +const lowerValue = (value: string | string[] | any) => { + if (typeof value === "string") { + value = value.toLowerCase(); + } else if (value instanceof Array) { + value = value.map(crntValue => { + if (typeof crntValue === "string") { + return crntValue.toLowerCase(); + } + + return crntValue; + }); + } + + return value; +} \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index c23da193..9b5f7e53 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,6 @@ export * from './copyFileAsync'; export * from './existsAsync'; +export * from './fieldWhenClause'; export * from './mkdirAsync'; export * from './readFileAsync'; export * from './readdirAsync';