@orchestrator-ui/orchestrator-ui-components 5.3.1 → 5.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +8 -8
  4. package/CHANGELOG.md +15 -0
  5. package/dist/index.d.ts +82 -31
  6. package/dist/index.js +2434 -1419
  7. package/dist/index.js.map +1 -1
  8. package/package.json +2 -2
  9. package/src/components/WfoContentHeader/WfoContentHeader.tsx +4 -1
  10. package/src/components/WfoForms/formFields/AcceptField.tsx +2 -2
  11. package/src/components/WfoForms/formFields/AcceptFieldStyling.ts +1 -1
  12. package/src/components/WfoForms/formFields/BoolField.tsx +1 -1
  13. package/src/components/WfoForms/formFields/DividerField.tsx +1 -1
  14. package/src/components/WfoForms/formFields/ErrorField.tsx +1 -1
  15. package/src/components/WfoForms/formFields/LabelField.tsx +1 -1
  16. package/src/components/WfoForms/formFields/LongTextField.tsx +1 -1
  17. package/src/components/WfoForms/formFields/NumField.tsx +1 -1
  18. package/src/components/WfoForms/formFields/RadioField.tsx +1 -1
  19. package/src/components/WfoForms/formFields/SubmitField.tsx +1 -1
  20. package/src/components/WfoForms/formFields/SummaryFieldStyling.ts +8 -11
  21. package/src/components/WfoForms/formFields/TextField.tsx +1 -1
  22. package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocomplete.tsx +4 -3
  23. package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocompleteStyles.ts +1 -1
  24. package/src/components/WfoForms/formFields/deprecated/FileUploadField.tsx +1 -1
  25. package/src/components/WfoForms/formFields/deprecated/SubscriptionField.tsx +0 -1
  26. package/src/components/WfoForms/formFields/index.ts +1 -0
  27. package/src/components/WfoForms/formFields/types.ts +1 -0
  28. package/src/components/WfoPageTemplate/WfoPageHeader/WfoHamburgerMenu.tsx +26 -4
  29. package/src/components/WfoPydanticForm/Footer.tsx +0 -1
  30. package/src/components/WfoPydanticForm/Header.tsx +4 -1
  31. package/src/components/WfoPydanticForm/Row.tsx +1 -1
  32. package/src/components/WfoPydanticForm/WfoPydanticForm.tsx +92 -45
  33. package/src/components/WfoPydanticForm/fields/Integer.tsx +44 -0
  34. package/src/components/WfoPydanticForm/fields/Radio.tsx +27 -0
  35. package/src/components/WfoPydanticForm/fields/Summary.tsx +2 -3
  36. package/src/components/WfoPydanticForm/fields/WfoArrayField/WfoArrayField.tsx +108 -0
  37. package/src/components/WfoPydanticForm/fields/WfoArrayField/arrayFieldStyles.ts +34 -0
  38. package/src/components/WfoPydanticForm/fields/WfoArrayField/index.ts +2 -0
  39. package/src/components/WfoPydanticForm/fields/WfoArrayField/styles.ts +34 -0
  40. package/src/components/WfoPydanticForm/fields/WfoObjectField/WfoObjectField.tsx +29 -0
  41. package/src/components/WfoPydanticForm/fields/WfoObjectField/getWfoObjectFieldStyles.ts +13 -0
  42. package/src/components/WfoPydanticForm/fields/WfoObjectField/index.ts +2 -0
  43. package/src/components/WfoPydanticForm/fields/index.ts +4 -0
  44. package/src/components/WfoPydanticForm/fields/styles.ts +13 -0
  45. package/src/components/WfoPydanticForm/index.ts +3 -0
  46. package/src/components/WfoSettings/WfoAoStackStatus.tsx +40 -0
  47. package/src/components/WfoTable/WfoTable/WfoTable.tsx +2 -3
  48. package/src/components/WfoTable/utils/tableUtils.spec.ts +29 -0
  49. package/src/components/WfoTable/utils/tableUtils.ts +9 -0
  50. package/src/configuration/version.ts +1 -1
  51. package/src/contexts/OrchestratorConfigContext.tsx +2 -0
  52. package/src/icons/WfoChartBar.tsx +34 -0
  53. package/src/icons/index.ts +1 -0
  54. package/src/messages/en-GB.json +6 -2
  55. package/src/messages/nl-NL.json +1 -0
  56. package/src/pages/settings/WfoSettingsPage.tsx +9 -1
  57. package/src/rtk/slices/pydanticForm.ts +2 -2
  58. package/src/rtk/storeProvider.tsx +4 -4
  59. package/src/rtk/utils.ts +20 -0
  60. package/src/theme/defaultOrchestratorTheme.ts +25 -0
  61. package/src/types/forms.ts +0 -17
  62. package/src/types/types.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "5.3.1",
