Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-components): fdm support in rule based core #4706

Merged
merged 39 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1bf19c7
add a hook to get all instances from all direct connections and merge…
danpriori Aug 2, 2024
2a4a932
move direct connection with properties hook and adapt the initial fun…
danpriori Aug 7, 2024
4178c29
adapting styling groups accross components to support fdm styling gro…
danpriori Aug 8, 2024
072ddbc
insert fdm types for rule type definitions
danpriori Aug 9, 2024
062d32a
refactoring expression types
danpriori Aug 9, 2024
cc21e37
add datetime and boolean expressions statements
danpriori Aug 11, 2024
6c064fb
refactoring and add property trigger for numeric expression supportin…
danpriori Aug 11, 2024
0c00b6b
add optional parameters for the fdm typing type
danpriori Aug 12, 2024
9652578
fix property types
danpriori Aug 13, 2024
94990d4
fix date statement and fdm externalid for styling list
danpriori Aug 14, 2024
c761767
fix datetime limit type for between and notbetween
danpriori Aug 14, 2024
01b96bc
add expression safeguards
danpriori Aug 14, 2024
79e8b04
refactoring and remove duplicated timeserie ids when traversing expre…
danpriori Aug 15, 2024
eacfd1e
update and export fdm types and some cleanup
danpriori Aug 15, 2024
84e41d4
add fdm new conditions
danpriori Aug 15, 2024
547b33a
stories cleanup
danpriori Aug 15, 2024
bc5759e
cleanup fdmsdk log
danpriori Aug 15, 2024
7c3023d
Merge branch 'master' into danpriori/BND3D-4440-fdm-support-in-rule-b…
danpriori Aug 16, 2024
cb5a96b
use isLoading flag for the spinner accuracy and some refactoring on l…
danpriori Aug 16, 2024
c01a542
reduce complexity a bit
danpriori Aug 17, 2024
52e3dc3
refactoring for some small optimizations
danpriori Aug 17, 2024
e2f3a47
lint fix
danpriori Aug 17, 2024
6dcaf86
export fdm types for rule based
danpriori Aug 23, 2024
b431279
refactoring some rule type definitions to support correct typing data
danpriori Aug 24, 2024
bae8c30
fix datetimecondition definition
danpriori Aug 24, 2024
d92aefc
fix boolean condition types and export unique types list for numeric …
danpriori Aug 26, 2024
38609cc
add into index
danpriori Aug 26, 2024
df1d9c4
dont request assetids from ts if it is empty
danpriori Aug 27, 2024
de9d55a
changes from cr
danpriori Aug 28, 2024
d49a527
Merge branch 'master' into danpriori/BND3D-4440-fdm-support-in-rule-b…
danpriori Aug 28, 2024
96e4e6f
Merge branch 'danpriori/BND3D-4440-fdm-support-in-rule-based-core' of…
danpriori Aug 28, 2024
38b69a9
lint fix
danpriori Aug 28, 2024
349a1cd
Merge branch 'master' into danpriori/BND3D-4440-fdm-support-in-rule-b…
danpriori Aug 28, 2024
cca35f4
Merge remote-tracking branch 'origin/master' into danpriori/BND3D-444…
danpriori Aug 28, 2024
9137322
Merge branch 'danpriori/BND3D-4440-fdm-support-in-rule-based-core' of…
danpriori Aug 28, 2024
8678ff5
Merge branch 'master' into danpriori/BND3D-4440-fdm-support-in-rule-b…
danpriori Aug 28, 2024
84b9713
use createFdmKey - cr
danpriori Aug 28, 2024
9a85ccf
Merge branch 'danpriori/BND3D-4440-fdm-support-in-rule-based-core' of…
danpriori Aug 28, 2024
2b9a892
add createFdmKey for uniqBy
danpriori Aug 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ export const RuleBasedOutputsButton = ({
setIsRuleLoading(hasRuleLoading);
}, [isAllMappingsFetched, currentStylingGroups, isRuleLoadingFromContext, newRuleSetEnabled]);

