@orchestrator-ui/orchestrator-ui-components 6.8.0 → 7.0.1
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.
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-lint.log +5 -2
- package/.turbo/turbo-test.log +9 -10
- package/CHANGELOG.md +19 -0
- package/dist/index.d.ts +164 -4306
- package/dist/index.js +1739 -5747
- package/dist/index.js.map +1 -1
- package/package.json +4 -8
- package/src/components/WfoPydanticForm/Footer.tsx +33 -6
- package/src/components/WfoPydanticForm/RenderFormErrors.tsx +2 -1
- package/src/components/WfoPydanticForm/Row.tsx +3 -1
- package/src/components/WfoPydanticForm/fields/WfoInteger.tsx +5 -1
- package/src/components/WfoPydanticForm/fields/WfoSummary.tsx +3 -5
- package/src/components/WfoPydanticForm/fields/styles.ts +72 -0
- package/src/components/WfoSearchPage/WfoSearch/WfoSearch.tsx +42 -54
- package/src/components/WfoSearchPage/utils.ts +9 -1
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStep.tsx +10 -27
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStepForm.tsx +1 -1
- package/src/components/index.ts +0 -1
- package/src/configuration/version.ts +1 -1
- package/src/contexts/OrchestratorConfigContext.tsx +0 -1
- package/src/hooks/useSearch.ts +12 -2
- package/src/hooks/useSearchPagination.ts +4 -0
- package/src/messages/en-GB.json +5 -3
- package/src/pages/processes/WfoStartProcessPage.tsx +5 -107
- package/src/rtk/endpoints/index.ts +0 -2
- package/src/rtk/endpoints/search.ts +13 -4
- package/src/types/index.ts +0 -1
- package/src/types/search.ts +7 -0
- package/src/types/types.ts +0 -1
- package/src/components/WfoForms/AutoFieldLoader.tsx +0 -118
- package/src/components/WfoForms/AutoFields.tsx +0 -49
- package/src/components/WfoForms/CreateForm.tsx +0 -75
- package/src/components/WfoForms/UserInputForm.tsx +0 -697
- package/src/components/WfoForms/UserInputFormStyling.ts +0 -80
- package/src/components/WfoForms/UserInputFormWizard.tsx +0 -127
- package/src/components/WfoForms/formFields/AcceptField.tsx +0 -243
- package/src/components/WfoForms/formFields/AcceptFieldStyling.ts +0 -35
- package/src/components/WfoForms/formFields/BoolField.tsx +0 -77
- package/src/components/WfoForms/formFields/BoolFieldStyling.ts +0 -64
- package/src/components/WfoForms/formFields/ConnectedSelectField.tsx +0 -19
- package/src/components/WfoForms/formFields/CustomerField.tsx +0 -77
- package/src/components/WfoForms/formFields/DateField.tsx +0 -72
- package/src/components/WfoForms/formFields/DividerField.tsx +0 -29
- package/src/components/WfoForms/formFields/ErrorField.tsx +0 -40
- package/src/components/WfoForms/formFields/ErrorsField.tsx +0 -34
- package/src/components/WfoForms/formFields/LabelField.tsx +0 -43
- package/src/components/WfoForms/formFields/ListAddField.tsx +0 -95
- package/src/components/WfoForms/formFields/ListDelField.tsx +0 -95
- package/src/components/WfoForms/formFields/ListField.tsx +0 -117
- package/src/components/WfoForms/formFields/ListItemField.tsx +0 -40
- package/src/components/WfoForms/formFields/ListSelectField.tsx +0 -95
- package/src/components/WfoForms/formFields/LocationCodeField.tsx +0 -60
- package/src/components/WfoForms/formFields/LongTextField.tsx +0 -68
- package/src/components/WfoForms/formFields/NestField.tsx +0 -107
- package/src/components/WfoForms/formFields/NumField.tsx +0 -85
- package/src/components/WfoForms/formFields/OptGroupField.tsx +0 -74
- package/src/components/WfoForms/formFields/RadioField.tsx +0 -87
- package/src/components/WfoForms/formFields/SelectField/SelectField.tsx +0 -177
- package/src/components/WfoForms/formFields/SelectField/index.ts +0 -1
- package/src/components/WfoForms/formFields/SelectField/styles.ts +0 -52
- package/src/components/WfoForms/formFields/SubmitField.tsx +0 -50
- package/src/components/WfoForms/formFields/SubscriptionSummaryField.tsx +0 -74
- package/src/components/WfoForms/formFields/SummaryField.tsx +0 -104
- package/src/components/WfoForms/formFields/SummaryFieldStyling.ts +0 -44
- package/src/components/WfoForms/formFields/TextField.tsx +0 -81
- package/src/components/WfoForms/formFields/commonStyles.ts +0 -32
- package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocomplete.tsx +0 -99
- package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocompleteStyles.ts +0 -41
- package/src/components/WfoForms/formFields/deprecated/ContactPersonNameField.tsx +0 -263
- package/src/components/WfoForms/formFields/deprecated/FileUploadField.tsx +0 -151
- package/src/components/WfoForms/formFields/deprecated/ImsNodeIdField.tsx +0 -109
- package/src/components/WfoForms/formFields/deprecated/ImsPortIdField.tsx +0 -233
- package/src/components/WfoForms/formFields/deprecated/ImsPortIdFieldStyling.ts +0 -17
- package/src/components/WfoForms/formFields/deprecated/IpNetworkField.tsx +0 -105
- package/src/components/WfoForms/formFields/deprecated/IpPrefixTableField.tsx +0 -390
- package/src/components/WfoForms/formFields/deprecated/IpPrefixTableFieldStyling.ts +0 -117
- package/src/components/WfoForms/formFields/deprecated/SplitPrefix.tsx +0 -138
- package/src/components/WfoForms/formFields/deprecated/SplitPrefixStyling.ts +0 -11
- package/src/components/WfoForms/formFields/deprecated/SubscriptionField.tsx +0 -263
- package/src/components/WfoForms/formFields/deprecated/SubscriptionFieldStyling.ts +0 -33
- package/src/components/WfoForms/formFields/deprecated/TimestampField.tsx +0 -110
- package/src/components/WfoForms/formFields/deprecated/VlanField.tsx +0 -300
- package/src/components/WfoForms/formFields/deprecated/index.ts +0 -15
- package/src/components/WfoForms/formFields/deprecated/types.ts +0 -74
- package/src/components/WfoForms/formFields/deprecated/utils.ts +0 -1
- package/src/components/WfoForms/formFields/index.ts +0 -30
- package/src/components/WfoForms/formFields/listFieldStyling.ts +0 -86
- package/src/components/WfoForms/formFields/types.ts +0 -41
- package/src/components/WfoForms/formFields/utils.spec.ts +0 -296
- package/src/components/WfoForms/formFields/utils.ts +0 -69
- package/src/components/WfoForms/index.ts +0 -5
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStepFormOld.tsx +0 -67
- package/src/hooks/deprecated/useGetSurfSubcriptionDropdownOptions.ts +0 -37
- package/src/hooks/deprecated/useIsTaggedPort.ts +0 -25
- package/src/rtk/endpoints/deprecated/index.ts +0 -1
- package/src/rtk/endpoints/deprecated/surfSubscriptionDropdownOptions.ts +0 -53
- package/src/rtk/endpoints/formFields.ts +0 -131
- package/src/rtk/endpoints/ipam.ts +0 -54
- package/src/types/deprecated/SurfSubscriptionDropdownOptionsFilterParams.ts +0 -10
- package/src/types/deprecated/index.ts +0 -1
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019-2023 SURF.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
*
|
|
8
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
* See the License for the specific language governing permissions and
|
|
12
|
-
* limitations under the License.
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
import React, { useEffect, useRef } from 'react';
|
|
16
|
-
|
|
17
|
-
import scrollIntoView from 'scroll-into-view';
|
|
18
|
-
|
|
19
|
-
import { EuiFlexItem } from '@elastic/eui';
|
|
20
|
-
|
|
21
|
-
import { useWithOrchestratorTheme } from '@/hooks';
|
|
22
|
-
|
|
23
|
-
import { ContactPerson } from '../types';
|
|
24
|
-
import { isEmpty } from '../utils';
|
|
25
|
-
import { getContactPersonStyles } from './ContactPersonAutocompleteStyles';
|
|
26
|
-
|
|
27
|
-
interface ContactPersonAutocompleteProps {
|
|
28
|
-
query: string;
|
|
29
|
-
selectedItem: number;
|
|
30
|
-
personIndex: number;
|
|
31
|
-
itemSelected: (value: ContactPerson, index: number) => void;
|
|
32
|
-
suggestions: ContactPerson[];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const ContactPersonAutocomplete = ({
|
|
36
|
-
query,
|
|
37
|
-
selectedItem,
|
|
38
|
-
personIndex,
|
|
39
|
-
itemSelected,
|
|
40
|
-
suggestions,
|
|
41
|
-
}: ContactPersonAutocompleteProps) => {
|
|
42
|
-
const { contactPersonAutocompleteStyling } = useWithOrchestratorTheme(
|
|
43
|
-
getContactPersonStyles,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
// Intentionally not done with state since we don't need a rerender
|
|
47
|
-
// This is only to store a ref for the scroll into view part
|
|
48
|
-
const selectedRowRef = useRef(null);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (!isEmpty(suggestions) && selectedRowRef.current) {
|
|
52
|
-
scrollIntoView(selectedRowRef.current);
|
|
53
|
-
}
|
|
54
|
-
}, [selectedItem, suggestions]);
|
|
55
|
-
|
|
56
|
-
const itemName = (item: ContactPerson, query: string) => {
|
|
57
|
-
const name = item.name;
|
|
58
|
-
const nameToLower = name.toLowerCase();
|
|
59
|
-
const indexOf = nameToLower.indexOf(query.toLowerCase());
|
|
60
|
-
const first = name.substring(0, indexOf);
|
|
61
|
-
const middle = name.substring(indexOf, indexOf + query.length);
|
|
62
|
-
const last = name.substring(indexOf + query.length);
|
|
63
|
-
return (
|
|
64
|
-
<span>
|
|
65
|
-
{first}
|
|
66
|
-
<span className="matched">{middle}</span>
|
|
67
|
-
{last}
|
|
68
|
-
</span>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
return isEmpty(suggestions) ? null : (
|
|
73
|
-
<EuiFlexItem css={contactPersonAutocompleteStyling}>
|
|
74
|
-
<section className={`autocomplete`}>
|
|
75
|
-
<table className="result">
|
|
76
|
-
<tbody>
|
|
77
|
-
{suggestions.map((item, index) => (
|
|
78
|
-
<tr
|
|
79
|
-
key={index}
|
|
80
|
-
className={
|
|
81
|
-
selectedItem === index ? 'active' : ''
|
|
82
|
-
}
|
|
83
|
-
onClick={() => itemSelected(item, personIndex)}
|
|
84
|
-
ref={
|
|
85
|
-
selectedItem === index
|
|
86
|
-
? selectedRowRef
|
|
87
|
-
: null
|
|
88
|
-
}
|
|
89
|
-
>
|
|
90
|
-
<td>{itemName(item, query)}</td>
|
|
91
|
-
<td>{item.email || ''}</td>
|
|
92
|
-
</tr>
|
|
93
|
-
))}
|
|
94
|
-
</tbody>
|
|
95
|
-
</table>
|
|
96
|
-
</section>
|
|
97
|
-
</EuiFlexItem>
|
|
98
|
-
);
|
|
99
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
|
|
3
|
-
import { WfoTheme } from '@/hooks';
|
|
4
|
-
|
|
5
|
-
export const getContactPersonStyles = ({ theme }: WfoTheme) => {
|
|
6
|
-
const contactPersonAutocompleteStyling = css`
|
|
7
|
-
.autocomplete-container {
|
|
8
|
-
position: relative;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
section.autocomplete {
|
|
12
|
-
position: relative;
|
|
13
|
-
z-index: 2000;
|
|
14
|
-
width: 100%;
|
|
15
|
-
border-radius: ${theme.border.radius.medium};
|
|
16
|
-
background-color: ${theme.colors.lightShade};
|
|
17
|
-
margin-bottom: 20px;
|
|
18
|
-
|
|
19
|
-
table.result {
|
|
20
|
-
z-index: 2000;
|
|
21
|
-
|
|
22
|
-
tbody tr {
|
|
23
|
-
cursor: pointer;
|
|
24
|
-
|
|
25
|
-
td {
|
|
26
|
-
padding: 10px;
|
|
27
|
-
width: 50%;
|
|
28
|
-
vertical-align: middle;
|
|
29
|
-
span.matched {
|
|
30
|
-
font-weight: bold;
|
|
31
|
-
text-decoration: underline;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
38
|
-
return {
|
|
39
|
-
contactPersonAutocompleteStyling,
|
|
40
|
-
};
|
|
41
|
-
};
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019-2023 SURF.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
*
|
|
8
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
* See the License for the specific language governing permissions and
|
|
12
|
-
* limitations under the License.
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
import React, { Ref, useEffect, useState } from 'react';
|
|
16
|
-
|
|
17
|
-
import { isFunction } from 'lodash';
|
|
18
|
-
import get from 'lodash/get';
|
|
19
|
-
import { useTranslations } from 'next-intl';
|
|
20
|
-
import {
|
|
21
|
-
connectField,
|
|
22
|
-
filterDOMProps,
|
|
23
|
-
joinName,
|
|
24
|
-
useField,
|
|
25
|
-
useForm,
|
|
26
|
-
} from 'uniforms';
|
|
27
|
-
|
|
28
|
-
import { EuiFieldText, EuiFormRow, EuiText } from '@elastic/eui';
|
|
29
|
-
|
|
30
|
-
import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
|
|
31
|
-
import { useWithOrchestratorTheme } from '@/hooks';
|
|
32
|
-
import { useContactPersonsQuery } from '@/rtk/endpoints/formFields';
|
|
33
|
-
import { getFormFieldsBaseStyle } from '@/theme';
|
|
34
|
-
|
|
35
|
-
import { ContactPerson, FieldProps } from '../types';
|
|
36
|
-
import { ContactPersonAutocomplete } from './ContactPersonAutocomplete';
|
|
37
|
-
|
|
38
|
-
export function stop(e: React.SyntheticEvent) {
|
|
39
|
-
if (e !== undefined && e !== null) {
|
|
40
|
-
e.preventDefault();
|
|
41
|
-
e.stopPropagation();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type ContactPersonNameFieldProps = FieldProps<
|
|
46
|
-
string,
|
|
47
|
-
{
|
|
48
|
-
customerId?: string;
|
|
49
|
-
customerKey?: string;
|
|
50
|
-
}
|
|
51
|
-
>;
|
|
52
|
-
|
|
53
|
-
declare module 'uniforms' {
|
|
54
|
-
interface FilterDOMProps {
|
|
55
|
-
customerId: never;
|
|
56
|
-
customerKey: never;
|
|
57
|
-
organisationKey: never;
|
|
58
|
-
organisationId: never;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
filterDOMProps.register(
|
|
62
|
-
'customerId',
|
|
63
|
-
'customerKey',
|
|
64
|
-
'organisationKey',
|
|
65
|
-
'organisationId',
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
function ContactPersonName({
|
|
69
|
-
disabled,
|
|
70
|
-
id,
|
|
71
|
-
inputRef = React.createRef() as Ref<HTMLInputElement>,
|
|
72
|
-
label,
|
|
73
|
-
description,
|
|
74
|
-
name,
|
|
75
|
-
onChange,
|
|
76
|
-
placeholder,
|
|
77
|
-
readOnly,
|
|
78
|
-
value,
|
|
79
|
-
error,
|
|
80
|
-
showInlineError,
|
|
81
|
-
errorMessage,
|
|
82
|
-
customerId,
|
|
83
|
-
customerKey,
|
|
84
|
-
...props
|
|
85
|
-
}: ContactPersonNameFieldProps) {
|
|
86
|
-
const { formRowStyle } = useWithOrchestratorTheme(getCommonFormFieldStyles);
|
|
87
|
-
const { formFieldBaseStyle } = useWithOrchestratorTheme(
|
|
88
|
-
getFormFieldsBaseStyle,
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const t = useTranslations('pydanticForms');
|
|
92
|
-
const { model, onChange: formOnChange, schema } = useForm();
|
|
93
|
-
|
|
94
|
-
const contactsPersonFieldNameArray = joinName(null, name).slice(0, -1);
|
|
95
|
-
const emailFieldName = joinName(contactsPersonFieldNameArray, 'email');
|
|
96
|
-
const contactsFieldName = joinName(
|
|
97
|
-
contactsPersonFieldNameArray.slice(0, -1),
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const chosenPersons: ContactPerson[] = get(model, contactsFieldName, []);
|
|
101
|
-
// We cant call useField conditionally so if we don't have a parent we call it for ourself
|
|
102
|
-
const useFieldName = contactsPersonFieldNameArray.length
|
|
103
|
-
? contactsFieldName
|
|
104
|
-
: name;
|
|
105
|
-
const contactsField = useField(useFieldName, {}, { absoluteName: true })[0];
|
|
106
|
-
|
|
107
|
-
const customerIdFieldName =
|
|
108
|
-
customerKey || contactsField.field.customerKey || 'customer_id';
|
|
109
|
-
|
|
110
|
-
// Get initial value for org field if it exists (we cant really test)
|
|
111
|
-
let customerInitialValue;
|
|
112
|
-
try {
|
|
113
|
-
customerInitialValue = schema.getInitialValue(customerIdFieldName, {});
|
|
114
|
-
} catch {
|
|
115
|
-
customerInitialValue = '';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const customerIdValue =
|
|
119
|
-
customerId ||
|
|
120
|
-
contactsField.field.customerId ||
|
|
121
|
-
get(model, customerIdFieldName, customerInitialValue);
|
|
122
|
-
|
|
123
|
-
const [displayAutocomplete, setDisplayAutocomplete] = useState(false);
|
|
124
|
-
const [contactPersons, setContactPersons] = useState<ContactPerson[]>([]);
|
|
125
|
-
const [selectedIndex, setSelectedIndex] = useState(-1);
|
|
126
|
-
|
|
127
|
-
const { data, error: fetchError } = useContactPersonsQuery(
|
|
128
|
-
{ customerIdValue },
|
|
129
|
-
{ skip: !customerIdValue },
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
const suggestions = value
|
|
133
|
-
? contactPersons
|
|
134
|
-
.filter(
|
|
135
|
-
(item) =>
|
|
136
|
-
item.name.toLowerCase().indexOf(value.toLowerCase()) > -1,
|
|
137
|
-
)
|
|
138
|
-
.filter(
|
|
139
|
-
(item) =>
|
|
140
|
-
!chosenPersons.some(
|
|
141
|
-
(person) => person.email === item.email,
|
|
142
|
-
),
|
|
143
|
-
)
|
|
144
|
-
: [];
|
|
145
|
-
|
|
146
|
-
useEffect(() => {
|
|
147
|
-
if (customerIdValue) {
|
|
148
|
-
if (data) {
|
|
149
|
-
setContactPersons(data);
|
|
150
|
-
}
|
|
151
|
-
if (fetchError) {
|
|
152
|
-
setContactPersons([]);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}, [customerIdValue, data, fetchError]);
|
|
156
|
-
|
|
157
|
-
useEffect(() => {
|
|
158
|
-
// Set focus to the last name component to be created
|
|
159
|
-
if (!isFunction(inputRef)) {
|
|
160
|
-
inputRef!.current?.focus();
|
|
161
|
-
}
|
|
162
|
-
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
163
|
-
|
|
164
|
-
function onChangeInternal(e: React.FormEvent<HTMLInputElement>) {
|
|
165
|
-
stop(e);
|
|
166
|
-
const target = e.target as HTMLInputElement;
|
|
167
|
-
const value = target.value;
|
|
168
|
-
|
|
169
|
-
onChange(value);
|
|
170
|
-
setDisplayAutocomplete(true);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function itemSelected(item: ContactPerson) {
|
|
174
|
-
onChange(item.name || '');
|
|
175
|
-
formOnChange(emailFieldName, item.email || '');
|
|
176
|
-
setDisplayAutocomplete(false);
|
|
177
|
-
setSelectedIndex(-1);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function onAutocompleteKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
|
181
|
-
if (!suggestions) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
if (e.keyCode === 40 && selectedIndex < suggestions.length - 1) {
|
|
185
|
-
//keyDown
|
|
186
|
-
stop(e);
|
|
187
|
-
setSelectedIndex(selectedIndex + 1);
|
|
188
|
-
}
|
|
189
|
-
if (e.keyCode === 38 && selectedIndex >= 0) {
|
|
190
|
-
//keyUp
|
|
191
|
-
stop(e);
|
|
192
|
-
setSelectedIndex(selectedIndex - 1);
|
|
193
|
-
}
|
|
194
|
-
if (e.keyCode === 13) {
|
|
195
|
-
//enter
|
|
196
|
-
if (selectedIndex >= 0) {
|
|
197
|
-
stop(e);
|
|
198
|
-
itemSelected(suggestions[selectedIndex]);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (e.keyCode === 27) {
|
|
202
|
-
//escape
|
|
203
|
-
stop(e);
|
|
204
|
-
setDisplayAutocomplete(false);
|
|
205
|
-
setSelectedIndex(-1);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function onBlurAutoComplete(e: React.FocusEvent<HTMLElement>) {
|
|
210
|
-
stop(e);
|
|
211
|
-
setTimeout(() => setDisplayAutocomplete(false), 350);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return (
|
|
215
|
-
<section {...filterDOMProps(props)}>
|
|
216
|
-
<EuiFormRow
|
|
217
|
-
label={label}
|
|
218
|
-
labelAppend={<EuiText size="m">{description}</EuiText>}
|
|
219
|
-
error={showInlineError ? errorMessage : false}
|
|
220
|
-
isInvalid={error}
|
|
221
|
-
id={id}
|
|
222
|
-
fullWidth
|
|
223
|
-
css={formRowStyle}
|
|
224
|
-
>
|
|
225
|
-
<>
|
|
226
|
-
<EuiFieldText
|
|
227
|
-
css={formFieldBaseStyle}
|
|
228
|
-
disabled={disabled}
|
|
229
|
-
fullWidth
|
|
230
|
-
name={name}
|
|
231
|
-
isInvalid={error}
|
|
232
|
-
onChange={onChangeInternal}
|
|
233
|
-
placeholder={
|
|
234
|
-
placeholder ||
|
|
235
|
-
t('widgets.contactPersonName.placeholder')
|
|
236
|
-
}
|
|
237
|
-
readOnly={readOnly}
|
|
238
|
-
type="text"
|
|
239
|
-
value={value ?? ''}
|
|
240
|
-
onKeyDown={onAutocompleteKeyDown}
|
|
241
|
-
onBlur={onBlurAutoComplete}
|
|
242
|
-
autoComplete="off"
|
|
243
|
-
/>{' '}
|
|
244
|
-
<div className="autocomplete-container">
|
|
245
|
-
{!!(displayAutocomplete && suggestions.length) && (
|
|
246
|
-
<ContactPersonAutocomplete
|
|
247
|
-
query={value ?? ''}
|
|
248
|
-
itemSelected={itemSelected}
|
|
249
|
-
selectedItem={selectedIndex}
|
|
250
|
-
suggestions={suggestions}
|
|
251
|
-
personIndex={0}
|
|
252
|
-
/>
|
|
253
|
-
)}
|
|
254
|
-
</div>
|
|
255
|
-
</>
|
|
256
|
-
</EuiFormRow>
|
|
257
|
-
</section>
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
export const ContactPersonNameField = connectField(ContactPersonName, {
|
|
262
|
-
kind: 'leaf',
|
|
263
|
-
});
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2024 SURF.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
*
|
|
8
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
* See the License for the specific language governing permissions and
|
|
12
|
-
* limitations under the License.
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
import React, { useState } from 'react';
|
|
16
|
-
|
|
17
|
-
import { useTranslations } from 'next-intl';
|
|
18
|
-
import { connectField, filterDOMProps } from 'uniforms';
|
|
19
|
-
|
|
20
|
-
import { EuiFilePicker, EuiFormRow, EuiText } from '@elastic/eui';
|
|
21
|
-
|
|
22
|
-
import { FieldProps } from '@/components';
|
|
23
|
-
import { getCommonFormFieldStyles } from '@/components/WfoForms/formFields/commonStyles';
|
|
24
|
-
import { useOrchestratorTheme, useWithOrchestratorTheme } from '@/hooks';
|
|
25
|
-
import { useUploadFileMutation } from '@/rtk/endpoints/fileUpload';
|
|
26
|
-
|
|
27
|
-
export type FileUploadProps = FieldProps<string>;
|
|
28
|
-
|
|
29
|
-
function FileUpload({
|
|
30
|
-
id,
|
|
31
|
-
label,
|
|
32
|
-
description,
|
|
33
|
-
onChange,
|
|
34
|
-
error,
|
|
35
|
-
showInlineError,
|
|
36
|
-
errorMessage,
|
|
37
|
-
...props
|
|
38
|
-
}: FileUploadProps) {
|
|
39
|
-
const t = useTranslations('pydanticForms.widgets.fileUpload');
|
|
40
|
-
const { theme } = useOrchestratorTheme();
|
|
41
|
-
const [uploadFile, { isLoading, reset }] = useUploadFileMutation();
|
|
42
|
-
const [hasInValidFiletypes, setHasInValidFiletypes] = useState(false);
|
|
43
|
-
const [hasError, setHasError] = useState(false);
|
|
44
|
-
const [hasFileToBig, setHasFileToBig] = useState(false);
|
|
45
|
-
|
|
46
|
-
const { formRowStyle } = useWithOrchestratorTheme(getCommonFormFieldStyles);
|
|
47
|
-
|
|
48
|
-
const {
|
|
49
|
-
allowed_file_types: allowedMimeTypes,
|
|
50
|
-
url,
|
|
51
|
-
filesize_limit: fileSizeLimit,
|
|
52
|
-
} = props.field;
|
|
53
|
-
|
|
54
|
-
const cimUrl = url.replace('/cim', '');
|
|
55
|
-
|
|
56
|
-
const resetErrors = () => {
|
|
57
|
-
setHasInValidFiletypes(false);
|
|
58
|
-
setHasError(false);
|
|
59
|
-
setHasFileToBig(false);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const getErrorText = (): string => {
|
|
63
|
-
if (hasInValidFiletypes) {
|
|
64
|
-
return t('invalidFiletype');
|
|
65
|
-
}
|
|
66
|
-
if (hasError) {
|
|
67
|
-
return t('errorUploading');
|
|
68
|
-
}
|
|
69
|
-
if (hasFileToBig) {
|
|
70
|
-
return t('fileToBig', { fileSizeLimit });
|
|
71
|
-
}
|
|
72
|
-
return '';
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const handleUploadedFiles = (files: FileList | null) => {
|
|
76
|
-
const file = files?.item(0) || null;
|
|
77
|
-
|
|
78
|
-
if (!file) return;
|
|
79
|
-
|
|
80
|
-
const { type, size } = file;
|
|
81
|
-
|
|
82
|
-
if (allowedMimeTypes && !allowedMimeTypes.includes(type)) {
|
|
83
|
-
resetErrors();
|
|
84
|
-
setHasInValidFiletypes(true);
|
|
85
|
-
return;
|
|
86
|
-
} else if (size > fileSizeLimit) {
|
|
87
|
-
resetErrors();
|
|
88
|
-
setHasFileToBig(true);
|
|
89
|
-
return;
|
|
90
|
-
} else {
|
|
91
|
-
uploadFile({ url: cimUrl, file })
|
|
92
|
-
.then((response) => {
|
|
93
|
-
if (response.error) {
|
|
94
|
-
resetErrors();
|
|
95
|
-
setHasError(true);
|
|
96
|
-
return;
|
|
97
|
-
} else {
|
|
98
|
-
onChange(response.data.file_id);
|
|
99
|
-
resetErrors();
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
.catch((error) => {
|
|
103
|
-
resetErrors();
|
|
104
|
-
setHasError(true);
|
|
105
|
-
console.error(error);
|
|
106
|
-
return;
|
|
107
|
-
});
|
|
108
|
-
reset();
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<section {...filterDOMProps(props)}>
|
|
114
|
-
<EuiFormRow
|
|
115
|
-
css={formRowStyle}
|
|
116
|
-
label={label}
|
|
117
|
-
labelAppend={<EuiText size="m">{description}</EuiText>}
|
|
118
|
-
error={showInlineError ? errorMessage : false}
|
|
119
|
-
isInvalid={error}
|
|
120
|
-
id={id}
|
|
121
|
-
fullWidth
|
|
122
|
-
>
|
|
123
|
-
<>
|
|
124
|
-
<EuiFilePicker
|
|
125
|
-
onChange={handleUploadedFiles}
|
|
126
|
-
isInvalid={
|
|
127
|
-
hasError || hasInValidFiletypes || hasFileToBig
|
|
128
|
-
}
|
|
129
|
-
display="large"
|
|
130
|
-
isLoading={isLoading}
|
|
131
|
-
initialPromptText={t('initialPromptText')}
|
|
132
|
-
multiple={false}
|
|
133
|
-
accept={allowedMimeTypes}
|
|
134
|
-
/>
|
|
135
|
-
<div
|
|
136
|
-
css={{
|
|
137
|
-
color: theme.colors.danger,
|
|
138
|
-
marginTop: theme.size.base,
|
|
139
|
-
marginLeft: theme.size.xs,
|
|
140
|
-
fontWeight: theme.font.weight.semiBold,
|
|
141
|
-
}}
|
|
142
|
-
>
|
|
143
|
-
{getErrorText()}
|
|
144
|
-
</div>
|
|
145
|
-
</>
|
|
146
|
-
</EuiFormRow>
|
|
147
|
-
</section>
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export const FileUploadField = connectField(FileUpload, { kind: 'leaf' });
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019-2023 SURF.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
*
|
|
8
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
* See the License for the specific language governing permissions and
|
|
12
|
-
* limitations under the License.
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
import React, { useEffect, useState } from 'react';
|
|
16
|
-
|
|
17
|
-
import { get } from 'lodash';
|
|
18
|
-
import { useTranslations } from 'next-intl';
|
|
19
|
-
import { connectField, filterDOMProps } from 'uniforms';
|
|
20
|
-
|
|
21
|
-
import { useImsNodesQuery } from '@/rtk/endpoints/formFields';
|
|
22
|
-
|
|
23
|
-
import { SelectFieldProps, UnconnectedSelectField } from '../SelectField';
|
|
24
|
-
import { ImsNode } from './types';
|
|
25
|
-
|
|
26
|
-
export type ImsNodeIdFieldProps = {
|
|
27
|
-
onChange: (value?: number | undefined) => void;
|
|
28
|
-
value?: number;
|
|
29
|
-
locationCode: string;
|
|
30
|
-
status?: string;
|
|
31
|
-
unsubscribedOnly?: boolean;
|
|
32
|
-
} & Omit<
|
|
33
|
-
SelectFieldProps,
|
|
34
|
-
| 'placeholder'
|
|
35
|
-
| 'transform'
|
|
36
|
-
| 'allowedValues'
|
|
37
|
-
| 'onChange'
|
|
38
|
-
| 'value'
|
|
39
|
-
| 'name'
|
|
40
|
-
>;
|
|
41
|
-
|
|
42
|
-
declare module 'uniforms' {
|
|
43
|
-
interface FilterDOMProps {
|
|
44
|
-
locationCode: never;
|
|
45
|
-
status: never;
|
|
46
|
-
unsubscribedOnly: never;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
filterDOMProps.register('locationCode', 'status', 'unsubscribedOnly');
|
|
50
|
-
|
|
51
|
-
function ImsNodeId({
|
|
52
|
-
value,
|
|
53
|
-
onChange,
|
|
54
|
-
locationCode,
|
|
55
|
-
status = 'PL',
|
|
56
|
-
unsubscribedOnly = true,
|
|
57
|
-
...props
|
|
58
|
-
}: ImsNodeIdFieldProps) {
|
|
59
|
-
const t = useTranslations('pydanticForms');
|
|
60
|
-
const [nodes, setNodes] = useState<ImsNode[]>([]);
|
|
61
|
-
const { data, isLoading, error } = useImsNodesQuery(
|
|
62
|
-
{
|
|
63
|
-
locationCode,
|
|
64
|
-
status,
|
|
65
|
-
unsubscribedOnly,
|
|
66
|
-
},
|
|
67
|
-
{ skip: !(locationCode && status) },
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
if (data) {
|
|
72
|
-
setNodes(data);
|
|
73
|
-
}
|
|
74
|
-
if (error) {
|
|
75
|
-
console.error(error);
|
|
76
|
-
}
|
|
77
|
-
}, [locationCode, status, unsubscribedOnly, data, error]);
|
|
78
|
-
|
|
79
|
-
const placeholder =
|
|
80
|
-
isLoading && locationCode
|
|
81
|
-
? t('widgets.node_select.nodes_loading')
|
|
82
|
-
: nodes.length
|
|
83
|
-
? t('widgets.node_select.select_node')
|
|
84
|
-
: t('forms.widgets.node_select.no_nodes_placeholder');
|
|
85
|
-
|
|
86
|
-
const imsNodeIdLabelLookup =
|
|
87
|
-
nodes?.reduce<{ [index: string]: string }>(function (mapping, node) {
|
|
88
|
-
mapping[node.id.toString()] = node.name;
|
|
89
|
-
return mapping;
|
|
90
|
-
}, {}) ?? {};
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<UnconnectedSelectField
|
|
94
|
-
name=""
|
|
95
|
-
{...props}
|
|
96
|
-
allowedValues={Object.keys(imsNodeIdLabelLookup)}
|
|
97
|
-
value={value?.toString()}
|
|
98
|
-
transform={(id: string) => get(imsNodeIdLabelLookup, id, id)}
|
|
99
|
-
onChange={
|
|
100
|
-
((str: string) => onChange(parseInt(str, 10))) as unknown as (
|
|
101
|
-
v: string | string[] | undefined,
|
|
102
|
-
) => void
|
|
103
|
-
}
|
|
104
|
-
placeholder={placeholder}
|
|
105
|
-
/>
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export const ImsNodeIdField = connectField(ImsNodeId, { kind: 'leaf' });
|