@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,390 +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, { useCallback, useEffect, useState } from 'react';
|
|
16
|
-
import ReactSelect, { SingleValue } from 'react-select';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
EuiBadge,
|
|
20
|
-
EuiButton,
|
|
21
|
-
EuiButtonIcon,
|
|
22
|
-
EuiCheckbox,
|
|
23
|
-
EuiFieldText,
|
|
24
|
-
EuiFlexGroup,
|
|
25
|
-
EuiFlexItem,
|
|
26
|
-
EuiFormRow,
|
|
27
|
-
EuiInMemoryTable,
|
|
28
|
-
EuiPanel,
|
|
29
|
-
EuiText,
|
|
30
|
-
} from '@elastic/eui';
|
|
31
|
-
|
|
32
|
-
import { ipPrefixTableFieldStyling } from '@/components';
|
|
33
|
-
import { useIpBlocksQuery, usePrefixFiltersQuery } from '@/rtk/endpoints/ipam';
|
|
34
|
-
import type { Option } from '@/types';
|
|
35
|
-
|
|
36
|
-
import { prop } from '../types';
|
|
37
|
-
import { IpBlock, IpPrefix, SortOption } from './types';
|
|
38
|
-
import { ipamStates } from './utils';
|
|
39
|
-
|
|
40
|
-
type SortKeys = 'id' | 'prefix' | 'description' | 'state_repr';
|
|
41
|
-
|
|
42
|
-
interface IProps {
|
|
43
|
-
id: string;
|
|
44
|
-
name: string;
|
|
45
|
-
onChange: (prefix: IpBlock) => void;
|
|
46
|
-
onManualOverride: (prefixString: string) => void;
|
|
47
|
-
selected_prefix_id?: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const IpPrefixTableField = ({
|
|
51
|
-
id,
|
|
52
|
-
name,
|
|
53
|
-
onChange,
|
|
54
|
-
onManualOverride,
|
|
55
|
-
selected_prefix_id,
|
|
56
|
-
}: IProps) => {
|
|
57
|
-
const [ipBlocks, setIpBlocks] = useState<IpBlock[]>([]);
|
|
58
|
-
const [filteredPrefixes, setFilteredPrefixes] = useState<IpPrefix[]>([]);
|
|
59
|
-
const [filter, setFilter] = useState<{
|
|
60
|
-
state: number[];
|
|
61
|
-
prefix?: IpPrefix;
|
|
62
|
-
}>({
|
|
63
|
-
state: [
|
|
64
|
-
ipamStates.indexOf('Free'),
|
|
65
|
-
ipamStates.indexOf('Allocated'),
|
|
66
|
-
ipamStates.indexOf('Planned'),
|
|
67
|
-
ipamStates.indexOf('Subnet'),
|
|
68
|
-
],
|
|
69
|
-
prefix: undefined,
|
|
70
|
-
});
|
|
71
|
-
const [sorted] = useState<SortOption<SortKeys>>({
|
|
72
|
-
name: 'prefix',
|
|
73
|
-
descending: false,
|
|
74
|
-
});
|
|
75
|
-
const [manualOverrideVisible, setManualOverrideVisible] =
|
|
76
|
-
useState<boolean>(false);
|
|
77
|
-
const [manualOverrideValue, setManualOverrideValue] = useState<string>('');
|
|
78
|
-
const [selectionDone, setSelectionDone] = useState<boolean>(false);
|
|
79
|
-
const [parentPrefix, setParentPrefix] = useState<number>(1);
|
|
80
|
-
const { data: prefixFiltersData } = usePrefixFiltersQuery();
|
|
81
|
-
const { data: ipBlocksData, isFetching } = useIpBlocksQuery({
|
|
82
|
-
parentPrefix: parentPrefix,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
if (prefixFiltersData) {
|
|
87
|
-
setFilteredPrefixes(prefixFiltersData);
|
|
88
|
-
setFilter((prevFilter) => ({
|
|
89
|
-
...prevFilter,
|
|
90
|
-
prefix: prefixFiltersData[0],
|
|
91
|
-
}));
|
|
92
|
-
}
|
|
93
|
-
}, [prefixFiltersData]);
|
|
94
|
-
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
if (ipBlocksData) {
|
|
97
|
-
const selectedPrefix = filteredPrefixes.find(
|
|
98
|
-
(prefix) => prefix.id === parentPrefix,
|
|
99
|
-
);
|
|
100
|
-
setIpBlocks(ipBlocksData);
|
|
101
|
-
setFilter((prevFilter) => ({
|
|
102
|
-
...prevFilter,
|
|
103
|
-
prefix: selectedPrefix || prevFilter.prefix,
|
|
104
|
-
}));
|
|
105
|
-
}
|
|
106
|
-
}, [ipBlocksData, prefixFiltersData, filteredPrefixes, parentPrefix]);
|
|
107
|
-
|
|
108
|
-
const filterAndSortBlocks = useCallback(() => {
|
|
109
|
-
let filteredIpBlocks = ipBlocks;
|
|
110
|
-
const keys = Object.keys(filter) as ('state' | 'prefix')[];
|
|
111
|
-
keys.map((key) => {
|
|
112
|
-
if (key === 'state') {
|
|
113
|
-
filteredIpBlocks = filteredIpBlocks.filter((i) =>
|
|
114
|
-
filter[key].includes(i[key]),
|
|
115
|
-
);
|
|
116
|
-
} else if (key === 'prefix' && filter.prefix !== undefined) {
|
|
117
|
-
filteredIpBlocks = filteredIpBlocks.filter(
|
|
118
|
-
(i) => i.parent === filter.prefix!.id,
|
|
119
|
-
);
|
|
120
|
-
} else if (key !== 'prefix') {
|
|
121
|
-
filteredIpBlocks = filteredIpBlocks.filter(
|
|
122
|
-
(i) => prop(i, key) === prop(filter, key),
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
return key;
|
|
126
|
-
});
|
|
127
|
-
filteredIpBlocks.sort(sortBy(sorted.name));
|
|
128
|
-
return sorted.descending
|
|
129
|
-
? filteredIpBlocks.reverse()
|
|
130
|
-
: filteredIpBlocks;
|
|
131
|
-
}, [filter, ipBlocks, sorted.descending, sorted.name]);
|
|
132
|
-
|
|
133
|
-
const filterParentPrefix = (e: SingleValue<Option>) => {
|
|
134
|
-
const newParentPrefix = parseInt(e!.value, 10);
|
|
135
|
-
setParentPrefix(newParentPrefix);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const sortBy =
|
|
139
|
-
(name: SortKeys) =>
|
|
140
|
-
(a: IpBlock, b: IpBlock): number => {
|
|
141
|
-
const aVal = prop(a, name);
|
|
142
|
-
const bVal = prop(b, name);
|
|
143
|
-
try {
|
|
144
|
-
return typeof aVal === 'string' && typeof bVal === 'string'
|
|
145
|
-
? aVal.toLowerCase().localeCompare(bVal.toLowerCase())
|
|
146
|
-
: (aVal as number) - (bVal as number);
|
|
147
|
-
} catch (e) {
|
|
148
|
-
console.error(e);
|
|
149
|
-
}
|
|
150
|
-
return 0;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const filterState = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
154
|
-
const target = e.target as HTMLInputElement;
|
|
155
|
-
const stateFilter = parseInt(target.value, 10);
|
|
156
|
-
|
|
157
|
-
const newFilter = { ...filter };
|
|
158
|
-
if (target.checked) {
|
|
159
|
-
newFilter.state.push(stateFilter);
|
|
160
|
-
} else {
|
|
161
|
-
newFilter.state = newFilter.state.filter((e) => e !== stateFilter);
|
|
162
|
-
}
|
|
163
|
-
setFilter(newFilter);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const selectPrefix = (prefix: IpBlock) => () => {
|
|
167
|
-
if (prefix.state === 0 || prefix.state === 1) {
|
|
168
|
-
setSelectionDone(true);
|
|
169
|
-
onChange(prefix);
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
const ipBlocksFiltered = filterAndSortBlocks();
|
|
173
|
-
|
|
174
|
-
const columns = [
|
|
175
|
-
{
|
|
176
|
-
field: 'id',
|
|
177
|
-
name: 'ID',
|
|
178
|
-
sortable: true,
|
|
179
|
-
truncateText: true,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
field: 'prefix',
|
|
183
|
-
name: 'Prefix',
|
|
184
|
-
sortable: true,
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
field: 'description',
|
|
188
|
-
name: 'Description',
|
|
189
|
-
truncateText: true,
|
|
190
|
-
sortable: true,
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
field: 'state',
|
|
194
|
-
name: 'Status',
|
|
195
|
-
sortable: true,
|
|
196
|
-
render: (prefixState: number) => (
|
|
197
|
-
<EuiBadge color={prefixState === 3 ? 'danger' : 'success'}>
|
|
198
|
-
{ipamStates[prefixState]}
|
|
199
|
-
</EuiBadge>
|
|
200
|
-
),
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
field: 'Action',
|
|
204
|
-
name: '',
|
|
205
|
-
render: (id: string, record: IpBlock) =>
|
|
206
|
-
record.state !== 3 ? (
|
|
207
|
-
<EuiButton
|
|
208
|
-
onClick={selectPrefix(record)}
|
|
209
|
-
id={`select-prefix-${id}-button`}
|
|
210
|
-
>
|
|
211
|
-
Select
|
|
212
|
-
</EuiButton>
|
|
213
|
-
) : null,
|
|
214
|
-
},
|
|
215
|
-
];
|
|
216
|
-
|
|
217
|
-
const options: Option[] = filteredPrefixes.map((fp) => ({
|
|
218
|
-
value: fp.id.toString(),
|
|
219
|
-
label: fp.prefix,
|
|
220
|
-
}));
|
|
221
|
-
const value = options.find(
|
|
222
|
-
(option) => option.value === parentPrefix?.toString(),
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
const pagination = {
|
|
226
|
-
initialPageSize: 25,
|
|
227
|
-
pageSizeOptions: [25, 50, 100, 250],
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
if (selected_prefix_id && selectionDone) {
|
|
231
|
-
return (
|
|
232
|
-
<EuiButton
|
|
233
|
-
id="undo-parent-prefix-choice-button"
|
|
234
|
-
iconType="editorUndo"
|
|
235
|
-
onClick={() => setSelectionDone(false)}
|
|
236
|
-
>
|
|
237
|
-
Reset parent prefix choice
|
|
238
|
-
</EuiButton>
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
// Todo 482: re-implement when this component is refactored to function based
|
|
242
|
-
// const customStyles = getReactSelectTheme(this.context.theme);
|
|
243
|
-
|
|
244
|
-
return (
|
|
245
|
-
<EuiFlexItem css={ipPrefixTableFieldStyling}>
|
|
246
|
-
<div>
|
|
247
|
-
<EuiFlexGroup
|
|
248
|
-
gutterSize="s"
|
|
249
|
-
style={{ marginTop: '5px', marginBottom: '10px' }}
|
|
250
|
-
>
|
|
251
|
-
<EuiFlexItem grow={false}>
|
|
252
|
-
<EuiText>
|
|
253
|
-
<h4>Manual override?</h4>
|
|
254
|
-
</EuiText>
|
|
255
|
-
</EuiFlexItem>
|
|
256
|
-
<EuiFlexItem grow={false}>
|
|
257
|
-
<EuiButtonIcon
|
|
258
|
-
iconType={
|
|
259
|
-
manualOverrideVisible
|
|
260
|
-
? 'arrowDown'
|
|
261
|
-
: 'arrowRight'
|
|
262
|
-
}
|
|
263
|
-
aria-label="Toggle manual override"
|
|
264
|
-
onClick={() =>
|
|
265
|
-
setManualOverrideVisible(!manualOverrideVisible)
|
|
266
|
-
}
|
|
267
|
-
/>
|
|
268
|
-
</EuiFlexItem>
|
|
269
|
-
<EuiFlexItem></EuiFlexItem>
|
|
270
|
-
</EuiFlexGroup>
|
|
271
|
-
{manualOverrideVisible && (
|
|
272
|
-
<EuiPanel style={{ marginBottom: '20px' }}>
|
|
273
|
-
<EuiFormRow
|
|
274
|
-
style={{ marginTop: '15px' }}
|
|
275
|
-
label="Manually enter a prefix"
|
|
276
|
-
labelAppend={
|
|
277
|
-
<EuiText size="m">
|
|
278
|
-
Generating free spaces for a big IPv6 root
|
|
279
|
-
prefix could yield an enormous list. If you
|
|
280
|
-
know the address of a free subnet you can
|
|
281
|
-
provide it here. The prefix will be created
|
|
282
|
-
in the biggest existing prefix above it in
|
|
283
|
-
one of the root prefixes.
|
|
284
|
-
</EuiText>
|
|
285
|
-
}
|
|
286
|
-
helpText="Example: 145.145.10/17"
|
|
287
|
-
>
|
|
288
|
-
<EuiFieldText
|
|
289
|
-
value={manualOverrideValue}
|
|
290
|
-
onChange={(e) =>
|
|
291
|
-
setManualOverrideValue(e.target.value)
|
|
292
|
-
}
|
|
293
|
-
></EuiFieldText>
|
|
294
|
-
</EuiFormRow>
|
|
295
|
-
<EuiButton
|
|
296
|
-
onClick={() =>
|
|
297
|
-
onManualOverride(manualOverrideValue)
|
|
298
|
-
}
|
|
299
|
-
>
|
|
300
|
-
Confirm
|
|
301
|
-
</EuiButton>
|
|
302
|
-
</EuiPanel>
|
|
303
|
-
)}
|
|
304
|
-
</div>
|
|
305
|
-
{!manualOverrideVisible && (
|
|
306
|
-
<>
|
|
307
|
-
<div>
|
|
308
|
-
<EuiFlexGroup gutterSize="s">
|
|
309
|
-
<EuiFlexItem
|
|
310
|
-
grow={false}
|
|
311
|
-
style={{ marginTop: '6px' }}
|
|
312
|
-
>
|
|
313
|
-
State:
|
|
314
|
-
</EuiFlexItem>
|
|
315
|
-
<EuiFlexItem grow={false}>
|
|
316
|
-
<EuiCheckbox
|
|
317
|
-
id="checkbox-allocated"
|
|
318
|
-
label="Allocated"
|
|
319
|
-
name="checkbox-allocated"
|
|
320
|
-
onChange={filterState}
|
|
321
|
-
value={ipamStates.indexOf('Allocated')}
|
|
322
|
-
checked={filter.state.includes(
|
|
323
|
-
ipamStates.indexOf('Allocated'),
|
|
324
|
-
)}
|
|
325
|
-
/>
|
|
326
|
-
</EuiFlexItem>
|
|
327
|
-
<EuiFlexItem grow={false}>
|
|
328
|
-
<EuiCheckbox
|
|
329
|
-
id="checkbox-planned"
|
|
330
|
-
label="Planned"
|
|
331
|
-
name="checkbox-planned"
|
|
332
|
-
onChange={filterState}
|
|
333
|
-
value={ipamStates.indexOf('Planned')}
|
|
334
|
-
checked={filter.state.includes(
|
|
335
|
-
ipamStates.indexOf('Planned'),
|
|
336
|
-
)}
|
|
337
|
-
/>
|
|
338
|
-
</EuiFlexItem>
|
|
339
|
-
<EuiFlexItem grow={false}>
|
|
340
|
-
<EuiCheckbox
|
|
341
|
-
id="checkbox-free"
|
|
342
|
-
label="Free"
|
|
343
|
-
name="checkbox-free"
|
|
344
|
-
onChange={filterState}
|
|
345
|
-
value={ipamStates.indexOf('Free')}
|
|
346
|
-
checked={filter.state.includes(
|
|
347
|
-
ipamStates.indexOf('Free'),
|
|
348
|
-
)}
|
|
349
|
-
/>
|
|
350
|
-
</EuiFlexItem>
|
|
351
|
-
</EuiFlexGroup>
|
|
352
|
-
<div
|
|
353
|
-
style={{
|
|
354
|
-
marginTop: '4px',
|
|
355
|
-
marginBottom: '4px',
|
|
356
|
-
}}
|
|
357
|
-
>
|
|
358
|
-
Root filter
|
|
359
|
-
</div>
|
|
360
|
-
<span>
|
|
361
|
-
<ReactSelect
|
|
362
|
-
id={`${id}.root-filter`}
|
|
363
|
-
// Todo 482: re-implement when this component is refactored to function based
|
|
364
|
-
// styles={customStyles}
|
|
365
|
-
inputId={`${id}.root-filter.search`}
|
|
366
|
-
name={`${name}.root-filter`}
|
|
367
|
-
options={options}
|
|
368
|
-
onChange={filterParentPrefix}
|
|
369
|
-
value={value}
|
|
370
|
-
/>
|
|
371
|
-
</span>
|
|
372
|
-
</div>
|
|
373
|
-
<EuiInMemoryTable
|
|
374
|
-
id="test"
|
|
375
|
-
style={{ marginTop: '6px' }}
|
|
376
|
-
itemId="id"
|
|
377
|
-
tableCaption="Prefix table"
|
|
378
|
-
loading={isFetching}
|
|
379
|
-
items={ipBlocksFiltered}
|
|
380
|
-
columns={columns}
|
|
381
|
-
pagination={pagination}
|
|
382
|
-
sorting={true}
|
|
383
|
-
/>
|
|
384
|
-
</>
|
|
385
|
-
)}
|
|
386
|
-
</EuiFlexItem>
|
|
387
|
-
);
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
export default IpPrefixTableField;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
|
|
3
|
-
const DARK_GREY_COLOR = '#333333';
|
|
4
|
-
const LIGHTER_GREY_COLOR = '#999999';
|
|
5
|
-
const LIGHT_GOLD_COLOR = '#fca456';
|
|
6
|
-
const LIGHT_PRIMARY_COLOR = '#0da3f5';
|
|
7
|
-
const LIGHT_SUCCESS_COLOR = '#68ff1d';
|
|
8
|
-
|
|
9
|
-
function shadeColor(color: string, percent: number) {
|
|
10
|
-
let R = parseInt(color.substring(1, 3), 16);
|
|
11
|
-
let G = parseInt(color.substring(3, 5), 16);
|
|
12
|
-
let B = parseInt(color.substring(5, 7), 16);
|
|
13
|
-
|
|
14
|
-
R = parseInt(String((R * (100 + percent)) / 100));
|
|
15
|
-
G = parseInt(String((G * (100 + percent)) / 100));
|
|
16
|
-
B = parseInt(String((B * (100 + percent)) / 100));
|
|
17
|
-
|
|
18
|
-
R = R < 255 ? R : 255;
|
|
19
|
-
G = G < 255 ? G : 255;
|
|
20
|
-
B = B < 255 ? B : 255;
|
|
21
|
-
|
|
22
|
-
const RR =
|
|
23
|
-
R.toString(16).length === 1 ? '0' + R.toString(16) : R.toString(16);
|
|
24
|
-
const GG =
|
|
25
|
-
G.toString(16).length === 1 ? '0' + G.toString(16) : G.toString(16);
|
|
26
|
-
const BB =
|
|
27
|
-
B.toString(16).length === 1 ? '0' + B.toString(16) : B.toString(16);
|
|
28
|
-
|
|
29
|
-
return '#' + RR + GG + BB;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const ipPrefixTableFieldStyling = css`
|
|
33
|
-
table.ip-blocks {
|
|
34
|
-
word-break: break-all;
|
|
35
|
-
margin-bottom: 20px;
|
|
36
|
-
|
|
37
|
-
td,
|
|
38
|
-
th {
|
|
39
|
-
text-align: left;
|
|
40
|
-
}
|
|
41
|
-
tr {
|
|
42
|
-
border-bottom: 1px solid ${LIGHTER_GREY_COLOR};
|
|
43
|
-
}
|
|
44
|
-
tr.Allocated {
|
|
45
|
-
cursor: pointer;
|
|
46
|
-
background-color: ${LIGHT_PRIMARY_COLOR};
|
|
47
|
-
&:hover {
|
|
48
|
-
background-color: ${shadeColor(LIGHT_PRIMARY_COLOR, -10)};
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
tr.Planned {
|
|
52
|
-
cursor: default;
|
|
53
|
-
background-color: ${LIGHT_GOLD_COLOR};
|
|
54
|
-
}
|
|
55
|
-
tr.Free {
|
|
56
|
-
cursor: pointer;
|
|
57
|
-
background-color: ${LIGHT_SUCCESS_COLOR};
|
|
58
|
-
&:hover {
|
|
59
|
-
background-color: ${shadeColor(LIGHT_SUCCESS_COLOR, -10)};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
tr.Subnet {
|
|
63
|
-
background-color: ${shadeColor(LIGHT_PRIMARY_COLOR, -30)};
|
|
64
|
-
cursor: default;
|
|
65
|
-
}
|
|
66
|
-
tr.selected {
|
|
67
|
-
background-color: ${DARK_GREY_COLOR};
|
|
68
|
-
color: white;
|
|
69
|
-
&:hover {
|
|
70
|
-
background-color: black;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
thead {
|
|
74
|
-
display: block;
|
|
75
|
-
th {
|
|
76
|
-
cursor: pointer;
|
|
77
|
-
padding: 5px 5px 10px 5px;
|
|
78
|
-
}
|
|
79
|
-
th.id {
|
|
80
|
-
min-width: 8em;
|
|
81
|
-
}
|
|
82
|
-
th.prefix {
|
|
83
|
-
min-width: 15em;
|
|
84
|
-
}
|
|
85
|
-
th.description {
|
|
86
|
-
width: 30em;
|
|
87
|
-
}
|
|
88
|
-
th.state {
|
|
89
|
-
min-width: 25em;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
tbody {
|
|
94
|
-
min-width: 1000px;
|
|
95
|
-
height: 240px;
|
|
96
|
-
display: block;
|
|
97
|
-
overflow: auto;
|
|
98
|
-
td {
|
|
99
|
-
word-break: break-word;
|
|
100
|
-
word-wrap: break-word;
|
|
101
|
-
padding: 15px 5px;
|
|
102
|
-
}
|
|
103
|
-
td.id {
|
|
104
|
-
min-width: 8em;
|
|
105
|
-
}
|
|
106
|
-
td.prefix {
|
|
107
|
-
min-width: 15em;
|
|
108
|
-
}
|
|
109
|
-
td.description {
|
|
110
|
-
width: 30em;
|
|
111
|
-
}
|
|
112
|
-
td.state {
|
|
113
|
-
min-width: 25em;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
`;
|
|
@@ -1,138 +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
|
-
import ReactSelect, { SingleValue } from 'react-select';
|
|
17
|
-
|
|
18
|
-
import { range } from 'lodash';
|
|
19
|
-
|
|
20
|
-
import { EuiFlexItem } from '@elastic/eui';
|
|
21
|
-
|
|
22
|
-
import { splitPrefixStyling } from '@/components';
|
|
23
|
-
import { useFreeSubnetsQuery } from '@/rtk/endpoints/ipam';
|
|
24
|
-
import type { Option } from '@/types';
|
|
25
|
-
|
|
26
|
-
interface IProps {
|
|
27
|
-
id: string;
|
|
28
|
-
name: string;
|
|
29
|
-
subnet: string;
|
|
30
|
-
prefixlen: number;
|
|
31
|
-
prefixMin: number;
|
|
32
|
-
onChange: (value: string) => void;
|
|
33
|
-
selectedSubnet?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const SplitPrefix: React.FC<IProps> = ({
|
|
37
|
-
id,
|
|
38
|
-
name,
|
|
39
|
-
subnet,
|
|
40
|
-
prefixlen,
|
|
41
|
-
prefixMin,
|
|
42
|
-
onChange,
|
|
43
|
-
selectedSubnet,
|
|
44
|
-
}) => {
|
|
45
|
-
const [subnets, setSubnets] = useState<string[]>([]);
|
|
46
|
-
const [desiredPrefixlen, setDesiredPrefixlen] = useState<number>(prefixMin);
|
|
47
|
-
const { data, isFetching } = useFreeSubnetsQuery({
|
|
48
|
-
subnet,
|
|
49
|
-
netmask: prefixlen,
|
|
50
|
-
prefixLen: desiredPrefixlen,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
if (isFetching) {
|
|
55
|
-
setSubnets([]);
|
|
56
|
-
}
|
|
57
|
-
if (data) {
|
|
58
|
-
const filteredSubnets = data.filter(
|
|
59
|
-
(x) => parseInt(x.split('/')[1], 10) === desiredPrefixlen,
|
|
60
|
-
);
|
|
61
|
-
setSubnets(filteredSubnets);
|
|
62
|
-
setDesiredPrefixlen(desiredPrefixlen);
|
|
63
|
-
}
|
|
64
|
-
}, [data, desiredPrefixlen, isFetching]);
|
|
65
|
-
|
|
66
|
-
const changePrefixLength = (e: SingleValue<Option<number>>) => {
|
|
67
|
-
const desiredPrefixlen = e?.value;
|
|
68
|
-
if (desiredPrefixlen) {
|
|
69
|
-
setDesiredPrefixlen(desiredPrefixlen);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const selectSubnet = (e: SingleValue<Option>) => {
|
|
74
|
-
onChange(e?.value ?? '');
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// IPv4 subnet size should be between /32 and /12
|
|
78
|
-
// IPv6 subnet size should be between /128 and /32
|
|
79
|
-
const version = subnet.indexOf(':') === -1 ? 4 : 6;
|
|
80
|
-
const minPrefixLength = version === 4 ? 12 : 32;
|
|
81
|
-
const minimalSelectablePrefixLength =
|
|
82
|
-
minPrefixLength > prefixMin ? minPrefixLength : prefixMin;
|
|
83
|
-
const maximalSelectablePrefixLength =
|
|
84
|
-
version === 4 ? 32 : minimalSelectablePrefixLength + 12;
|
|
85
|
-
|
|
86
|
-
const prefixlengths = range(
|
|
87
|
-
maximalSelectablePrefixLength - minimalSelectablePrefixLength + 1,
|
|
88
|
-
).map((x) => minimalSelectablePrefixLength + x);
|
|
89
|
-
|
|
90
|
-
const length_options: Option<number>[] = prefixlengths.map((pl) => ({
|
|
91
|
-
value: pl,
|
|
92
|
-
label: pl.toString(),
|
|
93
|
-
}));
|
|
94
|
-
const length_value = length_options.find(
|
|
95
|
-
(option) => option.value === desiredPrefixlen,
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const prefix_options = subnets.map((sn) => ({
|
|
99
|
-
label: sn,
|
|
100
|
-
value: sn,
|
|
101
|
-
}));
|
|
102
|
-
|
|
103
|
-
const prefix_value = prefix_options.find(
|
|
104
|
-
(option) => option.value === selectedSubnet,
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
return (
|
|
108
|
-
<EuiFlexItem css={splitPrefixStyling}>
|
|
109
|
-
<section>
|
|
110
|
-
<h3>
|
|
111
|
-
Selected prefix: {subnet}/{prefixlen}
|
|
112
|
-
</h3>
|
|
113
|
-
<div>Desired netmask of the new subnet:</div>
|
|
114
|
-
<ReactSelect
|
|
115
|
-
id={`${id}.desired-netmask`}
|
|
116
|
-
name={`${name}.desired-netmask`}
|
|
117
|
-
onChange={changePrefixLength}
|
|
118
|
-
options={length_options}
|
|
119
|
-
value={length_value}
|
|
120
|
-
/>
|
|
121
|
-
<div>
|
|
122
|
-
<div>Desired prefix:</div>
|
|
123
|
-
<ReactSelect
|
|
124
|
-
isDisabled={isFetching}
|
|
125
|
-
isLoading={isFetching}
|
|
126
|
-
id={`${id}.desired-prefix`}
|
|
127
|
-
name={`${name}.desired-prefix`}
|
|
128
|
-
options={prefix_options}
|
|
129
|
-
onChange={selectSubnet}
|
|
130
|
-
value={prefix_value}
|
|
131
|
-
/>
|
|
132
|
-
</div>
|
|
133
|
-
</section>
|
|
134
|
-
</EuiFlexItem>
|
|
135
|
-
);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
export default SplitPrefix;
|