@oneblink/apps-react 2.14.2 → 3.0.0-beta.2

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.
@@ -1,10 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import clsx from 'clsx';
3
+ import sanitizeHtml from '../services/sanitize-html';
3
4
  export default function QuillHTML({ html, ...props }) {
5
+ const __html = React.useMemo(() => sanitizeHtml(html), [html]);
4
6
  return (React.createElement("div", { ...props, className: clsx(props.className, 'ql-editor'),
5
7
  // eslint-disable-next-line react/no-danger
6
8
  dangerouslySetInnerHTML: {
7
- __html: html,
9
+ __html,
8
10
  } }));
9
11
  }
10
12
  //# sourceMappingURL=QuillHTML.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuillHTML.js","sourceRoot":"","sources":["../../src/components/QuillHTML.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,GAAG,KAAK,EAGT;IACC,OAAO,CACL,gCACM,KAAK,EACT,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC;QAC7C,2CAA2C;QAC3C,uBAAuB,EAAE;YACvB,MAAM,EAAE,IAAI;SACb,GACD,CACH,CAAA;AACH,CAAC","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\n\nexport default function QuillHTML({\n html,\n ...props\n}: React.ComponentProps<'div'> & {\n html: string\n}) {\n return (\n <div\n {...props}\n className={clsx(props.className, 'ql-editor')}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: html,\n }}\n />\n )\n}\n"]}
1
+ {"version":3,"file":"QuillHTML.js","sourceRoot":"","sources":["../../src/components/QuillHTML.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,YAAY,MAAM,2BAA2B,CAAA;AAEpD,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,GAAG,KAAK,EAGT;IACC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9D,OAAO,CACL,gCACM,KAAK,EACT,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC;QAC7C,2CAA2C;QAC3C,uBAAuB,EAAE;YACvB,MAAM;SACP,GACD,CACH,CAAA;AACH,CAAC","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport sanitizeHtml from '../services/sanitize-html'\n\nexport default function QuillHTML({\n html,\n ...props\n}: React.ComponentProps<'div'> & {\n html: string\n}) {\n const __html = React.useMemo(() => sanitizeHtml(html), [html])\n return (\n <div\n {...props}\n className={clsx(props.className, 'ql-editor')}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html,\n }}\n />\n )\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { Tooltip } from '@mui/material';
3
3
  import clsx from 'clsx';
4
- import useReplaceableHTML from '../../hooks/useReplaceableHTML';
4
+ import useReplaceableText from '../../hooks/useReplaceableText';
5
5
  import QuillHTML from '../QuillHTML';
6
6
  function FormElementLabelContainer({ className, element, id, required, children, leading, }) {
7
7
  return (React.createElement("div", { className: clsx('ob-form__element', className) },
@@ -17,12 +17,12 @@ function FormElementLabelContainer({ className, element, id, required, children,
17
17
  children));
18
18
  }
19
19
  export function HintTooltip({ hint }) {
20
- const html = useReplaceableHTML(hint);
20
+ const html = useReplaceableText(hint);
21
21
  return (React.createElement(Tooltip, { title: React.createElement(QuillHTML, { html: html, className: "ob-hint-tooltip" }), arrow: true, enterTouchDelay: 0, leaveTouchDelay: 10000 },
22
22
  React.createElement("i", { className: "material-icons has-text-grey-light ob-label__hint" }, "info")));
23
23
  }
24
24
  export function HintBelowLabel({ hint }) {
25
- const html = useReplaceableHTML(hint);
25
+ const html = useReplaceableText(hint);
26
26
  return React.createElement(QuillHTML, { html: html, className: "ob-hint-text" });
27
27
  }
28
28
  export default React.memo(FormElementLabelContainer);
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementLabelContainer.js","sourceRoot":"","sources":["../../../src/components/renderer/FormElementLabelContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,kBAAkB,MAAM,gCAAgC,CAAA;AAC/D,OAAO,SAAS,MAAM,cAAc,CAAA;AAEpC,SAAS,yBAAyB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,EAAE,EACF,QAAQ,EACR,QAAQ,EACR,OAAO,GAQR;IACC,OAAO,CACL,6BAAK,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;QACjD,6BAAK,SAAS,EAAC,2BAA2B;YACvC,OAAO;YACR,+BACE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE;oBAC1B,gCAAgC,EAAE,QAAQ;iBAC3C,CAAC,EACF,OAAO,EAAE,EAAE,IAEV,OAAO,CAAC,KAAK,CACR;YACP,OAAO,CAAC,IAAI;gBACX,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAC/D,oBAAC,WAAW,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CACpC,CACC;QACL,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY,KAAK,aAAa,IAAI,CACzD,6BAAK,SAAS,EAAC,yBAAyB;YACtC,oBAAC,cAAc,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CAClC,CACP;QACA,QAAQ,CACL,CACP,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,EAAoB;IACpD,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CACL,oBAAC,OAAO,IACN,KAAK,EAAE,oBAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAC,iBAAiB,GAAG,EAC5D,KAAK,QACL,eAAe,EAAE,CAAC,EAClB,eAAe,EAAE,KAAK;QAEtB,2BAAG,SAAS,EAAC,mDAAmD,WAAS,CACjE,CACX,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAoB;IACvD,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,oBAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAC,cAAc,GAAG,CAAA;AAC3D,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { Tooltip } from '@mui/material'\nimport clsx from 'clsx'\nimport { FormTypes } from '@oneblink/types'\nimport useReplaceableHTML from '../../hooks/useReplaceableHTML'\nimport QuillHTML from '../QuillHTML'\n\nfunction FormElementLabelContainer({\n className,\n element,\n id,\n required,\n children,\n leading,\n}: {\n className: string\n element: FormTypes.FormElementBase\n id: string\n required: boolean\n children: React.ReactNode\n leading?: React.ReactNode\n}) {\n return (\n <div className={clsx('ob-form__element', className)}>\n <div className=\"label ob-label__container\">\n {leading}\n <label\n className={clsx('ob-label', {\n 'ob-label__required is-required': required,\n })}\n htmlFor={id}\n >\n {element.label}\n </label>\n {element.hint &&\n (element.hintPosition === 'TOOLTIP' || !element.hintPosition) && (\n <HintTooltip hint={element.hint} />\n )}\n </div>\n {element.hint && element.hintPosition === 'BELOW_LABEL' && (\n <div className=\"ob-hint-text__container\">\n <HintBelowLabel hint={element.hint} />\n </div>\n )}\n {children}\n </div>\n )\n}\n\nexport function HintTooltip({ hint }: { hint: string }) {\n const html = useReplaceableHTML(hint)\n\n return (\n <Tooltip\n title={<QuillHTML html={html} className=\"ob-hint-tooltip\" />}\n arrow\n enterTouchDelay={0}\n leaveTouchDelay={10000}\n >\n <i className=\"material-icons has-text-grey-light ob-label__hint\">info</i>\n </Tooltip>\n )\n}\n\nexport function HintBelowLabel({ hint }: { hint: string }) {\n const html = useReplaceableHTML(hint)\n\n return <QuillHTML html={html} className=\"ob-hint-text\" />\n}\n\nexport default React.memo(FormElementLabelContainer)\n"]}
1
+ {"version":3,"file":"FormElementLabelContainer.js","sourceRoot":"","sources":["../../../src/components/renderer/FormElementLabelContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,kBAAkB,MAAM,gCAAgC,CAAA;AAC/D,OAAO,SAAS,MAAM,cAAc,CAAA;AAEpC,SAAS,yBAAyB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,EAAE,EACF,QAAQ,EACR,QAAQ,EACR,OAAO,GAQR;IACC,OAAO,CACL,6BAAK,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;QACjD,6BAAK,SAAS,EAAC,2BAA2B;YACvC,OAAO;YACR,+BACE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE;oBAC1B,gCAAgC,EAAE,QAAQ;iBAC3C,CAAC,EACF,OAAO,EAAE,EAAE,IAEV,OAAO,CAAC,KAAK,CACR;YACP,OAAO,CAAC,IAAI;gBACX,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAC/D,oBAAC,WAAW,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CACpC,CACC;QACL,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY,KAAK,aAAa,IAAI,CACzD,6BAAK,SAAS,EAAC,yBAAyB;YACtC,oBAAC,cAAc,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CAClC,CACP;QACA,QAAQ,CACL,CACP,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,EAAoB;IACpD,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CACL,oBAAC,OAAO,IACN,KAAK,EAAE,oBAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAC,iBAAiB,GAAG,EAC5D,KAAK,QACL,eAAe,EAAE,CAAC,EAClB,eAAe,EAAE,KAAK;QAEtB,2BAAG,SAAS,EAAC,mDAAmD,WAAS,CACjE,CACX,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAoB;IACvD,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,oBAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAC,cAAc,GAAG,CAAA;AAC3D,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { Tooltip } from '@mui/material'\nimport clsx from 'clsx'\nimport { FormTypes } from '@oneblink/types'\nimport useReplaceableText from '../../hooks/useReplaceableText'\nimport QuillHTML from '../QuillHTML'\n\nfunction FormElementLabelContainer({\n className,\n element,\n id,\n required,\n children,\n leading,\n}: {\n className: string\n element: FormTypes.FormElementBase\n id: string\n required: boolean\n children: React.ReactNode\n leading?: React.ReactNode\n}) {\n return (\n <div className={clsx('ob-form__element', className)}>\n <div className=\"label ob-label__container\">\n {leading}\n <label\n className={clsx('ob-label', {\n 'ob-label__required is-required': required,\n })}\n htmlFor={id}\n >\n {element.label}\n </label>\n {element.hint &&\n (element.hintPosition === 'TOOLTIP' || !element.hintPosition) && (\n <HintTooltip hint={element.hint} />\n )}\n </div>\n {element.hint && element.hintPosition === 'BELOW_LABEL' && (\n <div className=\"ob-hint-text__container\">\n <HintBelowLabel hint={element.hint} />\n </div>\n )}\n {children}\n </div>\n )\n}\n\nexport function HintTooltip({ hint }: { hint: string }) {\n const html = useReplaceableText(hint)\n\n return (\n <Tooltip\n title={<QuillHTML html={html} className=\"ob-hint-tooltip\" />}\n arrow\n enterTouchDelay={0}\n leaveTouchDelay={10000}\n >\n <i className=\"material-icons has-text-grey-light ob-label__hint\">info</i>\n </Tooltip>\n )\n}\n\nexport function HintBelowLabel({ hint }: { hint: string }) {\n const html = useReplaceableText(hint)\n\n return <QuillHTML html={html} className=\"ob-hint-text\" />\n}\n\nexport default React.memo(FormElementLabelContainer)\n"]}
@@ -44,12 +44,12 @@ const AutocompleteFilter = React.memo(function AutocompleteFilter({ id, element,
44
44
  React.createElement(FormElementOptions, { options: element.options, conditionallyShownOptionsElement: conditionallyShownOptionsElement },
45
45
  React.createElement(AutocompleteDropdown, { id: id, label: label, disabled: element.readOnly, placeholder: element.placeholderValue, required: element.required, value: value, validationMessage: validationMessage, displayValidationMessage: displayValidationMessage, onChangeValue: onChange, onChangeLabel: setLabel, onSearch: handleSearch, searchDebounceMs: 0, searchMinCharacters: 0, isDirty: isDirty, setIsDirty: setIsDirty })))));
46
46
  });
47
- const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, value, onChange, validationMessage, displayValidationMessage, searchUrl, isDirty, setIsDirty, }) {
47
+ const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, value, onChange, validationMessage, displayValidationMessage, searchUrl, searchQuerystringParameter, isDirty, setIsDirty, }) {
48
48
  const [label, setLabel] = React.useState('');
49
49
  const handleSearch = React.useCallback(async (search, abortSignal) => {
50
50
  const headers = await generateHeaders();
51
51
  const url = new URL(searchUrl);
52
- url.searchParams.append('value', search);
52
+ url.searchParams.append(searchQuerystringParameter, search);
53
53
  const response = await fetch(url.href, {
54
54
  headers,
55
55
  signal: abortSignal,
@@ -60,7 +60,7 @@ const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, v
60
60
  }
61
61
  const data = await response.json();
62
62
  return formElementsService.parseFormElementOptionsSet(data);
63
- }, [searchUrl]);
63
+ }, [searchQuerystringParameter, searchUrl]);
64
64
  // Ensure the label is set if the value is set outside of this component
