Skip to content

Commit 06ac2d0

Browse files
lokanandaprabhucursoragentKarthik Jeeyarkarthikjeeyar
authored
[release-1.10.z] Backport orchestrator fixes for 1.10 (#3234, #3260, #3264, #3253) (#3270)
* fix(orchestrator-form): evaluate conditional ui:hidden with scoped form data Evaluate sibling when paths against the current object/step form data so conditionally hidden fields show and hide correctly in wizards. Fix the review step toggle by iterating schema properties when including hidden fields and applying the same scoped condition evaluation. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(orchestrator): add changeset for scoped conditional ui:hidden fix Co-authored-by: Cursor <cursoragent@cursor.com> * chore(orchestrator): clarify changeset for conditional hidden fields fix Co-authored-by: Cursor <cursoragent@cursor.com> * fix(orchestrator): restore status and date filters on workflow runs Filtering workflow runs by status or date failed after query variables were introduced. Use the correct filter types so results load instead of showing an error. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(orchestrator-form): hide wizard steps for conditional ui:hidden Evaluate conditional ui:hidden when filtering wizard steps using scoped form data and root fallbacks, align validation with visible steps, and add isNotEmptyList/notContains operators with unit tests. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(orchestrator-form): update API reports for HiddenCondition operators Co-authored-by: Cursor <cursoragent@cursor.com> * chore(orchestrator): revert unrelated report-alpha.api.md ordering change Co-authored-by: Cursor <cursoragent@cursor.com> * Update workspaces/orchestrator/.changeset/conditional-step-hiding-operators.md Co-authored-by: Karthik Jeeyar <karthik@redhat.com> * detect GitHub SAML SSO session expiry and prompt users to re-authorize --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Karthik Jeeyar <karthik@redhat.com> Co-authored-by: Karthik <karthik.jk11@gmail.com>
1 parent 18023a1 commit 06ac2d0

41 files changed

Lines changed: 936 additions & 64 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-react': patch
3+
---
4+
5+
Hide wizard steps when conditional `ui:hidden` rules evaluate to true, and add `isNotEmptyList`/`notContains` operators for conditional hidden expressions.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-react': patch
3+
---
4+
5+
Remove unnecessary gaps from conditionally hidden form fields.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-orchestrator-backend': patch
3+
---
4+
5+
Fix an issue where filtering workflow runs by status or date could show an error instead of results.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-widgets': patch
3+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-react': patch
4+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-api': patch
5+
'@red-hat-developer-hub/backstage-plugin-orchestrator': patch
6+
---
7+
8+
detect GitHub SAML SSO session expiry and prompt users to re-authorize

workspaces/orchestrator/plugins/orchestrator-backend/src/helpers/filterBuilder.ts

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,53 @@ function handleNestedFilter(
111111
return filterClause;
112112
}
113113

114-
function handleBetweenOperator(filter: FieldFilter): FilterClause {
114+
function getGraphQLVariableType(
115+
fieldName: string,
116+
fieldDef: IntrospectionField | undefined,
117+
type: ProcessType,
118+
isArray: boolean,
119+
): string {
120+
if (isEnumFilter(fieldName, type)) {
121+
return isArray ? '[ProcessInstanceState!]' : 'ProcessInstanceState';
122+
}
123+
124+
if (fieldDef?.type.name === TypeName.Date) {
125+
return 'DateTime!';
126+
}
127+
128+
if (isArray) {
129+
return '[String!]';
130+
}
131+
132+
return 'String';
133+
}
134+
135+
function handleBetweenOperator(
136+
filter: FieldFilter,
137+
fieldDef: IntrospectionField | undefined,
138+
): FilterClause {
115139
if (!Array.isArray(filter.value) || filter.value.length !== 2) {
116140
throw new Error('Between operator requires an array of two elements');
117141
}
142+
const paramType = getGraphQLVariableType(
143+
filter.field,
144+
fieldDef,
145+
'ProcessInstance',
146+
false,
147+
);
118148
const filterClauseVariableArray: FilterClauseVariable[] = [];
119149
const clauseVariableName1 = `clauseVariable${nonSecureRandomAlphaNumeric()}`;
120150
const filterClauseVariable1: FilterClauseVariable = {
121151
clauseVariableName: clauseVariableName1,
122152
formattedValue: filter.value[0],
123-
clauseVariableType: 'String',
153+
clauseVariableType: paramType,
124154
};
125155

126156
const clauseVariableName2 = `clauseVariable${nonSecureRandomAlphaNumeric()}`;
127157
const filterClauseVariable2: FilterClauseVariable = {
128158
clauseVariableName: clauseVariableName2,
129159
formattedValue: filter.value[1],
130-
clauseVariableType: 'String',
160+
clauseVariableType: paramType,
131161
};
132162

133163
const clause = `${filter.field}: {${getGraphQLOperator(
@@ -193,23 +223,25 @@ function handleBinaryOperator(
193223
}
194224
}
195225
let formattedValue: any;
196-
let paramType: string;
197-
if (Array.isArray(binaryFilter.value)) {
198-
formattedValue = binaryFilter.value.map(v =>
226+
const isArray = Array.isArray(binaryFilter.value);
227+
if (isArray) {
228+
formattedValue = (binaryFilter.value as unknown[]).map((v: unknown) =>
199229
formatValue(binaryFilter.field, v, fieldDef, type),
200230
);
201-
paramType = isEnumFilter(binaryFilter.field, type)
202-
? '[ProcessInstanceState!]'
203-
: '[String!]';
204231
} else {
205232
formattedValue = formatValue(
206233
binaryFilter.field,
207234
binaryFilter.value,
208235
fieldDef,
209236
type,
210237
);
211-
paramType = 'String';
212238
}
239+
const paramType = getGraphQLVariableType(
240+
binaryFilter.field,
241+
fieldDef,
242+
type,
243+
isArray,
244+
);
213245

214246
const clauseVariableName = `clauseVariable${nonSecureRandomAlphaNumeric()}`;
215247
const clause = `${binaryFilter.field}: {${getGraphQLOperator(binaryFilter.operator)}: $${clauseVariableName}}`;
@@ -273,7 +305,7 @@ export function buildFilterCondition(
273305
case FieldFilterOperatorEnum.IsNull:
274306
return handleIsNullOperator(filters);
275307
case FieldFilterOperatorEnum.Between:
276-
return handleBetweenOperator(filters);
308+
return handleBetweenOperator(filters, fieldDef);
277309
case FieldFilterOperatorEnum.Eq:
278310
case FieldFilterOperatorEnum.Like:
279311
case FieldFilterOperatorEnum.In:

workspaces/orchestrator/plugins/orchestrator-backend/src/helpers/filterBuilders.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ describe('column filters', () => {
128128
filter: Filter | undefined;
129129
expectedResult: string | FilterClause;
130130
expectedFormattedValue: Array<string | boolean | string[]>;
131+
expectedVariableTypes?: string[];
131132
};
132133
describe('empty filter testcases', () => {
133134
const emptyFilterTestCases: FilterTestCase[] = [
@@ -519,6 +520,7 @@ describe('column filters', () => {
519520
),
520521
expectedResult: `start: {equal: $variable1}`,
521522
expectedFormattedValue: [testDate1],
523+
expectedVariableTypes: ['DateTime!'],
522524
},
523525
{
524526
name: 'returns correct filter for single date field with isNull operator (false as boolean)',
@@ -595,6 +597,7 @@ describe('column filters', () => {
595597
]),
596598
expectedResult: `start: {between: {from: $variable1, to: $variable2}}`,
597599
expectedFormattedValue: [testDate1, testDate2],
600+
expectedVariableTypes: ['DateTime!', 'DateTime!'],
598601
},
599602
{
600603
name: 'returns correct OR filter for multiple id fields with equal, isNull, and GT operators',
@@ -683,6 +686,7 @@ describe('column filters', () => {
683686
filter,
684687
expectedResult,
685688
expectedFormattedValue,
689+
expectedVariableTypes,
686690
}) => {
687691
it(`${name}`, () => {
688692
const result = buildFilterCondition(
@@ -698,6 +702,9 @@ describe('column filters', () => {
698702
`$${item.clauseVariableName}`,
699703
);
700704
expect(item.formattedValue).toEqual(expectedFormattedValue[index]);
705+
expect(item.clauseVariableType).toBe(
706+
expectedVariableTypes?.[index] ?? item.clauseVariableType,
707+
);
701708
});
702709
expect(formattedClause).toBe(result.clause);
703710
});
@@ -718,6 +725,7 @@ describe('column filters', () => {
718725
),
719726
expectedResult: `state: {equal: $variable1}`,
720727
expectedFormattedValue: ['COMPLETED'],
728+
expectedVariableTypes: ['ProcessInstanceState'],
721729
},
722730
];
723731

@@ -728,6 +736,7 @@ describe('column filters', () => {
728736
filter,
729737
expectedResult,
730738
expectedFormattedValue,
739+
expectedVariableTypes,
731740
}) => {
732741
it(`${name}`, () => {
733742
const result = buildFilterCondition(
@@ -743,6 +752,9 @@ describe('column filters', () => {
743752
`$${item.clauseVariableName}`,
744753
);
745754
expect(item.formattedValue).toEqual(expectedFormattedValue[index]);
755+
expect(item.clauseVariableType).toBe(
756+
expectedVariableTypes?.[index] ?? item.clauseVariableType,
757+
);
746758
});
747759
expect(formattedClause).toBe(result.clause);
748760
});

workspaces/orchestrator/plugins/orchestrator-form-api/report.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export type OrchestratorFormContextProps = {
5353
setIsChangedByUser: (id: string, isChangedByUser: boolean) => void;
5454
handleFetchStarted?: () => void;
5555
handleFetchEnded?: () => void;
56+
onSamlSsoError?: (error: Error) => void;
5657
};
5758

5859
// @public
@@ -90,7 +91,7 @@ export const useOrchestratorFormApiOrDefault: () => OrchestratorFormApi;
9091

9192
// Warnings were encountered during analysis:
9293
//
93-
// src/api.d.ts:131:22 - (ae-undocumented) Missing documentation for "useOrchestratorFormApiOrDefault".
94+
// src/api.d.ts:132:22 - (ae-undocumented) Missing documentation for "useOrchestratorFormApiOrDefault".
9495

9596
// (No @packageDocumentation comment for this package)
9697
```

workspaces/orchestrator/plugins/orchestrator-form-api/src/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type OrchestratorFormContextProps = {
4646
setIsChangedByUser: (id: string, isChangedByUser: boolean) => void;
4747
handleFetchStarted?: () => void;
4848
handleFetchEnded?: () => void;
49+
onSamlSsoError?: (error: Error) => void;
4950
};
5051

5152
/**

workspaces/orchestrator/plugins/orchestrator-form-react/report.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export interface HiddenConditionObject {
3737
is?: JsonValue | JsonValue[];
3838
isEmpty?: boolean;
3939
isNot?: JsonValue | JsonValue[];
40+
isNotEmptyList?: boolean;
41+
notContains?: JsonValue;
4042
when: string;
4143
}
4244

@@ -56,6 +58,7 @@ export type OrchestratorFormProps = {
5658
schema: JSONSchema7;
5759
updateSchema: OrchestratorFormContextProps['updateSchema'];
5860
setAuthTokenDescriptors: OrchestratorFormContextProps['setAuthTokenDescriptors'];
61+
onSamlSsoError?: OrchestratorFormContextProps['onSamlSsoError'];
5962
isExecuting: boolean;
6063
handleExecute: (parameters: JsonObject) => Promise<void>;
6164
handleExecuteAsEvent?: (parameters: JsonObject) => Promise<void>;

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/HiddenObjectFieldTemplate.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ const HiddenObjectFieldTemplate = (
7676
ButtonTemplates: { AddButton },
7777
} = registry.templates;
7878

79-
const rootFormData =
80-
(formContext?.formData as JsonObject) || (formData as JsonObject) || {};
79+
const rootFormData = (formContext?.formData as JsonObject) || {};
80+
const localFormData = (formData as JsonObject) || rootFormData;
8181

8282
return (
8383
<>
@@ -105,7 +105,11 @@ const HiddenObjectFieldTemplate = (
105105
const hiddenCondition = getHiddenCondition(uiSchema, element.name);
106106
const isHiddenByCondition =
107107
hiddenCondition !== undefined
108-
? evaluateHiddenCondition(hiddenCondition, rootFormData)
108+
? evaluateHiddenCondition(
109+
hiddenCondition,
110+
localFormData,
111+
rootFormData,
112+
)
109113
: false;
110114
const isHidden = element.hidden || isHiddenByCondition;
111115

0 commit comments

Comments
 (0)