diff --git a/addon/components/navbar-auth-dropdown/component.js b/addon/components/navbar-auth-dropdown/component.js index 20485b3ed..33fa1f68a 100644 --- a/addon/components/navbar-auth-dropdown/component.js +++ b/addon/components/navbar-auth-dropdown/component.js @@ -1,6 +1,7 @@ import Ember from 'ember'; import layout from './template'; import config from 'ember-get-config'; +import { serviceLinks } from '../../const/service-links'; /** * @module ember-osf @@ -23,7 +24,7 @@ export default Ember.Component.extend({ layout, session: Ember.inject.service(), currentUser: Ember.inject.service(), - + i18n: Ember.inject.service(), tagName: 'li', classNames: ['dropdown'], classNameBindings: ['notAuthenticated:sign-in'], @@ -38,6 +39,7 @@ export default Ember.Component.extend({ */ signupUrl: config.OSF.url + 'register', + serviceLinks: serviceLinks, gravatarUrl: Ember.computed('user', function() { let imgLink = this.get('user.links.profile_image'); diff --git a/addon/components/navbar-auth-dropdown/template.hbs b/addon/components/navbar-auth-dropdown/template.hbs index 18cc22ce1..6e5df4593 100644 --- a/addon/components/navbar-auth-dropdown/template.hbs +++ b/addon/components/navbar-auth-dropdown/template.hbs @@ -1,40 +1,40 @@ {{# if session.isAuthenticated }} {{! TODO: Replace display name functionality if possible- for now truncate via CSS at end of label }} - + {{else if allowLogin}} {{#if institution}} {{! TODO: How does the page know whether this is an institution view? Implement in the future }}
- Sign in + {{t 'eosf.authDropdown.signIn'}}
{{else}} -
- Sign Up - Sign in +
+ +
{{/if}} {{/if}} \ No newline at end of file diff --git a/addon/components/osf-footer/component.js b/addon/components/osf-footer/component.js index ce22798f9..864816744 100644 --- a/addon/components/osf-footer/component.js +++ b/addon/components/osf-footer/component.js @@ -1,5 +1,6 @@ import Ember from 'ember'; import layout from './template'; +import { serviceLinks } from '../../const/service-links'; /** * @module ember-osf @@ -12,6 +13,7 @@ import layout from './template'; */ export default Ember.Component.extend({ layout, + serviceLinks: serviceLinks, supportEmail: Ember.computed(function() { return 'Pbagnpg'.replace( /[a-zA-Z]/g, diff --git a/addon/components/osf-footer/template.hbs b/addon/components/osf-footer/template.hbs index 36f900cb1..1f9c9ecdb 100644 --- a/addon/components/osf-footer/template.hbs +++ b/addon/components/osf-footer/template.hbs @@ -5,11 +5,11 @@

OSF

diff --git a/addon/components/osf-navbar/component.js b/addon/components/osf-navbar/component.js index 8a8300087..b12f86ae1 100644 --- a/addon/components/osf-navbar/component.js +++ b/addon/components/osf-navbar/component.js @@ -1,5 +1,7 @@ import Ember from 'ember'; import layout from './template'; +import { serviceLinks, osfServices } from '../../const/service-links'; +import hostAppName from '../../mixins/host-app-name'; import config from 'ember-get-config'; /** @@ -8,35 +10,58 @@ import config from 'ember-get-config'; */ /** - * Display the OSF navbar + * Display the new OSF navbar - features primary navigation to toggle between services - HOME, PREPRINTS, REGISTRIES, and MEETINGS, + * and secondary navigation links for each particular service. * * Sample usage: * ```handlebars * {{osf-navbar * loginAction=loginAction - * hideSearch=true}} + * }} * ``` * * @class osf-navbar */ -export default Ember.Component.extend({ +export default Ember.Component.extend(hostAppName, { layout, session: Ember.inject.service(), - onSearchPage: false, - /** - * Whether search icons and functionality show up - * @property hideSearch - * @type {Boolean} - */ - hideSearch: false, - + osfServices: osfServices, + serviceLinks: serviceLinks, host: config.OSF.url, - + currentService: Ember.computed('hostAppName', function() { // Pulls current service name from consuming service's config file + let appName = this.get('hostAppName') || 'Home'; + if (appName === 'Dummy App') { + appName = 'Home'; + } + return appName.toUpperCase(); + }), + currentServiceLink: Ember.computed('serviceLinks', 'currentService', function() { + const serviceMapping = { + HOME: 'osfHome', + PREPRINTS: 'preprintsHome', + REGISTRIES: 'registriesHome', + MEETINGS: 'meetingsHome' + }; + const service = this.get('currentService'); + return this.get('serviceLinks')[serviceMapping[service]]; + }), showSearch: false, - actions: { + // Toggles whether search bar is displayed (for searching OSF) toggleSearch() { this.toggleProperty('showSearch'); + this.send('closeSecondaryNavigation'); }, + closeSecondaryNavigation() { + this.$('.navbar-collapse').collapse('hide'); + }, + closeSearch() { + this.set('showSearch', false); + }, + closeSecondaryAndSearch() { + this.send('closeSecondaryNavigation'); + this.send('closeSearch'); + } } + }); diff --git a/addon/components/osf-navbar/style.scss b/addon/components/osf-navbar/style.scss deleted file mode 100644 index 6c2670b0e..000000000 --- a/addon/components/osf-navbar/style.scss +++ /dev/null @@ -1,24 +0,0 @@ -a.navbar-service::before { - content: "/"; - padding-right: 8px; - color: #ccc; -} - -#navbarScope a.nav-user-dropdown { - padding-top: 12px; - padding-bottom: 11px; -} - -#navbarScope .btn-top-signup { - padding: 2px 20px; - margin-top: 5px; - line-height: 1.7; - background-color: #5cb85c; - border-color: #4cae4c; -} - -#navbarScope .btn-top-login { - padding: 2px 30px; - margin-top: 5px; - line-height: 1.7; -} diff --git a/addon/components/osf-navbar/template.hbs b/addon/components/osf-navbar/template.hbs index f38f2d75d..fff4f6a16 100644 --- a/addon/components/osf-navbar/template.hbs +++ b/addon/components/osf-navbar/template.hbs @@ -2,63 +2,54 @@ {{#if showSearch}} + {{!SEARCH DROPDOWN (FOR HOME SERVICE) - redirects to /search/?q=search_query}} {{search-dropdown action='toggleSearch'}} {{/if}} -
+
\ No newline at end of file diff --git a/addon/components/search-dropdown/component.js b/addon/components/search-dropdown/component.js index fcf90e93d..2de66a530 100644 --- a/addon/components/search-dropdown/component.js +++ b/addon/components/search-dropdown/component.js @@ -19,20 +19,25 @@ import config from 'ember-get-config'; export default Ember.Component.extend({ layout, host: config.OSF.url, + i18n: Ember.inject.service(), query: null, + isOpen: false, // is help modal open? actions: { // Runs toggleSearch in parent component, osf-navbar toggleSearch() { this.sendAction('action'); }, - updateQuery(value) { - this.set('query', value); - }, search() { var query = this.get('query'); if (query) { window.location.href = this.host + 'search/?q=' + query; } + }, + close() { + this.set('isOpen', false); + }, + toggleHelpModal() { + this.toggleProperty('isOpen'); } } }); diff --git a/addon/components/search-dropdown/template.hbs b/addon/components/search-dropdown/template.hbs index d367c58a9..687b6ddda 100644 --- a/addon/components/search-dropdown/template.hbs +++ b/addon/components/search-dropdown/template.hbs @@ -1,17 +1,48 @@ +{{!Green OSF Search bar}} + +{{!Search help modal - appears after clicking question mark on green search dropdown}} +
+ {{#bs-modal open=isOpen body=false header=false footer=false}} + {{#bs-modal-header}} + + {{/bs-modal-header}} + {{#bs-modal-body}} +

{{t 'eosf.searchHelpModal.queries'}}

+

+ {{t 'eosf.searchHelpModal.searchUsesThe'}} Lucene {{t 'eosf.searchHelpModal.searchSyntax'}}. + {{t 'eosf.searchHelpModal.helpDescription'}} +

+ + {{/bs-modal-body}} + + {{#bs-modal-footer}} +
+ +
+ {{/bs-modal-footer}} + {{/bs-modal}} + +
\ No newline at end of file diff --git a/addon/const/service-links.js b/addon/const/service-links.js new file mode 100644 index 000000000..be8a3bf93 --- /dev/null +++ b/addon/const/service-links.js @@ -0,0 +1,71 @@ +import config from 'ember-get-config'; + +/** + * @module ember-osf + * @submodule const + */ + +/** + * @class service-links + */ + +/** + * Provides some common osf links in a central location + * @property service-links + * @final + * @type {Object} + */ + +const osfUrl = config.OSF.url; +const serviceLinks = { + exploreActivity: `${osfUrl}explore/activity/`, + meetingsHome: `${osfUrl}meetings/`, + myProjects: `${osfUrl}myprojects/`, + osfHome: osfUrl, + osfSupport: `${osfUrl}support/`, + preprintsDiscover: `${osfUrl}preprints/discover/`, + preprintsHome: `${osfUrl}preprints/`, + preprintsSubmit: `${osfUrl}preprints/submit/`, + preprintsSupport: 'http://help.osf.io/m/preprints/', + profile: `${osfUrl}profile/`, + registriesDiscover: `${osfUrl}registries/discover/`, + registriesHome: `${osfUrl}registries/`, + registriesSupport: 'http://help.osf.io/m/registrations/', + settings: `${osfUrl}settings/` +}; + + +/** + * @class osf-services + */ + +/** + * Provides list of OSF services and their links + * @property osfServices + * @final + * @type {Array} + */ + +const osfServices = [ + { + name: 'HOME', + url: serviceLinks.osfHome, + }, + { + name: 'PREPRINTS', + url: serviceLinks.preprintsHome + }, + { + name: 'REGISTRIES', + url: serviceLinks.registriesHome + }, + { + name: 'MEETINGS', + url: serviceLinks.meetingsHome + } +]; + +export { + serviceLinks, + osfServices +}; diff --git a/addon/helpers/build-secondary-nav-links.js b/addon/helpers/build-secondary-nav-links.js new file mode 100644 index 000000000..33c077e64 --- /dev/null +++ b/addon/helpers/build-secondary-nav-links.js @@ -0,0 +1,86 @@ +import Ember from 'ember'; +import { serviceLinks } from '../const/service-links'; + +/** + * @module ember-osf + * @submodule helpers + */ + +/** + * Returns secondary links corresponding to a given service + * + * @class buildSecondaryNavLinks + * @param {String} currentService name of current service (HOME, PREPRINTS, REGISTRIES, or MEETINGS) + * @return {Array} Returns array of secondary link information + */ + +export default Ember.Helper.extend({ // Helper defined using a class, so can inject dependencies. + i18n: Ember.inject.service(), + session: Ember.inject.service(), + compute(params) { // Helpers defined using a class need a compute function + const i18n = this.get('i18n'); + const currentService = params[0].toUpperCase(); + const session = this.get('session'); + let links = Ember.Object.create({ + HOME: [ + { + name: `${session.get('isAuthenticated') ? i18n.t('eosf.navbar.myProjects') : i18n.t('eosf.navbar.browse')}`, + href: `${session.get('isAuthenticated') ? serviceLinks.myProjects : serviceLinks.exploreActivity}` + }, + { + name: i18n.t('eosf.navbar.search'), + href: '#' + } + + ], + PREPRINTS: [ + { + name: i18n.t('eosf.navbar.addAPreprint'), + href: serviceLinks.preprintsSubmit + }, + { + name: i18n.t('eosf.navbar.search'), + href: serviceLinks.preprintsDiscover + }, + { + name: i18n.t('eosf.navbar.support'), + href: serviceLinks.preprintsSupport + }, + + ], + REGISTRIES: [ + { + name: i18n.t('eosf.navbar.search'), + href: serviceLinks.registriesDiscover + }, + { + name: i18n.t('eosf.navbar.support'), + href: serviceLinks.registriesSupport + }, + + ], + MEETINGS: [ + { + name: i18n.t('eosf.navbar.search'), + href: serviceLinks.meetingsHome + } + ] + }); + + // If unauthenticated, add support link to HOME links. (If authenticated, support link can be found under Auth dropdown) + if (!session.get('isAuthenticated')) { + links.HOME.push( + { + name: i18n.t('eosf.navbar.support'), + href: serviceLinks.osfSupport + } + ); + } + + if (Object.keys(links).includes(currentService)) { + return links[currentService]; + } + return links.HOME; // Return Home links by default + + } +}); diff --git a/addon/locales/en-us/translations.js b/addon/locales/en-us/translations.js index b17377b56..a908bf1eb 100644 --- a/addon/locales/en-us/translations.js +++ b/addon/locales/en-us/translations.js @@ -18,6 +18,37 @@ export default { labelInputPassword: 'Password', textTosNotice: 'By clicking "Create account", you agree to our Terms and that you have read our Privacy Policy, including our information on Cookie Use.', buttonSubmit: 'Create account' + }, + navbar: { + addAPreprint: 'Add a preprint', + browse: 'Browse', + cancelSearch: 'Cancel search', + goHome: 'Go home', + myProjects: 'My Projects', + search: 'Search', + searchHelp: 'Search help', + searchTheOSF: 'Search the OSF', + sendSearch: 'Send search query', + support: 'Support', + togglePrimary: 'Toggle primary navigation', + toggleSecondary: 'Toggle secondary navigation', + }, + authDropdown: { + logOut: 'Log out', + myProfile: 'My Profile', + osfSupport: 'OSF Support', + settings: 'Settings', + signUp: 'Sign Up', + signIn: 'Sign in', + toggleAuthDropdown: 'Toggle auth dropdown' + }, + searchHelpModal: { + close: 'Close', + searchHelp: 'Search help', + queries: 'Queries', + searchUsesThe: 'Search uses the ', + searchSyntax: 'search syntax', + helpDescription: 'This gives you many options, but can be very simple as well. Examples of valid searches include:' } } }; diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss index ba9e1ecae..006e4942a 100644 --- a/addon/styles/addon.scss +++ b/addon/styles/addon.scss @@ -2,8 +2,8 @@ @import 'components/file-browser/style'; @import 'components/file-widget/style'; @import 'components/navbar-auth-dropdown/style'; -@import 'components/osf-navbar/style'; @import 'components/osf-mode-footer/style'; @import 'components/search-dropdown/style'; @import 'components/sign-up/style'; @import 'components/tags-widget/style'; + diff --git a/app/helpers/build-secondary-nav-links.js b/app/helpers/build-secondary-nav-links.js new file mode 100644 index 000000000..43491a74a --- /dev/null +++ b/app/helpers/build-secondary-nav-links.js @@ -0,0 +1 @@ +export { default, buildSecondaryNavLinks } from 'ember-osf/helpers/build-secondary-nav-links'; diff --git a/bower.json b/bower.json index 328f0e7a2..8ca2facc5 100644 --- a/bower.json +++ b/bower.json @@ -18,7 +18,7 @@ }, "devDependencies": { "bootstrap": "~3.3.5", - "osf-style": "https://github.com/CenterForOpenScience/osf-style.git#48197d234baf07c321c56edfd9f48b5624374453" + "osf-style": "https://github.com/pattisdr/osf-style.git#b9522678b25a3aa40bf017993b47582927130a8e" }, "resolutions": { "jquery": "~2.1.3" diff --git a/tests/dummy/app/styles/app.scss b/tests/dummy/app/styles/app.scss index 1762dc04d..ce94d2db9 100644 --- a/tests/dummy/app/styles/app.scss +++ b/tests/dummy/app/styles/app.scss @@ -7,7 +7,6 @@ body { - padding-top: 50px; position: relative; -webkit-font-smoothing: antialiased; font-family: 'Open Sans', 'Helvetica Neue', sans-serif; diff --git a/tests/integration/components/osf-navbar/component-test.js b/tests/integration/components/osf-navbar/component-test.js index 3beb6d1c9..7b3bd2d7c 100644 --- a/tests/integration/components/osf-navbar/component-test.js +++ b/tests/integration/components/osf-navbar/component-test.js @@ -6,12 +6,9 @@ moduleForComponent('osf-navbar', 'Integration | Component | osf navbar', { }); test('it renders', function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - this.set('loginAction', ()=>{}); this.render(hbs`{{osf-navbar loginAction=loginAction}}`); - assert.notEqual(this.$().text().trim(), ''); + assert.ok(this.$('primary-nav').context.innerText.replace(/\s+/g, " ").includes('OSF')); // TODO: Implement tests that check a variety of different conditionals used by navbar to control what is displayed }); diff --git a/tests/integration/helpers/build-secondary-nav-links-test.js b/tests/integration/helpers/build-secondary-nav-links-test.js new file mode 100644 index 000000000..23dd52c34 --- /dev/null +++ b/tests/integration/helpers/build-secondary-nav-links-test.js @@ -0,0 +1,101 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; +import Ember from 'ember'; +import tHelper from "ember-i18n/helper"; + +// Stub i18n service +const i18nStub = Ember.Service.extend({ + t: function(word) { + const translated = { + 'eosf.navbar.myProjects': 'My Projects', + 'eosf.navbar.search': 'Search', + 'eosf.navbar.addAPreprint': 'Add a preprint', + 'eosf.navbar.support': 'Support', + 'eosf.navbar.browse': 'Browse' + }; + return translated[word]; + } +}); + +// Session Stub No Auth +const sessionStubUnauthenticated = Ember.Service.extend({ + isAuthenticated: false +}); + +// Session Stub Auth +const sessionStubAuthenticated = Ember.Service.extend({ + isAuthenticated: true +}); + +moduleForComponent('build-secondary-navLinks', 'build-secondary-navLinks', { + integration: true, + + beforeEach() { + // register the helper: + this.registry.register('helper:t', tHelper); + this.register('service:i18n', i18nStub); + this.inject.service('i18n', { as: 'i18n' }); + } +}); + +test('returns preprints service links', function(assert) { + this.set('currentService', 'PREPRINTS'); + this.render(hbs` + {{#each (build-secondary-navLinks currentService session) as |navLink|}} + {{navLink.name}} + {{/each}} + `); + + assert.equal(this.$()[0].innerText, 'Add a preprint Search Support'); +}); + + +test('returns home service links, authenticated', function(assert) { + this.register('service:session', sessionStubAuthenticated); + this.inject.service('session', { as: 'sessionStub' }); + + this.set('currentService', 'HOME'); + this.render(hbs` + {{#each (build-secondary-navLinks currentService session) as |navLink|}} + {{navLink.name}} + {{/each}} + `); + + assert.equal(this.$()[0].innerText, 'My Projects Search'); +}); + + +test('returns home service links, unauthenticated', function(assert) { + this.register('service:session', sessionStubUnauthenticated); + this.inject.service('session', { as: 'sessionStub' }); + this.set('currentService', 'HOME'); + this.render(hbs` + {{#each (build-secondary-navLinks currentService session) as |navLink|}} + {{navLink.name}} + {{/each}} + `); + + assert.equal(this.$()[0].innerText, 'Browse Search Support'); +}); + +test('returns Registries service links', function(assert) { + this.set('currentService', 'REGISTRIES'); + this.render(hbs` + {{#each (build-secondary-navLinks currentService session) as |navLink|}} + {{navLink.name}} + {{/each}} + `); + + assert.equal(this.$()[0].innerText, 'Search Support'); +}); + +test('returns meetings service links', function(assert) { + this.set('currentService', 'MEETINGS'); + this.render(hbs` + {{#each (build-secondary-navLinks currentService session) as |navLink|}} + {{navLink.name}} + {{/each}} + `); + + assert.equal(this.$()[0].innerText, 'Search'); +});