65
65
  React.useEffect(() => {
66
66
  if (!label && typeof value === 'string') {
@@ -77,7 +77,7 @@ function FormElementAutocomplete({ conditionallyShownOptionsElement, onChange, .
77
77
  onChange(props.element, newValue);
78
78
  }, [onChange, props.element]);
79
79
  if (props.element.optionsType === 'SEARCH' && props.element.searchUrl) {
80
- return (React.createElement(AutocompleteFetch, { ...props, onChange: handleChange, searchUrl: props.element.searchUrl }));
80
+ return (React.createElement(AutocompleteFetch, { ...props, onChange: handleChange, searchUrl: props.element.searchUrl, searchQuerystringParameter: props.element.searchQuerystringParameter || 'value' }));
81
81
  }
82
82
  return (React.createElement(AutocompleteFilter, { ...props, onChange: handleChange, conditionallyShownOptionsElement: conditionallyShownOptionsElement }));
83
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementAutocomplete.js","sourceRoot":"","sources":["../../src/form-elements/FormElementAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { generateHeaders } from '@oneblink/apps/dist/services/fetch'\n\nimport FormElementOptions from '../components/renderer/FormElementOptions'\nimport useFormElementOptions from '../hooks/useFormElementOptions'\nimport AutocompleteDropdown from '../components/renderer/AutocompleteDropdown'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormTypes } from '@oneblink/types'\nimport {\n FormElementValueChangeHandler,\n FormElementConditionallyShownElement,\n IsDirtyProps,\n} from '../types/form'\n\ntype _BaseProps = {\n id: string\n element: FormTypes.AutoCompleteElement\n value: unknown | undefined\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\ntype _AutocompleteChangeHandlerProps = _BaseProps & {\n onChange: (newValue: unknown | undefined) => void\n}\n\ntype _AutocompleteConditionallyShowOptionProps = {\n conditionallyShownOptionsElement:\n | FormElementConditionallyShownElement\n | undefined\n}\n\ntype AutocompleteFilterProps = _AutocompleteChangeHandlerProps &\n _AutocompleteConditionallyShowOptionProps\n\ntype AutocompleteFetchProps = _AutocompleteChangeHandlerProps & {\n searchUrl: string\n}\n\ntype Props = _BaseProps &\n _AutocompleteConditionallyShowOptionProps & {\n onChange: FormElementValueChangeHandler<string>\n }\n\nconst AutocompleteFilter = React.memo(function AutocompleteFilter({\n id,\n element,\n value,\n onChange,\n conditionallyShownOptionsElement,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: AutocompleteFilterProps) {\n const [label, setLabel] = React.useState('')\n\n const onFilter = React.useCallback(\n (option: FormTypes.ChoiceElementOption) => {\n // If the user has typed nothing in, display all options\n if (!label) {\n return true\n }\n\n const lowerCase = label.toLowerCase()\n\n return option.label.toLowerCase().includes(lowerCase)\n },\n [label],\n )\n\n const handleChange = React.useCallback(\n //useFormElementOptions expects the first arg to be the element\n (element: FormTypes.FormElement, newValue: unknown) => onChange(newValue),\n [onChange],\n )\n\n const filteredOptions = useFormElementOptions({\n element,\n value,\n onChange: handleChange,\n conditionallyShownOptionsElement,\n onFilter,\n })\n\n const handleSearch = React.useCallback(async () => {\n return filteredOptions\n }, [filteredOptions])\n\n // Ensure the label matches the value selected\n React.useEffect(() => {\n if (!Array.isArray(element.options)) {\n return\n }\n\n const option = element.options.find((option) => option.value === value)\n if (option && label !== option.label) {\n setLabel(option.label)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [element.options, value])\n\n return (\n <div className=\"cypress-autocomplete-filter-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <FormElementOptions\n options={element.options}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n onSearch={handleSearch}\n searchDebounceMs={0}\n searchMinCharacters={0}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementOptions>\n </FormElementLabelContainer>\n </div>\n )\n})\n\nconst AutocompleteFetch = React.memo(function AutocompleteFetch({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n searchUrl,\n isDirty,\n setIsDirty,\n}: AutocompleteFetchProps) {\n const [label, setLabel] = React.useState('')\n\n const handleSearch = React.useCallback(\n async (search: string, abortSignal: AbortSignal) => {\n const headers = await generateHeaders()\n const url = new URL(searchUrl)\n url.searchParams.append('value', search)\n const response = await fetch(url.href, {\n headers,\n signal: abortSignal,\n })\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(text)\n }\n\n const data = await response.json()\n return formElementsService.parseFormElementOptionsSet(data)\n },\n [searchUrl],\n )\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (!label && typeof value === 'string') {\n setLabel(value)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-autocomplete-search-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n searchDebounceMs={750}\n searchMinCharacters={1}\n onSearch={handleSearch}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementLabelContainer>\n </div>\n )\n})\n\nfunction FormElementAutocomplete({\n conditionallyShownOptionsElement,\n onChange,\n ...props\n}: Props) {\n const handleChange = React.useCallback(\n (newValue: unknown) => {\n onChange(props.element, newValue as string | undefined)\n },\n [onChange, props.element],\n )\n if (props.element.optionsType === 'SEARCH' && props.element.searchUrl) {\n return (\n <AutocompleteFetch\n {...props}\n onChange={handleChange}\n searchUrl={props.element.searchUrl}\n />\n )\n }\n\n return (\n <AutocompleteFilter\n {...props}\n onChange={handleChange}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n />\n )\n}\n\nexport default React.memo(FormElementAutocomplete)\n"]}
1
+ {"version":3,"file":"FormElementAutocomplete.js","sourceRoot":"","sources":["../../src/form-elements/FormElementAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { generateHeaders } from '@oneblink/apps/dist/services/fetch'\n\nimport FormElementOptions from '../components/renderer/FormElementOptions'\nimport useFormElementOptions from '../hooks/useFormElementOptions'\nimport AutocompleteDropdown from '../components/renderer/AutocompleteDropdown'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormTypes } from '@oneblink/types'\nimport {\n FormElementValueChangeHandler,\n FormElementConditionallyShownElement,\n IsDirtyProps,\n} from '../types/form'\n\ntype _BaseProps = {\n id: string\n element: FormTypes.AutoCompleteElement\n value: unknown | undefined\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\ntype _AutocompleteChangeHandlerProps = _BaseProps & {\n onChange: (newValue: unknown | undefined) => void\n}\n\ntype _AutocompleteConditionallyShowOptionProps = {\n conditionallyShownOptionsElement:\n | FormElementConditionallyShownElement\n | undefined\n}\n\ntype AutocompleteFilterProps = _AutocompleteChangeHandlerProps &\n _AutocompleteConditionallyShowOptionProps\n\ntype AutocompleteFetchProps = _AutocompleteChangeHandlerProps & {\n searchUrl: string\n searchQuerystringParameter: string\n}\n\ntype Props = _BaseProps &\n _AutocompleteConditionallyShowOptionProps & {\n onChange: FormElementValueChangeHandler<string>\n }\n\nconst AutocompleteFilter = React.memo(function AutocompleteFilter({\n id,\n element,\n value,\n onChange,\n conditionallyShownOptionsElement,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: AutocompleteFilterProps) {\n const [label, setLabel] = React.useState('')\n\n const onFilter = React.useCallback(\n (option: FormTypes.ChoiceElementOption) => {\n // If the user has typed nothing in, display all options\n if (!label) {\n return true\n }\n\n const lowerCase = label.toLowerCase()\n\n return option.label.toLowerCase().includes(lowerCase)\n },\n [label],\n )\n\n const handleChange = React.useCallback(\n //useFormElementOptions expects the first arg to be the element\n (element: FormTypes.FormElement, newValue: unknown) => onChange(newValue),\n [onChange],\n )\n\n const filteredOptions = useFormElementOptions({\n element,\n value,\n onChange: handleChange,\n conditionallyShownOptionsElement,\n onFilter,\n })\n\n const handleSearch = React.useCallback(async () => {\n return filteredOptions\n }, [filteredOptions])\n\n // Ensure the label matches the value selected\n React.useEffect(() => {\n if (!Array.isArray(element.options)) {\n return\n }\n\n const option = element.options.find((option) => option.value === value)\n if (option && label !== option.label) {\n setLabel(option.label)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [element.options, value])\n\n return (\n <div className=\"cypress-autocomplete-filter-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <FormElementOptions\n options={element.options}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n onSearch={handleSearch}\n searchDebounceMs={0}\n searchMinCharacters={0}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementOptions>\n </FormElementLabelContainer>\n </div>\n )\n})\n\nconst AutocompleteFetch = React.memo(function AutocompleteFetch({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n searchUrl,\n searchQuerystringParameter,\n isDirty,\n setIsDirty,\n}: AutocompleteFetchProps) {\n const [label, setLabel] = React.useState('')\n\n const handleSearch = React.useCallback(\n async (search: string, abortSignal: AbortSignal) => {\n const headers = await generateHeaders()\n const url = new URL(searchUrl)\n url.searchParams.append(searchQuerystringParameter, search)\n const response = await fetch(url.href, {\n headers,\n signal: abortSignal,\n })\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(text)\n }\n\n const data = await response.json()\n return formElementsService.parseFormElementOptionsSet(data)\n },\n [searchQuerystringParameter, searchUrl],\n )\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (!label && typeof value === 'string') {\n setLabel(value)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-autocomplete-search-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n searchDebounceMs={750}\n searchMinCharacters={1}\n onSearch={handleSearch}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementLabelContainer>\n </div>\n )\n})\n\nfunction FormElementAutocomplete({\n conditionallyShownOptionsElement,\n onChange,\n ...props\n}: Props) {\n const handleChange = React.useCallback(\n (newValue: unknown) => {\n onChange(props.element, newValue as string | undefined)\n },\n [onChange, props.element],\n )\n if (props.element.optionsType === 'SEARCH' && props.element.searchUrl) {\n return (\n <AutocompleteFetch\n {...props}\n onChange={handleChange}\n searchUrl={props.element.searchUrl}\n searchQuerystringParameter={\n props.element.searchQuerystringParameter || 'value'\n }\n />\n )\n }\n\n return (\n <AutocompleteFilter\n {...props}\n onChange={handleChange}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n />\n )\n}\n\nexport default React.memo(FormElementAutocomplete)\n"]}
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import ExpressionParser from 'morph-expressions';
3
3
  import escapeString from 'escape-string-regexp';
4
- import sanitizeHtmlStandard from '../services/sanitize-html';
5
4
  import useFormSubmissionModel from '../hooks/useFormSubmissionModelContext';
6
5
  import { Sentry } from '@oneblink/apps';
7
6
  import { localisationService } from '@oneblink/apps';
@@ -25,9 +24,9 @@ function FormElementCalculation({ element, onChange, value }) {
25
24
  htmlTemplate = element.preCalculationDisplay;
26
25
  }
27
26
  const numberValue = typeof value === 'number' ? value : 0;
28
- return sanitizeHtmlStandard((htmlTemplate || '').replace(/{result}/gi, element.displayAsCurrency
27
+ return (htmlTemplate || '').replace(/{result}/gi, element.displayAsCurrency
29
28
  ? localisationService.formatCurrency(numberValue)
30
- : localisationService.formatNumber(numberValue)));
29
+ : localisationService.formatNumber(numberValue));
31
30
  }, [element, value]);
32
31
  const registerProperty = React.useCallback((exprParser, { replacement, nestedElementNames, }) => {
33
32
  exprParser.registerProperty(replacement, (submission) => {
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementCalculation.js","sourceRoot":"","sources":["../../src/form-elements/FormElementCalculation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,gBAAgB,MAAM,mBAAmB,CAAA;AAChD,OAAO,YAAY,MAAM,sBAAsB,CAAA;AAC/C,OAAO,oBAAoB,MAAM,2BAA2B,CAAA;AAC5D,OAAO,sBAAsB,MAAM,wCAAwC,CAAA;AAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAKpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,SAAS,MAAM,yBAAyB,CAAA;AAO/C,MAAM,gBAAgB,GAAG,CAAC,KAA0B,EAAE,EAAE;IACtD,OAAO,CAAC,KAAK,IAAI,KAAK,KAAK,CAAC,CAAA;AAC9B,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,CAAC,GAAY,EAA6B,EAAE;IACpE,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,IAAI,GAAG,CAAA;AAClE,CAAC,CAAA;AAED,SAAS,sBAAsB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAS;IACjE,MAAM,EAAE,mBAAmB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAExD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACnC,IAAI,YAAY,CAAA;QAEhB,IAAI,CAAC,KAAK,CAAC,KAAe,CAAC,EAAE;YAC3B,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;SACpC;aAAM;YACL,OAAO,CAAC,GAAG,CACT,mEAAmE,CACpE,CAAA;YACD,YAAY,GAAG,OAAO,CAAC,qBAAqB,CAAA;SAC7C;QAED,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACzD,OAAO,oBAAoB,CACzB,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,OAAO,CAC1B,YAAY,EACZ,OAAO,CAAC,iBAAiB;YACvB,CAAC,CAAC,mBAAmB,CAAC,cAAc,CAAC,WAAW,CAAC;YACjD,CAAC,CAAC,mBAAmB,CAAC,YAAY,CAAC,WAAW,CAAC,CAClD,CACF,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;IAEpB,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CACxC,CACE,UAAmC,EACnC,EACE,WAAW,EACX,kBAAkB,GAInB,EACD,EAAE;QACF,UAAU,CAAC,gBAAgB,CACzB,WAAW,EACX,CAAC,UAA+B,EAAE,EAAE;YAClC,MAAM,kBAAkB,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAA;YAE5D,OAAO,kBAAkB,CAAC,MAAM,CAC9B,CACE,YAAiC,EACjC,WAAmB,EACnB,KAAa,EACb,EAAE;gBACF,qCAAqC;gBACrC,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;oBACpC,OAAO,YAAY,CAAA;iBACpB;gBAED,8DAA8D;gBAC9D,0CAA0C;gBAC1C,kCAAkC;gBAClC,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;oBACpC,OAAO,UAAU,CAAC,YAAY,CAAC,CAAA;iBAChC;gBAED,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;oBAC/B,8CAA8C;oBAC9C,2CAA2C;oBAC3C,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;wBACxB,OAAO,GAAG,CAAA;qBACX;oBAED,oDAAoD;oBACpD,sDAAsD;oBACtD,oCAAoC;oBACpC,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/C,UAAU,CAAC,KAAK,CAAC,CAClB,CAAA;oBACD,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE;wBACxD,OAAO,aAAa,CAAC,MAAM,CACzB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,GAAG,KAAK,EACjC,CAAC,CACF,CAAA;qBACF;oBAED,uDAAuD;oBACvD,iDAAiD;oBACjD,sCAAsC;oBACtC,2BAA2B;oBAE3B,wDAAwD;oBACxD,iDAAiD;oBACjD,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;oBAErD,IAAI,qBAAqB,GAAG,KAAK,CAAA;oBACjC,MAAM,mBAAmB,GAAG,YAAY,CAAC,MAAM,CAC7C,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE;wBAC7B,IAAI,KAAK,EAAE;4BACT,MAAM,gBAAgB,GAAG,KAAK,CAAC,eAAe,CAAC,CAAA;4BAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;gCACnC,IAAI,gBAAgB,CAAC,MAAM,EAAE;oCAC3B,mBAAmB,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAA;oCAC7C,qBAAqB,GAAG,IAAI,CAAA;iCAC7B;6BACF;iCAAM;gCACL,mBAAmB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;6BAC3C;yBACF;wBACD,OAAO,mBAAmB,CAAA;oBAC5B,CAAC,EACD,EAAE,CACH,CAAA;oBAED,yFAAyF;oBACzF,IAAI,qBAAqB,EAAE;wBACzB,OAAO,mBAAmB,CAAA;qBAC3B;oBAED,OAAO,mBAAmB,CAAC,MAAM,CAC/B,CAAC,KAAa,EAAE,kBAAuC,EAAE,EAAE;wBACzD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;4BACvB,OAAO,GAAG,CAAA;yBACX;wBACD,MAAM,KAAK,GAAG,UAAU,CAAC,kBAA4B,CAAC,CAAA;wBACtD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;4BACvB,OAAO,GAAG,CAAA;yBACX;wBACD,OAAO,KAAK,GAAG,KAAK,CAAA;oBACtB,CAAC,EACD,CAAC,CACF,CAAA;iBACF;gBAED,yEAAyE;gBACzE,IACE,iBAAiB,CAAC,YAAY,CAAC;oBAC/B,OAAO,YAAY,CAAC,KAAK,KAAK,QAAQ,EACtC;oBACA,OAAO,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;iBACtC;gBAED,0DAA0D;gBAC1D,gDAAgD;gBAChD,OAAO,GAAG,CAAA;YACZ,CAAC,EACD,kBAAkB,CACnB,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC,EACD,EAAE,CACH,CAAA;IAED,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACnD,MAAM,UAAU,GAAG,IAAI,gBAAgB,EAAE,CAAA;QACzC,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAa,EAAE,SAAiB,EAAE,EAAE;YACxE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;gBAClD,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;aAC5C;YACD,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;QACF,UAAU,CAAC,gBAAgB,CACzB,QAAQ,EACR,CAAC,KAA0B,EAAE,YAAoB,EAAE,EAAE;YACnD,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE;gBAC3B,OAAO,YAAY,IAAI,CAAC,CAAA;aACzB;YACD,OAAO,KAAK,CAAA;QACd,CAAC,CACF,CAAA;QAED,IAAI;YACF,IAAI,CAAC,OAAO,CAAC,WAAW;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;YACxE,MAAM,YAAY,GAAa,EAAE,CAAA;YACjC,mBAAmB,CAAC,qBAAqB,CACvC,OAAO,CAAC,WAAW,EACnB,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;gBAClB,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YAChC,CAAC,CACF,CAAA;YAED,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;gBAC5D,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,YAAY,WAAW,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;gBACvE,MAAM,WAAW,GAAG,IAAI,KAAK,EAAE,CAAA;gBAC/B,gBAAgB,CAAC,UAAU,EAAE;oBAC3B,WAAW;oBACX,kBAAkB,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC;iBAC3C,CAAC,CAAA;gBACF,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;YACzC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAA;YAE7B,OAAO;gBACL,WAAW,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC1C,QAAQ,EAAE,KAAK;aAChB,CAAA;SACF;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CACV,wDAAwD,EACxD,OAAO,EACP,CAAC,CACF,CAAA;YACD,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;YAC1B,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,IAAI;aACf,CAAA;SACF;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAA;IAE/B,iBAAiB;IACjB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,WAAW;YAAE,OAAM;QACxB,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QACtD,IAAI,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE;YAClE,OAAM;SACP;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;YACpB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;SAC5B;aAAM;YACL,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;SAC7B;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAA;IAEhE,OAAO,CACL,6BAAK,SAAS,EAAC,6BAA6B;QAC1C,6BAAK,SAAS,EAAC,iCAAiC;YAC9C,oBAAC,SAAS,IACR,IAAI,EAAE,SAAS,EACf,SAAS,EAAC,oDAAoD,GAC9D;YACD,QAAQ,IAAI,CACX,6BACE,SAAS,EAAC,6CAA6C,EACvD,IAAI,EAAC,OAAO;gBAEZ,6BAAK,SAAS,EAAC,sBAAsB;oBACnC,6BAAK,SAAS,EAAC,kBAAkB;wBAC/B,2BAAG,SAAS,EAAC,iCAAiC,YAAU,CACpD;oBACN,6BAAK,SAAS,EAAC,QAAQ;wBACrB,wFAA6D,CACzD,CACF,CACF,CACP,CACG,CACF,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport ExpressionParser from 'morph-expressions'\nimport escapeString from 'escape-string-regexp'\nimport sanitizeHtmlStandard from '../services/sanitize-html'\nimport useFormSubmissionModel from '../hooks/useFormSubmissionModelContext'\nimport { FormTypes } from '@oneblink/types'\nimport { Sentry } from '@oneblink/apps'\nimport { localisationService } from '@oneblink/apps'\nimport {\n FormElementValueChangeHandler,\n FormSubmissionModel,\n} from '../types/form'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport QuillHTML from '../components/QuillHTML'\ntype Props = {\n element: FormTypes.CalculationElement\n onChange: FormElementValueChangeHandler<number>\n value: unknown | undefined\n}\n\nconst isUnenteredValue = (value: unknown | undefined) => {\n return !value && value !== 0\n}\n\nconst isObjectWithValue = (obj: unknown): obj is { value: unknown } => {\n return typeof obj === 'object' && obj !== null && 'value' in obj\n}\n\nfunction FormElementCalculation({ element, onChange, value }: Props) {\n const { formSubmissionModel } = useFormSubmissionModel()\n\n const htmlValue = React.useMemo(() => {\n let htmlTemplate\n\n if (!isNaN(value as number)) {\n htmlTemplate = element.defaultValue\n } else {\n console.log(\n '[Calculation] Was not a number... setting pre-calculation display',\n )\n htmlTemplate = element.preCalculationDisplay\n }\n\n const numberValue = typeof value === 'number' ? value : 0\n return sanitizeHtmlStandard(\n (htmlTemplate || '').replace(\n /{result}/gi,\n element.displayAsCurrency\n ? localisationService.formatCurrency(numberValue)\n : localisationService.formatNumber(numberValue),\n ),\n )\n }, [element, value])\n\n const registerProperty = React.useCallback(\n (\n exprParser: typeof ExpressionParser,\n {\n replacement,\n nestedElementNames,\n }: {\n replacement: string\n nestedElementNames: string[]\n },\n ) => {\n exprParser.registerProperty(\n replacement,\n (submission: FormSubmissionModel) => {\n const defaultAccumulator = submission[nestedElementNames[0]]\n\n return nestedElementNames.reduce(\n (\n elementValue: unknown | undefined,\n elementName: string,\n index: number,\n ) => {\n // Numbers can just be returned as is\n if (typeof elementValue === 'number') {\n return elementValue\n }\n\n // attempt to get a number from the element value as a string.\n // NaN is accounted for is the calculation\n // so we can return that from here\n if (typeof elementValue === 'string') {\n return parseFloat(elementValue)\n }\n\n if (Array.isArray(elementValue)) {\n // If there are no entries, we can return null\n // to prevent the calculation from running.\n if (!elementValue.length) {\n return NaN\n }\n\n // An array could be an element that allows multiple\n // values e.g. checkboxes. If thats that case, we just\n // add them all together and move on\n const elementValues = elementValue.map((entry) =>\n parseFloat(entry),\n )\n if (elementValues.every((entry) => !Number.isNaN(entry))) {\n return elementValues.reduce(\n (number, entry) => number + entry,\n 0,\n )\n }\n\n // Other wise attempt to process it as a repeatable set\n // If we found another repeatable set to process,\n // pass it to the next element name to\n // iterate over the entries\n\n // If we are processing the entries in a repeatable set,\n // we can sum the numbers elements in the entries\n const nextElementName = nestedElementNames[index + 1]\n\n let isNestedRepeatableSet = false\n const nestedElementValues = elementValue.reduce(\n (nestedElementValues, entry) => {\n if (entry) {\n const nextElementValue = entry[nextElementName]\n if (Array.isArray(nextElementValue)) {\n if (nextElementValue.length) {\n nestedElementValues.push(...nextElementValue)\n isNestedRepeatableSet = true\n }\n } else {\n nestedElementValues.push(nextElementValue)\n }\n }\n return nestedElementValues\n },\n [],\n )\n\n // If the nested element values are all arrays, we can pass them on to the next iteration\n if (isNestedRepeatableSet) {\n return nestedElementValues\n }\n\n return nestedElementValues.reduce(\n (total: number, nestedElementValue: unknown | undefined) => {\n if (Number.isNaN(total)) {\n return NaN\n }\n const value = parseFloat(nestedElementValue as string)\n if (Number.isNaN(value)) {\n return NaN\n }\n return total + value\n },\n 0,\n )\n }\n\n // \"compliance\" form element has an object value with a \"value\" property.\n if (\n isObjectWithValue(elementValue) &&\n typeof elementValue.value === 'string'\n ) {\n return parseFloat(elementValue.value)\n }\n\n // We did not find a number value from the known elements,\n // we will assume we are at the end of the line.\n return NaN\n },\n defaultAccumulator,\n )\n },\n )\n },\n [],\n )\n\n const { calculation, hasError } = React.useMemo(() => {\n const exprParser = new ExpressionParser()\n exprParser.registerFunction('ROUND', (value: number, precision: number) => {\n if (!Number.isNaN(value) && Number.isFinite(value)) {\n return parseFloat(value.toFixed(precision))\n }\n return null\n })\n exprParser.registerFunction(\n 'ISNULL',\n (value: unknown | undefined, defaultValue: number) => {\n if (isUnenteredValue(value)) {\n return defaultValue || 0\n }\n return value\n },\n )\n\n try {\n if (!element.calculation) throw new Error('Element has no calculation.')\n const elementNames: string[] = []\n formElementsService.matchElementsTagRegex(\n element.calculation,\n ({ elementName }) => {\n elementNames.push(elementName)\n },\n )\n\n const code = elementNames.reduce((code, elementName, index) => {\n const regex = new RegExp(escapeString(`{ELEMENT:${elementName}}`), 'g')\n const replacement = `a${index}`\n registerProperty(exprParser, {\n replacement,\n nestedElementNames: elementName.split('|'),\n })\n return code.replace(regex, replacement)\n }, element.calculation || '')\n\n return {\n calculation: exprParser.parse(code.trim()),\n hasError: false,\n }\n } catch (e) {\n console.warn(\n 'Error while setting up parsing for calculation element',\n element,\n e,\n )\n Sentry.captureException(e)\n return {\n calculation: null,\n hasError: true,\n }\n }\n }, [element, registerProperty])\n\n // MODEL LISTENER\n React.useEffect(() => {\n if (!calculation) return\n const newValue = calculation.eval(formSubmissionModel)\n if (value === newValue || (value === undefined && isNaN(newValue))) {\n return\n }\n if (!isNaN(newValue)) {\n onChange(element, newValue)\n } else {\n onChange(element, undefined)\n }\n }, [calculation, element, formSubmissionModel, onChange, value])\n\n return (\n <div className=\"cypress-calculation-element\">\n <div className=\"ob-form__element ob-calculation\">\n <QuillHTML\n html={htmlValue}\n className=\"cypress-calculation-result ob-calculation__content\"\n />\n {hasError && (\n <div\n className=\"notification cypress-calculation-is-invalid\"\n role=\"alert\"\n >\n <div className=\"columns is-vcentered\">\n <div className=\"column is-narrow\">\n <i className=\"material-icons has-text-warning\">error</i>\n </div>\n <div className=\"column\">\n <p>There is an error in the calculation for this element.</p>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default React.memo(FormElementCalculation)\n"]}
1
+ {"version":3,"file":"FormElementCalculation.js","sourceRoot":"","sources":["../../src/form-elements/FormElementCalculation.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport ExpressionParser from 'morph-expressions'\nimport escapeString from 'escape-string-regexp'\nimport useFormSubmissionModel from '../hooks/useFormSubmissionModelContext'\nimport { FormTypes } from '@oneblink/types'\nimport { Sentry } from '@oneblink/apps'\nimport { localisationService } from '@oneblink/apps'\nimport {\n FormElementValueChangeHandler,\n FormSubmissionModel,\n} from '../types/form'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport QuillHTML from '../components/QuillHTML'\ntype Props = {\n element: FormTypes.CalculationElement\n onChange: FormElementValueChangeHandler<number>\n value: unknown | undefined\n}\n\nconst isUnenteredValue = (value: unknown | undefined) => {\n return !value && value !== 0\n}\n\nconst isObjectWithValue = (obj: unknown): obj is { value: unknown } => {\n return typeof obj === 'object' && obj !== null && 'value' in obj\n}\n\nfunction FormElementCalculation({ element, onChange, value }: Props) {\n const { formSubmissionModel } = useFormSubmissionModel()\n\n const htmlValue = React.useMemo(() => {\n let htmlTemplate\n\n if (!isNaN(value as number)) {\n htmlTemplate = element.defaultValue\n } else {\n console.log(\n '[Calculation] Was not a number... setting pre-calculation display',\n )\n htmlTemplate = element.preCalculationDisplay\n }\n\n const numberValue = typeof value === 'number' ? value : 0\n return (htmlTemplate || '').replace(\n /{result}/gi,\n element.displayAsCurrency\n ? localisationService.formatCurrency(numberValue)\n : localisationService.formatNumber(numberValue),\n )\n }, [element, value])\n\n const registerProperty = React.useCallback(\n (\n exprParser: typeof ExpressionParser,\n {\n replacement,\n nestedElementNames,\n }: {\n replacement: string\n nestedElementNames: string[]\n },\n ) => {\n exprParser.registerProperty(\n replacement,\n (submission: FormSubmissionModel) => {\n const defaultAccumulator = submission[nestedElementNames[0]]\n\n return nestedElementNames.reduce(\n (\n elementValue: unknown | undefined,\n elementName: string,\n index: number,\n ) => {\n // Numbers can just be returned as is\n if (typeof elementValue === 'number') {\n return elementValue\n }\n\n // attempt to get a number from the element value as a string.\n // NaN is accounted for is the calculation\n // so we can return that from here\n if (typeof elementValue === 'string') {\n return parseFloat(elementValue)\n }\n\n if (Array.isArray(elementValue)) {\n // If there are no entries, we can return null\n // to prevent the calculation from running.\n if (!elementValue.length) {\n return NaN\n }\n\n // An array could be an element that allows multiple\n // values e.g. checkboxes. If thats that case, we just\n // add them all together and move on\n const elementValues = elementValue.map((entry) =>\n parseFloat(entry),\n )\n if (elementValues.every((entry) => !Number.isNaN(entry))) {\n return elementValues.reduce(\n (number, entry) => number + entry,\n 0,\n )\n }\n\n // Other wise attempt to process it as a repeatable set\n // If we found another repeatable set to process,\n // pass it to the next element name to\n // iterate over the entries\n\n // If we are processing the entries in a repeatable set,\n // we can sum the numbers elements in the entries\n const nextElementName = nestedElementNames[index + 1]\n\n let isNestedRepeatableSet = false\n const nestedElementValues = elementValue.reduce(\n (nestedElementValues, entry) => {\n if (entry) {\n const nextElementValue = entry[nextElementName]\n if (Array.isArray(nextElementValue)) {\n if (nextElementValue.length) {\n nestedElementValues.push(...nextElementValue)\n isNestedRepeatableSet = true\n }\n } else {\n nestedElementValues.push(nextElementValue)\n }\n }\n return nestedElementValues\n },\n [],\n )\n\n // If the nested element values are all arrays, we can pass them on to the next iteration\n if (isNestedRepeatableSet) {\n return nestedElementValues\n }\n\n return nestedElementValues.reduce(\n (total: number, nestedElementValue: unknown | undefined) => {\n if (Number.isNaN(total)) {\n return NaN\n }\n const value = parseFloat(nestedElementValue as string)\n if (Number.isNaN(value)) {\n return NaN\n }\n return total + value\n },\n 0,\n )\n }\n\n // \"compliance\" form element has an object value with a \"value\" property.\n if (\n isObjectWithValue(elementValue) &&\n typeof elementValue.value === 'string'\n ) {\n return parseFloat(elementValue.value)\n }\n\n // We did not find a number value from the known elements,\n // we will assume we are at the end of the line.\n return NaN\n },\n defaultAccumulator,\n )\n },\n )\n },\n [],\n )\n\n const { calculation, hasError } = React.useMemo(() => {\n const exprParser = new ExpressionParser()\n exprParser.registerFunction('ROUND', (value: number, precision: number) => {\n if (!Number.isNaN(value) && Number.isFinite(value)) {\n return parseFloat(value.toFixed(precision))\n }\n return null\n })\n exprParser.registerFunction(\n 'ISNULL',\n (value: unknown | undefined, defaultValue: number) => {\n if (isUnenteredValue(value)) {\n return defaultValue || 0\n }\n return value\n },\n )\n\n try {\n if (!element.calculation) throw new Error('Element has no calculation.')\n const elementNames: string[] = []\n formElementsService.matchElementsTagRegex(\n element.calculation,\n ({ elementName }) => {\n elementNames.push(elementName)\n },\n )\n\n const code = elementNames.reduce((code, elementName, index) => {\n const regex = new RegExp(escapeString(`{ELEMENT:${elementName}}`), 'g')\n const replacement = `a${index}`\n registerProperty(exprParser, {\n replacement,\n nestedElementNames: elementName.split('|'),\n })\n return code.replace(regex, replacement)\n }, element.calculation || '')\n\n return {\n calculation: exprParser.parse(code.trim()),\n hasError: false,\n }\n } catch (e) {\n console.warn(\n 'Error while setting up parsing for calculation element',\n element,\n e,\n )\n Sentry.captureException(e)\n return {\n calculation: null,\n hasError: true,\n }\n }\n }, [element, registerProperty])\n\n // MODEL LISTENER\n React.useEffect(() => {\n if (!calculation) return\n const newValue = calculation.eval(formSubmissionModel)\n if (value === newValue || (value === undefined && isNaN(newValue))) {\n return\n }\n if (!isNaN(newValue)) {\n onChange(element, newValue)\n } else {\n onChange(element, undefined)\n }\n }, [calculation, element, formSubmissionModel, onChange, value])\n\n return (\n <div className=\"cypress-calculation-element\">\n <div className=\"ob-form__element ob-calculation\">\n <QuillHTML\n html={htmlValue}\n className=\"cypress-calculation-result ob-calculation__content\"\n />\n {hasError && (\n <div\n className=\"notification cypress-calculation-is-invalid\"\n role=\"alert\"\n >\n <div className=\"columns is-vcentered\">\n <div className=\"column is-narrow\">\n <i className=\"material-icons has-text-warning\">error</i>\n </div>\n <div className=\"column\">\n <p>There is an error in the calculation for this element.</p>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default React.memo(FormElementCalculation)\n"]}
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import useReplaceableHTML from '../hooks/useReplaceableHTML';
2
+ import useReplaceableText from '../hooks/useReplaceableText';
3
3
  import QuillHTML from '../components/QuillHTML';
4
4
  function FormElementHTML({ element }) {
5
- const html = useReplaceableHTML(element.defaultValue);
5
+ const html = useReplaceableText(element.defaultValue);
6
6
  return (React.createElement("div", { className: "cypress-html-element" },
7
7
  React.createElement("div", { className: "ob-form__element ob-information cypress-html-element" },
8
8
  React.createElement(QuillHTML, { html: html, className: "cypress-html-element-content ob-information__content" }))));
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementHTML.js","sourceRoot":"","sources":["../../src/form-elements/FormElementHTML.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,kBAAkB,MAAM,6BAA6B,CAAA;AAC5D,OAAO,SAAS,MAAM,yBAAyB,CAAA;AAM/C,SAAS,eAAe,CAAC,EAAE,OAAO,EAAS;IACzC,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;IAErD,OAAO,CACL,6BAAK,SAAS,EAAC,sBAAsB;QACnC,6BAAK,SAAS,EAAC,sDAAsD;YACnE,oBAAC,SAAS,IACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,sDAAsD,GAChE,CACE,CACF,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { FormTypes } from '@oneblink/types'\nimport useReplaceableHTML from '../hooks/useReplaceableHTML'\nimport QuillHTML from '../components/QuillHTML'\n\ntype Props = {\n element: FormTypes.HtmlElement\n}\n\nfunction FormElementHTML({ element }: Props) {\n const html = useReplaceableHTML(element.defaultValue)\n\n return (\n <div className=\"cypress-html-element\">\n <div className=\"ob-form__element ob-information cypress-html-element\">\n <QuillHTML\n html={html}\n className=\"cypress-html-element-content ob-information__content\"\n />\n </div>\n </div>\n )\n}\n\nexport default React.memo(FormElementHTML)\n"]}
1
+ {"version":3,"file":"FormElementHTML.js","sourceRoot":"","sources":["../../src/form-elements/FormElementHTML.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,kBAAkB,MAAM,6BAA6B,CAAA;AAC5D,OAAO,SAAS,MAAM,yBAAyB,CAAA;AAM/C,SAAS,eAAe,CAAC,EAAE,OAAO,EAAS;IACzC,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;IAErD,OAAO,CACL,6BAAK,SAAS,EAAC,sBAAsB;QACnC,6BAAK,SAAS,EAAC,sDAAsD;YACnE,oBAAC,SAAS,IACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,sDAAsD,GAChE,CACE,CACF,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { FormTypes } from '@oneblink/types'\nimport useReplaceableText from '../hooks/useReplaceableText'\nimport QuillHTML from '../components/QuillHTML'\n\ntype Props = {\n element: FormTypes.HtmlElement\n}\n\nfunction FormElementHTML({ element }: Props) {\n const html = useReplaceableText(element.defaultValue)\n\n return (\n <div className=\"cypress-html-element\">\n <div className=\"ob-form__element ob-information cypress-html-element\">\n <QuillHTML\n html={html}\n className=\"cypress-html-element-content ob-information__content\"\n />\n </div>\n </div>\n )\n}\n\nexport default React.memo(FormElementHTML)\n"]}
@@ -14,21 +14,36 @@ export default function useDynamicOptionsLoaderState(form, setFormSubmission) {
14
14
  if (abortController.signal.aborted || !optionsByElementId.length) {
15
15
  return;
16
16
  }
17
- const nonOkResponse = optionsByElementId.find((optionsForElementId) => !optionsForElementId.ok);
18
- if (nonOkResponse && !nonOkResponse.ok) {
19
- setState(nonOkResponse);
17
+ const nonOkResponse = optionsByElementId.find((optionsForElementId) => optionsForElementId.type === 'ERROR');
18
+ if (nonOkResponse && nonOkResponse.type === 'ERROR') {
19
+ setState({
20
+ elementId: nonOkResponse.elementId,
21
+ error: nonOkResponse.error,
22
+ });
20
23
  return;
21
24
  }
22
25
  setFormSubmission((currentFormSubmission) => {
23
26
  const clonedForm = _cloneDeep(currentFormSubmission.definition);
24
27
  for (const optionsForElementId of optionsByElementId) {
25
- if (optionsForElementId.ok) {
26
- formElementsService.forEachFormElementWithOptions(clonedForm.elements, (formElement) => {
27
- if (formElement.id === optionsForElementId.elementId) {
28
- formElement.options = optionsForElementId.options;
28
+ formElementsService.forEachFormElementWithOptions(clonedForm.elements, (formElement) => {
29
+ if (formElement.id === optionsForElementId.elementId) {
30
+ switch (optionsForElementId.type) {
31
+ case 'OPTIONS': {
32
+ formElement.options = optionsForElementId.options;
33
+ break;
34
+ }
35
+ case 'SEARCH': {
36
+ if (formElement.type === 'autocomplete') {
37
+ formElement.optionsType = 'SEARCH';
38
+ formElement.searchUrl = optionsForElementId.url;
39
+ formElement.searchQuerystringParameter =
40
+ optionsForElementId.searchQuerystringParameter;
41
+ }
42
+ break;
43
+ }
29
44
  }
30
- });
31
- }
45
+ }
46
+ });
32
47
  }
33
48
  return {
34
49
  ...currentFormSubmission,
@@ -1 +1 @@
1
- {"version":3,"file":"useDynamicOptionsLoaderState.js","sourceRoot":"","sources":["../../src/hooks/useDynamicOptionsLoaderState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,UAAU,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAqB,MAAM,gBAAgB,CAAA;AAI/D,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAClD,IAAoB,EACpB,iBAAoC;IAKpC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GACrB,KAAK,CAAC,QAAQ,CAAkD,IAAI,CAAC,CAAA;IACvE,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,KAAK,EAAE;YACT,OAAM;SACP;QAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAE5C;QAAA,CAAC,KAAK,IAAI,EAAE;YACX,MAAM,kBAAkB,GAAG,MAAM,WAAW,CAAC,4BAA4B,CACvE,IAAI,CACL,CAAA;YAED,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE;gBAChE,OAAM;aACP;YAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAC3C,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,EAAE,CACjD,CAAA;YACD,IAAI,aAAa,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE;gBACtC,QAAQ,CAAC,aAAa,CAAC,CAAA;gBACvB,OAAM;aACP;YAED,iBAAiB,CAAC,CAAC,qBAAqB,EAAE,EAAE;gBAC1C,MAAM,UAAU,GAAmB,UAAU,CAC3C,qBAAqB,CAAC,UAAU,CACjC,CAAA;gBACD,KAAK,MAAM,mBAAmB,IAAI,kBAAkB,EAAE;oBACpD,IAAI,mBAAmB,CAAC,EAAE,EAAE;wBAC1B,mBAAmB,CAAC,6BAA6B,CAC/C,UAAU,CAAC,QAAQ,EACnB,CAAC,WAAW,EAAE,EAAE;4BACd,IAAI,WAAW,CAAC,EAAE,KAAK,mBAAmB,CAAC,SAAS,EAAE;gCACpD,WAAW,CAAC,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAA;6BAClD;wBACH,CAAC,CACF,CAAA;qBACF;iBACF;gBACD,OAAO;oBACL,GAAG,qBAAqB;oBACxB,UAAU,EAAE,UAAU;iBACvB,CAAA;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,EAAE,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,eAAe,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAA;IAEpC,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import * as React from 'react'\nimport _cloneDeep from 'lodash.clonedeep'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { formService, OneBlinkAppsError } from '@oneblink/apps'\nimport { FormTypes } from '@oneblink/types'\nimport { SetFormSubmission } from '../types/form'\n\nexport default function useDynamicOptionsLoaderState(\n form: FormTypes.Form,\n setFormSubmission: SetFormSubmission,\n): {\n elementId: string\n error: OneBlinkAppsError\n} | null {\n const [state, setState] =\n React.useState<ReturnType<typeof useDynamicOptionsLoaderState>>(null)\n React.useEffect(() => {\n if (state) {\n return\n }\n\n const abortController = new AbortController()\n\n ;(async () => {\n const optionsByElementId = await formService.getFormElementDynamicOptions(\n form,\n )\n\n if (abortController.signal.aborted || !optionsByElementId.length) {\n return\n }\n\n const nonOkResponse = optionsByElementId.find(\n (optionsForElementId) => !optionsForElementId.ok,\n )\n if (nonOkResponse && !nonOkResponse.ok) {\n setState(nonOkResponse)\n return\n }\n\n setFormSubmission((currentFormSubmission) => {\n const clonedForm: FormTypes.Form = _cloneDeep(\n currentFormSubmission.definition,\n )\n for (const optionsForElementId of optionsByElementId) {\n if (optionsForElementId.ok) {\n formElementsService.forEachFormElementWithOptions(\n clonedForm.elements,\n (formElement) => {\n if (formElement.id === optionsForElementId.elementId) {\n formElement.options = optionsForElementId.options\n }\n },\n )\n }\n }\n return {\n ...currentFormSubmission,\n definition: clonedForm,\n }\n })\n })()\n\n return () => {\n abortController.abort()\n }\n }, [form, setFormSubmission, state])\n\n return state\n}\n"]}
1
+ {"version":3,"file":"useDynamicOptionsLoaderState.js","sourceRoot":"","sources":["../../src/hooks/useDynamicOptionsLoaderState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,UAAU,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAqB,MAAM,gBAAgB,CAAA;AAI/D,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAClD,IAAoB,EACpB,iBAAoC;IAEpC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAG9B,IAAI,CAAC,CAAA;IACf,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,KAAK,EAAE;YACT,OAAM;SACP;QAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAE5C;QAAA,CAAC,KAAK,IAAI,EAAE;YACX,MAAM,kBAAkB,GAAG,MAAM,WAAW,CAAC,4BAA4B,CACvE,IAAI,CACL,CAAA;YAED,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE;gBAChE,OAAM;aACP;YAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAC3C,CAAC,mBAAmB,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,KAAK,OAAO,CAC9D,CAAA;YACD,IAAI,aAAa,IAAI,aAAa,CAAC,IAAI,KAAK,OAAO,EAAE;gBACnD,QAAQ,CAAC;oBACP,SAAS,EAAE,aAAa,CAAC,SAAS;oBAClC,KAAK,EAAE,aAAa,CAAC,KAAK;iBAC3B,CAAC,CAAA;gBACF,OAAM;aACP;YAED,iBAAiB,CAAC,CAAC,qBAAqB,EAAE,EAAE;gBAC1C,MAAM,UAAU,GAAmB,UAAU,CAC3C,qBAAqB,CAAC,UAAU,CACjC,CAAA;gBACD,KAAK,MAAM,mBAAmB,IAAI,kBAAkB,EAAE;oBACpD,mBAAmB,CAAC,6BAA6B,CAC/C,UAAU,CAAC,QAAQ,EACnB,CAAC,WAAW,EAAE,EAAE;wBACd,IAAI,WAAW,CAAC,EAAE,KAAK,mBAAmB,CAAC,SAAS,EAAE;4BACpD,QAAQ,mBAAmB,CAAC,IAAI,EAAE;gCAChC,KAAK,SAAS,CAAC,CAAC;oCACd,WAAW,CAAC,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAA;oCACjD,MAAK;iCACN;gCACD,KAAK,QAAQ,CAAC,CAAC;oCACb,IAAI,WAAW,CAAC,IAAI,KAAK,cAAc,EAAE;wCACvC,WAAW,CAAC,WAAW,GAAG,QAAQ,CAAA;wCAClC,WAAW,CAAC,SAAS,GAAG,mBAAmB,CAAC,GAAG,CAAA;wCAC/C,WAAW,CAAC,0BAA0B;4CACpC,mBAAmB,CAAC,0BAA0B,CAAA;qCACjD;oCACD,MAAK;iCACN;6BACF;yBACF;oBACH,CAAC,CACF,CAAA;iBACF;gBACD,OAAO;oBACL,GAAG,qBAAqB;oBACxB,UAAU,EAAE,UAAU;iBACvB,CAAA;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,EAAE,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,eAAe,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAA;IAEpC,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import * as React from 'react'\nimport _cloneDeep from 'lodash.clonedeep'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { formService, OneBlinkAppsError } from '@oneblink/apps'\nimport { FormTypes } from '@oneblink/types'\nimport { SetFormSubmission } from '../types/form'\n\nexport default function useDynamicOptionsLoaderState(\n form: FormTypes.Form,\n setFormSubmission: SetFormSubmission,\n) {\n const [state, setState] = React.useState<{\n elementId: string\n error: OneBlinkAppsError\n } | null>(null)\n React.useEffect(() => {\n if (state) {\n return\n }\n\n const abortController = new AbortController()\n\n ;(async () => {\n const optionsByElementId = await formService.getFormElementDynamicOptions(\n form,\n )\n\n if (abortController.signal.aborted || !optionsByElementId.length) {\n return\n }\n\n const nonOkResponse = optionsByElementId.find(\n (optionsForElementId) => optionsForElementId.type === 'ERROR',\n )\n if (nonOkResponse && nonOkResponse.type === 'ERROR') {\n setState({\n elementId: nonOkResponse.elementId,\n error: nonOkResponse.error,\n })\n return\n }\n\n setFormSubmission((currentFormSubmission) => {\n const clonedForm: FormTypes.Form = _cloneDeep(\n currentFormSubmission.definition,\n )\n for (const optionsForElementId of optionsByElementId) {\n formElementsService.forEachFormElementWithOptions(\n clonedForm.elements,\n (formElement) => {\n if (formElement.id === optionsForElementId.elementId) {\n switch (optionsForElementId.type) {\n case 'OPTIONS': {\n formElement.options = optionsForElementId.options\n break\n }\n case 'SEARCH': {\n if (formElement.type === 'autocomplete') {\n formElement.optionsType = 'SEARCH'\n formElement.searchUrl = optionsForElementId.url\n formElement.searchQuerystringParameter =\n optionsForElementId.searchQuerystringParameter\n }\n break\n }\n }\n }\n },\n )\n }\n return {\n ...currentFormSubmission,\n definition: clonedForm,\n }\n })\n })()\n\n return () => {\n abortController.abort()\n }\n }, [form, setFormSubmission, state])\n\n return state\n}\n"]}
@@ -13,6 +13,9 @@ export default function useLogin({ username, password, newPassword, newPasswordC
13
13
  isPasswordTemporary: boolean;
14
14
  isResettingTemporaryPassword: boolean;
15
15
  resetTemporaryPassword: () => Promise<void>;
16
+ isMfaCodeRequired: boolean;
17
+ isSubmittingMfaCode: boolean;
18
+ submitMfaCode: () => Promise<void>;
16
19
  isShowingForgotPassword: boolean;
17
20
  showForgotPassword: () => void;
18
21
  hideForgotPassword: () => void;
@@ -42,12 +42,13 @@ export default function useLogin({ username, password, newPassword, newPasswordC
42
42
  isInvalid: newPassword !== newPasswordConfirmed,
43
43
  };
44
44
  }, [newPassword, newPasswordConfirmed]);
45
- // Login & Reset Password
46
- const [{ isResettingTemporaryPassword, isLoggingIn, loginError, resetTemporaryPasswordCallback, }, setLoginState,] = React.useState({
45
+ // Login, Reset Password, MFA
46
+ const [{ isResettingTemporaryPassword, isLoggingIn, loginError, loginAttemptResponse, isSubmittingMfaCode, }, setLoginState,] = React.useState({
47
47
  isResettingTemporaryPassword: false,
48
48
  isLoggingIn: false,
49
49
  loginError: null,
50
- resetTemporaryPasswordCallback: null,
50
+ loginAttemptResponse: undefined,
51
+ isSubmittingMfaCode: false,
51
52
  });
52
53
  const clearLoginError = React.useCallback(() => setLoginState((current) => ({
53
54
  ...current,
@@ -68,34 +69,29 @@ export default function useLogin({ username, password, newPassword, newPasswordC
68
69
  }));
69
70
  return;
70
71
  }
71
- setLoginState({
72
- isResettingTemporaryPassword: false,
73
- resetTemporaryPasswordCallback: null,
72
+ setLoginState((currentState) => ({
73
+ ...currentState,
74
74
  isLoggingIn: true,
75
75
  loginError: null,
76
- });
76
+ }));
77
77
  try {
78
- const newResetPasswordCallback = await authService.loginUsernamePassword(username, password);
79
- if (newResetPasswordCallback) {
80
- if (isMounted.current) {
81
- setLoginState({
82
- isResettingTemporaryPassword: false,
83
- isLoggingIn: false,
84
- resetTemporaryPasswordCallback: newResetPasswordCallback,
85
- loginError: null,
86
- });
87
- }
78
+ const newLoginAttemptResponse = await authService.loginUsernamePassword(username, password);
79
+ if (isMounted.current) {
80
+ setLoginState((currentState) => ({
81
+ ...currentState,
82
+ isLoggingIn: false,
83
+ loginAttemptResponse: newLoginAttemptResponse,
84
+ }));
88
85
  }
89
86
  }
90
87
  catch (error) {
91
88
  Sentry.captureException(error);
92
89
  if (isMounted.current) {
93
- setLoginState({
94
- isResettingTemporaryPassword: false,
90
+ setLoginState((currentState) => ({
91
+ ...currentState,
95
92
  isLoggingIn: false,
96
- resetTemporaryPasswordCallback: null,
97
93
  loginError: error,
98
- });
94
+ }));
99
95
  }
100
96
  }
101
97
  }, [
@@ -106,6 +102,7 @@ export default function useLogin({ username, password, newPassword, newPasswordC
106
102
  usernameValidation.isInvalid,
107
103
  ]);
108
104
  const resetTemporaryPassword = React.useCallback(async () => {
105
+ const resetTemporaryPasswordCallback = loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.resetPasswordCallback;
109
106
  if (!resetTemporaryPasswordCallback) {
110
107
  return;
111
108
  }
@@ -129,7 +126,14 @@ export default function useLogin({ username, password, newPassword, newPasswordC
129
126
  loginError: null,
130
127
  }));
131
128
  try {
132
- await resetTemporaryPasswordCallback(newPassword);
129
+ const resetPasswordResponse = await resetTemporaryPasswordCallback(newPassword);
130
+ if (isMounted.current) {
131
+ setLoginState((currentState) => ({
132
+ ...currentState,
133
+ isResettingTemporaryPassword: false,
134
+ loginAttemptResponse: resetPasswordResponse,
135
+ }));
136
+ }
133
137
  }
134
138
  catch (error) {
135
139
  Sentry.captureException(error);
@@ -143,11 +147,42 @@ export default function useLogin({ username, password, newPassword, newPasswordC
143
147
  }
144
148
  }, [
145
149
  isMounted,
150
+ loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.resetPasswordCallback,
146
151
  newPassword,
147
152
  newPasswordConfirmedValidation.isInvalid,
148
153
  newPasswordValidation.isInvalid,
149
- resetTemporaryPasswordCallback,
150
154
  ]);
155
+ const submitMfaCode = React.useCallback(async () => {
156
+ const mfaCodeCallback = loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.mfaCodeCallback;
157
+ if (!mfaCodeCallback) {
158
+ return;
159
+ }
160
+ setLoginState((current) => ({
161
+ ...current,
162
+ isSubmittingMfaCode: true,
163
+ loginError: null,
164
+ }));
165
+ try {
166
+ const mfaResponse = await mfaCodeCallback(code);
167
+ if (isMounted.current) {
168
+ setLoginState((currentState) => ({
169
+ ...currentState,
170
+ isSubmittingMfaCode: false,
171
+ loginAttemptResponse: mfaResponse,
172
+ }));
173
+ }
174
+ }
175
+ catch (error) {
176
+ Sentry.captureException(error);
177
+ if (isMounted.current) {
178
+ setLoginState((current) => ({
179
+ ...current,
180
+ isSubmittingMfaCode: false,
181
+ loginError: error,
182
+ }));
183
+ }
184
+ }
185
+ }, [code, isMounted, loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.mfaCodeCallback]);
151
186
  // Forgot Password
152
187
  const [isShowingForgotPassword, showForgotPassword, hideForgotPassword] = useBooleanState(false);
153
188
  const [{ resetForgottenPasswordCallback, isSendingForgotPasswordCode, isResettingForgottenPassword, forgotPasswordError, }, setForgotPasswordState,] = React.useState({
@@ -269,9 +304,13 @@ export default function useLogin({ username, password, newPassword, newPasswordC
269
304
  loginError,
270
305
  clearLoginError,
271
306
  // Reset Temp Password
272
- isPasswordTemporary: !!resetTemporaryPasswordCallback,
307
+ isPasswordTemporary: !!(loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.resetPasswordCallback),
273
308
  isResettingTemporaryPassword,
274
309
  resetTemporaryPassword,
310
+ // MFA Code
311
+ isMfaCodeRequired: !!(loginAttemptResponse === null || loginAttemptResponse === void 0 ? void 0 : loginAttemptResponse.mfaCodeCallback),
312
+ isSubmittingMfaCode,
313
+ submitMfaCode,
275
314
  // Showing Forgot Password
276
315
  isShowingForgotPassword,
277
316
  showForgotPassword,
@@ -1 +1 @@
1
- {"version":3,"file":"useLogin.js","sourceRoot":"","sources":["../../src/hooks/useLogin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { authService, Sentry } from '@oneblink/apps'\n\nimport useIsMounted from './useIsMounted'\nimport useBooleanState from './useBooleanState'\n\nexport default function useLogin({\n username,\n password,\n newPassword,\n newPasswordConfirmed,\n code,\n}: {\n username: string\n password: string\n newPassword: string\n newPasswordConfirmed: string\n code: string\n}) {\n const isMounted = useIsMounted()\n\n // Validation\n const usernameValidation = React.useMemo(() => {\n return {\n isInvalid: !username.trim(),\n }\n }, [username])\n\n const passwordValidation = React.useMemo(() => {\n return {\n isInvalid: !password.trim(),\n }\n }, [password])\n\n const codeValidation = React.useMemo(() => {\n return {\n isInvalid: !code.trim(),\n }\n }, [code])\n\n const newPasswordValidation = React.useMemo(() => {\n const validation = {\n hasLowercaseLetter: /[a-z]+/.test(newPassword),\n hasUpperCaseLetter: /[A-Z]+/.test(newPassword),\n hasNumber: /\\d+/.test(newPassword),\n hasSpecialCharacter: /[\\^$*.[\\]{}()?|\\-\"!@#%&/,><':;|_~`]+/.test(\n newPassword,\n ),\n hasMinLength: newPassword.length >= 8,\n isInvalid: true,\n }\n validation.isInvalid =\n !validation.hasLowercaseLetter ||\n !validation.hasUpperCaseLetter ||\n !validation.hasNumber ||\n !validation.hasSpecialCharacter ||\n !validation.hasMinLength\n return validation\n }, [newPassword])\n\n const newPasswordConfirmedValidation = React.useMemo(() => {\n return {\n isInvalid: newPassword !== newPasswordConfirmed,\n }\n }, [newPassword, newPasswordConfirmed])\n\n // Login & Reset Password\n const [\n {\n isResettingTemporaryPassword,\n isLoggingIn,\n loginError,\n resetTemporaryPasswordCallback,\n },\n setLoginState,\n ] = React.useState<{\n isResettingTemporaryPassword: boolean\n isLoggingIn: boolean\n loginError: null | Error\n resetTemporaryPasswordCallback: null | ((newPassword: string) => void)\n }>({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n loginError: null,\n resetTemporaryPasswordCallback: null,\n })\n const clearLoginError = React.useCallback(\n () =>\n setLoginState((current) => ({\n ...current,\n loginError: null,\n })),\n [],\n )\n const loginWithUsernamePassword = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid email address'),\n }))\n return\n }\n if (passwordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n setLoginState({\n isResettingTemporaryPassword: false,\n resetTemporaryPasswordCallback: null,\n isLoggingIn: true,\n loginError: null,\n })\n\n try {\n const newResetPasswordCallback = await authService.loginUsernamePassword(\n username,\n password,\n )\n if (newResetPasswordCallback) {\n if (isMounted.current) {\n setLoginState({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n resetTemporaryPasswordCallback: newResetPasswordCallback,\n loginError: null,\n })\n }\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n resetTemporaryPasswordCallback: null,\n loginError: error as Error,\n })\n }\n }\n }, [\n isMounted,\n password,\n passwordValidation.isInvalid,\n username,\n usernameValidation.isInvalid,\n ])\n\n const resetTemporaryPassword = React.useCallback(async () => {\n if (!resetTemporaryPasswordCallback) {\n return\n }\n\n if (newPasswordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n if (newPasswordConfirmedValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isResettingPassword: true,\n loginError: null,\n }))\n\n try {\n await resetTemporaryPasswordCallback(newPassword)\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isResettingPassword: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n newPassword,\n newPasswordConfirmedValidation.isInvalid,\n newPasswordValidation.isInvalid,\n resetTemporaryPasswordCallback,\n ])\n\n // Forgot Password\n const [isShowingForgotPassword, showForgotPassword, hideForgotPassword] =\n useBooleanState(false)\n const [\n {\n resetForgottenPasswordCallback,\n isSendingForgotPasswordCode,\n isResettingForgottenPassword,\n forgotPasswordError,\n },\n setForgotPasswordState,\n ] = React.useState<{\n isSendingForgotPasswordCode: boolean\n forgotPasswordError: null | Error\n resetForgottenPasswordCallback:\n | null\n | ((code: string, newPassword: string) => void)\n isResettingForgottenPassword: boolean\n }>({\n isSendingForgotPasswordCode: false,\n forgotPasswordError: null,\n resetForgottenPasswordCallback: null,\n isResettingForgottenPassword: false,\n })\n const clearForgotPasswordError = React.useCallback(\n () =>\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: null,\n })),\n [],\n )\n const sendForgotPasswordCode = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid email address'),\n }))\n return\n }\n\n setForgotPasswordState({\n isSendingForgotPasswordCode: true,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n\n try {\n const newResetForgottenPasswordCallback =\n await authService.forgotPassword(username)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: newResetForgottenPasswordCallback,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: error as Error,\n isResettingForgottenPassword: false,\n })\n }\n }\n }, [isMounted, username, usernameValidation.isInvalid])\n\n const resetForgottenPassword = React.useCallback(async () => {\n if (!resetForgottenPasswordCallback) {\n return\n }\n\n if (codeValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error(\n 'Please enter the code that was sent to your email address',\n ),\n }))\n }\n if (newPasswordValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid password'),\n }))\n return\n }\n if (newPasswordConfirmedValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: true,\n forgotPasswordError: null,\n }))\n\n try {\n await resetForgottenPasswordCallback(code, newPassword)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n hideForgotPassword()\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: false,\n forgotPasswordError: error as Error,\n }))\n }\n }\n }, [\n resetForgottenPasswordCallback,\n codeValidation.isInvalid,\n newPasswordValidation.isInvalid,\n newPasswordConfirmedValidation.isInvalid,\n code,\n newPassword,\n isMounted,\n hideForgotPassword,\n ])\n\n const loginWithGoogle = React.useCallback(() => {\n authService.loginHostedUI('Google')\n }, [])\n\n return {\n // Login\n loginWithGoogle,\n loginWithUsernamePassword,\n isLoggingIn,\n loginError,\n clearLoginError,\n // Reset Temp Password\n isPasswordTemporary: !!resetTemporaryPasswordCallback,\n isResettingTemporaryPassword,\n resetTemporaryPassword,\n // Showing Forgot Password\n isShowingForgotPassword,\n showForgotPassword,\n hideForgotPassword,\n forgotPasswordError,\n clearForgotPasswordError,\n // Sending Forgot Password Code\n isSendingForgotPasswordCode,\n sendForgotPasswordCode,\n // Resetting Forgotten Password\n hasSentForgotPasswordCode: !!resetForgottenPasswordCallback,\n isResettingForgottenPassword,\n resetForgottenPassword,\n // Validation\n usernameValidation,\n passwordValidation,\n codeValidation,\n newPasswordValidation,\n newPasswordConfirmedValidation,\n }\n}\n"]}
1
+ {"version":3,"file":"useLogin.js","sourceRoot":"","sources":["../../src/hooks/useLogin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { authService, Sentry } from '@oneblink/apps'\n\nimport useIsMounted from './useIsMounted'\nimport useBooleanState from './useBooleanState'\n\nexport default function useLogin({\n username,\n password,\n newPassword,\n newPasswordConfirmed,\n code,\n}: {\n username: string\n password: string\n newPassword: string\n newPasswordConfirmed: string\n code: string\n}) {\n const isMounted = useIsMounted()\n\n // Validation\n const usernameValidation = React.useMemo(() => {\n return {\n isInvalid: !username.trim(),\n }\n }, [username])\n\n const passwordValidation = React.useMemo(() => {\n return {\n isInvalid: !password.trim(),\n }\n }, [password])\n\n const codeValidation = React.useMemo(() => {\n return {\n isInvalid: !code.trim(),\n }\n }, [code])\n\n const newPasswordValidation = React.useMemo(() => {\n const validation = {\n hasLowercaseLetter: /[a-z]+/.test(newPassword),\n hasUpperCaseLetter: /[A-Z]+/.test(newPassword),\n hasNumber: /\\d+/.test(newPassword),\n hasSpecialCharacter: /[\\^$*.[\\]{}()?|\\-\"!@#%&/,><':;|_~`]+/.test(\n newPassword,\n ),\n hasMinLength: newPassword.length >= 8,\n isInvalid: true,\n }\n validation.isInvalid =\n !validation.hasLowercaseLetter ||\n !validation.hasUpperCaseLetter ||\n !validation.hasNumber ||\n !validation.hasSpecialCharacter ||\n !validation.hasMinLength\n return validation\n }, [newPassword])\n\n const newPasswordConfirmedValidation = React.useMemo(() => {\n return {\n isInvalid: newPassword !== newPasswordConfirmed,\n }\n }, [newPassword, newPasswordConfirmed])\n\n // Login, Reset Password, MFA\n const [\n {\n isResettingTemporaryPassword,\n isLoggingIn,\n loginError,\n loginAttemptResponse,\n isSubmittingMfaCode,\n },\n setLoginState,\n ] = React.useState<{\n isResettingTemporaryPassword: boolean\n isLoggingIn: boolean\n loginError: null | Error\n loginAttemptResponse: authService.LoginAttemptResponse | undefined\n isSubmittingMfaCode: boolean\n }>({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n loginError: null,\n loginAttemptResponse: undefined,\n isSubmittingMfaCode: false,\n })\n const clearLoginError = React.useCallback(\n () =>\n setLoginState((current) => ({\n ...current,\n loginError: null,\n })),\n [],\n )\n const loginWithUsernamePassword = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid email address'),\n }))\n return\n }\n if (passwordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: true,\n loginError: null,\n }))\n\n try {\n const newLoginAttemptResponse = await authService.loginUsernamePassword(\n username,\n password,\n )\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginAttemptResponse: newLoginAttemptResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n password,\n passwordValidation.isInvalid,\n username,\n usernameValidation.isInvalid,\n ])\n\n const resetTemporaryPassword = React.useCallback(async () => {\n const resetTemporaryPasswordCallback =\n loginAttemptResponse?.resetPasswordCallback\n if (!resetTemporaryPasswordCallback) {\n return\n }\n\n if (newPasswordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n if (newPasswordConfirmedValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isResettingPassword: true,\n loginError: null,\n }))\n\n try {\n const resetPasswordResponse = await resetTemporaryPasswordCallback(\n newPassword,\n )\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isResettingTemporaryPassword: false,\n loginAttemptResponse: resetPasswordResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isResettingPassword: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n loginAttemptResponse?.resetPasswordCallback,\n newPassword,\n newPasswordConfirmedValidation.isInvalid,\n newPasswordValidation.isInvalid,\n ])\n\n const submitMfaCode = React.useCallback(async () => {\n const mfaCodeCallback = loginAttemptResponse?.mfaCodeCallback\n if (!mfaCodeCallback) {\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: true,\n loginError: null,\n }))\n\n try {\n const mfaResponse = await mfaCodeCallback(code)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isSubmittingMfaCode: false,\n loginAttemptResponse: mfaResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: false,\n loginError: error as Error,\n }))\n }\n }\n }, [code, isMounted, loginAttemptResponse?.mfaCodeCallback])\n\n // Forgot Password\n const [isShowingForgotPassword, showForgotPassword, hideForgotPassword] =\n useBooleanState(false)\n const [\n {\n resetForgottenPasswordCallback,\n isSendingForgotPasswordCode,\n isResettingForgottenPassword,\n forgotPasswordError,\n },\n setForgotPasswordState,\n ] = React.useState<{\n isSendingForgotPasswordCode: boolean\n forgotPasswordError: null | Error\n resetForgottenPasswordCallback:\n | null\n | ((code: string, newPassword: string) => void)\n isResettingForgottenPassword: boolean\n }>({\n isSendingForgotPasswordCode: false,\n forgotPasswordError: null,\n resetForgottenPasswordCallback: null,\n isResettingForgottenPassword: false,\n })\n const clearForgotPasswordError = React.useCallback(\n () =>\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: null,\n })),\n [],\n )\n const sendForgotPasswordCode = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid email address'),\n }))\n return\n }\n\n setForgotPasswordState({\n isSendingForgotPasswordCode: true,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n\n try {\n const newResetForgottenPasswordCallback =\n await authService.forgotPassword(username)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: newResetForgottenPasswordCallback,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: error as Error,\n isResettingForgottenPassword: false,\n })\n }\n }\n }, [isMounted, username, usernameValidation.isInvalid])\n\n const resetForgottenPassword = React.useCallback(async () => {\n if (!resetForgottenPasswordCallback) {\n return\n }\n\n if (codeValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error(\n 'Please enter the code that was sent to your email address',\n ),\n }))\n }\n if (newPasswordValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid password'),\n }))\n return\n }\n if (newPasswordConfirmedValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: true,\n forgotPasswordError: null,\n }))\n\n try {\n await resetForgottenPasswordCallback(code, newPassword)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n hideForgotPassword()\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: false,\n forgotPasswordError: error as Error,\n }))\n }\n }\n }, [\n resetForgottenPasswordCallback,\n codeValidation.isInvalid,\n newPasswordValidation.isInvalid,\n newPasswordConfirmedValidation.isInvalid,\n code,\n newPassword,\n isMounted,\n hideForgotPassword,\n ])\n\n const loginWithGoogle = React.useCallback(() => {\n authService.loginHostedUI('Google')\n }, [])\n\n return {\n // Login\n loginWithGoogle,\n loginWithUsernamePassword,\n isLoggingIn,\n loginError,\n clearLoginError,\n // Reset Temp Password\n isPasswordTemporary: !!loginAttemptResponse?.resetPasswordCallback,\n isResettingTemporaryPassword,\n resetTemporaryPassword,\n // MFA Code\n isMfaCodeRequired: !!loginAttemptResponse?.mfaCodeCallback,\n isSubmittingMfaCode,\n submitMfaCode,\n // Showing Forgot Password\n isShowingForgotPassword,\n showForgotPassword,\n hideForgotPassword,\n forgotPasswordError,\n clearForgotPasswordError,\n // Sending Forgot Password Code\n isSendingForgotPasswordCode,\n sendForgotPasswordCode,\n // Resetting Forgotten Password\n hasSentForgotPasswordCode: !!resetForgottenPasswordCallback,\n isResettingForgottenPassword,\n resetForgottenPassword,\n // Validation\n usernameValidation,\n passwordValidation,\n codeValidation,\n newPasswordValidation,\n newPasswordConfirmedValidation,\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export default function useReplaceableText(text: string): string;
@@ -2,16 +2,14 @@ import { localisationService } from '@oneblink/apps';
2
2
  import * as React from 'react';
3
3
  import useFormSubmissionModel from './useFormSubmissionModelContext';
4
4
  import { useRepeatableSetIndexText } from '../form-elements/FormElementRepeatableSet';
5
- import sanitizeHtml from '../services/sanitize-html';
6
- export default function useReplaceableHTML(text) {
5
+ export default function useReplaceableText(text) {
7
6
  const textWithIndex = useRepeatableSetIndexText(text);
8
- const html = React.useMemo(() => sanitizeHtml(textWithIndex), [textWithIndex]);
9
7
  const { formSubmissionModel, elements } = useFormSubmissionModel();
10
8
  return React.useMemo(() => {
11
- return localisationService.replaceInjectablesWithElementValues(html, {
9
+ return localisationService.replaceInjectablesWithElementValues(textWithIndex, {
12
10
  submission: formSubmissionModel,
13
11
  formElements: elements,
14
12
  });
15
- }, [elements, formSubmissionModel, html]);
13
+ }, [elements, formSubmissionModel, textWithIndex]);
16
14
  }
17
- //# sourceMappingURL=useReplaceableHTML.js.map
15
+ //# sourceMappingURL=useReplaceableText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useReplaceableText.js","sourceRoot":"","sources":["../../src/hooks/useReplaceableText.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,sBAAsB,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAA;AAErF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,IAAY;IACrD,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAA;IACrD,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAClE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxB,OAAO,mBAAmB,CAAC,mCAAmC,CAC5D,aAAa,EACb;YACE,UAAU,EAAE,mBAAmB;YAC/B,YAAY,EAAE,QAAQ;SACvB,CACF,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAA;AACpD,CAAC","sourcesContent":["import { localisationService } from '@oneblink/apps'\nimport * as React from 'react'\nimport useFormSubmissionModel from './useFormSubmissionModelContext'\nimport { useRepeatableSetIndexText } from '../form-elements/FormElementRepeatableSet'\n\nexport default function useReplaceableText(text: string) {\n const textWithIndex = useRepeatableSetIndexText(text)\n const { formSubmissionModel, elements } = useFormSubmissionModel()\n return React.useMemo(() => {\n return localisationService.replaceInjectablesWithElementValues(\n textWithIndex,\n {\n submission: formSubmissionModel,\n formElements: elements,\n },\n )\n }, [elements, formSubmissionModel, textWithIndex])\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oneblink/apps-react",
3
3
  "description": "Helper functions for OneBlink apps in ReactJS.",
4
- "version": "2.14.2",
4
+ "version": "3.0.0-beta.2",
5
5
  "author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/oneblink/apps-react/issues"
@@ -47,7 +47,7 @@
47
47
  "@mui/lab": "^5.0.0-alpha.95",
48
48
  "@mui/material": "^5.10.1",
49
49
  "@mui/x-date-pickers": "^5.0.0-beta.6",
50
- "@oneblink/apps": "^3.2.0-beta.4",
50
+ "@oneblink/apps": "^4.0.0-beta.2",
51
51
  "@oneblink/release-cli": "^2.0.2",
52
52
  "@oneblink/types": "github:oneblink/types",
53
53
  "@types/blueimp-load-image": "^5.16.0",
@@ -1 +0,0 @@
1
- export default function useReplaceableHTML(text: string): string;
@@ -1 +0,0 @@
1
- {"version":3,"file":"useReplaceableHTML.js","sourceRoot":"","sources":["../../src/hooks/useReplaceableHTML.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,sBAAsB,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAA;AACrF,OAAO,YAAY,MAAM,2BAA2B,CAAA;AAEpD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,IAAY;IACrD,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAA;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;IAC9E,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAClE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxB,OAAO,mBAAmB,CAAC,mCAAmC,CAAC,IAAI,EAAE;YACnE,UAAU,EAAE,mBAAmB;YAC/B,YAAY,EAAE,QAAQ;SACvB,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import { localisationService } from '@oneblink/apps'\nimport * as React from 'react'\nimport useFormSubmissionModel from './useFormSubmissionModelContext'\nimport { useRepeatableSetIndexText } from '../form-elements/FormElementRepeatableSet'\nimport sanitizeHtml from '../services/sanitize-html'\n\nexport default function useReplaceableHTML(text: string) {\n const textWithIndex = useRepeatableSetIndexText(text)\n const html = React.useMemo(() => sanitizeHtml(textWithIndex), [textWithIndex])\n const { formSubmissionModel, elements } = useFormSubmissionModel()\n return React.useMemo(() => {\n return localisationService.replaceInjectablesWithElementValues(html, {\n submission: formSubmissionModel,\n formElements: elements,\n })\n }, [elements, formSubmissionModel, html])\n}\n"]}