Skip to content

Commit 2c595d5

Browse files
achmeloJakub Balhar
andauthored
feat: use material in wizard (#2004)
* Initial transfer working for Dialog and Inputs Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Remove Mineral from DialogDropdown Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Use Material in ConfirmDialog Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Dropdown correctly opens Dialog Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Replace YAML VIsualizer elements with Material Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Checkbox is displayed Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Improve visual for the Dialog Dropdown Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Clean visual for dialog buttons Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Improve Dropdown positioning Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Add Arrow Down Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Clean styling on buttons within WIzard Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * Remove Material from the Inputs as dependency Signed-off-by: Jakub Balhar <jakub.balhar@broadcom.net> * working version of wizard nav Signed-off-by: achmelo <a.chmelo@gmail.com> * style tweaks Signed-off-by: achmelo <a.chmelo@gmail.com> * align text to the right Signed-off-by: achmelo <a.chmelo@gmail.com> * fix tests Signed-off-by: achmelo <a.chmelo@gmail.com> * replace enzyme with react testing library where necessary Signed-off-by: achmelo <a.chmelo@gmail.com> * eslint fixes Signed-off-by: achmelo <a.chmelo@gmail.com> * eslint Signed-off-by: achmelo <a.chmelo@gmail.com> * prettier fix Signed-off-by: achmelo <a.chmelo@gmail.com> * remove test file, dep versions, fix display of inputs Signed-off-by: achmelo <a.chmelo@gmail.com> Co-authored-by: Jakub Balhar <jakub.balhar@broadcom.net>
1 parent 7323b48 commit 2c595d5

File tree

15 files changed

+1016
-209
lines changed

15 files changed

+1016
-209
lines changed

api-catalog-ui/frontend/package-lock.json

Lines changed: 638 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-catalog-ui/frontend/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@
7171
"includeFailureMsg": true
7272
},
7373
"devDependencies": {
74+
"@testing-library/dom": "8.11.1",
75+
"@testing-library/jest-dom": "5.16.1",
76+
"@testing-library/react": "12.1.2",
77+
"@testing-library/user-event": "13.5.0",
7478
"ansi-regex": "5.0.1",
7579
"body-parser": "1.18.3",
7680
"concurrently": "5.3.0",

api-catalog-ui/frontend/src/components/Dashboard/Dashboard.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,18 @@ a {
129129
margin-right: 10px;
130130
}
131131

132-
#refresh-api-button {
132+
#refresh-api-button, #onboard-wizard-button, #wizard-done-button, #wizard-cancel-button, #onboard-wizard-button.MuiButton-label, .wizardForm .MuiButton-label, .wizardForm button.MuiButtonBase-root.MuiButton-root.MuiButton-text {
133133
font-size: 16px;
134134
height: 2em;
135135
color: #3272d9;
136136
background-color: #ffffff;
137137
}
138138

139-
#refresh-api-button:hover {
139+
#refresh-api-button:hover, #onboard-wizard-button:hover, #wizard-done-button:hover, #wizard-cancel-button:hover, #onboard-wizard-button.MuiButton-label:hover, .wizardForm .MuiButton-label:hover, .wizardForm button.MuiButtonBase-root.MuiButton-root.MuiButton-text:hover {
140140
background-color: #F4F7FA;
141141
border: none;
142142
}
143143

144+
.MuiButton-root, .MuiButton-label, #onboard-wizard-button.MuiButton-label {
145+
text-transform: capitalize;
146+
}

api-catalog-ui/frontend/src/components/Login/Login.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ form#login-form {
8181
margin: 150px 0px;
8282
}
8383

