-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master' into essntl-4194-group…
…s-table
- Loading branch information
Showing
20 changed files
with
2,157 additions
and
1,256 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/components/InventoryGroups/Modals/CreateGroupModal.cy.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* eslint-disable camelcase */ | ||
import React from 'react'; | ||
import { mount } from '@cypress/react'; | ||
import CreateGroupModal from './CreateGroupModal'; | ||
import { | ||
TEXT_INPUT | ||
} from '@redhat-cloud-services/frontend-components-utilities'; | ||
import { Provider } from 'react-redux'; | ||
import { MemoryRouter } from 'react-router-dom'; | ||
import { getStore } from '../../../store'; | ||
|
||
const mockResponse = [ | ||
{ | ||
count: 50, | ||
page: 20, | ||
per_page: 20, | ||
total: 50, | ||
results: [ | ||
{ | ||
created_at: '2020-02-09T10:16:07.996Z', | ||
host_ids: ['bA6deCFc19564430AB814bf8F70E8cEf'], | ||
id: '3f01b55457674041b75e41829bcee1dca', | ||
name: 'sre-group0', | ||
updated_at: '2020-02-09T10:16:07.996Z' | ||
}, | ||
{ | ||
created_at: '2020-02-09T10:16:07.996Z', | ||
host_ids: ['bA6deCFc19564430AB814bf8F70E8cEf'], | ||
id: '3f01b55457674041b75e41829bcee1dca', | ||
name: 'sre-group1', | ||
updated_at: '2020-02-09T10:16:07.996Z' | ||
}, | ||
{ | ||
created_at: '2020-02-09T10:16:07.996Z', | ||
host_ids: ['bA6deCFc19564430AB814bf8F70E8cEf'], | ||
id: '3f01b55457674041b75e41829bcee1dca', | ||
name: 'sre-group2', | ||
updated_at: '2020-02-09T10:16:07.996Z' | ||
}, | ||
{ | ||
created_at: '2020-02-09T10:16:07.996Z', | ||
host_ids: ['bA6deCFc19564430AB814bf8F70E8cEf'], | ||
id: '3f01b55457674041b75e41829bcee1dca', | ||
name: 'sre-group3', | ||
updated_at: '2020-02-09T10:16:07.996Z' | ||
} | ||
] | ||
} | ||
]; | ||
|
||
describe('Create Group Modal', () => { | ||
before(() => { | ||
cy.window().then(window => window.insights = { | ||
chrome: { | ||
isProd: false, | ||
auth: { | ||
getUser: () => { | ||
return Promise.resolve({}); | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
beforeEach(() => { | ||
|
||
cy.intercept('POST', '**/api/inventory/v1/groups', { | ||
statusCode: 504 | ||
}).as('create_group'); | ||
cy.intercept('GET', '**/api/inventory/v1/groups', { | ||
statusCode: 200, body: { | ||
...mockResponse | ||
} | ||
}).as('validate'); | ||
|
||
mount( | ||
<MemoryRouter> | ||
<Provider store={getStore()}> | ||
<CreateGroupModal isModalOpen={true} reloadData={() => console.log('data reloaded')}/> | ||
</Provider> | ||
</MemoryRouter> | ||
); | ||
}); | ||
|
||
it('Input is fillable and firing a validation request that succeeds', () => { | ||
cy.get(TEXT_INPUT).type('sre-group0'); | ||
cy.wait('@validate').then((xhr) => { | ||
expect(xhr.request.url).to.contain('groups');} | ||
); | ||
cy.get(`button[type="submit"]`).should('have.attr', 'aria-disabled', 'true'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import React, { useCallback, useMemo } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { createGroupSchema } from './ModalSchemas/schemes'; | ||
import Modal from './Modal'; | ||
import apiWithToast from '../utils/apiWithToast'; | ||
import { | ||
createGroup, | ||
validateGroupName | ||
} from '../utils/api'; | ||
import { useDispatch } from 'react-redux'; | ||
import awesomeDebouncePromise from 'awesome-debounce-promise'; | ||
|
||
const CreateGroupModal = ({ | ||
isModalOpen, | ||
setIsModalOpen, | ||
reloadData | ||
}) => { | ||
const dispatch = useDispatch(); | ||
|
||
const handleCreateGroup = useCallback( | ||
(values) => { | ||
const statusMessages = { | ||
onSuccess: { | ||
title: 'Success', | ||
description: `${values.name} has been created successfully` | ||
}, | ||
onError: { title: 'Error', description: 'Failed to create group' } | ||
}; | ||
return apiWithToast(dispatch, () => createGroup(values), statusMessages); | ||
}, | ||
[isModalOpen] | ||
); | ||
|
||
const schema = useMemo(() => { | ||
const check = async (value) => { | ||
const results = await validateGroupName(value); | ||
if (results === true) { | ||
throw 'Group name already exists'; | ||
} | ||
|
||
return undefined; | ||
}; | ||
|
||
// eslint-disable-next-line new-cap | ||
const d = awesomeDebouncePromise(check, 500, { onlyResolvesLast: false }); | ||
return createGroupSchema(d); | ||
}, []); | ||
|
||
return ( | ||
<Modal | ||
data-testid="create-group-modal" | ||
isModalOpen={isModalOpen} | ||
closeModal={() => setIsModalOpen(false)} | ||
title="Create group" | ||
submitLabel="Create" | ||
schema={schema} | ||
reloadData={reloadData} | ||
onSubmit={handleCreateGroup} | ||
/> | ||
); | ||
}; | ||
|
||
export default CreateGroupModal; | ||
|
||
CreateGroupModal.propTypes = { | ||
isModalOpen: PropTypes.bool, | ||
setIsModalOpen: PropTypes.func, | ||
reloadData: PropTypes.func, | ||
deviceIds: PropTypes.array, | ||
isOpen: PropTypes.bool | ||
}; |
24 changes: 24 additions & 0 deletions
24
src/components/InventoryGroups/Modals/CreateGroupModal.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import { getStore } from '../../../store'; | ||
import { Provider } from 'react-redux'; | ||
import { MemoryRouter } from 'react-router-dom'; | ||
|
||
import CreateGroupModal from './CreateGroupModal'; | ||
|
||
describe('CreateGroupModal', () => { | ||
it('renders correctly', () => { | ||
render( | ||
<MemoryRouter> | ||
<Provider store={getStore()}> | ||
<CreateGroupModal isModalOpen={true} reloadData={() => console.log('data reloaded')}/> | ||
</Provider> | ||
</MemoryRouter> | ||
); | ||
expect(screen.getByRole('heading', { name: /Create group/ })).toBeInTheDocument(); | ||
expect(screen.getByRole('textbox')).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: /Create/ })).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: /Cancel/ })).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import React from 'react'; | ||
import { Modal } from '@patternfly/react-core'; | ||
import FormRenderer from '@data-driven-forms/react-form-renderer/form-renderer'; | ||
import FormTemplate from '@data-driven-forms/pf4-component-mapper/form-template'; | ||
import componentMapper from '@data-driven-forms/pf4-component-mapper/component-mapper'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const RepoModal = ({ | ||
isModalOpen, | ||
title, | ||
titleIconVariant, | ||
closeModal, | ||
submitLabel, | ||
schema, | ||
initialValues, | ||
variant, | ||
reloadData, | ||
size, | ||
onSubmit | ||
}) => { | ||
return ( | ||
<Modal | ||
ouiaId="group-modal" | ||
variant={size ?? 'small'} | ||
title={title} | ||
titleIconVariant={titleIconVariant ?? null} | ||
isOpen={isModalOpen} | ||
onClose={closeModal} | ||
> | ||
<FormRenderer | ||
schema={schema} | ||
FormTemplate={(props) => ( | ||
<FormTemplate | ||
{...props} | ||
submitLabel={submitLabel} | ||
disableSubmit={['invalid']} | ||
buttonsProps={{ | ||
submit: { variant } | ||
}} | ||
/> | ||
)} | ||
initialValues={initialValues} | ||
componentMapper={componentMapper} | ||
//reload comes from the table and fetches fresh data | ||
onSubmit={async (values) => { | ||
await onSubmit(values); | ||
setTimeout(async () => await reloadData(), 500); | ||
closeModal(); | ||
}} | ||
onCancel={() => closeModal()} | ||
/> | ||
</Modal> | ||
); | ||
}; | ||
|
||
RepoModal.propTypes = { | ||
isModalOpen: PropTypes.bool, | ||
title: PropTypes.string, | ||
closeModal: PropTypes.func, | ||
reloadData: PropTypes.func, | ||
submitLabel: PropTypes.string, | ||
schema: PropTypes.object, | ||
initialValues: PropTypes.object, | ||
variant: PropTypes.string, | ||
onSubmit: PropTypes.func, | ||
size: PropTypes.string, | ||
additionalMappers: PropTypes.object, | ||
titleIconVariant: PropTypes.any, | ||
validatorMapper: PropTypes.object | ||
}; | ||
|
||
export default RepoModal; |
24 changes: 24 additions & 0 deletions
24
src/components/InventoryGroups/Modals/ModalSchemas/schemes.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import validatorTypes from '@data-driven-forms/react-form-renderer/validator-types'; | ||
import componentTypes from '@data-driven-forms/react-form-renderer/component-types'; | ||
import { nameValidator } from '../../helpers/validate'; | ||
|
||
export const createGroupSchema = (namePresenceValidator) => ({ | ||
fields: [ | ||
{ | ||
component: componentTypes.TEXT_FIELD, | ||
name: 'name', | ||
label: 'Group name', | ||
helperText: | ||
'Can only contain letters, numbers, spaces, hyphens ( - ), and underscores( _ ).', | ||
isRequired: true, | ||
autoFocus: true, | ||
validate: [ | ||
// async validator has to be first in the list | ||
namePresenceValidator, | ||
{ type: validatorTypes.REQUIRED }, | ||
{ type: validatorTypes.MAX_LENGTH, threshold: 50 }, | ||
nameValidator | ||
] | ||
} | ||
] | ||
}); |
Oops, something went wrong.