@thecb/components 7.2.1 → 7.3.2-beta.0
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/dist/index.cjs.js +56 -314
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +57 -314
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/.DS_Store +0 -0
- package/src/components/atoms/radio-button-with-label/RadioButtonWithLabel.js +7 -2
- package/src/components/molecules/.DS_Store +0 -0
- package/src/components/molecules/index.js +0 -1
- package/src/components/molecules/radio-group/RadioGroup.js +3 -0
- package/src/components/atoms/radio-button-with-label/RadioButtonWithLabel.stories.js +0 -39
- package/src/components/molecules/internal-user-info-form/InternalUserInfoForm.js +0 -266
- package/src/components/molecules/internal-user-info-form/InternalUserInfoForm.state.js +0 -26
- package/src/components/molecules/internal-user-info-form/index.js +0 -11
package/package.json
CHANGED
|
Binary file
|
|
@@ -3,6 +3,7 @@ import { Cluster } from "../../atoms/layouts";
|
|
|
3
3
|
import Text from "../text";
|
|
4
4
|
import styled from "styled-components";
|
|
5
5
|
import { colors } from "../../../constants";
|
|
6
|
+
import { noop } from "../../../util/general";
|
|
6
7
|
|
|
7
8
|
const HiddenRadioInput = styled.input`
|
|
8
9
|
// can still select the element with the keyboard, but it's invisible and doesn't interfere with the spacing of other elements around it
|
|
@@ -53,7 +54,8 @@ const RadioButtonWithLabel = ({
|
|
|
53
54
|
groupName,
|
|
54
55
|
setValue,
|
|
55
56
|
ariaInvalid,
|
|
56
|
-
index
|
|
57
|
+
index,
|
|
58
|
+
handleChange = noop // optional, for custom event handling in ingesting app
|
|
57
59
|
}) => (
|
|
58
60
|
<InputAndLabelContainer align="center" childGap="0.5rem">
|
|
59
61
|
<HiddenRadioInput
|
|
@@ -63,7 +65,10 @@ const RadioButtonWithLabel = ({
|
|
|
63
65
|
name={groupName}
|
|
64
66
|
id={id}
|
|
65
67
|
value={value}
|
|
66
|
-
onChange={e =>
|
|
68
|
+
onChange={e => {
|
|
69
|
+
setValue(e.target.value);
|
|
70
|
+
handleChange(e);
|
|
71
|
+
}}
|
|
67
72
|
defaultChecked={index === 0}
|
|
68
73
|
/>
|
|
69
74
|
<Text
|
|
Binary file
|
|
@@ -11,7 +11,6 @@ export { default as FooterWithSubfooter } from "./footer-with-subfooter";
|
|
|
11
11
|
export { default as ForgotPasswordForm } from "./forgot-password-form";
|
|
12
12
|
export { default as HighlightTabRow } from "./highlight-tab-row";
|
|
13
13
|
export { iconsMap as ObligationIcons } from "./obligation/icons";
|
|
14
|
-
export { default as InternalUserInfoForm } from "./internal-user-info-form";
|
|
15
14
|
export { default as LoginForm } from "./login-form";
|
|
16
15
|
export { default as Modal } from "./modal";
|
|
17
16
|
export { default as Module } from "./module";
|
|
@@ -3,6 +3,7 @@ import RadioButtonWithLabel from "../../atoms/radio-button-with-label/RadioButto
|
|
|
3
3
|
import { Stack } from "../../atoms";
|
|
4
4
|
import { colors } from "../../../constants";
|
|
5
5
|
import styled from "styled-components";
|
|
6
|
+
import { noop } from "../../../util/general";
|
|
6
7
|
|
|
7
8
|
const DefaultHeading = styled.div`
|
|
8
9
|
font-size: 0.875rem;
|
|
@@ -25,6 +26,7 @@ const RadioGroup = ({
|
|
|
25
26
|
),
|
|
26
27
|
config,
|
|
27
28
|
extraStyles,
|
|
29
|
+
handleChange = noop, // optional, for custom event handling in ingesting app
|
|
28
30
|
// redux-freeform props - this is similar to how FormInput works, duplicated because the radio input is hidden for styling overrides
|
|
29
31
|
field,
|
|
30
32
|
fieldActions
|
|
@@ -45,6 +47,7 @@ const RadioGroup = ({
|
|
|
45
47
|
{...c}
|
|
46
48
|
groupName={groupName}
|
|
47
49
|
setValue={setValue}
|
|
50
|
+
handleChange={handleChange}
|
|
48
51
|
aria-invalid={
|
|
49
52
|
(field.dirty && field.hasErrors) ||
|
|
50
53
|
(field.hasErrors && showErrors)
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import RadioButtonWithLabel from "./RadioButtonWithLabel";
|
|
3
|
-
import { Box } from "../layouts";
|
|
4
|
-
import page from "../../../../.storybook/page";
|
|
5
|
-
|
|
6
|
-
export const radioButtonWithLabel = () => {
|
|
7
|
-
const [selected, setSelected] = useState("");
|
|
8
|
-
const handleRadioClick = e => {
|
|
9
|
-
setSelected(e.currentTarget.value);
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<Box>
|
|
14
|
-
<RadioButtonWithLabel
|
|
15
|
-
id="some-id"
|
|
16
|
-
value="some-value"
|
|
17
|
-
labelText="A radio button with a label."
|
|
18
|
-
handleRadioClick={handleRadioClick}
|
|
19
|
-
selected={selected}
|
|
20
|
-
/>
|
|
21
|
-
<RadioButtonWithLabel
|
|
22
|
-
id="another-id"
|
|
23
|
-
value="another-value"
|
|
24
|
-
labelText="Another radio button with a label."
|
|
25
|
-
handleRadioClick={handleRadioClick}
|
|
26
|
-
selected={selected}
|
|
27
|
-
/>
|
|
28
|
-
</Box>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
radioButtonWithLabel.storyName = "RadioButtonWithLabel";
|
|
33
|
-
|
|
34
|
-
const story = page({
|
|
35
|
-
title: "Components|Atoms/RadioButtonWithLabel",
|
|
36
|
-
Component: RadioButtonWithLabel
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
export default story;
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
2
|
-
import { required, isProbablyEmail } from "redux-freeform";
|
|
3
|
-
import { Stack, Box, Cluster } from "../../atoms/layouts";
|
|
4
|
-
import ButtonWithAction from "../../atoms/button-with-action";
|
|
5
|
-
import Heading from "../../atoms/heading";
|
|
6
|
-
import Text from "../../atoms/text";
|
|
7
|
-
import { noop } from "../../../util/general";
|
|
8
|
-
import {
|
|
9
|
-
FormInput,
|
|
10
|
-
FormContainer,
|
|
11
|
-
FormInputColumn
|
|
12
|
-
} from "../../atoms/form-layouts";
|
|
13
|
-
import FormSelect from "../../atoms/form-select";
|
|
14
|
-
import SearchableSelect from "../../atoms/searchable-select";
|
|
15
|
-
import { GHOST_GREY } from "../../../constants/colors";
|
|
16
|
-
|
|
17
|
-
const RESEARCHER = "RESEARCHER";
|
|
18
|
-
const AGENCY_ADMIN = "AGENCY_ADMIN";
|
|
19
|
-
const CLIENT_ADMIN = "CLIENT_ADMIN";
|
|
20
|
-
const SUPERVISOR = "SUPERVISOR";
|
|
21
|
-
const CB_ADMIN = "CITYBASE_ADMIN";
|
|
22
|
-
const CREATE_CLIENT_ADMIN = "CREATE_CLIENT_ADMIN";
|
|
23
|
-
const PROFILE = "PROFILE";
|
|
24
|
-
const ADD = "ADD";
|
|
25
|
-
const EDIT = "EDIT";
|
|
26
|
-
|
|
27
|
-
const roleDescriptions = {
|
|
28
|
-
[RESEARCHER]: "Researcher",
|
|
29
|
-
[AGENCY_ADMIN]: "Agency admin",
|
|
30
|
-
[CLIENT_ADMIN]: "Client admin",
|
|
31
|
-
[SUPERVISOR]: "Supervisor",
|
|
32
|
-
[CB_ADMIN]: "Citybase admin"
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const InternalUserInfoForm = ({
|
|
36
|
-
variant = "default",
|
|
37
|
-
fields,
|
|
38
|
-
actions,
|
|
39
|
-
clearOnDismount,
|
|
40
|
-
showErrors,
|
|
41
|
-
handleSubmit = noop,
|
|
42
|
-
closeForm,
|
|
43
|
-
allAgencyOptions,
|
|
44
|
-
selectedAgencies,
|
|
45
|
-
allSelected,
|
|
46
|
-
toggleSelectAllAgencies = noop,
|
|
47
|
-
selectAgency,
|
|
48
|
-
roleOptions,
|
|
49
|
-
clientOptions,
|
|
50
|
-
namesDisabled,
|
|
51
|
-
emailDisabled,
|
|
52
|
-
roleDisabled,
|
|
53
|
-
selectionDisabled,
|
|
54
|
-
formType,
|
|
55
|
-
openChangePasswordForm,
|
|
56
|
-
firstName,
|
|
57
|
-
lastName
|
|
58
|
-
}) => {
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
if (formType === CREATE_CLIENT_ADMIN) {
|
|
61
|
-
actions.fields.client.addValidator(required());
|
|
62
|
-
}
|
|
63
|
-
if (formType !== PROFILE) {
|
|
64
|
-
actions.fields.email.addValidator(required());
|
|
65
|
-
actions.fields.role.addValidator(required());
|
|
66
|
-
}
|
|
67
|
-
}, []);
|
|
68
|
-
if (clearOnDismount) {
|
|
69
|
-
useEffect(() => () => actions.form.clear(), []);
|
|
70
|
-
}
|
|
71
|
-
const clientErrorMessages = {
|
|
72
|
-
[required.error]: "Client is required"
|
|
73
|
-
};
|
|
74
|
-
const firstNameErrorMessages = {
|
|
75
|
-
[required.error]: "First name is required"
|
|
76
|
-
};
|
|
77
|
-
const lastNameErrorMessages = {
|
|
78
|
-
[required.error]: "Last name is required"
|
|
79
|
-
};
|
|
80
|
-
const emailErrorMessages = {
|
|
81
|
-
[isProbablyEmail.error]: "Invalid email address"
|
|
82
|
-
};
|
|
83
|
-
const roleErrorMessages = {
|
|
84
|
-
[required.error]: "Role is required"
|
|
85
|
-
};
|
|
86
|
-
return (
|
|
87
|
-
<FormContainer
|
|
88
|
-
variant={variant}
|
|
89
|
-
role="form"
|
|
90
|
-
aria-label="user-info-form"
|
|
91
|
-
extraStyles={`padding: 0;`}
|
|
92
|
-
>
|
|
93
|
-
{formType === PROFILE && (
|
|
94
|
-
<Box padding="1.5rem">
|
|
95
|
-
<Cluster justify="flex-start" align="center">
|
|
96
|
-
<Box padding="1.25rem" borderRadius="50%" background="#CACED8">
|
|
97
|
-
<Heading variant="h4" weight="700">
|
|
98
|
-
{firstName.charAt(0).toUpperCase()}
|
|
99
|
-
{lastName.charAt(0).toUpperCase()}
|
|
100
|
-
</Heading>
|
|
101
|
-
</Box>
|
|
102
|
-
<Text variant="p" weight="700" extraStyles={`padding-left: 1rem;`}>
|
|
103
|
-
{firstName} {lastName}
|
|
104
|
-
</Text>
|
|
105
|
-
</Cluster>
|
|
106
|
-
</Box>
|
|
107
|
-
)}
|
|
108
|
-
{formType === CREATE_CLIENT_ADMIN && (
|
|
109
|
-
<Box
|
|
110
|
-
padding="1.5rem 1.5rem 0.5rem"
|
|
111
|
-
borderColor={GHOST_GREY}
|
|
112
|
-
borderSize="1px"
|
|
113
|
-
borderWidthOverride="0 0 1px 0"
|
|
114
|
-
>
|
|
115
|
-
<FormInputColumn>
|
|
116
|
-
<Heading variant="h6" weight="700" margin="0 0 1rem">
|
|
117
|
-
Select Client
|
|
118
|
-
</Heading>
|
|
119
|
-
<FormSelect
|
|
120
|
-
labelTextWhenNoError="Client"
|
|
121
|
-
errorMessages={clientErrorMessages}
|
|
122
|
-
options={clientOptions.map(client => ({
|
|
123
|
-
text: client,
|
|
124
|
-
value: client,
|
|
125
|
-
id: client
|
|
126
|
-
}))}
|
|
127
|
-
field={fields.client}
|
|
128
|
-
fieldActions={actions.fields.client}
|
|
129
|
-
showErrors={showErrors}
|
|
130
|
-
onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
|
|
131
|
-
/>
|
|
132
|
-
</FormInputColumn>
|
|
133
|
-
</Box>
|
|
134
|
-
)}
|
|
135
|
-
<Box
|
|
136
|
-
padding={
|
|
137
|
-
formType === PROFILE ? "1.5rem 1.5rem 0" : "1.5rem 1.5rem 0.5rem"
|
|
138
|
-
}
|
|
139
|
-
borderColor={GHOST_GREY}
|
|
140
|
-
borderSize="1px"
|
|
141
|
-
borderWidthOverride={formType === PROFILE ? "1px 0 0" : "0 0 1px 0"}
|
|
142
|
-
>
|
|
143
|
-
<FormInputColumn>
|
|
144
|
-
<Heading variant="h6" weight="700" margin="0 0 1rem">
|
|
145
|
-
Personal Information
|
|
146
|
-
</Heading>
|
|
147
|
-
<FormInput
|
|
148
|
-
labelTextWhenNoError="First Name"
|
|
149
|
-
errorMessages={firstNameErrorMessages}
|
|
150
|
-
field={fields.firstName}
|
|
151
|
-
fieldActions={actions.fields.firstName}
|
|
152
|
-
showErrors={showErrors}
|
|
153
|
-
onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
|
|
154
|
-
disabled={namesDisabled}
|
|
155
|
-
autocomplete="given-name"
|
|
156
|
-
/>
|
|
157
|
-
<FormInput
|
|
158
|
-
labelTextWhenNoError="Last Name"
|
|
159
|
-
errorMessages={lastNameErrorMessages}
|
|
160
|
-
field={fields.lastName}
|
|
161
|
-
fieldActions={actions.fields.lastName}
|
|
162
|
-
showErrors={showErrors}
|
|
163
|
-
onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
|
|
164
|
-
disabled={namesDisabled}
|
|
165
|
-
autocomplete="family-name"
|
|
166
|
-
/>
|
|
167
|
-
<FormInput
|
|
168
|
-
labelTextWhenNoError="Email"
|
|
169
|
-
errorMessages={emailErrorMessages}
|
|
170
|
-
field={fields.email}
|
|
171
|
-
fieldActions={actions.fields.email}
|
|
172
|
-
showErrors={showErrors}
|
|
173
|
-
onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
|
|
174
|
-
disabled={emailDisabled}
|
|
175
|
-
autocomplete="email"
|
|
176
|
-
/>
|
|
177
|
-
{formType === PROFILE && (
|
|
178
|
-
<FormInput
|
|
179
|
-
labelTextWhenNoError="Password"
|
|
180
|
-
errorMessages={{}}
|
|
181
|
-
field={{ rawValue: "•••••••••••••" }}
|
|
182
|
-
disabled={true}
|
|
183
|
-
decorator={
|
|
184
|
-
<Text
|
|
185
|
-
variant="pS"
|
|
186
|
-
color={`#15749D`}
|
|
187
|
-
onClick={openChangePasswordForm}
|
|
188
|
-
extraStyles={`cursor: pointer;`}
|
|
189
|
-
>
|
|
190
|
-
Change Password
|
|
191
|
-
</Text>
|
|
192
|
-
}
|
|
193
|
-
/>
|
|
194
|
-
)}
|
|
195
|
-
</FormInputColumn>
|
|
196
|
-
</Box>
|
|
197
|
-
<Box padding="1.5rem">
|
|
198
|
-
{formType !== PROFILE && (
|
|
199
|
-
<Box padding="0 0 0.5rem">
|
|
200
|
-
<FormInputColumn>
|
|
201
|
-
<Heading variant="h6" weight="700" margin="0 0 1rem">
|
|
202
|
-
User Settings
|
|
203
|
-
</Heading>
|
|
204
|
-
<FormSelect
|
|
205
|
-
labelTextWhenNoError="User Role"
|
|
206
|
-
errorMessages={roleErrorMessages}
|
|
207
|
-
options={roleOptions.map(role => ({
|
|
208
|
-
text: roleDescriptions[role],
|
|
209
|
-
value: role,
|
|
210
|
-
id: role
|
|
211
|
-
}))}
|
|
212
|
-
field={fields.role}
|
|
213
|
-
fieldActions={actions.fields.role}
|
|
214
|
-
showErrors={showErrors}
|
|
215
|
-
onKeyDown={e => e.key === "Enter" && handleSubmit(e)}
|
|
216
|
-
disabled={roleDisabled}
|
|
217
|
-
/>
|
|
218
|
-
</FormInputColumn>
|
|
219
|
-
</Box>
|
|
220
|
-
)}
|
|
221
|
-
{(formType === ADD || formType === EDIT) && (
|
|
222
|
-
<Box padding="0.5rem 0 1.5rem">
|
|
223
|
-
<FormInputColumn>
|
|
224
|
-
<Text variant="p">Select which agencies the user can view</Text>
|
|
225
|
-
<SearchableSelect
|
|
226
|
-
actions={actions}
|
|
227
|
-
fields={fields}
|
|
228
|
-
items={allAgencyOptions}
|
|
229
|
-
selectedItems={selectedAgencies}
|
|
230
|
-
allSelected={allSelected}
|
|
231
|
-
toggleSelectAllItems={toggleSelectAllAgencies}
|
|
232
|
-
selectItem={selectAgency}
|
|
233
|
-
disabled={selectionDisabled}
|
|
234
|
-
/>
|
|
235
|
-
</FormInputColumn>
|
|
236
|
-
</Box>
|
|
237
|
-
)}
|
|
238
|
-
<Box padding="0">
|
|
239
|
-
<Stack childGap="1rem" direction="row" justify="flex-end">
|
|
240
|
-
<ButtonWithAction
|
|
241
|
-
text="Cancel"
|
|
242
|
-
action={() => {
|
|
243
|
-
if (formType !== CREATE_CLIENT_ADMIN) {
|
|
244
|
-
toggleSelectAllAgencies(false);
|
|
245
|
-
}
|
|
246
|
-
closeForm();
|
|
247
|
-
}}
|
|
248
|
-
variant={"secondary"}
|
|
249
|
-
dataQa="Cancel"
|
|
250
|
-
extraStyles={`margin: 0rem; padding: 0.75rem 1.5rem; border-radius: 4px;`}
|
|
251
|
-
/>
|
|
252
|
-
<ButtonWithAction
|
|
253
|
-
text="Save"
|
|
254
|
-
action={handleSubmit}
|
|
255
|
-
variant="primary"
|
|
256
|
-
dataQa="Save"
|
|
257
|
-
extraStyles={`margin: 0rem; padding: 0.75rem 1.5rem; border-radius: 4px;`}
|
|
258
|
-
/>
|
|
259
|
-
</Stack>
|
|
260
|
-
</Box>
|
|
261
|
-
</Box>
|
|
262
|
-
</FormContainer>
|
|
263
|
-
);
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
export default InternalUserInfoForm;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { createFormState, required, isProbablyEmail } from "redux-freeform";
|
|
2
|
-
|
|
3
|
-
const formConfig = {
|
|
4
|
-
client: {
|
|
5
|
-
validators: []
|
|
6
|
-
},
|
|
7
|
-
firstName: {
|
|
8
|
-
validators: [required()]
|
|
9
|
-
},
|
|
10
|
-
lastName: {
|
|
11
|
-
validators: [required()]
|
|
12
|
-
},
|
|
13
|
-
email: {
|
|
14
|
-
validators: [isProbablyEmail()]
|
|
15
|
-
},
|
|
16
|
-
role: {
|
|
17
|
-
validators: []
|
|
18
|
-
},
|
|
19
|
-
searchTerm: {
|
|
20
|
-
validators: []
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const { reducer, mapStateToProps, mapDispatchToProps } = createFormState(
|
|
25
|
-
formConfig
|
|
26
|
-
);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import InternalUserInfoForm from "./InternalUserInfoForm";
|
|
2
|
-
import {
|
|
3
|
-
reducer,
|
|
4
|
-
mapStateToProps,
|
|
5
|
-
mapDispatchToProps
|
|
6
|
-
} from "./InternalUserInfoForm.state";
|
|
7
|
-
|
|
8
|
-
InternalUserInfoForm.reducer = reducer;
|
|
9
|
-
InternalUserInfoForm.mapStateToProps = mapStateToProps;
|
|
10
|
-
InternalUserInfoForm.mapDispatchToProps = mapDispatchToProps;
|
|
11
|
-
export default InternalUserInfoForm;
|