From 3e55aeff1831b134ff65da3388e964e0ba1983a2 Mon Sep 17 00:00:00 2001 From: SanttuA Date: Mon, 6 May 2024 15:49:52 +0300 Subject: [PATCH] Changed main navbar for admin users Admin users will now have all external links within a dropdown menu 'Links'. --- app/i18n/messages/en.json | 3 +- app/i18n/messages/fi.json | 1 + app/i18n/messages/sv.json | 1 + app/shared/main-navbar/AdminDropdownLinks.js | 62 ++++++++++++++++ .../main-navbar/AdminDropdownLinks.spec.js | 71 +++++++++++++++++++ app/shared/main-navbar/MainNavbar.js | 36 ++++------ app/shared/main-navbar/MainNavbar.spec.js | 56 +++------------ app/shared/main-navbar/_main-navbar.scss | 49 ++++++++++--- 8 files changed, 201 insertions(+), 78 deletions(-) create mode 100644 app/shared/main-navbar/AdminDropdownLinks.js create mode 100644 app/shared/main-navbar/AdminDropdownLinks.spec.js diff --git a/app/i18n/messages/en.json b/app/i18n/messages/en.json index aac7f8b2b..ab8d77a07 100644 --- a/app/i18n/messages/en.json +++ b/app/i18n/messages/en.json @@ -229,6 +229,7 @@ "Navbar.language-english": "English", "Navbar.language-finnish": "Finnish", "Navbar.language-swedish": "Swedish", + "Navbar.links": "Links", "Navbar.login": "Log in", "Navbar.logout": "Log out", "Navbar.manageReservations": "Manage Reservations", @@ -551,4 +552,4 @@ "UserReservationsPage.regularEmptyMessage": "No standard reservations", "UserReservationsPage.regularReservationsHeader": "Standard reservations", "UserReservationsPage.title": "My reservations" -} \ No newline at end of file +} diff --git a/app/i18n/messages/fi.json b/app/i18n/messages/fi.json index 8510c8f8f..0b0e70420 100644 --- a/app/i18n/messages/fi.json +++ b/app/i18n/messages/fi.json @@ -229,6 +229,7 @@ "Navbar.language-english": "Englanti", "Navbar.language-finnish": "Suomi", "Navbar.language-swedish": "Ruotsi", + "Navbar.links": "Linkit", "Navbar.login": "Kirjaudu sisään", "Navbar.logout": "Kirjaudu ulos", "Navbar.manageReservations": " Varausten hallinta", diff --git a/app/i18n/messages/sv.json b/app/i18n/messages/sv.json index e4365617d..67a4736ed 100644 --- a/app/i18n/messages/sv.json +++ b/app/i18n/messages/sv.json @@ -231,6 +231,7 @@ "Navbar.language-english": "Engelska", "Navbar.language-finnish": "Finska", "Navbar.language-swedish": "Svenska", + "Navbar.links": "Länkar", "Navbar.login": "Logga in", "Navbar.logout": "Logga ut", "Navbar.manageReservations": "Administrera Bokningar", diff --git a/app/shared/main-navbar/AdminDropdownLinks.js b/app/shared/main-navbar/AdminDropdownLinks.js new file mode 100644 index 000000000..a34c93c67 --- /dev/null +++ b/app/shared/main-navbar/AdminDropdownLinks.js @@ -0,0 +1,62 @@ +import React from 'react'; +import NavDropdown from 'react-bootstrap/lib/NavDropdown'; +import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'; +import PropTypes from 'prop-types'; +import MenuItem from 'react-bootstrap/lib/MenuItem'; + +import { injectT } from 'i18n'; +import constants from 'constants/AppConstants'; +import FAIcon from 'shared/fontawesome-icon'; + +function AdminDropdownLinks({ currentLanguage, gitbookURL, t }) { + return ( + + + {t('Navbar.adminMaintenance')} + + + + + + {t('Navbar.adminGuide')} + + + + + {t('Navbar.feedback')} + + + + ); +} + +AdminDropdownLinks.propTypes = { + currentLanguage: PropTypes.string.isRequired, + gitbookURL: PropTypes.string.isRequired, + t: PropTypes.func.isRequired, +}; + +export default injectT(AdminDropdownLinks); diff --git a/app/shared/main-navbar/AdminDropdownLinks.spec.js b/app/shared/main-navbar/AdminDropdownLinks.spec.js new file mode 100644 index 000000000..d2a198486 --- /dev/null +++ b/app/shared/main-navbar/AdminDropdownLinks.spec.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { MenuItem, NavDropdown } from 'react-bootstrap'; +import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'; + +import constants from 'constants/AppConstants'; +import AdminDropdownLinks from './AdminDropdownLinks'; +import { shallowWithIntl } from 'utils/testUtils'; +import FAIcon from 'shared/fontawesome-icon'; + + +describe('shared/main-navbar/AdminDropdownLinks', () => { + const defaultProps = { + currentLanguage: 'fi', + gitbookURL: 'https://gitbook.com/abc' + }; + + function getWrapper(props) { + return shallowWithIntl(); + } + + describe('renders', () => { + test('NavDropdown', () => { + const navDropdown = getWrapper().find(NavDropdown); + expect(navDropdown).toHaveLength(1); + expect(navDropdown.prop('className')).toBe('nav-link-dropdown'); + expect(navDropdown.prop('eventKey')).toBe('link-dropdown'); + expect(navDropdown.prop('id')).toBe('nav-admin-dropdown'); + expect(navDropdown.prop('title')).toBe('Navbar.links'); + }); + + test('all MenuItems', () => { + const menuItems = getWrapper().find(MenuItem); + expect(menuItems).toHaveLength(3); + + menuItems.forEach(menuItem => { + expect(menuItem.prop('className')).toBe('nav-dropdown-link'); + expect(menuItem.prop('rel')).toBe('noreferrer'); + expect(menuItem.prop('target')).toBe('_blank'); + }); + }); + + test('first menu item has correct unique props', () => { + const menuItem = getWrapper().find(MenuItem).first(); + expect(menuItem.prop('href')).toBe(constants.NAV_ADMIN_URLS.respa); + expect(menuItem.prop('eventKey')).toBe('adminMaintenance'); + expect(menuItem.prop('children')).toContain('Navbar.adminMaintenance'); + }); + + test('second menu item has correct unique props', () => { + const menuItem = getWrapper().find(MenuItem).at(1); + expect(menuItem.prop('href')).toBe(defaultProps.gitbookURL); + expect(menuItem.prop('eventKey')).toBe('adminGuide'); + expect(menuItem.prop('children')).toContain('Navbar.adminGuide'); + }); + + test('third menu item has correct unique props', () => { + const menuItem = getWrapper().find(MenuItem).at(2); + expect(menuItem.prop('href')).toBe( + `https://opaskartta.turku.fi/eFeedback/${defaultProps.currentLanguage}/Feedback/30/1039` + ); + expect(menuItem.prop('eventKey')).toBe('feedback'); + expect(menuItem.prop('children')).toContain('Navbar.feedback'); + }); + + test('all FAIcons', () => { + const icons = getWrapper().find(FAIcon); + expect(icons).toHaveLength(3); + icons.forEach(icon => expect(icon.prop('icon')).toBe(faExternalLinkAlt)); + }); + }); +}); diff --git a/app/shared/main-navbar/MainNavbar.js b/app/shared/main-navbar/MainNavbar.js index d1b6ca8d2..1b943b387 100644 --- a/app/shared/main-navbar/MainNavbar.js +++ b/app/shared/main-navbar/MainNavbar.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; -import React, { Fragment } from 'react'; +import React from 'react'; import { Link } from 'react-router-dom'; import { LinkContainer } from 'react-router-bootstrap'; import classNames from 'classnames'; @@ -13,6 +13,7 @@ import constants from 'constants/AppConstants'; import FAIcon from 'shared/fontawesome-icon'; import { injectT } from 'i18n'; import { getSearchPageUrl } from 'utils/searchUtils'; +import AdminDropdownLinks from './AdminDropdownLinks'; class MainNavbar extends React.Component { constructor(props) { @@ -88,27 +89,20 @@ class MainNavbar extends React.Component { )} - {isAdmin - && ( - - - this.collapseItem()}> - {t('Navbar.manageReservations')} - - - - {t('Navbar.adminMaintenance')} - - - - {t('Navbar.adminGuide')} - - - - ) - } - {(isAdmin || authUserAmr === 'turku_adfs') && ( + {(isLoggedIn && isAdmin) && ( + + this.collapseItem()}> + {t('Navbar.manageReservations')} + + + )} + + {isAdmin && ( + + )} + + {(!isAdmin && authUserAmr === 'turku_adfs') && ( { const pathname = 'somepath'; @@ -113,49 +113,11 @@ describe('shared/main-navbar/MainNavbar', () => { expect(myReservationsLink).toHaveLength(1); }); - test('renders a link to respa admin UI', () => { - const respaAdminLink = getLoggedInAdminWrapper().find(NavItem).filter({ eventKey: 'adminGuide' }); - expect(respaAdminLink).toHaveLength(1); - }); - - test('renders a link to respa admin UI, open new tab when clicked', () => { - const respaAdminLink = getLoggedInAdminWrapper() - .find(NavItem).filter({ eventKey: 'adminGuide' }); - expect(respaAdminLink.prop('target')).toEqual('_blank'); - }); - - test('renders a link to default(finnish) varaamo gitbook when language is not swedish', () => { - const gitbookLink = getLoggedInAdminWrapper() - .find(NavItem).filter({ href: constants.NAV_ADMIN_URLS.gitbook }); - expect(gitbookLink).toHaveLength(1); - }); - - test('renders a link to swedish varaamo gitbook when language is swedish', () => { - const gitbookLink = getLoggedInAdminWrapper({ currentLanguage: 'sv' }) - .find(NavItem).filter({ href: constants.NAV_ADMIN_URLS.gitbook_sv }); - expect(gitbookLink).toHaveLength(1); - }); - - test('renders a link to varaamo gitbook, open new tab when clicked', () => { - const gitbookLink = getLoggedInAdminWrapper() - .find(NavItem).filter({ href: constants.NAV_ADMIN_URLS.gitbook }); - expect(gitbookLink.prop('target')).toEqual('_blank'); - }); - - test('renders a external link icon to next to respa admin UI text', () => { - const maintenanceLink = getLoggedInAdminWrapper() - .find(NavItem).filter({ eventKey: 'adminGuide' }); - const icon = maintenanceLink.find(FAIcon); - - expect(icon).toHaveLength(1); - }); - - test('renders an icon next to varaamo gitbook text', () => { - const gitbookLink = getLoggedInAdminWrapper() - .find(NavItem).filter({ href: constants.NAV_ADMIN_URLS.gitbook }); - - const icon = gitbookLink.find(FAIcon); - expect(icon).toHaveLength(1); + test('renders AdminDropdownLinks', () => { + const adminDropdownLinks = getLoggedInAdminWrapper().find(AdminDropdownLinks); + expect(adminDropdownLinks).toHaveLength(1); + expect(adminDropdownLinks.prop('currentLanguage')).toBe('fi'); + expect(adminDropdownLinks.prop('gitbookURL')).toBe(constants.NAV_ADMIN_URLS.gitbook); }); }); @@ -201,9 +163,9 @@ describe('shared/main-navbar/MainNavbar', () => { describe('Feedback link', () => { describe('when user is admin', () => { - test('is visible', () => { + test('is not visible', () => { const nav = getWrapper({ isAdmin: true }).find(NavItem).filter({ eventKey: 'feedback' }); - expect(nav).toHaveLength(1); + expect(nav).toHaveLength(0); }); }); @@ -215,7 +177,7 @@ describe('shared/main-navbar/MainNavbar', () => { }); describe('when visible', () => { - const wrapper = getWrapper({ authUserAmr: 'turku_adfs', isAdmin: true }); + const wrapper = getWrapper({ authUserAmr: 'turku_adfs', isAdmin: false }); test('NavItem is rendered correctly', () => { const link = wrapper.find(NavItem).filter({ eventKey: 'feedback' }); diff --git a/app/shared/main-navbar/_main-navbar.scss b/app/shared/main-navbar/_main-navbar.scss index ee5a723ff..e5c614bf0 100644 --- a/app/shared/main-navbar/_main-navbar.scss +++ b/app/shared/main-navbar/_main-navbar.scss @@ -5,7 +5,7 @@ $externalIconMarginLeft: 5px; margin-bottom: 0; .navbar-nav li, - .navbar-nav > .active { + .navbar-nav>.active { a { color: $white; @@ -33,17 +33,18 @@ $externalIconMarginLeft: 5px; .navbar-toggle .icon-bar { color: $white; } + .navbar-toggle .icon-bar { background-color: $white; } - .navbar-brand, .navbar-toggle { + .navbar-brand, + .navbar-toggle { font-size: inherit; - @include add-focus(){ + @include add-focus() { color: $white; - }; - + } } @@ -58,6 +59,30 @@ $externalIconMarginLeft: 5px; @include add-focus; } + + #nav-admin-dropdown { + color: $white; + } + + .dropdown-menu { + a { + color: black; + } + + .nav-dropdown-link { + a { + @media (max-width: $screen-md-min) { + color: $white; + + &:hover { + color: $white; + } + } + + @include add-focus; + } + } + } } } @@ -70,11 +95,11 @@ $externalIconMarginLeft: 5px; .app-MainNavbar { - @include high-contrast{ + @include high-contrast { border-bottom: 1px solid $black; .navbar-nav li, - .navbar-nav > .active { + .navbar-nav>.active { a { color: $black; @@ -99,11 +124,17 @@ $externalIconMarginLeft: 5px; .navbar-toggle .icon-bar { color: $black; } + .navbar-toggle .icon-bar { background-color: $black; } - } + .navbar-nav li #nav-admin-dropdown { + color: $black; + } + .navbar-nav li .dropdown-menu .nav-dropdown-link a { + color: $black; + } + } } -// ----------