Skip to content

Commit

Permalink
fix(Designer): Allow WorkflowParameters and AppSettings to be used wi…
Browse files Browse the repository at this point in the history
…thin each other in dynamic data (#4410)

* Recursively evaluate wf params and app settings in dynamic data

* Removed console log

* Adjusted vscode
  • Loading branch information
rllyy97 committed Mar 22, 2024
1 parent c7b8e8b commit 6f9b652
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ const DesignerEditor = () => {
<BJSWorkflowProvider
workflow={{ definition: workflow?.definition, connectionReferences, parameters, kind: workflow?.kind }}
runInstance={runInstanceData}
appSettings={settingsData?.properties}
>
<div style={{ height: 'inherit', width: 'inherit' }}>
<DesignerCommandBar
Expand Down
1 change: 1 addition & 0 deletions apps/vs-code-react/src/app/designer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export const DesignerApp = () => {
kind: standardApp.kind,
}}
runInstance={runInstance}
appSettings={panelMetaData?.localSettings}
>
<Designer />
</BJSWorkflowProvider>
Expand Down
7 changes: 6 additions & 1 deletion libs/designer/src/lib/core/BJSWorkflowProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import { parseWorkflowKind } from './utils/workflow';
import type { LogicAppsV2 } from '@microsoft/logic-apps-shared';
import { useDeepCompareEffect } from '@react-hookz/web';
import React, { useContext, useEffect } from 'react';
import { useQuery } from 'react-query';
import { useDispatch } from 'react-redux';

export interface BJSWorkflowProviderProps {
workflow: Workflow;
runInstance?: LogicAppsV2.RunInstanceDefinition | null;
children?: React.ReactNode;
appSettings?: Record<string, any>;
}

const DataProviderInner: React.FC<BJSWorkflowProviderProps> = ({ workflow, children, runInstance }) => {
const DataProviderInner: React.FC<BJSWorkflowProviderProps> = ({ workflow, children, runInstance, appSettings }) => {
const dispatch = useDispatch<AppDispatch>();
useDeepCompareEffect(() => {
dispatch(initWorkflowSpec('BJS'));
Expand All @@ -26,6 +28,9 @@ const DataProviderInner: React.FC<BJSWorkflowProviderProps> = ({ workflow, child
dispatch(initializeGraphState({ workflowDefinition: workflow, runInstance }));
}, [runInstance, workflow]);

// Store app settings in query to access outside of functional components
useQuery({ queryKey: ['appSettings'], initialData: appSettings });

return <>{children}</>;
};

Expand Down
46 changes: 30 additions & 16 deletions libs/designer/src/lib/core/utils/parameters/dynamicdata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Constants from '../../../common/constants';
import type { ConnectionReference } from '../../../common/models/workflow';
import { getReactQueryClient } from '../../ReactQueryProvider';
import { getCustomSwaggerIfNeeded } from '../../actions/bjsworkflow/initialize';
import type { SerializedParameter } from '../../actions/bjsworkflow/serializer';
import { getConnection, getConnectorWithSwagger } from '../../queries/connections';
Expand Down Expand Up @@ -447,6 +448,10 @@ function getParametersForDynamicInvoke(
const intl = getIntl();
const operationParameters: SerializedParameter[] = [];

// Get app settings from query client
const queryClient = getReactQueryClient();
const appSettings = queryClient.getQueryData(['appSettings']);

for (const [parameterName, parameter] of Object.entries(referenceParameters ?? {})) {
const referenceParameterName = (parameter?.parameterReference ?? parameter?.parameter ?? 'undefined') as string;
const operationParameter = operationInputs?.[parameterName];
Expand Down Expand Up @@ -505,7 +510,7 @@ function getParametersForDynamicInvoke(
}
}

evaluateTemplateExpressions(operationParameters, workflowParameters);
evaluateTemplateExpressions(operationParameters, workflowParameters, appSettings);

return operationParameters;
}
Expand Down Expand Up @@ -770,33 +775,42 @@ function isOpenApiParameter(param: InputParameter): boolean {

function evaluateTemplateExpressions(
parameters: SerializedParameter[],
workflowParameters: Record<string, WorkflowParameterDefinition>
workflowParameters: Record<string, WorkflowParameterDefinition>,
appSettings: any
): void {
if (!Object.keys(workflowParameters).length) {
return;
}

const outputParameters = Object.keys(workflowParameters).reduce(
(result: Record<string, any>, parameterId: string) => ({
...result,
[workflowParameters[parameterId].name as string]:
workflowParameters[parameterId].defaultValue ?? workflowParameters[parameterId].value,
}),
{}
);

const options: ExpressionEvaluatorOptions = {
fuzzyEvaluation: true,
context: {
parameters: Object.keys(workflowParameters).reduce(
(result: Record<string, any>, parameterId: string) => ({
...result,
[workflowParameters[parameterId].name as string]:
workflowParameters[parameterId].defaultValue ?? workflowParameters[parameterId].value,
}),
{}
),
appsettings: {},
parameters: outputParameters,
appsettings: appSettings,
},
};

const evaluator = new ExpressionEvaluator(options);
for (const parameter of parameters) evaluateParameter(parameter, evaluator);
}

for (const parameter of parameters) {
const value = parameter.value;
if (isTemplateExpression(value)) {
parameter.value = evaluator.evaluate(value);
}
// Recursively evaluate in case there is a expression within the expression
function evaluateParameter(parameter: SerializedParameter, evaluator: ExpressionEvaluator): void {
const value = parameter.value;
if (isTemplateExpression(value)) {
// eslint-disable-next-line no-param-reassign
parameter.value = evaluator.evaluate(value);
}
if (value !== parameter.value) {
evaluateParameter(parameter, evaluator);
}
}

0 comments on commit 6f9b652

Please sign in to comment.