const handleAllMappingsFetched = useCallback((value: boolean) => {
setIsAllMappingsFetched(value);
}, []);

const onChange = useCallback(
(data: string | undefined): void => {
const emptySelection = generateEmptyRuleForSelection(
Expand Down Expand Up @@ -175,7 +171,7 @@ export const RuleBasedOutputsButton = ({
{ruleInstances !== undefined && ruleInstances?.length > 0 && (
<RuleBasedOutputsSelector
onRuleSetChanged={ruleSetStylingChanged}
onAllMappingsFetched={handleAllMappingsFetched}
onAllMappingsFetched={setIsAllMappingsFetched}
ruleSet={currentRuleSetEnabled?.rule.properties}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/*!
* Copyright 2024 Cognite AS
*/
import { useEffect, type ReactElement, useState } from 'react';
import { useEffect, type ReactElement, useState, useMemo } from 'react';

import { CogniteCadModel } from '@cognite/reveal';
import { type RuleOutputSet, type AllMappingStylingGroupAndStyleIndex } from './types';
import {
type RuleOutputSet,
type AllMappingStylingGroupAndStyleIndex,
type FdmInstanceNodeWithConnectionAndProperties
} from './types';
import { generateRuleBasedOutputs } from './utils';
import { use3dModels } from '../../hooks/use3dModels';
import { type Datapoints, type Asset, type AssetMapping3D } from '@cognite/sdk';
import { isDefined } from '../../utilities/isDefined';
import {
type FdmInstanceNodeWithConnectionAndProperties,
type AssetIdsAndTimeseries
} from '../../data-providers/types';
import { type AssetIdsAndTimeseries } from '../../data-providers/types';
import { useAssetsAndTimeseriesLinkageDataQuery } from '../../query/useAssetsAndTimeseriesLinkageDataQuery';
import { useAssetMappedNodesForRevisions } from '../CacheProvider/AssetMappingAndNode3DCacheProvider';
import { type CadModelOptions } from '../Reveal3DResources/types';
Expand Down Expand Up @@ -63,10 +64,11 @@ export function RuleBasedOutputsSelector({
const { data: fdmMappedEquipmentEdges, isLoading: isFdmMappingsEdgesLoading } =
useMappedEdgesForRevisions(cadModels, true);

const fdmConnectionWithNodeAndViewList =
fdmMappedEquipmentEdges !== undefined
const fdmConnectionWithNodeAndViewList = useMemo(() => {
return fdmMappedEquipmentEdges !== undefined
? Array.from(fdmMappedEquipmentEdges.values()).flat()
: [];
}, [fdmMappedEquipmentEdges]);

const { data: fdmMappings, isLoading: isFdmMappingsLoading } =
useAll3dDirectConnectionsWithProperties(fdmConnectionWithNodeAndViewList);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*!
* Copyright 2024 Cognite AS
*/

import { type FdmPropertyType } from '../../Reveal3DResources/types';
import { type Expression, type TriggerTypeData } from '../types';
import { getFdmPropertyTrigger } from '../utils';

export const checkBooleanExpressionStatement = (
triggerTypeData: TriggerTypeData[],
expression: Expression
): boolean | undefined => {
const condition = expression.type === 'booleanExpression' ? expression.condition : undefined;
const trigger = expression.type === 'booleanExpression' ? expression.trigger : undefined;

let expressionResult: boolean | undefined = false;

if (condition === undefined || trigger === undefined) return;

const currentTriggerData = triggerTypeData.find(
(triggerType) => triggerType.type === trigger?.type
);

const isFdmTrigger = trigger?.type === 'fdm' && currentTriggerData?.type === 'fdm';

if (isFdmTrigger && currentTriggerData.instanceNode.items.length === 0) return;

const fdmItemsTrigger =
isFdmTrigger && currentTriggerData.instanceNode.items[0] !== undefined
? currentTriggerData.instanceNode.items[0]
: undefined;

const fdmPropertyTrigger = isFdmTrigger
? (fdmItemsTrigger?.properties as FdmPropertyType<unknown>)
: undefined;

const propertyTrigger = getFdmPropertyTrigger<boolean>(fdmPropertyTrigger, trigger);

switch (condition.type) {
case 'equals': {
expressionResult = propertyTrigger === true;
break;
}
case 'notEquals': {
expressionResult = propertyTrigger === false;
break;
}
}
return expressionResult;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*!
* Copyright 2024 Cognite AS
*/

import { type FdmPropertyType } from '../../Reveal3DResources/types';
import { type TriggerTypeData, type DatetimeExpression } from '../types';
import { getFdmPropertyTrigger } from '../utils';

export const checkDatetimeExpressionStatement = (
triggerTypeData: TriggerTypeData[],
expression: DatetimeExpression
): boolean | undefined => {
const { trigger, condition } = expression;

let expressionResult: boolean | undefined = false;

const currentTriggerData = triggerTypeData.find(
(triggerType) => triggerType.type === trigger?.type
);

const isFdmTrigger = trigger?.type === 'fdm' && currentTriggerData?.type === 'fdm';

if (isFdmTrigger && currentTriggerData.instanceNode.items.length === 0) return;

const fdmItemsTrigger =
isFdmTrigger && currentTriggerData.instanceNode.items[0] !== undefined
? currentTriggerData.instanceNode.items[0]
: undefined;

const fdmPropertyTrigger = isFdmTrigger
? (fdmItemsTrigger?.properties as FdmPropertyType<unknown>)
: undefined;

const propertyTrigger = new Date(
getFdmPropertyTrigger<string>(fdmPropertyTrigger, trigger) ?? ''
);

switch (condition.type) {
case 'before': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger < conditionValue : false;
break;
}
case 'notBefore': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger >= conditionValue : false;
break;
}
case 'onOrBefore': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger <= conditionValue : false;
break;
}
case 'between': {
const lowerBound = new Date(condition.lowerBound);
const upperBound = new Date(condition.upperBound);
expressionResult =
propertyTrigger !== undefined
? lowerBound < propertyTrigger && propertyTrigger < upperBound
: false;
break;
}
case 'notBetween': {
const lowerBound = new Date(condition.lowerBound);
const upperBound = new Date(condition.upperBound);
expressionResult =
propertyTrigger !== undefined
? !(lowerBound < propertyTrigger && propertyTrigger < upperBound)
: false;
break;
}
case 'after': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger > conditionValue : false;
break;
}
case 'notAfter': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger <= conditionValue : false;
break;
}
case 'onOrAfter': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger >= conditionValue : false;
break;
}
case 'on': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger === conditionValue : false;
break;
}
case 'notOn': {
const conditionValue = new Date(condition.parameter);
expressionResult = propertyTrigger !== undefined ? propertyTrigger !== conditionValue : false;
break;
}
}

return expressionResult;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*!
* Copyright 2024 Cognite AS
*/

import { type FdmPropertyType } from '../../Reveal3DResources/types';
import { type NumericExpression, type TriggerTypeData } from '../types';
import { getFdmPropertyTrigger, getTriggerNumericData } from '../utils';

export const checkNumericExpressionStatement = (
triggerTypeData: TriggerTypeData[],
expression: NumericExpression
): boolean | undefined => {
const { trigger, condition } = expression;

let expressionResult: boolean = false;
let propertyTrigger: number | undefined;

const currentTriggerData = triggerTypeData.find(
(triggerType) => triggerType.type === trigger?.type
);

const isFdmTrigger = trigger?.type === 'fdm' && currentTriggerData?.type === 'fdm';

const assetOrTimeseriesDataTrigger = !isFdmTrigger
? getTriggerNumericData(triggerTypeData, trigger)
: undefined;

const fdmItemsTrigger =
isFdmTrigger && currentTriggerData.instanceNode.items[0] !== undefined
? currentTriggerData.instanceNode.items[0]
: undefined;

const fdmPropertyTrigger = isFdmTrigger
? (fdmItemsTrigger?.properties as FdmPropertyType<unknown>)
: undefined;

if (assetOrTimeseriesDataTrigger === undefined && fdmPropertyTrigger === undefined) return;

if (isFdmTrigger) {
propertyTrigger = getFdmPropertyTrigger<number>(fdmPropertyTrigger, trigger);
} else {
propertyTrigger = assetOrTimeseriesDataTrigger;
}

if (propertyTrigger === undefined) return;

switch (condition.type) {
case 'equals': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger === parameter;
break;
}
case 'notEquals': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger !== parameter;
break;
}
case 'lessThan': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger < parameter;
break;
}
case 'greaterThan': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger > parameter;
break;
}
case 'lessThanOrEquals': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger <= parameter;
break;
}
case 'greaterThanOrEquals': {
const parameter = condition.parameters[0];
expressionResult = propertyTrigger >= parameter;
break;
}
case 'within': {
const lower = condition.lowerBoundInclusive;
const upper = condition.upperBoundInclusive;
expressionResult = lower < propertyTrigger && propertyTrigger < upper;
break;
}
case 'outside': {
const lower = condition.lowerBoundExclusive;
const upper = condition.upperBoundExclusive;
expressionResult = propertyTrigger <= lower && upper <= propertyTrigger;
break;
}
}

