Line data Source code
1 43 : import React from 'react';
2 :
3 : import { Button } from "@patternfly/react-core/dist/esm/components/Button";
4 : import { FormGroup } from "@patternfly/react-core/dist/esm/components/Form";
5 : import { TextInput } from "@patternfly/react-core/dist/esm/components/TextInput";
6 : import { Grid } from "@patternfly/react-core/dist/esm/layouts/Grid";
7 : import { TrashIcon } from '@patternfly/react-icons';
8 : import { FormHelper } from "cockpit-components-form-helper.jsx";
9 :
10 : import cockpit from 'cockpit';
11 :
12 : import * as utils from './util.js';
13 :
14 43 : const _ = cockpit.gettext;
15 :
16 3 : export function validateEnvVar(env, key) {
17 3 : const re = /^[a-zA-Z_]{1,}[a-zA-Z0-9_]*$/;
18 3 : switch (key) {
19 3 : case "envKey":
20 3 : if (!env)
21 1 : return _("Key must not be empty");
22 3 : if (/^\d/.test(env))
23 1 : return _("Key must not begin with a digit");
24 3 : if (!re.test(env))
25 1 : return _("Key contains invalid characters");
26 3 : break;
27 3 : case "envValue":
28 3 : break;
29 0 : default:
30 0 : console.error(`Unknown key "${key}"`); // not-covered: unreachable assertion
31 3 : }
32 3 : }
33 :
34 3 : const handleEnvValue = (key, value, idx, onChange, additem, _itemCount, companionField) => {
35 : // Allow the input of KEY=VALUE separated value pairs for bulk import only if the other
36 : // field is not empty.
37 2 : if (value.includes('=') && !companionField) {
38 2 : const parts = value.trim().split(" ");
39 2 : let index = idx;
40 2 : for (const part of parts) {
41 2 : const [envKey, ...envVar] = part.split('=');
42 0 : if (!envKey || !envVar) {
43 0 : continue;
44 0 : }
45 :
46 2 : if (index !== idx) {
47 2 : additem();
48 2 : }
49 2 : onChange(index, 'envKey', envKey);
50 2 : onChange(index, 'envValue', envVar.join('='));
51 2 : index++;
52 2 : }
53 2 : } else {
54 3 : onChange(idx, key, value);
55 3 : }
56 3 : };
57 :
58 3 : export const EnvVar = ({ id, item, onChange, idx, removeitem, additem, itemCount, validationFailed, onValidationChange }) =>
59 : (
60 3 : <Grid hasGutter id={id}>
61 3 : <FormGroup className="pf-m-6-col-on-md"
62 3 : id={id + "-key-group"}
63 3 : label={_("Key")}
64 3 : fieldId={id + "-key-address"}
65 3 : isRequired
66 : >
67 3 : <TextInput id={id + "-key"}
68 3 : value={item.envKey || ''}
69 1 : validated={validationFailed?.envKey ? "error" : "default"}
70 3 : onChange={(_event, value) => {
71 3 : utils.validationClear(validationFailed, "envKey", onValidationChange);
72 1 : utils.validationDebounce(() => onValidationChange({ ...validationFailed, envKey: validateEnvVar(value, "envKey") }));
73 3 : handleEnvValue('envKey', value, idx, onChange, additem, itemCount, item.envValue);
74 3 : }} />
75 3 : <FormHelper helperTextInvalid={validationFailed?.envKey} />
76 3 : </FormGroup>
77 3 : <FormGroup className="pf-m-6-col-on-md"
78 3 : id={id + "-value-group"}
79 3 : label={_("Value")}
80 3 : fieldId={id + "-value-address"}
81 : >
82 3 : <TextInput id={id + "-value"}
83 3 : value={item.envValue || ''}
84 0 : validated={validationFailed?.envValue ? "error" : "default"}
85 2 : onChange={(_event, value) => {
86 2 : utils.validationClear(validationFailed, "envValue", onValidationChange);
87 0 : utils.validationDebounce(() => onValidationChange({ ...validationFailed, envValue: validateEnvVar(value, "envValue") }));
88 2 : handleEnvValue('envValue', value, idx, onChange, additem, itemCount, item.envKey);
89 2 : }} />
90 3 : <FormHelper helperTextInvalid={validationFailed?.envValue} />
91 3 : </FormGroup>
92 3 : <FormGroup className="pf-m-1-col-on-md remove-button-group">
93 3 : <Button variant='plain'
94 3 : className="btn-close"
95 3 : id={id + "-btn-close"}
96 3 : size="sm"
97 3 : aria-label={_("Remove item")}
98 3 : icon={<TrashIcon />}
99 3 : onClick={() => removeitem(idx)} />
100 3 : </FormGroup>
101 3 : </Grid>
102 : );
|