diff options
author | softwarefactory-project-zuul[bot] <33884098+softwarefactory-project-zuul[bot]@users.noreply.github.com> | 2019-07-02 00:57:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-02 00:57:50 +0200 |
commit | 4fb055345d8806cd7b76420dca5ddca089c71bab (patch) | |
tree | 7e87823162aaf718725087cd42a290b54bc744c5 | |
parent | Merge pull request #4200 from ansible/jakemcdermott-contrib-formatter (diff) | |
parent | Prettify files (diff) | |
download | awx-4fb055345d8806cd7b76420dca5ddca089c71bab.tar.xz awx-4fb055345d8806cd7b76420dca5ddca089c71bab.zip |
Merge pull request #4199 from mabashian/264-notification-type-column
Show notification type in its own column
Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
7 files changed, 305 insertions, 202 deletions
diff --git a/awx/ui_next/src/api/mixins/Notifications.mixin.js b/awx/ui_next/src/api/mixins/Notifications.mixin.js index 9072e30874..eccadc5dc2 100644 --- a/awx/ui_next/src/api/mixins/Notifications.mixin.js +++ b/awx/ui_next/src/api/mixins/Notifications.mixin.js @@ -1,5 +1,9 @@ const NotificationsMixin = parent => class extends parent { + readOptionsNotificationTemplates(id) { + return this.http.options(`${this.baseUrl}${id}/notification_templates/`); + } + readNotificationTemplates(id, params = {}) { return this.http.get(`${this.baseUrl}${id}/notification_templates/`, { params, diff --git a/awx/ui_next/src/components/NotificationsList/NotificationListItem.jsx b/awx/ui_next/src/components/NotificationsList/NotificationListItem.jsx index f8e243ad39..9578aec49e 100644 --- a/awx/ui_next/src/components/NotificationsList/NotificationListItem.jsx +++ b/awx/ui_next/src/components/NotificationsList/NotificationListItem.jsx @@ -4,7 +4,6 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Link } from 'react-router-dom'; import { - Badge, Switch as PFSwitch, DataListItem, DataListItemRow, @@ -39,6 +38,7 @@ function NotificationListItem(props) { errorTurnedOn, toggleNotification, i18n, + typeLabels, } = props; return ( @@ -60,9 +60,9 @@ function NotificationListItem(props) { {notification.name} </b> </Link> - <Badge css="text-transform: capitalize;" isRead> - {notification.notification_type} - </Badge> + </DataListCell>, + <DataListCell key="type"> + {typeLabels[notification.notification_type]} </DataListCell>, <DataListCell righthalf="true" key="toggles"> <Switch @@ -108,6 +108,7 @@ NotificationListItem.propTypes = { errorTurnedOn: bool, successTurnedOn: bool, toggleNotification: func.isRequired, + typeLabels: shape().isRequired, }; NotificationListItem.defaultProps = { diff --git a/awx/ui_next/src/components/NotificationsList/NotificationListItem.test.jsx b/awx/ui_next/src/components/NotificationsList/NotificationListItem.test.jsx index 8c2d5afd47..74d1f6a070 100644 --- a/awx/ui_next/src/components/NotificationsList/NotificationListItem.test.jsx +++ b/awx/ui_next/src/components/NotificationsList/NotificationListItem.test.jsx @@ -6,6 +6,16 @@ describe('<NotificationListItem canToggleNotifications />', () => { let wrapper; let toggleNotification; + const mockNotif = { + id: 9000, + name: 'Foo', + notification_type: 'slack', + }; + + const typeLabels = { + slack: 'Slack', + }; + beforeEach(() => { toggleNotification = jest.fn(); }); @@ -18,34 +28,45 @@ describe('<NotificationListItem canToggleNotifications />', () => { jest.clearAllMocks(); }); - test('initially renders succesfully', () => { + test('initially renders succesfully and displays correct label', () => { wrapper = mountWithContexts( <NotificationListItem - notification={{ - id: 9000, - name: 'Foo', - notification_type: 'slack', - }} + notification={mockNotif} toggleNotification={toggleNotification} detailUrl="/foo" canToggleNotifications + typeLabels={typeLabels} /> ); expect(wrapper.find('NotificationListItem')).toMatchSnapshot(); }); + test('displays correct label in correct column', () => { + wrapper = mountWithContexts( + <NotificationListItem + notification={mockNotif} + toggleNotification={toggleNotification} + detailUrl="/foo" + canToggleNotifications + typeLabels={typeLabels} + /> + ); + const typeCell = wrapper + .find('DataListCell') + .at(1) + .find('div'); + expect(typeCell.text()).toBe('Slack'); + }); + test('handles success click when toggle is on', () => { wrapper = mountWithContexts( <NotificationListItem - notification={{ - id: 9000, - name: 'Foo', - notification_type: 'slack', - }} + notification={mockNotif} successTurnedOn toggleNotification={toggleNotification} detailUrl="/foo" canToggleNotifications + typeLabels={typeLabels} /> ); wrapper @@ -59,15 +80,12 @@ describe('<NotificationListItem canToggleNotifications />', () => { test('handles success click when toggle is off', () => { wrapper = mountWithContexts( <NotificationListItem - notification={{ - id: 9000, - name: 'Foo', - notification_type: 'slack', - }} + notification={mockNotif} successTurnedOn={false} toggleNotification={toggleNotification} detailUrl="/foo" canToggleNotifications + typeLabels={typeLabels} /> ); wrapper @@ -81,15 +99,12 @@ describe('<NotificationListItem canToggleNotifications />', () => { test('handles error click when toggle is on', () => { wrapper = mountWithContexts( <NotificationListItem - notification={{ - id: 9000, - name: 'Foo', - notification_type: 'slack', - }} + notification={mockNotif} errorTurnedOn toggleNotification={toggleNotification} detailUrl="/foo" canToggleNotifications + typeLabels={typeLabels} /> ); wrapper @@ -103,15 +118,12 @@ describe('<NotificationListItem canToggleNotifications />', () => { test('handles error click when toggle is off', () => { wrapper = mountWithContexts( <NotificationListItem - notification={{ - id: 9000, - name: 'Foo', - notification_type: 'slack', - }} + notification={mockNotif} errorTurnedOn={false} toggleNotification={toggleNotification} detailUrl="/foo" canToggleNotifications + typeLabels={typeLabels} /> ); wrapper diff --git a/awx/ui_next/src/components/NotificationsList/__snapshots__/NotificationListItem.test.jsx.snap b/awx/ui_next/src/components/NotificationsList/__snapshots__/NotificationListItem.test.jsx.snap index 8f17dfe0c1..8a147d78c8 100644 --- a/awx/ui_next/src/components/NotificationsList/__snapshots__/NotificationListItem.test.jsx.snap +++ b/awx/ui_next/src/components/NotificationsList/__snapshots__/NotificationListItem.test.jsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`<NotificationListItem canToggleNotifications /> initially renders succesfully 1`] = ` +exports[`<NotificationListItem canToggleNotifications /> initially renders succesfully and displays correct label 1`] = ` <NotificationListItem canToggleNotifications={true} detailUrl="/foo" @@ -15,6 +15,11 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe } successTurnedOn={false} toggleNotification={[MockFunction]} + typeLabels={ + Object { + "slack": "Slack", + } + } > <DataListItem aria-labelledby="items-list-item-9000" @@ -52,11 +57,9 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe Foo </b> </ForwardRef> - <ForwardRef - isRead={true} - > - slack - </ForwardRef> + </ForwardRef>, + <ForwardRef> + Slack </ForwardRef>, <ForwardRef righthalf="true" @@ -189,47 +192,55 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe </Link> </StyledComponent> </Styled(Link)> - <Styled(Badge) - isRead={true} - > - <StyledComponent - forwardedComponent={ - Object { - "$$typeof": Symbol(react.forward_ref), - "attrs": Array [], - "componentStyle": ComponentStyle { - "componentId": "sc-bwzfXH", - "isStatic": true, - "lastClassName": "chTbOZ", - "rules": Array [ - "text-transform: capitalize;", - ], - }, - "displayName": "Styled(Badge)", - "foldedComponentIds": Array [], - "render": [Function], - "styledComponentId": "sc-bwzfXH", - "target": [Function], - "toString": [Function], - "warnTooManyClasses": [Function], - "withComponent": [Function], - } - } - forwardedRef={null} - isRead={true} - > - <Badge - className="sc-bwzfXH chTbOZ" - isRead={true} - > - <span - className="pf-c-badge pf-m-read sc-bwzfXH chTbOZ" - > - slack - </span> - </Badge> - </StyledComponent> - </Styled(Badge)> + </div> + </DataListCell> + </StyledComponent> + </NotificationListItem__DataListCell> + <NotificationListItem__DataListCell + key="type" + > + <StyledComponent + forwardedComponent={ + Object { + "$$typeof": Symbol(react.forward_ref), + "attrs": Array [], + "componentStyle": ComponentStyle { + "componentId": "NotificationListItem__DataListCell-j7c411-0", + "isStatic": false, + "lastClassName": "hoXOpW", + "rules": Array [ + "display:flex;justify-content:", + [Function], + ";padding-bottom:", + [Function], + ";@media screen and (min-width:768px){justify-content:", + [Function], + ";padding-bottom:0;}", + ], + }, + "displayName": "NotificationListItem__DataListCell", + "foldedComponentIds": Array [], + "render": [Function], + "styledComponentId": "NotificationListItem__DataListCell-j7c411-0", + "target": [Function], + "toString": [Function], + "warnTooManyClasses": [Function], + "withComponent": [Function], + } + } + forwardedRef={null} + > + <DataListCell + alignRight={false} + className="NotificationListItem__DataListCell-j7c411-0 kIdLtz" + isFilled={true} + isIcon={false} + width={1} + > + <div + className="pf-c-data-list__cell NotificationListItem__DataListCell-j7c411-0 kIdLtz" + > + Slack </div> </DataListCell> </StyledComponent> diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx index 0e9b24e353..ec0334d3a9 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx @@ -35,6 +35,7 @@ class OrganizationNotifications extends Component { notifications: [], successTemplateIds: [], errorTemplateIds: [], + typeLabels: null, }; this.handleNotificationToggle = this.handleNotificationToggle.bind(this); this.handleNotificationErrorClose = this.handleNotificationErrorClose.bind( @@ -56,13 +57,23 @@ class OrganizationNotifications extends Component { async loadNotifications() { const { id, location } = this.props; + const { typeLabels } = this.state; const params = parseNamespacedQueryString(QS_CONFIG, location.search); + const promises = [OrganizationsAPI.readNotificationTemplates(id, params)]; + + if (!typeLabels) { + promises.push(OrganizationsAPI.readOptionsNotificationTemplates(id)); + } + this.setState({ contentError: null, hasContentLoading: true }); try { - const { - data: { count: itemCount = 0, results: notifications = [] }, - } = await OrganizationsAPI.readNotificationTemplates(id, params); + const [ + { + data: { count: itemCount = 0, results: notifications = [] }, + }, + optionsResponse, + ] = await Promise.all(promises); let idMatchParams; if (notifications.length > 0) { @@ -79,12 +90,31 @@ class OrganizationNotifications extends Component { OrganizationsAPI.readNotificationTemplatesError(id, idMatchParams), ]); - this.setState({ + const stateToUpdate = { itemCount, notifications, successTemplateIds: successTemplates.results.map(s => s.id), errorTemplateIds: errorTemplates.results.map(e => e.id), - }); + }; + + if (!typeLabels) { + const { + data: { + actions: { + GET: { + notification_type: { choices }, + }, + }, + }, + } = optionsResponse; + // The structure of choices looks like [['slack', 'Slack'], ['email', 'Email'], ...] + stateToUpdate.typeLabels = choices.reduce( + (map, notifType) => ({ ...map, [notifType[0]]: notifType[1] }), + {} + ); + } + + this.setState(stateToUpdate); } catch (err) { this.setState({ contentError: err }); } finally { @@ -148,6 +178,7 @@ class OrganizationNotifications extends Component { notifications, successTemplateIds, errorTemplateIds, + typeLabels, } = this.state; return ( @@ -169,6 +200,7 @@ class OrganizationNotifications extends Component { toggleNotification={this.handleNotificationToggle} errorTurnedOn={errorTemplateIds.includes(notification.id)} successTurnedOn={successTemplateIds.includes(notification.id)} + typeLabels={typeLabels} /> )} /> diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.test.jsx b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.test.jsx index a023a157a7..6aa6ee12d4 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.test.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.test.jsx @@ -8,26 +8,37 @@ import OrganizationNotifications from './OrganizationNotifications'; jest.mock('@api'); describe('<OrganizationNotifications />', () => { - let data; + const data = { + count: 2, + results: [ + { + id: 1, + name: 'Notification one', + url: '/api/v2/notification_templates/1/', + notification_type: 'email', + }, + { + id: 2, + name: 'Notification two', + url: '/api/v2/notification_templates/2/', + notification_type: 'email', + }, + ], + }; + + OrganizationsAPI.readOptionsNotificationTemplates.mockReturnValue({ + data: { + actions: { + GET: { + notification_type: { + choices: [['email', 'Email']], + }, + }, + }, + }, + }); beforeEach(() => { - data = { - count: 2, - results: [ - { - id: 1, - name: 'Notification one', - url: '/api/v2/notification_templates/1/', - notification_type: 'email', - }, - { - id: 2, - name: 'Notification two', - url: '/api/v2/notification_templates/2/', - notification_type: 'email', - }, - ], - }; OrganizationsAPI.readNotificationTemplates.mockReturnValue({ data }); OrganizationsAPI.readNotificationTemplatesSuccess.mockReturnValue({ data: { results: [{ id: 1 }] }, diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap index 1e0c33d06d..03ce55e487 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap @@ -410,9 +410,9 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` "$$typeof": Symbol(react.forward_ref), "attrs": Array [], "componentStyle": ComponentStyle { - "componentId": "sc-bxivhb", + "componentId": "sc-htpNat", "isStatic": true, - "lastClassName": "gYEJOJ", + "lastClassName": "dqEVhr", "rules": Array [ "flex-grow: 1;", ], @@ -420,7 +420,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` "displayName": "Styled(ToolbarItem)", "foldedComponentIds": Array [], "render": [Function], - "styledComponentId": "sc-bxivhb", + "styledComponentId": "sc-htpNat", "target": [Function], "toString": [Function], "warnTooManyClasses": [Function], @@ -430,10 +430,10 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` forwardedRef={null} > <ToolbarItem - className="sc-bxivhb gYEJOJ" + className="sc-htpNat dqEVhr" > <div - className="pf-l-toolbar__item sc-bxivhb gYEJOJ" + className="pf-l-toolbar__item sc-htpNat dqEVhr" > <WithI18n columns={ @@ -1441,9 +1441,9 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` "$$typeof": Symbol(react.forward_ref), "attrs": Array [], "componentStyle": ComponentStyle { - "componentId": "sc-htpNat", + "componentId": "sc-bwzfXH", "isStatic": true, - "lastClassName": "jWbbwS", + "lastClassName": "iNPUwu", "rules": Array [ "padding: 0;", ], @@ -1451,7 +1451,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` "displayName": "Styled(Button)", "foldedComponentIds": Array [], "render": [Function], - "styledComponentId": "sc-htpNat", + "styledComponentId": "sc-bwzfXH", "target": [Function], "toString": [Function], "warnTooManyClasses": [Function], @@ -1464,7 +1464,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` > <Button aria-label="Sort" - className="sc-htpNat jWbbwS" + className="sc-bwzfXH iNPUwu" component="button" isActive={false} isBlock={false} @@ -1479,7 +1479,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` <button aria-disabled={null} aria-label="Sort" - className="pf-c-button pf-m-plain sc-htpNat jWbbwS" + className="pf-c-button pf-m-plain sc-bwzfXH iNPUwu" disabled={false} onClick={[Function]} tabIndex={null} @@ -1619,6 +1619,11 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` } successTurnedOn={true} toggleNotification={[Function]} + typeLabels={ + Object { + "email": "Email", + } + } > <I18n update={true} @@ -1639,6 +1644,11 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` } successTurnedOn={true} toggleNotification={[Function]} + typeLabels={ + Object { + "email": "Email", + } + } > <DataListItem aria-labelledby="items-list-item-1" @@ -1676,11 +1686,9 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` Notification one </b> </ForwardRef> - <ForwardRef - isRead={true} - > - email - </ForwardRef> + </ForwardRef>, + <ForwardRef> + Email </ForwardRef>, <ForwardRef righthalf="true" @@ -1813,47 +1821,55 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` </Link> </StyledComponent> </Styled(Link)> - <Styled(Badge) - isRead={true} - > - <StyledComponent - forwardedComponent={ - Object { - "$$typeof": Symbol(react.forward_ref), - "attrs": Array [], - "componentStyle": ComponentStyle { - "componentId": "sc-bwzfXH", - "isStatic": true, - "lastClassName": "chTbOZ", - "rules": Array [ - "text-transform: capitalize;", - ], - }, - "displayName": "Styled(Badge)", - "foldedComponentIds": Array [], - "render": [Function], - "styledComponentId": "sc-bwzfXH", - "target": [Function], - "toString": [Function], - "warnTooManyClasses": [Function], - "withComponent": [Function], - } - } - forwardedRef={null} - isRead={true} - > - <Badge - className="sc-bwzfXH chTbOZ" - isRead={true} - > - <span - className="pf-c-badge pf-m-read sc-bwzfXH chTbOZ" - > - email - </span> - </Badge> - </StyledComponent> - </Styled(Badge)> + </div> + </DataListCell> + </StyledComponent> + </NotificationListItem__DataListCell> + <NotificationListItem__DataListCell + key="type" + > + <StyledComponent + forwardedComponent={ + Object { + "$$typeof": Symbol(react.forward_ref), + "attrs": Array [], + "componentStyle": ComponentStyle { + "componentId": "NotificationListItem__DataListCell-j7c411-0", + "isStatic": false, + "lastClassName": "hoXOpW", + "rules": Array [ + "display:flex;justify-content:", + [Function], + ";padding-bottom:", + [Function], + ";@media screen and (min-width:768px){justify-content:", + [Function], + ";padding-bottom:0;}", + ], + }, + "displayName": "NotificationListItem__DataListCell", + "foldedComponentIds": Array [], + "render": [Function], + "styledComponentId": "NotificationListItem__DataListCell-j7c411-0", + "target": [Function], + "toString": [Function], + "warnTooManyClasses": [Function], + "withComponent": [Function], + } + } + forwardedRef={null} + > + <DataListCell + alignRight={false} + className="NotificationListItem__DataListCell-j7c411-0 kIdLtz" + isFilled={true} + isIcon={false} + width={1} + > + <div + className="pf-c-data-list__cell NotificationListItem__DataListCell-j7c411-0 kIdLtz" + > + Email </div> </DataListCell> </StyledComponent> @@ -2094,6 +2110,11 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` } successTurnedOn={false} toggleNotification={[Function]} + typeLabels={ + Object { + "email": "Email", + } + } > <I18n update={true} @@ -2114,6 +2135,11 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` } successTurnedOn={false} toggleNotification={[Function]} + typeLabels={ + Object { + "email": "Email", + } + } > <DataListItem aria-labelledby="items-list-item-2" @@ -2151,11 +2177,9 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` Notification two </b> </ForwardRef> - <ForwardRef - isRead={true} - > - email - </ForwardRef> + </ForwardRef>, + <ForwardRef> + Email </ForwardRef>, <ForwardRef righthalf="true" @@ -2288,47 +2312,55 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = ` </Link> </StyledComponent> </Styled(Link)> - <Styled(Badge) - isRead={true} - > - <StyledComponent - forwardedComponent={ - Object { - "$$typeof": Symbol(react.forward_ref), - "attrs": Array [], - "componentStyle": ComponentStyle { - "componentId": "sc-bwzfXH", - "isStatic": true, - "lastClassName": "chTbOZ", - "rules": Array [ - "text-transform: capitalize;", - ], - }, - "displayName": "Styled(Badge)", - "foldedComponentIds": Array [], - "render": [Function], - "styledComponentId": "sc-bwzfXH", - "target": [Function], - "toString": [Function], - "warnTooManyClasses": [Function], - "withComponent": [Function], - } - } - forwardedRef={null} - isRead={true} - > - <Badge - className="sc-bwzfXH chTbOZ" - isRead={true} - > - <span - className="pf-c-badge pf-m-read sc-bwzfXH chTbOZ" - > - email - </span> - </Badge> - </StyledComponent> - </Styled(Badge)> + </div> + </DataListCell> + </StyledComponent> + </NotificationListItem__DataListCell> + <NotificationListItem__DataListCell + key="type" + > + <StyledComponent + forwardedComponent={ + Object { + "$$typeof": Symbol(react.forward_ref), + "attrs": Array [], + "componentStyle": ComponentStyle { + "componentId": "NotificationListItem__DataListCell-j7c411-0", + "isStatic": false, + "lastClassName": "hoXOpW", + "rules": Array [ + "display:flex;justify-content:", + [Function], + ";padding-bottom:", + [Function], + ";@media screen and (min-width:768px){justify-content:", + [Function], + ";padding-bottom:0;}", + ], + }, + "displayName": "NotificationListItem__DataListCell", + "foldedComponentIds": Array [], + "render": [Function], + "styledComponentId": "NotificationListItem__DataListCell-j7c411-0", + "target": [Function], + "toString": [Function], + "warnTooManyClasses": [Function], + "withComponent": [Function], + } + } + forwardedRef={null} + > + <DataListCell + alignRight={false} + className="NotificationListItem__DataListCell-j7c411-0 kIdLtz" + isFilled={true} + isIcon={false} + width={1} + > + <div + className="pf-c-data-list__cell NotificationListItem__DataListCell-j7c411-0 kIdLtz" + > + Email </div> </DataListCell> </StyledComponent> |