return expressionResult;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*!
* Copyright 2024 Cognite AS
*/

import { type FdmPropertyType } from '../../Reveal3DResources/types';
import { type StringExpression, type TriggerTypeData } from '../types';
import { getFdmPropertyTrigger } from '../utils';

export const checkStringExpressionStatement = (
triggerTypeData: TriggerTypeData[],
expression: StringExpression
): boolean | undefined => {
const { trigger, condition } = expression;

let expressionResult: boolean | undefined = false;

let propertyTrigger: string | undefined;

const currentTriggerData = triggerTypeData.find(
(triggerType) => triggerType.type === trigger?.type
);

const isMetadataAndAssetTrigger =
trigger?.type === 'metadata' &&
currentTriggerData?.type === 'metadata' &&
currentTriggerData?.asset !== undefined;

const isFdmTrigger = trigger?.type === 'fdm' && currentTriggerData?.type === 'fdm';

const assetTrigger = isMetadataAndAssetTrigger
? currentTriggerData?.asset[trigger.type]?.[trigger.key]
: undefined;

const fdmItemsTrigger =
isFdmTrigger && currentTriggerData.instanceNode.items[0] !== undefined
? currentTriggerData.instanceNode.items[0]
: undefined;

const fdmPropertyTrigger = isFdmTrigger
? (fdmItemsTrigger?.properties as FdmPropertyType<unknown>)
: undefined;

if (isMetadataAndAssetTrigger) {
propertyTrigger = assetTrigger;
} else if (isFdmTrigger) {
propertyTrigger = getFdmPropertyTrigger<string>(fdmPropertyTrigger, trigger);
}

switch (condition.type) {
case 'equals': {
expressionResult = propertyTrigger === condition.parameter;
break;
}
case 'notEquals': {
expressionResult = propertyTrigger !== condition.parameter;
break;
}
case 'contains': {
expressionResult = propertyTrigger?.includes(condition.parameter);
break;
}
case 'startsWith': {
expressionResult = propertyTrigger?.startsWith(condition.parameter);
break;
}
case 'endsWith': {
expressionResult = propertyTrigger?.endsWith(condition.parameter);
break;
}
}

return expressionResult;
};
Loading
Loading