84-
.MuiButton-label {
84+
.login-object .MuiButton-label {
8585
flex-direction: row;
8686
align-items: flex-start;
8787
padding: 6px 6px 6px 8px;
@@ -107,7 +107,7 @@ form#login-form {
107107
position: static;
108108
}
109109

110-
.MuiButton-label:hover {
110+
.login-object .MuiButton-label:hover {
111111
background-color: rgb(50, 114, 217);
112112
border: none;
113113
}

api-catalog-ui/frontend/src/components/Wizard/ConfirmDialog.jsx

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component } from 'react';
2-
import { Button, Dialog, DialogActions, DialogBody, DialogFooter, DialogHeader, DialogTitle, Text } from 'mineral-ui';
2+
import { Dialog, DialogContent, DialogContentText, DialogTitle, DialogActions, IconButton } from '@material-ui/core';
33
import * as YAML from 'yaml';
44

55
class ConfirmDialog extends Component {
@@ -17,26 +17,22 @@ class ConfirmDialog extends Component {
1717
render() {
1818
const { confirmDialog, serviceId, confirmStaticDefOverride } = this.props;
1919
return (
20-
<Dialog isOpen={confirmDialog} closeOnClickOutside={false}>
21-
<DialogHeader>
22-
<DialogTitle>Are you sure?</DialogTitle>
23-
</DialogHeader>
24-
<DialogBody>
25-
<Text>
20+
<Dialog open={confirmDialog}>
21+
<DialogTitle>Are you sure?</DialogTitle>
22+
<DialogContent>
23+
<DialogContentText>
2624
Static definition with serviceId <code>{serviceId}</code> already exists. Do you wish to
2725
overwrite it?
28-
</Text>
29-
</DialogBody>
30-
<DialogFooter>
31-
<DialogActions>
32-
<Button onClick={confirmStaticDefOverride} size="medium">
33-
No, I'll change my serviceId
34-
</Button>
35-
<Button onClick={this.override} size="medium">
36-
Yes, overwrite
37-
</Button>
38-
</DialogActions>
39-
</DialogFooter>
26+
</DialogContentText>
27+
</DialogContent>
28+
<DialogActions>
29+
<IconButton onClick={confirmStaticDefOverride} size="medium">
30+
No, I'll change my serviceId
31+
</IconButton>
32+
<IconButton onClick={this.override} size="medium">
33+
Yes, overwrite
34+
</IconButton>
35+
</DialogActions>
4036
</Dialog>
4137
);
4238
}

api-catalog-ui/frontend/src/components/Wizard/DialogDropdown.jsx

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@
99
*/
1010

1111
import { Component } from 'react';
12-
import { IconArrowDropDown } from 'mineral-ui-icons';
13-
import { Dropdown } from 'mineral-ui';
14-
import Button from 'mineral-ui/Button';
12+
import { Button, Menu, MenuItem } from '@material-ui/core';
13+
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
1514
import './wizard.css';
1615

1716
export default class DialogDropdown extends Component {
1817
constructor(props) {
1918
super(props);
2019
this.state = {
2120
data: this.props.data,
21+
isOpen: false,
22+
anchorEl: null,
2223
};
2324
this.handleClick = this.handleClick.bind(this);
25+
this.openMenu = this.openMenu.bind(this);
26+
this.closeMenu = this.closeMenu.bind(this);
2427
}
2528

2629
componentDidMount() {
@@ -30,6 +33,7 @@ export default class DialogDropdown extends Component {
3033
handleClick(event) {
3134
this.props.selectEnabler(event.target.innerText);
3235
this.props.toggleWizard();
36+
this.closeMenu();
3337
}
3438

3539
openOnClick() {
@@ -40,16 +44,53 @@ export default class DialogDropdown extends Component {
4044
}
4145
}
4246

47+
openMenu(event) {
48+
this.setState({ isOpen: true, anchorEl: event.target });
49+
}
50+
51+
closeMenu() {
52+
this.setState({ isOpen: false });
53+
}
54+
4355
renderDropdown() {
4456
if (!this.props.visible || !Array.isArray(this.state.data)) {
4557
return null;
4658
}
4759
return (
48-
<Dropdown data={this.state.data}>
49-
<Button id="wizard-YAML-button" size="medium" iconEnd={<IconArrowDropDown />}>
60+
<span>
61+
<Button
62+
aria-controls="wizard-menu"
63+
aria-haspopup="true"
64+
onClick={this.openMenu}
65+
size="medium"
66+
variant="outlined"
67+
id="onboard-wizard-button"
68+
style={{ borderRadius: '0.1875em' }}
69+
endIcon={<KeyboardArrowDownIcon />}
70+
>
5071
Onboard New API
5172
</Button>
52-
</Dropdown>
73+
<Menu
74+
id="wizard-menu"
75+
keepMounted
76+
open={this.state.isOpen}
77+
onClose={this.closeMenu}
78+
anchorEl={this.state.anchorEl}
79+
getContentAnchorEl={null}
80+
anchorOrigin={{
81+
vertical: 'bottom',
82+
horizontal: 'center',
83+
}}
84+
transformOrigin={{
85+
vertical: 'top',
86+
horizontal: 'center',
87+
}}
88+
>
89+
{this.state.data.map(itemType => (
90+
<MenuItem onClick={this.handleClick}>{itemType.text}</MenuItem>
91+
))}
92+
</Menu>
93+
</span>
5394
);
5495
}
5596

api-catalog-ui/frontend/src/components/Wizard/DialogDropdown.test.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
*/
1010
import * as enzyme from 'enzyme';
1111
import DialogDropdown from './DialogDropdown';
12+
import {render, screen} from '@testing-library/react'
13+
import '@testing-library/jest-dom/extend-expect';
14+
1215
describe('>>> DialogDropdown tests', () => {
1316
it('should have "Onboard New API" button', () => {
14-
const wrapper = enzyme.shallow(
17+
render(
1518
<DialogDropdown
1619
visible={true}
1720
data={[{
@@ -23,8 +26,8 @@ describe('>>> DialogDropdown tests', () => {
2326
toggleWizard={jest.fn()}
2427
/>
2528
);
26-
let button = wrapper.find('#wizard-YAML-button');
27-
expect(button.length).toEqual(1);
29+
const button = screen.getByRole('button');
30+
expect(button).toBeInTheDocument();
2831
});
2932
it('should not have "Onboard New API" button', () => {
3033
const wrapper = enzyme.shallow(

api-catalog-ui/frontend/src/components/Wizard/WizardComponents/WizardInputs.jsx

Lines changed: 55 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@
88
* Copyright Contributors to the Zowe Project.
99
*/
1010
import { Component } from 'react';
11-
import { Checkbox, FormField, Select, Tooltip } from 'mineral-ui';
12-
import TextInput from 'mineral-ui/TextInput';
13-
import Button from 'mineral-ui/Button';
14-
import { IconDelete } from 'mineral-ui-icons';
11+
import {
12+
Button,
13+
Checkbox,
14+
FormControl,
15+
FormControlLabel,
16+
FormHelperText,
17+
InputLabel,
18+
MenuItem,
19+
Select,
20+
Input,
21+
Tooltip,
22+
} from '@material-ui/core';
23+
import DeleteIcon from '@material-ui/icons/Delete';
1524

1625
class WizardInputs extends Component {
1726
constructor(props) {
@@ -27,11 +36,11 @@ class WizardInputs extends Component {
2736
* When users fills out an input the inputData object is updated with the new information
2837
* @param event object containing input's name, value and its data-index attr.
2938
*/
30-
handleInputChange = event => {
39+
handleInputChange = (event, index) => {
3140
const { name, checked } = event.target;
3241
let { value } = event.target;
3342
const objectToChange = this.props.data;
34-
const arrIndex = parseInt(event.target.getAttribute('data-index'));
43+
const arrIndex = typeof index !== 'undefined' ? index : parseInt(event.target.getAttribute('data-index'));
3544
const { maxLength, lowercase, regexRestriction, validUrl } = objectToChange.content[arrIndex][name];
3645
const prevValue = objectToChange.content[arrIndex][name].value;
3746
if (name === 'serviceId') {
@@ -203,9 +212,10 @@ class WizardInputs extends Component {
203212
* Select's onChange event contains only the changed value, so we create a usable event ourselves
204213
* @param entry each item's basic info - name value and index - we create event from that
205214
*/
206-
handleSelect = entry => {
207-
const { name, value, index } = entry;
208-
this.interferenceInjection({ title: value, name, index });
215+
handleSelect = (entry, values) => {
216+
const { index, itemKey } = values;
217+
const { value } = entry.target;
218+
this.interferenceInjection({ title: value, name: itemKey, index });
209219
};
210220

211221
/**
@@ -336,7 +346,7 @@ class WizardInputs extends Component {
336346
variant="danger"
337347
minimal
338348
size="medium"
339-
iconStart={!this.state[`delBtn${index}`] ? <IconDelete /> : undefined}
349+
iconStart={!this.state[`delBtn${index}`] ? <DeleteIcon /> : undefined}
340350
name={index}
341351
onClick={this.handleDelete}
342352
>
@@ -379,19 +389,7 @@ class WizardInputs extends Component {
379389
* @returns {JSX.Element} returns the input element
380390
*/
381391
renderInputElement(itemKey, index, inputNode) {
382-
const {
383-
question,
384-
value,
385-
empty,
386-
optional,
387-
options,
388-
maxLength,
389-
lowercase,
390-
tooltip,
391-
problem,
392-
type,
393-
disabled,
394-
} = inputNode;
392+
const { question, value, optional, options, maxLength, lowercase, tooltip, disabled } = inputNode;
395393
let caption = '';
396394
if (optional) {
397395
caption += 'Optional field; ';
@@ -407,61 +405,52 @@ class WizardInputs extends Component {
407405
} else {
408406
caption = undefined;
409407
}
410-
const error = empty || problem;
411-
const variant = error ? 'danger' : undefined;
412408
if (typeof value === 'boolean') {
413409
return (
414-
<Checkbox
415-
className="wCheckBox"
410+
<FormControlLabel
411+
control={
412+
<Checkbox
413+
className="wCheckBox"
414+
checked={value}
415+
onChange={event => this.handleInputChange(event, index)}
416+
name={itemKey}
417+
/>
418+
}
416419
label={question}
417-
checked={value}
418-
onChange={this.handleInputChange}
419-
name={itemKey}
420-
data-index={index}
420+
labelPlacement="bottom"
421421
/>
422422
);
423423
}
424424
if (Array.isArray(options)) {
425425
return (
426-
<FormField
427-
className="formField"
428-
input={Select}
429-
size="large"
430-
placeholder={itemKey}
431-
selectedItem={{ text: value }}
432-
label={question}
433-
variant={variant}
434-
caption={caption}
435-
data={options.map(entry => ({
436-
text: entry,
437-
onClick: () => this.handleSelect({ name: itemKey, index, value: entry }),
438-
}))}
439-
disabled={disabled}
440-
/>
426+
<FormControl className="formField" disabled={disabled}>
427+
<InputLabel shrink>{question}</InputLabel>
428+
<Select id={itemKey} value={value} onChange={event => this.handleSelect(event, { index, itemKey })}>
429+
{options.map(entry => (
430+
<MenuItem value={entry}>{entry}</MenuItem>
431+
))}
432+
</Select>
433+
</FormControl>
441434
);
442435
}
443-
const disableTooltip = false;
444436
let finalTooltip = tooltip;
445437
if (tooltip === undefined) {
446438
finalTooltip = 'filler';
447439
}
440+
const captionId = `my-helper${itemKey}`;
448441
return (
449-
<Tooltip className="wizardTooltip" content={finalTooltip} disabled={disableTooltip}>
450-
<FormField
451-
type={type}
452-
className="wizardFormFields"
453-
input={TextInput}
454-
size="large"
455-
name={itemKey}
456-
onChange={this.handleInputChange}
457-
data-index={index}
458-
placeholder={itemKey}
459-
value={value}
460-
label={question}
461-
variant={variant}
462-
caption={caption}
463-
disabled={disabled}
464-
/>
442+
<Tooltip className="wizardTooltip" title={finalTooltip}>
443+
<FormControl className="wizardFormFields" disabled={disabled}>
444+
<InputLabel shrink>{question}</InputLabel>
445+
<Input
446+
id={itemKey}
447+
name={itemKey}
448+
value={value}
449+
onChange={event => this.handleInputChange(event, index)}
450+
aria-describedby={captionId}
451+
/>
452+
<FormHelperText id={captionId}>{caption}</FormHelperText>
453+
</FormControl>
465454
</Tooltip>
466455
);
467456
}
@@ -472,7 +461,9 @@ class WizardInputs extends Component {
472461
<div className="wizardForm">
473462
{this.loadInputs()}
474463
{multiple && typeof isMinion === 'undefined' ? (
475-
<Button onClick={this.addFieldsToCurrentCategory}>Add more fields</Button>
464+
<Button onClick={this.addFieldsToCurrentCategory} style={{ borderRadius: '0.1875em' }}>
465+
Add more fields
466+
</Button>
476467
) : null}
477468
</div>
478469
);

0 commit comments

Comments
 (0)