3
+ "version": "5.3.3",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Library of UI Components used to display the workflow orchestrator frontend",
6
6
  "author": {
@@ -48,7 +48,7 @@
48
48
  "next-query-params": "^5.0.0",
49
49
  "object-hash": "^3.0.0",
50
50
  "prism-themes": "^1.9.0",
51
- "pydantic-forms": "^0.3.3",
51
+ "pydantic-forms": "^0.6.1",
52
52
  "react-diff-view": "^3.2.0",
53
53
  "react-draggable": "^4.4.6",
54
54
  "react-redux": "^9.1.2",
@@ -42,7 +42,10 @@ export const WfoContentHeader: FC<WfoContentHeaderProps> = ({
42
42
 
43
43
  {children && (
44
44
  <EuiFlexItem grow={0}>
45
- <EuiFlexGroup justifyContent="flexEnd">
45
+ <EuiFlexGroup
46
+ justifyContent="flexEnd"
47
+ alignItems="flexStart"
48
+ >
46
49
  <WfoRenderElementOrString>
47
50
  {children}
48
51
  </WfoRenderElementOrString>
@@ -21,7 +21,7 @@ import { EuiCheckbox, EuiFlexItem, EuiText } from '@elastic/eui';
21
21
 
22
22
  import { useWithOrchestratorTheme } from '@/hooks';
23
23
 
24
- import { getStyles } from './AcceptFieldStyling';
24
+ import { getAcceptFieldStyles } from './AcceptFieldStyling';
25
25
  import { FieldProps } from './types';
26
26
 
27
27
  type AcceptItemType =
@@ -73,7 +73,7 @@ function Accept({
73
73
  ...props
74
74
  }: AcceptFieldProps) {
75
75
  const t = useTranslations();
76
- const { acceptFieldStyle } = useWithOrchestratorTheme(getStyles);
76
+ const { acceptFieldStyle } = useWithOrchestratorTheme(getAcceptFieldStyles);
77
77
 
78
78
  const legacy = !data;
79
79
  const i18nBaseKey = data
@@ -2,7 +2,7 @@ import { css } from '@emotion/react';
2
2
 
3
3
  import { WfoTheme } from '@/hooks';
4
4
 
5
- export const getStyles = ({ theme }: WfoTheme) => {
5
+ export const getAcceptFieldStyles = ({ theme }: WfoTheme) => {
6
6
  const acceptFieldStyle = css({
7
7
  '.acceptField': {
8
8
  'label.warning': {
@@ -18,9 +18,9 @@ import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
19
  import { EuiCheckbox, EuiFlexItem, EuiFormRow, EuiText } from '@elastic/eui';
20
20
 
21
+ import { FieldProps } from '@/components';
21
22
  import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
22
23
  import { useWithOrchestratorTheme } from '@/hooks';
23
- import { FieldProps } from '@/types';
24
24
 
25
25
  import { boolFieldStyling } from './BoolFieldStyling';
26
26
 
@@ -18,7 +18,7 @@ import { connectField } from 'uniforms';
18
18
 
19
19
  import { EuiHorizontalRule } from '@elastic/eui';
20
20
 
21
- import { FieldProps } from '@/types';
21
+ import { FieldProps } from '@/components';
22
22
 
23
23
  export type DividerFieldProps = FieldProps<null, object, null, HTMLDivElement>;
24
24
 
@@ -16,7 +16,7 @@ import React from 'react';
16
16
 
17
17
  import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
- import { FieldProps } from '@/types';
19
+ import { FieldProps } from '@/components';
20
20
 
21
21
  export type ErrorFieldProps = FieldProps<null>;
22
22
 
@@ -16,8 +16,8 @@ import React from 'react';
16
16
 
17
17
  import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
+ import { FieldProps } from '@/components';
19
20
  import { useOrchestratorTheme } from '@/hooks';
20
- import { FieldProps } from '@/types';
21
21
 
22
22
  export type LabelFieldProps = FieldProps<null, object, null, HTMLDivElement>;
23
23
 
@@ -18,7 +18,7 @@ import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
19
  import { EuiFormRow, EuiText, EuiTextArea } from '@elastic/eui';
20
20
 
21
- import { FieldProps } from '@/types';
21
+ import { FieldProps } from '@/components';
22
22
 
23
23
  export type LongTextFieldProps = FieldProps<
24
24
  string,
@@ -18,10 +18,10 @@ import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
19
  import { EuiFieldNumber, EuiFormRow, EuiText } from '@elastic/eui';
20
20
 
21
+ import { FieldProps } from '@/components';
21
22
  import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
22
23
  import { useWithOrchestratorTheme } from '@/hooks';
23
24
  import { getFormFieldsBaseStyle } from '@/theme';
24
- import { FieldProps } from '@/types';
25
25
 
26
26
  export type NumFieldProps = FieldProps<
27
27
  number,
@@ -19,7 +19,7 @@ import { connectField, filterDOMProps } from 'uniforms';
19
19
 
20
20
  import { EuiFormRow, EuiRadio, EuiText } from '@elastic/eui';
21
21
 
22
- import { FieldProps } from '@/types';
22
+ import { FieldProps } from '@/components';
23
23
 
24
24
  const base64 =
25
25
  typeof btoa !== 'undefined'
@@ -16,7 +16,7 @@ import React from 'react';
16
16
 
17
17
  import { filterDOMProps, useForm } from 'uniforms';
18
18
 
19
- import { FieldProps } from '@/types';
19
+ import { FieldProps } from '@/components';
20
20
 
21
21
  export type SubmitFieldProps = FieldProps<
22
22
  null,
@@ -1,18 +1,15 @@
1
- import { tint } from '@elastic/eui';
2
1
  import { css } from '@emotion/react';
3
2
 
4
3
  import { WfoTheme } from '@/hooks';
5
4
 
6
5
  export const getStyles = ({ theme }: WfoTheme) => {
7
- const toShadeColor = (color: string) => tint(color, 0.9);
8
-
9
6
  const summaryFieldStyle = css({
10
7
  'div.emailMessage': {
11
8
  td: {
12
- color: theme.colors.text,
9
+ color: theme.colors.textParagraph,
13
10
  },
14
11
  p: {
15
- color: theme.colors.text,
12
+ color: theme.colors.textParagraph,
16
13
  },
17
14
  html: {
18
15
  marginLeft: '-10px',
@@ -26,18 +23,18 @@ export const getStyles = ({ theme }: WfoTheme) => {
26
23
  verticalAlign: 'top',
27
24
  },
28
25
  'td:not(:first-child):not(:last-child)': {
29
- borderRight: `1px solid ${theme.colors.lightestShade}`,
26
+ borderRight: `1px solid ${theme.colors.borderBasePlain}`,
30
27
  },
31
28
  '.label': {
32
29
  fontWeight: 'bold',
33
- color: theme.colors.lightestShade,
30
+ color: theme.colors.backgroundBaseSubdued,
34
31
  backgroundColor: theme.colors.primary,
35
- borderRight: `2px solid ${theme.colors.lightestShade}`,
36
- borderBottom: `1px solid ${theme.colors.lightestShade}`,
32
+ borderRight: `2px solid ${theme.colors.borderBasePlain}`,
33
+ borderBottom: `1px solid ${theme.colors.borderBasePlain}`,
37
34
  },
38
35
  '.value': {
39
- backgroundColor: toShadeColor(theme.colors.primary),
40
- borderBottom: `1px solid ${theme.colors.lightestShade}`,
36
+ backgroundColor: theme.colors.backgroundBasePrimary,
37
+ borderBottom: `1px solid ${theme.colors.borderBasePlain}`,
41
38
  },
42
39
  },
43
40
  });
@@ -18,10 +18,10 @@ import { connectField, filterDOMProps } from 'uniforms';
18
18
 
19
19
  import { EuiFieldText, EuiFormRow, EuiText } from '@elastic/eui';
20
20
 
21
+ import { FieldProps } from '@/components';
21
22
  import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
22
23
  import { useWithOrchestratorTheme } from '@/hooks';
23
24
  import { getFormFieldsBaseStyle } from '@/theme';
24
- import { FieldProps } from '@/types';
25
25
 
26
26
  export type TextFieldProps = FieldProps<string>;
27
27
 
@@ -22,7 +22,7 @@ import { useWithOrchestratorTheme } from '@/hooks';
22
22
 
23
23
  import { ContactPerson } from '../types';
24
24
  import { isEmpty } from '../utils';
25
- import { getStyles } from './ContactPersonAutocompleteStyles';
25
+ import { getContactPersonStyles } from './ContactPersonAutocompleteStyles';
26
26
 
27
27
  interface ContactPersonAutocompleteProps {
28
28
  query: string;
@@ -39,8 +39,9 @@ export const ContactPersonAutocomplete = ({
39
39
  itemSelected,
40
40
  suggestions,
41
41
  }: ContactPersonAutocompleteProps) => {
42
- const { contactPersonAutocompleteStyling } =
43
- useWithOrchestratorTheme(getStyles);
42
+ const { contactPersonAutocompleteStyling } = useWithOrchestratorTheme(
43
+ getContactPersonStyles,
44
+ );
44
45
 
45
46
  // Intentionally not done with state since we don't need a rerender
46
47
  // This is only to store a ref for the scroll into view part
@@ -2,7 +2,7 @@ import { css } from '@emotion/react';
2
2
 
3
3
  import { WfoTheme } from '@/hooks';
4
4
 
5
- export const getStyles = ({ theme }: WfoTheme) => {
5
+ export const getContactPersonStyles = ({ theme }: WfoTheme) => {
6
6
  const contactPersonAutocompleteStyling = css`
7
7
  .autocomplete-container {
8
8
  position: relative;
@@ -19,10 +19,10 @@ import { connectField, filterDOMProps } from 'uniforms';
19
19
 
20
20
  import { EuiFilePicker, EuiFormRow, EuiText } from '@elastic/eui';
21
21
 
22
+ import { FieldProps } from '@/components';
22
23
  import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
23
24
  import { useOrchestratorTheme, useWithOrchestratorTheme } from '@/hooks';
24
25
  import { useUploadFileMutation } from '@/rtk/endpoints/fileUpload';
25
- import { FieldProps } from '@/types';
26
26
 
27
27
  export type FileUploadProps = FieldProps<string>;
28
28
 
@@ -219,7 +219,6 @@ function SubscriptionFieldDefinition({
219
219
  <EuiButtonIcon
220
220
  className="reload-subscriptions-icon-button"
221
221
  id={`refresh-icon-${id}`}
222
- aria-label={`reload-${label}`}
223
222
  iconType="refresh"
224
223
  iconSize="l"
225
224
  disabled={isDisabled}
@@ -25,3 +25,4 @@ export * from './CustomerField';
25
25
  export * from './ConnectedSelectField';
26
26
  export * from './deprecated/FileUploadField';
27
27
  export * from './commonStyles';
28
+ export * from './types';
@@ -33,6 +33,7 @@ export type FieldProps<
33
33
  export interface ContactPerson {
34
34
  name: string;
35
35
  email: string;
36
+ phone?: string;
36
37
  }
37
38
 
38
39
  export interface Option<Value = string> {
@@ -3,13 +3,18 @@ import React, { useState } from 'react';
3
3
  import { signOut } from 'next-auth/react';
4
4
  import { useTranslations } from 'next-intl';
5
5
 
6
- import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui';
7
6
  import type { EuiContextMenuPanelDescriptor } from '@elastic/eui';
7
+ import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui';
8
8
 
9
9
  import { WfoLoading } from '@/components/WfoLoading';
10
10
  import { ORCHESTRATOR_UI_LIBRARY_VERSION } from '@/configuration';
11
11
  import { useGetOrchestratorConfig, useOrchestratorTheme } from '@/hooks';
12
- import { WfoLogoutIcon, WfoSquareStack3dStack, WfoXCircleFill } from '@/icons';
12
+ import {
13
+ WfoChartBar,
14
+ WfoLogoutIcon,
15
+ WfoSquareStack3dStack,
16
+ WfoXCircleFill,
17
+ } from '@/icons';
13
18
  import { WfoQuestionCircle } from '@/icons/WfoQuestionCircle';
14
19
  import { useGetVersionsQuery } from '@/rtk/endpoints/versions';
15
20
  import { toOptionalArrayEntry } from '@/utils';
@@ -18,14 +23,24 @@ export const WfoHamburgerMenu = () => {
18
23
  const t = useTranslations('hamburgerMenu');
19
24
  const [isPopoverOpen, setPopoverIsOpen] = useState(false);
20
25
  const { theme, isDarkThemeActive } = useOrchestratorTheme();
21
- const { enableSupportMenuItem, supportMenuItemUrl } =
22
- useGetOrchestratorConfig();
26
+ const {
27
+ enableSupportMenuItem,
28
+ supportMenuItemUrl,
29
+ enableAoStackStatus,
30
+ aoStackStatusUrl,
31
+ } = useGetOrchestratorConfig();
23
32
  const closePopover = () => {
24
33
  setPopoverIsOpen(false);
25
34
  };
35
+
26
36
  const handleOpenSupport = async (): Promise<undefined> => {
27
37
  window.open(supportMenuItemUrl, '_blank');
28
38
  };
39
+
40
+ const handleOpenStatus = async (): Promise<undefined> => {
41
+ window.open(aoStackStatusUrl, '_blank');
42
+ };
43
+
29
44
  const {
30
45
  data,
31
46
  isFetching,
@@ -92,6 +107,12 @@ export const WfoHamburgerMenu = () => {
92
107
  onClick: handleOpenSupport,
93
108
  };
94
109
 
110
+ const aoStackStatusItem = {
111
+ name: t('aoStatusPage'),
112
+ icon: <WfoChartBar width={26} height={26} />,
113
+ onClick: handleOpenStatus,
114
+ };
115
+
95
116
  const versionItem = {
96
117
  name: t('softwareVersions'),
97
118
  icon: <WfoSquareStack3dStack width={24} height={24} />,
@@ -100,6 +121,7 @@ export const WfoHamburgerMenu = () => {
100
121
 
101
122
  const panelItems = [
102
123
  ...toOptionalArrayEntry(supportItem, enableSupportMenuItem),
124
+ ...toOptionalArrayEntry(aoStackStatusItem, enableAoStackStatus),
103
125
  versionItem,
104
126
  { ...logoutItem },
105
127
  ];
@@ -50,7 +50,6 @@ export const Footer = () => {
50
50
  color={'primary'}
51
51
  iconSide="right"
52
52
  aria-label={t('previous')}
53
- disabled={isDisabled}
54
53
  >
55
54
  {t('previous')}
56
55
  </EuiButton>
@@ -14,5 +14,8 @@ const headerStyling = css`
14
14
  export const Header = () => {
15
15
  const { pydanticFormSchema } = usePydanticFormContext();
16
16
 
17
- return <h3 css={headerStyling}>{pydanticFormSchema?.title}</h3>;
17
+ return pydanticFormSchema?.title &&
18
+ pydanticFormSchema.title !== 'unknown' ? (
19
+ <h3 css={headerStyling}>{pydanticFormSchema?.title}</h3>
20
+ ) : undefined;
18
21
  };
@@ -4,7 +4,7 @@ import type { RowRenderComponent } from 'pydantic-forms';
4
4
 
5
5
  import { EuiFormRow, EuiText } from '@elastic/eui';
6
6
 
7
- import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
7
+ import { getCommonFormFieldStyles } from '@/components';
8
8
  import { useWithOrchestratorTheme } from '@/hooks';
9
9
 
10
10
  export const Row: RowRenderComponent = ({
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { AbstractIntlMessages, useMessages, useTranslations } from 'next-intl';
4
4
  import { useRouter } from 'next/router';
5
5
  import type {
6
- ComponentMatcher,
6
+ ComponentMatcherExtender,
7
7
  PydanticComponentMatcher,
8
8
  PydanticFormApiProvider,
9
9
  PydanticFormLabelProvider,
@@ -15,19 +15,27 @@ import {
15
15
  zodValidationPresets,
16
16
  } from 'pydantic-forms';
17
17
 
18
- import { FetchBaseQueryError } from '@reduxjs/toolkit/query';
19
-
20
18
  import { PATH_TASKS, PATH_WORKFLOWS, WfoLoading } from '@/components';
21
19
  import { StartWorkflowPayload } from '@/pages/processes/WfoStartProcessPage';
22
- import { HttpStatus } from '@/rtk';
20
+ import { HttpStatus, isFetchBaseQueryError, isRecord } from '@/rtk';
23
21
  import { useStartProcessMutation } from '@/rtk/endpoints/forms';
24
22
  import { useAppSelector } from '@/rtk/hooks';
25
- import { FormValidationError } from '@/types';
26
23
 
27
24
  import { Footer } from './Footer';
28
25
  import { Header } from './Header';
29
26
  import { Row } from './Row';
30
- import { Checkbox, Divider, Label, Summary, Text, TextArea } from './fields';
27
+ import {
28
+ Checkbox,
29
+ Divider,
30
+ Integer,
31
+ Label,
32
+ Radio,
33
+ Summary,
34
+ Text,
35
+ TextArea,
36
+ WfoArrayField,
37
+ WfoObjectField,
38
+ } from './fields';
31
39
 
32
40
  interface WfoPydanticFormProps {
33
41
  processName: string;
@@ -47,8 +55,8 @@ export const WfoPydanticForm = ({
47
55
  const [startProcess] = useStartProcessMutation();
48
56
  const router = useRouter();
49
57
  const t = useTranslations('pydanticForms.userInputForm');
50
- const componentMatcher = useAppSelector(
51
- (state) => state.pydanticForm?.componentMatcher,
58
+ const componentMatcherExtender = useAppSelector(
59
+ (state) => state.pydanticForm?.componentMatcherExtender,
52
60
  );
53
61
 
54
62
  const translationMessages: AbstractIntlMessages = useMessages();
@@ -82,40 +90,26 @@ export const WfoPydanticForm = ({
82
90
  userInputs: [{ ...startProcessPayload }, ...requestBody],
83
91
  });
84
92
  return response
85
- .then((result) => {
86
- return new Promise<Record<string, object | string>>(
87
- (resolve) => {
88
- if (result.error) {
89
- const error =
90
- result.error as FetchBaseQueryError;
91
- if (
92
- error.status === HttpStatus.FormNotComplete
93
- ) {
94
- const data = error.data as Record<
95
- string,
96
- object | string
97
- >;
98
- resolve(data);
99
- } else if (
100
- typeof error === 'object' &&
101
- error !== null
102
- ) {
103
- const validationError =
104
- error as FormValidationError;
105
- if (validationError?.status === 400) {
106
- resolve({
107
- ...validationError.data,
108
- status: validationError.status.toString(),
109
- });
110
- }
111
- }
112
- } else if (result.data) {
113
- resolve(result.data);
93
+ .then(({ error, data }) => {
94
+ return new Promise<Record<string, unknown>>((resolve) => {
95
+ if (
96
+ isFetchBaseQueryError(error) &&
97
+ isRecord(error.data)
98
+ ) {
99
+ if (error.status === HttpStatus.FormNotComplete) {
100
+ resolve(error.data);
101
+ } else if (error.status === HttpStatus.BadRequest) {
102
+ resolve({
103
+ ...error.data,
104
+ status: error.status,
105
+ });
114
106
  }
107
+ } else if (data) {
108
+ resolve(data);
109
+ }
115
110
 
116
- resolve({});
117
- },
118
- );
111
+ resolve({});
112
+ });
119
113
  })
120
114
  .catch((error) => {
121
115
  return new Promise<Record<string, object>>(
@@ -145,7 +139,9 @@ export const WfoPydanticForm = ({
145
139
  });
146
140
  };
147
141
 
148
- const wfoComponentMatcher: ComponentMatcher = (currentMatchers) => {
142
+ const wfoComponentMatcherExtender: ComponentMatcherExtender = (
143
+ currentMatchers,
144
+ ): PydanticComponentMatcher[] => {
149
145
  const wfoMatchers: PydanticComponentMatcher[] = [
150
146
  {
151
147
  id: 'textarea',
@@ -209,7 +205,57 @@ export const WfoPydanticForm = ({
209
205
  return field.type === PydanticFormFieldType.BOOLEAN;
210
206
  },
211
207
  },
212
- ...currentMatchers.filter((matcher) => matcher.id !== 'text'),
208
+ {
209
+ id: 'radio',
210
+ ElementMatch: {
211
+ Element: Radio,
212
+ isControlledElement: true,
213
+ },
214
+ matcher(field) {
215
+ // We are looking for a single value from a set list of options. With less than 4 options, use radio buttons.
216
+ return (
217
+ field.type === PydanticFormFieldType.STRING &&
218
+ field.options.length > 0 &&
219
+ field.options.length <= 3
220
+ );
221
+ },
222
+ },
223
+ {
224
+ id: 'integerfield',
225
+ ElementMatch: {
226
+ Element: Integer,
227
+ isControlledElement: true,
228
+ },
229
+ matcher(field) {
230
+ return field.type === PydanticFormFieldType.INTEGER;
231
+ },
232
+ validator: zodValidationPresets.integer,
233
+ },
234
+
235
+ ...currentMatchers
236
+ .filter((matcher) => matcher.id !== 'text')
237
+ .filter((matcher) => matcher.id !== 'array')
238
+ .filter((matcher) => matcher.id !== 'object'),
239
+ {
240
+ id: 'object',
241
+ ElementMatch: {
242
+ isControlledElement: false,
243
+ Element: WfoObjectField,
244
+ },
245
+ matcher: (field) => {
246
+ return field.type === PydanticFormFieldType.OBJECT;
247
+ },
248
+ },
249
+ {
250
+ id: 'array',
251
+ ElementMatch: {
252
+ isControlledElement: true,
253
+ Element: WfoArrayField,
254
+ },
255
+ matcher: (field) => {
256
+ return field.type === PydanticFormFieldType.ARRAY;
257
+ },
258
+ },
213
259
  {
214
260
  id: 'text',
215
261
  ElementMatch: {
@@ -222,8 +268,9 @@ export const WfoPydanticForm = ({
222
268
  validator: zodValidationPresets.string,
223
269
  },
224
270
  ];
225
-
226
- return componentMatcher ? componentMatcher(wfoMatchers) : wfoMatchers;
271
+ return componentMatcherExtender
272
+ ? componentMatcherExtender(wfoMatchers)
273
+ : wfoMatchers;
227
274
  };
228
275
 
229
276
  const handleCancel = () => {
@@ -243,7 +290,7 @@ export const WfoPydanticForm = ({
243
290
  footerRenderer: Footer,
244
291
  headerRenderer: Header,
245
292
  skipSuccessNotice: true,
246
- componentMatcher: wfoComponentMatcher,
293
+ componentMatcherExtender: wfoComponentMatcherExtender,
247
294
  labelProvider: pydanticLabelProvider,
248
295
  rowRenderer: Row,
249
296
  customTranslations: {
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+
3
+ import type { PydanticFormControlledElement } from 'pydantic-forms';
4
+
5
+ import { EuiFieldNumber } from '@elastic/eui';
6
+ import { css } from '@emotion/react';
7
+
8
+ import type { WfoTheme } from '@/hooks';
9
+ import { useWithOrchestratorTheme } from '@/hooks';
10
+
11
+ const getFormFieldsBaseStyle = ({ theme }: WfoTheme) => {
12
+ const formFieldBaseStyle = css({
13
+ backgroundColor: theme.colors.body,
14
+ color: theme.colors.text,
15
+ '&:focus': {
16
+ backgroundColor: theme.colors.emptyShade,
17
+ },
18
+ });
19
+
20
+ return {
21
+ formFieldBaseStyle,
22
+ };
23
+ };
24
+
25
+ export const Integer: PydanticFormControlledElement = ({
26
+ pydanticFormField,
27
+ onChange,
28
+ value,
29
+ disabled,
30
+ }) => {
31
+ const { formFieldBaseStyle } = useWithOrchestratorTheme(
32
+ getFormFieldsBaseStyle,
33
+ );
34
+
35
+ return (
36
+ <EuiFieldNumber
37
+ css={formFieldBaseStyle}
38
+ name={pydanticFormField.id}
39
+ onChange={(event) => onChange(parseInt(event.target.value))}
40
+ value={value}
41
+ disabled={disabled}
42
+ />
43
+ );
44
+ };
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+
3
+ import type { PydanticFormControlledElement } from 'pydantic-forms';
4
+
5
+ import { EuiRadioGroup } from '@elastic/eui';
6
+
7
+ export const Radio: PydanticFormControlledElement = ({
8
+ pydanticFormField,
9
+ onChange,
10
+ value,
11
+ disabled,
12
+ }) => {
13
+ const radioOptions = pydanticFormField.options.map((option) => ({
14
+ id: option.value,
15
+ label: option.label,
16
+ }));
17
+
18
+ return (
19
+ <EuiRadioGroup
20
+ options={radioOptions}
21
+ idSelected={value}
22
+ onChange={(id) => onChange(id)}
23
+ name={pydanticFormField.id}
24
+ disabled={disabled}
25
+ />
26
+ );
27
+ };