From ea5118935e1e9d4238fa29744b610044b9306351 Mon Sep 17 00:00:00 2001 From: Nick Sellen Date: Sat, 11 Jan 2020 17:01:02 +0100 Subject: [PATCH] Remove all IIFEs (#1172) Now we are in npm/webpack world we don't need these to give us scope. --- .../client/config/admin.client.routes.js | 166 +++-- .../client/config/contacts.client.routes.js | 100 ++- .../add-contact.client.controller.js | 140 ++-- .../confirm-contact.client.controller.js | 92 ++- .../list-contacts.client.controller.js | 52 +- .../remove-contact.client.controller.js | 110 ++- .../tr-contact-remove.client.directive.js | 56 +- .../directives/tr-contact.client.directive.js | 82 +-- .../services/contact-by.client.service.js | 32 +- .../client/services/contact.client.service.js | 44 +- .../services/contacts-list.client.service.js | 24 +- .../add-contact.client.controller.tests.js | 220 +++--- .../client/contacts.client.routes.tests.js | 166 +++-- .../remove-contact.client.controller.tests.js | 156 ++-- .../core/client/config/core.client.config.js | 42 +- .../core/client/config/core.client.routes.js | 58 +- modules/core/client/config/core.client.run.js | 28 +- .../controllers/app.client.controller.js | 486 ++++++------ .../message-center.client.directive.js | 84 ++- .../tr-board-credits.client.directive.js | 46 +- .../directives/tr-boards.client.directive.js | 124 ++-- .../tr-date-select.client.directive.js | 258 ++++--- .../directives/tr-editor.client.directive.js | 216 +++--- .../tr-flashcards.client.directive.js | 94 ++- .../tr-focustip.client.directive.js | 76 +- .../tr-highlight-on-focus.client.directive.js | 54 +- .../tr-languages.client.directive.js | 202 +++-- .../tr-location.client.directive.js | 282 ++++--- .../tr-page-title.client.directive.js | 38 +- .../tr-placeholder.client.directive.js | 34 +- .../tr-share-fb.client.directive.js | 114 ++- .../tr-share-twitter.client.directive.js | 178 +++-- .../directives/tr-spinner.client.directive.js | 114 ++- .../directives/tr-switch.client.directive.js | 72 +- .../directives/tr-time.client.directive.js | 162 ++-- .../tr-window-blur.client.directive.js | 84 ++- .../tr-window-focus.client.directive.js | 84 ++- .../core/client/filters/age.client.filter.js | 46 +- .../plain-text-length.client.filter.js | 44 +- .../filters/trusted-html.client.filter.js | 20 +- .../services/facebook.client.service.js | 230 +++--- .../firebase-messaging.client.service.js | 256 ++++--- .../services/languages.client.service.js | 42 +- .../services/location.client.service.js | 370 +++++----- .../services/maplayers.client.service.js | 318 ++++---- .../services/mapmarkers.client.service.js | 212 +++--- .../services/message-center-client.service.js | 196 +++-- .../native-app-bridge.client.service.js | 350 +++++---- .../client/services/push.client.service.js | 416 ++++++----- .../services/settings.client.service.js | 96 ++- .../tests/client/age.client.filter.tests.js | 32 +- .../client/app.client.controller.tests.js | 118 ++- .../plain-text-length.client.filter.tests.js | 44 +- .../tests/client/push.client.service.tests.js | 442 ++++++----- .../trusted-html.client.filter.tests.js | 16 +- .../client/config/messages.client.routes.js | 78 +- .../controllers/inbox.client.controller.js | 148 ++-- .../controllers/thread.client.controller.js | 654 +++++++++-------- .../thread-dimensions.client.directive.js | 226 +++--- .../directives/threads.client.directive.js | 34 +- .../unread-count.client.directive.js | 164 ++--- .../messages-count-poll.client.service.js | 166 +++-- .../services/messages-count.client.service.js | 18 +- .../services/messages-read.client.service.js | 36 +- .../services/messages.client.service.js | 114 ++- .../client/config/offers.client.routes.js | 226 +++--- .../offer-host-edit.client.controller.js | 256 ++++--- .../offer-host-view.client.controller.js | 96 ++- .../offer-meet-add.client.controller.js | 112 ++- .../offer-meet-edit.client.controller.js | 170 +++-- .../offer-meet-list.client.controller.js | 112 ++- .../controllers/offer.client.controller.js | 84 ++- .../tr-offer-host-view.client.directive.js | 168 +++-- .../tr-offer-valid-until.client.directive.js | 160 ++-- .../services/offers-by.client.service.js | 36 +- .../client/services/offers.client.service.js | 82 +-- .../client/config/pages.client.routes.js | 306 ++++---- .../controllers/faq.client.controller.js | 136 ++-- .../controllers/home.client.controller.js | 154 ++-- .../tests/client/pages.client.routes.tests.js | 402 +++++----- .../reference-thread.client.directive.js | 164 ++--- .../reference-thread.client.service.js | 32 +- .../client/config/search.client.routes.js | 168 +++-- .../search-map.client.controller.js | 688 +++++++++-------- .../search-signup.client.controller.js | 60 +- .../controllers/search.client.controller.js | 370 +++++----- .../tr-my-tribes-toggle.client.directive.js | 176 +++-- .../tr-tribes-toggle.client.directive.js | 168 +++-- .../tr-types-toggle.client.directive.js | 190 +++-- .../client/services/filters.client.service.js | 122 ++- .../services/search-map.client.service.js | 146 ++-- .../client/search.client.routes.tests.js | 142 ++-- .../client/config/statistics.client.routes.js | 48 +- .../statistics.client.controller.js | 80 +- .../services/statistics.client.service.js | 18 +- .../client/statistics.client.routes.tests.js | 104 ++- .../client/config/support.client.routes.js | 58 +- .../controllers/support.client.controller.js | 108 ++- .../client/services/support.client.service.js | 18 +- .../client/support.client.routes.tests.js | 90 ++- .../client/config/tribes.client.config.js | 92 ++- .../controllers/tribe.client.controller.js | 50 +- .../tribes-list.client.controller.js | 42 +- .../tr-tribe-badge.client.directive.js | 72 +- .../tr-tribe-join-button.client.directive.js | 370 +++++----- .../tr-tribe-styles.client.directive.js | 118 ++- .../tr-tribes-in-common.client.directive.js | 110 ++- .../client/services/tribe.client.service.js | 136 ++-- .../client/services/tribes.client.service.js | 30 +- .../client/config/users.client.config.js | 60 +- .../client/config/users.client.routes.js | 692 +++++++++--------- .../authentication.client.controller.js | 138 ++-- .../avatar-editor.client.controller.js | 190 +++-- .../confirm-email.client.controller.js | 120 ++- .../password-forgot.client.controller.js | 72 +- .../password-reset.client.controller.js | 78 +- .../profile-edit-about.client.controller.js | 84 ++- .../profile-edit-account.client.controller.js | 406 +++++----- ...rofile-edit-locations.client.controller.js | 58 +- ...profile-edit-networks.client.controller.js | 140 ++-- .../profile-edit-photo.client.controller.js | 298 ++++---- .../profile-edit-tribes.client.controller.js | 58 +- .../profile-edit.client.controller.js | 72 +- .../controllers/profile.client.controller.js | 184 +++-- .../controllers/remove.client.controller.js | 86 ++- .../controllers/signup.client.controller.js | 634 ++++++++-------- .../directives/tr-avatar.client.directive.js | 254 ++++--- .../tr-confirm-password.client.directive.js | 64 +- .../tr-memberships-list.client.directive.js | 52 +- .../tr-monkeybox.client.directive.js | 42 +- .../tr-validate-username.client.directive.js | 118 ++- .../services/authentication.client.service.js | 24 +- .../services/invitation.client.service.js | 34 +- .../signup-validation.client.service.js | 26 +- .../users-memberships.client.service.js | 40 +- .../services/users-mini.client.service.js | 30 +- .../services/users-profile.client.service.js | 28 +- .../client/services/users.client.service.js | 66 +- .../authentication.client.controller.tests.js | 164 ++--- ...password-forgot.client.controller.tests.js | 174 +++-- .../password-reset.client.controller.tests.js | 160 ++-- ...le-edit-account.client.controller.tests.js | 212 +++--- 142 files changed, 10149 insertions(+), 10435 deletions(-) diff --git a/modules/admin/client/config/admin.client.routes.js b/modules/admin/client/config/admin.client.routes.js index 14c71f9f06..31042c91aa 100644 --- a/modules/admin/client/config/admin.client.routes.js +++ b/modules/admin/client/config/admin.client.routes.js @@ -1,87 +1,85 @@ -(function () { - angular - .module('admin') - .config(AdminRoutes); +angular + .module('admin') + .config(AdminRoutes); - /* @ngInject */ - function AdminRoutes($stateProvider) { +/* @ngInject */ +function AdminRoutes($stateProvider) { - $stateProvider. - state('admin', { - url: '/admin', - template: '', // This should be lowercase - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin', - }, - }). - state('admin-audit-log', { - url: '/admin/audit-log', - // `template` is Angular state so - // it should be lowercase, with dashes - // This is the bridge towards (and from) React - template: '', - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin - Audit log', - }, - }). - state('admin-acquisition-stories', { - url: '/admin/acquisition-stories', - // `template` is Angular state so - // it should be lowercase, with dashes - // This is the bridge towards (and from) React - template: '', - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin - Acquisition stories', - }, - }). - state('admin-messages', { - url: '/admin/messages', - // `template` is Angular state so - // it should be lowercase, with dashes - // This is the bridge towards (and from) React - template: '', - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin - Messages', - }, - }). - state('admin-search-users', { - url: '/admin/search-users', - // `template` is Angular state so - // it should be lowercase, with dashes - // This is the bridge towards (and from) React - template: '', - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin - Search users', - }, - }). - state('admin-user', { - url: '/admin/user', - // `template` is Angular state so - // it should be lowercase, with dashes - // This is the bridge towards (and from) React - template: '', - requiresRole: 'admin', - requiresAuth: true, - footerHidden: true, - data: { - pageTitle: 'Admin - User', - }, - }); + $stateProvider. + state('admin', { + url: '/admin', + template: '', // This should be lowercase + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin', + }, + }). + state('admin-audit-log', { + url: '/admin/audit-log', + // `template` is Angular state so + // it should be lowercase, with dashes + // This is the bridge towards (and from) React + template: '', + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin - Audit log', + }, + }). + state('admin-acquisition-stories', { + url: '/admin/acquisition-stories', + // `template` is Angular state so + // it should be lowercase, with dashes + // This is the bridge towards (and from) React + template: '', + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin - Acquisition stories', + }, + }). + state('admin-messages', { + url: '/admin/messages', + // `template` is Angular state so + // it should be lowercase, with dashes + // This is the bridge towards (and from) React + template: '', + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin - Messages', + }, + }). + state('admin-search-users', { + url: '/admin/search-users', + // `template` is Angular state so + // it should be lowercase, with dashes + // This is the bridge towards (and from) React + template: '', + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin - Search users', + }, + }). + state('admin-user', { + url: '/admin/user', + // `template` is Angular state so + // it should be lowercase, with dashes + // This is the bridge towards (and from) React + template: '', + requiresRole: 'admin', + requiresAuth: true, + footerHidden: true, + data: { + pageTitle: 'Admin - User', + }, + }); - } -}()); +} diff --git a/modules/contacts/client/config/contacts.client.routes.js b/modules/contacts/client/config/contacts.client.routes.js index 40a34ba5fd..ec0f5c5303 100644 --- a/modules/contacts/client/config/contacts.client.routes.js +++ b/modules/contacts/client/config/contacts.client.routes.js @@ -1,59 +1,57 @@ import contactAddTemplateUrl from '@/modules/contacts/client/views/add-contact.client.view.html'; import contactConfirmTemplateUrl from '@/modules/contacts/client/views/confirm-contact.client.view.html'; -(function () { - angular - .module('contacts') - .config(ContactsRoutes); - - /* @ngInject */ - function ContactsRoutes($stateProvider) { - - $stateProvider. - state('contactAdd', { - url: '/contact-add/:userId', - templateUrl: contactAddTemplateUrl, - requiresAuth: true, - controller: 'ContactAddController', - controllerAs: 'contactAdd', - resolve: { - // A string value resolves to a service - ContactByService: 'ContactByService', - UsersMini: 'UsersMini', - - existingContact: function (ContactByService, $stateParams) { - return ContactByService.get({ userId: $stateParams.userId }); - }, - - friend: function (UsersMini, $stateParams) { - return UsersMini.get({ - userId: $stateParams.userId, - }); - }, +angular + .module('contacts') + .config(ContactsRoutes); + +/* @ngInject */ +function ContactsRoutes($stateProvider) { + + $stateProvider. + state('contactAdd', { + url: '/contact-add/:userId', + templateUrl: contactAddTemplateUrl, + requiresAuth: true, + controller: 'ContactAddController', + controllerAs: 'contactAdd', + resolve: { + // A string value resolves to a service + ContactByService: 'ContactByService', + UsersMini: 'UsersMini', + + existingContact: function (ContactByService, $stateParams) { + return ContactByService.get({ userId: $stateParams.userId }); }, - data: { - pageTitle: 'Add contact', - }, - }). - state('contactConfirm', { - url: '/contact-confirm/:contactId', - templateUrl: contactConfirmTemplateUrl, - requiresAuth: true, - controller: 'ContactConfirmController', - controllerAs: 'contactConfirm', - resolve: { - // A string value resolves to a service - Contact: 'Contact', - - contact: function (Contact, $stateParams) { - return Contact.get({ contactId: $stateParams.contactId }); - }, + friend: function (UsersMini, $stateParams) { + return UsersMini.get({ + userId: $stateParams.userId, + }); }, - data: { - pageTitle: 'Confirm contact', + }, + data: { + pageTitle: 'Add contact', + }, + }). + state('contactConfirm', { + url: '/contact-confirm/:contactId', + templateUrl: contactConfirmTemplateUrl, + requiresAuth: true, + controller: 'ContactConfirmController', + controllerAs: 'contactConfirm', + resolve: { + // A string value resolves to a service + Contact: 'Contact', + + contact: function (Contact, $stateParams) { + return Contact.get({ contactId: $stateParams.contactId }); }, - }); - } -}()); + }, + data: { + pageTitle: 'Confirm contact', + }, + }); + +} diff --git a/modules/contacts/client/controllers/add-contact.client.controller.js b/modules/contacts/client/controllers/add-contact.client.controller.js index b168b0e623..68b4a9b24e 100644 --- a/modules/contacts/client/controllers/add-contact.client.controller.js +++ b/modules/contacts/client/controllers/add-contact.client.controller.js @@ -1,85 +1,83 @@ -(function () { - angular - .module('contacts') - .controller('ContactAddController', ContactAddController); +angular + .module('contacts') + .controller('ContactAddController', ContactAddController); - /* @ngInject */ - function ContactAddController($state, $stateParams, Contact, Authentication, friend, existingContact) { +/* @ngInject */ +function ContactAddController($state, $stateParams, Contact, Authentication, friend, existingContact) { - // If no friend ID defined, go to elsewhere - if (!$stateParams.userId) { - $state.go('profile.about'); - } - - // ViewModel - const vm = this; - - // Exposed to the view - vm.add = add; - vm.isConnected = false; - vm.isLoading = false; - vm.friend = friend; - - vm.contact = new Contact({ - friendUserId: $stateParams.userId, - message: '

Hi!

I would like to add you as a contact.

- ' + Authentication.user.displayName + '

', - }); + // If no friend ID defined, go to elsewhere + if (!$stateParams.userId) { + $state.go('profile.about'); + } - /** - * Initialize controller - */ - init(); - function init() { + // ViewModel + const vm = this; - // Prevent connecting with yourself - if ($stateParams.userId === Authentication.user._id) { - vm.isConnected = true; - vm.error = 'You cannot connect with yourself. That is just silly!'; - return; - } + // Exposed to the view + vm.add = add; + vm.isConnected = false; + vm.isLoading = false; + vm.friend = friend; - // If contact doesn't exist, stop here - friend.$promise.then( - function () { - // User exists - }, - function () { - vm.isConnected = true; - vm.error = 'User does not exist.'; - }, - ); + vm.contact = new Contact({ + friendUserId: $stateParams.userId, + message: '

Hi!

I would like to add you as a contact.

- ' + Authentication.user.displayName + '

', + }); - // If contact already exists, stop here - existingContact.$promise.then(function (response) { - if (response) { - vm.isConnected = true; - vm.success = response.confirmed ? 'You two are already connected. Great!' : 'Connection already initiated; now it has to be confirmed.'; - } - }, function () { - vm.isConnected = false; - }); + /** + * Initialize controller + */ + init(); + function init() { + // Prevent connecting with yourself + if ($stateParams.userId === Authentication.user._id) { + vm.isConnected = true; + vm.error = 'You cannot connect with yourself. That is just silly!'; + return; } - // Add contact - function add() { - vm.isLoading = true; + // If contact doesn't exist, stop here + friend.$promise.then( + function () { + // User exists + }, + function () { + vm.isConnected = true; + vm.error = 'User does not exist.'; + }, + ); - vm.contact.$save(function () { - vm.isLoading = false; + // If contact already exists, stop here + existingContact.$promise.then(function (response) { + if (response) { vm.isConnected = true; - vm.success = 'Done! We sent an email to your contact and he/she still needs to confirm it.'; - }, function (error) { - vm.isLoading = false; - if (error.status === 409) { - // 409 means contact already existed - vm.success = (error.data.confirmed) ? 'You two are already connected. Great!' : 'Connection already initiated; now it has to be confirmed.'; - } else { - vm.error = error.message || 'Something went wrong. Try again.'; - } - }); + vm.success = response.confirmed ? 'You two are already connected. Great!' : 'Connection already initiated; now it has to be confirmed.'; + } + }, function () { + vm.isConnected = false; + }); - } + } + + // Add contact + function add() { + vm.isLoading = true; + + vm.contact.$save(function () { + vm.isLoading = false; + vm.isConnected = true; + vm.success = 'Done! We sent an email to your contact and he/she still needs to confirm it.'; + }, function (error) { + vm.isLoading = false; + if (error.status === 409) { + // 409 means contact already existed + vm.success = (error.data.confirmed) ? 'You two are already connected. Great!' : 'Connection already initiated; now it has to be confirmed.'; + } else { + vm.error = error.message || 'Something went wrong. Try again.'; + } + }); } -}()); + +} diff --git a/modules/contacts/client/controllers/confirm-contact.client.controller.js b/modules/contacts/client/controllers/confirm-contact.client.controller.js index a487927466..32e1223b73 100644 --- a/modules/contacts/client/controllers/confirm-contact.client.controller.js +++ b/modules/contacts/client/controllers/confirm-contact.client.controller.js @@ -1,55 +1,53 @@ -(function () { - angular - .module('contacts') - .controller('ContactConfirmController', ContactConfirmController); +angular + .module('contacts') + .controller('ContactConfirmController', ContactConfirmController); - /* @ngInject */ - function ContactConfirmController($stateParams, Authentication, contact) { +/* @ngInject */ +function ContactConfirmController($stateParams, Authentication, contact) { - // ViewModel - const vm = this; + // ViewModel + const vm = this; - // If no friend ID defined, go to elsewhere - if (!$stateParams.contactId) { - vm.error = 'Something went wrong. Try again.'; - } - - vm.isConnected = false; - vm.isLoading = true; - vm.contact = contact; - vm.confirmContact = confirmContact; + // If no friend ID defined, go to elsewhere + if (!$stateParams.contactId) { + vm.error = 'Something went wrong. Try again.'; + } - // First fetch contact object, just to make it sure it exists - vm.contact.$promise.then( - // Got contact - function () { - vm.isLoading = false; - if (vm.contact.confirmed === true) { - vm.isConnected = true; - vm.success = 'You two are already connected. Great!'; - } else if (vm.contact.userTo._id !== Authentication.user._id) { - vm.error = 'You must wait until they confirm your connection.'; - } - }, - // Error getting contact - function (errorResponse) { - vm.isWrongCode = true; - vm.error = errorResponse.status === 404 ? 'Could not find contact request. Check the confirmation link from email or you might be logged in with wrong user?' : 'Something went wrong. Try again.'; - }, - ); + vm.isConnected = false; + vm.isLoading = true; + vm.contact = contact; + vm.confirmContact = confirmContact; - function confirmContact() { - vm.isLoading = true; - vm.contact.confirm = true; - vm.contact.$update(function () { - vm.isLoading = false; + // First fetch contact object, just to make it sure it exists + vm.contact.$promise.then( + // Got contact + function () { + vm.isLoading = false; + if (vm.contact.confirmed === true) { vm.isConnected = true; - vm.success = 'You two are now connected!'; - }, function (errorResponse) { - vm.isLoading = false; - vm.error = errorResponse.data.message || 'Something went wrong. Try again.'; - }); - } + vm.success = 'You two are already connected. Great!'; + } else if (vm.contact.userTo._id !== Authentication.user._id) { + vm.error = 'You must wait until they confirm your connection.'; + } + }, + // Error getting contact + function (errorResponse) { + vm.isWrongCode = true; + vm.error = errorResponse.status === 404 ? 'Could not find contact request. Check the confirmation link from email or you might be logged in with wrong user?' : 'Something went wrong. Try again.'; + }, + ); + function confirmContact() { + vm.isLoading = true; + vm.contact.confirm = true; + vm.contact.$update(function () { + vm.isLoading = false; + vm.isConnected = true; + vm.success = 'You two are now connected!'; + }, function (errorResponse) { + vm.isLoading = false; + vm.error = errorResponse.data.message || 'Something went wrong. Try again.'; + }); } -}()); + +} diff --git a/modules/contacts/client/controllers/list-contacts.client.controller.js b/modules/contacts/client/controllers/list-contacts.client.controller.js index c30fbab2a1..fb4f9cf445 100644 --- a/modules/contacts/client/controllers/list-contacts.client.controller.js +++ b/modules/contacts/client/controllers/list-contacts.client.controller.js @@ -1,33 +1,31 @@ -(function () { - angular - .module('contacts') - .controller('ContactsListController', ContactsListController); +angular + .module('contacts') + .controller('ContactsListController', ContactsListController); - /* @ngInject */ - function ContactsListController($scope, $rootScope) { +/* @ngInject */ +function ContactsListController($scope, $rootScope) { - // ViewModel - const vm = this; + // ViewModel + const vm = this; - /** - * Fetch contact list for the profile currently open in parent view - * `profileCtrl` is a reference to a parent controller - */ - vm.contacts = $scope.profileCtrl.contacts; + /** + * Fetch contact list for the profile currently open in parent view + * `profileCtrl` is a reference to a parent controller + */ + vm.contacts = $scope.profileCtrl.contacts; - /** - * provide broadcast function for react removeContact component - */ - vm.broadcastRemoveContact = function (contact) { - $rootScope.$broadcast('contactRemoved', contact); - }; + /** + * provide broadcast function for react removeContact component + */ + vm.broadcastRemoveContact = function (contact) { + $rootScope.$broadcast('contactRemoved', contact); + }; - /** - * When contact removal modal signals that the contact was removed, remove it from this list as well - */ - $scope.$on('contactRemoved', function (event, removedContact) { - vm.contacts.splice(vm.contacts.indexOf(removedContact), 1); - }); + /** + * When contact removal modal signals that the contact was removed, remove it from this list as well + */ + $scope.$on('contactRemoved', function (event, removedContact) { + vm.contacts.splice(vm.contacts.indexOf(removedContact), 1); + }); - } -}()); +} diff --git a/modules/contacts/client/controllers/remove-contact.client.controller.js b/modules/contacts/client/controllers/remove-contact.client.controller.js index 2433b3e0ca..8ff3240fbf 100644 --- a/modules/contacts/client/controllers/remove-contact.client.controller.js +++ b/modules/contacts/client/controllers/remove-contact.client.controller.js @@ -1,68 +1,66 @@ -(function () { - angular - .module('contacts') - .controller('ContactRemoveController', ContactRemoveController); +angular + .module('contacts') + .controller('ContactRemoveController', ContactRemoveController); - /* @ngInject */ - function ContactRemoveController($scope, $rootScope, $uibModalInstance, messageCenterService, Contact, Authentication) { +/* @ngInject */ +function ContactRemoveController($scope, $rootScope, $uibModalInstance, messageCenterService, Contact, Authentication) { - const contactToRemove = $scope.contactToRemove; + const contactToRemove = $scope.contactToRemove; - // ViewModel - const vm = this; + // ViewModel + const vm = this; - // Exposed to the view - vm.isLoading = false; - vm.user = Authentication.user; - vm.contact = contactToRemove; - vm.removeContact = removeContact; - vm.cancelContactRemoval = cancelContactRemoval; + // Exposed to the view + vm.isLoading = false; + vm.user = Authentication.user; + vm.contact = contactToRemove; + vm.removeContact = removeContact; + vm.cancelContactRemoval = cancelContactRemoval; - // Different confirm button label and modal title depending on situation + // Different confirm button label and modal title depending on situation - if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.userFrom) { - // User is cancelling a request they sent - vm.labelConfirm = 'Yes, revoke request'; - vm.labelTitle = 'Revoke contact request?'; - vm.labelTime = 'Requested'; - } else if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.userTo) { - // Decline received request - vm.labelConfirm = 'Yes, decline request'; - vm.labelTitle = 'Decline contact request?'; - vm.labelTime = 'Requested'; - } else { - // Removing confirmed contact - vm.labelConfirm = 'Yes, remove contact'; - vm.labelTitle = 'Remove contact?'; - vm.labelTime = 'Connected since'; - } - - function removeContact() { - vm.isLoading = true; + if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.userFrom) { + // User is cancelling a request they sent + vm.labelConfirm = 'Yes, revoke request'; + vm.labelTitle = 'Revoke contact request?'; + vm.labelTime = 'Requested'; + } else if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.userTo) { + // Decline received request + vm.labelConfirm = 'Yes, decline request'; + vm.labelTitle = 'Decline contact request?'; + vm.labelTime = 'Requested'; + } else { + // Removing confirmed contact + vm.labelConfirm = 'Yes, remove contact'; + vm.labelTitle = 'Remove contact?'; + vm.labelTime = 'Connected since'; + } - // contact comes from the parent link() - Contact.delete({ contactId: contactToRemove._id }, - // Success - function () { + function removeContact() { + vm.isLoading = true; - // Let other controllers know that this was removed, so that they can react - $rootScope.$broadcast('contactRemoved', contactToRemove); + // contact comes from the parent link() + Contact.delete({ contactId: contactToRemove._id }, + // Success + function () { - $uibModalInstance.dismiss('cancel'); - }, - // Error - function () { - vm.isLoading = false; - $uibModalInstance.dismiss('cancel'); - messageCenterService.add('danger', 'Oops! Something went wrong. Try again later.', { timeout: 7000 }); - }, - ); - } + // Let other controllers know that this was removed, so that they can react + $rootScope.$broadcast('contactRemoved', contactToRemove); - // Close modal - function cancelContactRemoval() { - $uibModalInstance.dismiss('cancel'); - } + $uibModalInstance.dismiss('cancel'); + }, + // Error + function () { + vm.isLoading = false; + $uibModalInstance.dismiss('cancel'); + messageCenterService.add('danger', 'Oops! Something went wrong. Try again later.', { timeout: 7000 }); + }, + ); + } + // Close modal + function cancelContactRemoval() { + $uibModalInstance.dismiss('cancel'); } -}()); + +} diff --git a/modules/contacts/client/directives/tr-contact-remove.client.directive.js b/modules/contacts/client/directives/tr-contact-remove.client.directive.js index 605e6d08bb..afff77c139 100644 --- a/modules/contacts/client/directives/tr-contact-remove.client.directive.js +++ b/modules/contacts/client/directives/tr-contact-remove.client.directive.js @@ -1,35 +1,33 @@ import templateUrl from '@/modules/contacts/client/views/remove-contact.client.modal.html'; -(function () { - /** - * Remove contact directive to open up a modal to disconnect contacts - */ - angular - .module('contacts') - .directive('trContactRemove', trContactRemoveDirective); +/** + * Remove contact directive to open up a modal to disconnect contacts + */ +angular + .module('contacts') + .directive('trContactRemove', trContactRemoveDirective); - /* @ngInject */ - function trContactRemoveDirective($uibModal) { - return { - restrict: 'A', - scope: { - contactToRemove: '=trContactRemove', - }, - link: function (scope, element) { +/* @ngInject */ +function trContactRemoveDirective($uibModal) { + return { + restrict: 'A', + scope: { + contactToRemove: '=trContactRemove', + }, + link: function (scope, element) { - function openModal() { - $uibModal.open({ - templateUrl, - controllerAs: 'removeContactModal', - controller: 'ContactRemoveController', - scope: scope, - }); - } + function openModal() { + $uibModal.open({ + templateUrl, + controllerAs: 'removeContactModal', + controller: 'ContactRemoveController', + scope: scope, + }); + } - // Bind opening modal to the click - element.bind('click', openModal); + // Bind opening modal to the click + element.bind('click', openModal); - }, - }; - } -}()); + }, + }; +} diff --git a/modules/contacts/client/directives/tr-contact.client.directive.js b/modules/contacts/client/directives/tr-contact.client.directive.js index daa156e947..cf7d5041cf 100644 --- a/modules/contacts/client/directives/tr-contact.client.directive.js +++ b/modules/contacts/client/directives/tr-contact.client.directive.js @@ -1,51 +1,49 @@ import templateUrl from '@/modules/contacts/client/views/directives/tr-contact.client.view.html'; -(function () { - /** - * Produce a contact card - * - * Usage: - * ``` - *
- * ``` - * - * You can also define avatar size by passing `tr-contact-avatar-size="128"` - */ - angular - .module('contacts') - .directive('trContact', trContactDirective); +/** + * Produce a contact card + * + * Usage: + * ``` + *
+ * ``` + * + * You can also define avatar size by passing `tr-contact-avatar-size="128"` + */ +angular + .module('contacts') + .directive('trContact', trContactDirective); - /* @ngInject */ - function trContactDirective(Authentication) { - return { - templateUrl, - restrict: 'A', - replace: true, - scope: { - contact: '=trContact', - profileId: '=trContactProfileId', - avatarSize: '@trContactAvatarSize', - hideMeta: '=trContactHideMeta', - }, - controller: trContactController, - controllerAs: 'contactCtrl', - }; +/* @ngInject */ +function trContactDirective(Authentication) { + return { + templateUrl, + restrict: 'A', + replace: true, + scope: { + contact: '=trContact', + profileId: '=trContactProfileId', + avatarSize: '@trContactAvatarSize', + hideMeta: '=trContactHideMeta', + }, + controller: trContactController, + controllerAs: 'contactCtrl', + }; - /* @ngInject */ - function trContactController($scope) { + /* @ngInject */ + function trContactController($scope) { - // ViewModel - const vm = this; + // ViewModel + const vm = this; - // Exposed to the view - vm.contact = $scope.contact; - vm.profileId = $scope.profileId; - vm.avatarSize = $scope.avatarSize || 128; - vm.user = Authentication.user; + // Exposed to the view + vm.contact = $scope.contact; + vm.profileId = $scope.profileId; + vm.avatarSize = $scope.avatarSize || 128; + vm.user = Authentication.user; - // Hides meta info such as "connected since" - vm.hideMeta = $scope.hideMeta || false; + // Hides meta info such as "connected since" + vm.hideMeta = $scope.hideMeta || false; - } } -}()); +} diff --git a/modules/contacts/client/services/contact-by.client.service.js b/modules/contacts/client/services/contact-by.client.service.js index d56d92eaa3..08eba791c3 100644 --- a/modules/contacts/client/services/contact-by.client.service.js +++ b/modules/contacts/client/services/contact-by.client.service.js @@ -1,18 +1,16 @@ -(function () { - // ContactBy factory used for communicating with the contacts REST endpoints - // Read contact by userId - angular - .module('contacts') - .factory('ContactByService', ContactByService); +// ContactBy factory used for communicating with the contacts REST endpoints +// Read contact by userId +angular + .module('contacts') + .factory('ContactByService', ContactByService); - /* @ngInject */ - function ContactByService($resource) { - return $resource('/api/contact-by/:userId', { - userId: '@id', - }, { - get: { - method: 'GET', - }, - }); - } -}()); +/* @ngInject */ +function ContactByService($resource) { + return $resource('/api/contact-by/:userId', { + userId: '@id', + }, { + get: { + method: 'GET', + }, + }); +} diff --git a/modules/contacts/client/services/contact.client.service.js b/modules/contacts/client/services/contact.client.service.js index ce4f53225f..03ab6cc7ad 100644 --- a/modules/contacts/client/services/contact.client.service.js +++ b/modules/contacts/client/services/contact.client.service.js @@ -1,24 +1,22 @@ -(function () { - // Contact factory used for communicating with the contacts REST endpoints - // Read contact by contactId - angular - .module('contacts') - .factory('Contact', ContactService); +// Contact factory used for communicating with the contacts REST endpoints +// Read contact by contactId +angular + .module('contacts') + .factory('Contact', ContactService); - /* @ngInject */ - function ContactService($resource) { - return $resource('/api/contact/:contactId', { - contactId: '@_id', - }, { - get: { - method: 'GET', - }, - update: { - method: 'PUT', - }, - delete: { - method: 'DELETE', - }, - }); - } -}()); +/* @ngInject */ +function ContactService($resource) { + return $resource('/api/contact/:contactId', { + contactId: '@_id', + }, { + get: { + method: 'GET', + }, + update: { + method: 'PUT', + }, + delete: { + method: 'DELETE', + }, + }); +} diff --git a/modules/contacts/client/services/contacts-list.client.service.js b/modules/contacts/client/services/contacts-list.client.service.js index 86b4e84d94..2040a3dc2b 100644 --- a/modules/contacts/client/services/contacts-list.client.service.js +++ b/modules/contacts/client/services/contacts-list.client.service.js @@ -1,14 +1,12 @@ -(function () { - // ContactsList factory used for communicating with the contacts REST endpoints - // Read contact list by userId - angular - .module('contacts') - .factory('ContactsListService', ContactsListService); +// ContactsList factory used for communicating with the contacts REST endpoints +// Read contact list by userId +angular + .module('contacts') + .factory('ContactsListService', ContactsListService); - /* @ngInject */ - function ContactsListService($resource) { - return $resource('/api/contacts/:listUserId', { - listUserId: '@id', - }); - } -}()); +/* @ngInject */ +function ContactsListService($resource) { + return $resource('/api/contacts/:listUserId', { + listUserId: '@id', + }); +} diff --git a/modules/contacts/tests/client/add-contact.client.controller.tests.js b/modules/contacts/tests/client/add-contact.client.controller.tests.js index d3d166b3bd..29d3a3feb0 100644 --- a/modules/contacts/tests/client/add-contact.client.controller.tests.js +++ b/modules/contacts/tests/client/add-contact.client.controller.tests.js @@ -1,164 +1,161 @@ import '@/modules/contacts/client/contacts.client.module'; import AppConfig from '@/modules/core/client/app/config'; -(function () { - describe('ContactAddController', function () { - // Initialize global variables - let $httpBackend; - let Authentication; - let UsersMini; - let ContactByService; - let ContactAddController; - - const user1 = { - _id: 'user1', - displayName: 'User One', - }; - - const user2 = { - _id: 'user2', - displayName: 'User Two', - }; - - const contactRequest = { - friendUserId: user2._id, - message: '

Hi!

I would like to add you as a contact.

- ' + user1.displayName + '

', - }; - - // Load the main application module - beforeEach(function (done) { - angular.mock.module(AppConfig.appModuleName); +describe('ContactAddController', function () { + // Initialize global variables + let $httpBackend; + let Authentication; + let UsersMini; + let ContactByService; + let ContactAddController; + + const user1 = { + _id: 'user1', + displayName: 'User One', + }; + + const user2 = { + _id: 'user2', + displayName: 'User Two', + }; + + const contactRequest = { + friendUserId: user2._id, + message: '

Hi!

I would like to add you as a contact.

- ' + user1.displayName + '

', + }; + + // Load the main application module + beforeEach(function (done) { + angular.mock.module(AppConfig.appModuleName); + done(); + }); + + beforeEach(function (done) { + inject(function (_$httpBackend_, _Authentication_, _UsersMini_, _ContactByService_) { + $httpBackend = _$httpBackend_; + Authentication = _Authentication_; + UsersMini = _UsersMini_; + ContactByService = _ContactByService_; done(); }); + }); + + afterEach(function () { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + describe('logged in', function () { beforeEach(function (done) { - inject(function (_$httpBackend_, _Authentication_, _UsersMini_, _ContactByService_) { - $httpBackend = _$httpBackend_; - Authentication = _Authentication_; - UsersMini = _UsersMini_; - ContactByService = _ContactByService_; + inject(function ($controller) { + + Authentication.user = user1; + + ContactAddController = $controller('ContactAddController', { + friend: UsersMini.get({ userId: user2._id }), + existingContact: ContactByService.get({ userId: user2._id }), + $stateParams: { userId: user2._id }, + }); + done(); - }); - }); - afterEach(function () { - $httpBackend.verifyNoOutstandingExpectation(); - $httpBackend.verifyNoOutstandingRequest(); + }); }); - describe('logged in', function () { + describe('when user does not exist', function () { - beforeEach(function (done) { - inject(function ($controller) { + beforeEach(function () { + $httpBackend.expect('GET', '/api/users/mini/user2').respond(404); + $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); + }); - Authentication.user = user1; + it('displays an error message', function () { + $httpBackend.flush(); + expect(ContactAddController.error).toBe('User does not exist.'); + }); - ContactAddController = $controller('ContactAddController', { - friend: UsersMini.get({ userId: user2._id }), - existingContact: ContactByService.get({ userId: user2._id }), - $stateParams: { userId: user2._id }, - }); + }); - done(); + describe('when user exists', function () { - }); + beforeEach(function () { + $httpBackend.expect('GET', '/api/users/mini/user2').respond(200, user2); }); - describe('when user does not exist', function () { + describe('when unconfirmed contact exists', function () { beforeEach(function () { - $httpBackend.expect('GET', '/api/users/mini/user2').respond(404); - $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); + $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: false }); }); - it('displays an error message', function () { + it('displays a success message', function () { $httpBackend.flush(); - expect(ContactAddController.error).toBe('User does not exist.'); + expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); }); }); - describe('when user exists', function () { + describe('when confirmed contact exists', function () { beforeEach(function () { - $httpBackend.expect('GET', '/api/users/mini/user2').respond(200, user2); + $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: true }); }); - describe('when unconfirmed contact exists', function () { + it('Shows a nice message when the contact is confirmed', function () { + $httpBackend.flush(); + expect(ContactAddController.success).toBe('You two are already connected. Great!'); + }); - beforeEach(function () { - $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: false }); - }); + }); - it('displays a success message', function () { - $httpBackend.flush(); - expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); - }); + describe('when no contact exists', function () { + beforeEach(function () { + $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); }); - describe('when confirmed contact exists', function () { - - beforeEach(function () { - $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: true }); - }); - - it('Shows a nice message when the contact is confirmed', function () { - $httpBackend.flush(); - expect(ContactAddController.success).toBe('You two are already connected. Great!'); - }); + it('will make contact request', function () { + $httpBackend.expect('POST', '/api/contact', contactRequest).respond(200); + ContactAddController.add(); + $httpBackend.flush(); + expect(ContactAddController.success).toBe('Done! We sent an email to your contact and he/she still needs to confirm it.'); + }); + it('will make contact request with custom message', function () { + const customMessage = 'my custom message'; + ContactAddController.contact.message = customMessage; + $httpBackend.expect('POST', '/api/contact', { friendUserId: user2._id, message: customMessage }).respond(200); + ContactAddController.add(); + $httpBackend.flush(); + expect(ContactAddController.success).toBe('Done! We sent an email to your contact and he/she still needs to confirm it.'); }); - describe('when no contact exists', function () { - beforeEach(function () { - $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); - }); + describe('when unconfirmed contact conflict', function () { - it('will make contact request', function () { - $httpBackend.expect('POST', '/api/contact', contactRequest).respond(200); - ContactAddController.add(); - $httpBackend.flush(); - expect(ContactAddController.success).toBe('Done! We sent an email to your contact and he/she still needs to confirm it.'); + beforeEach(function () { + $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: false }); }); - it('will make contact request with custom message', function () { - const customMessage = 'my custom message'; - ContactAddController.contact.message = customMessage; - $httpBackend.expect('POST', '/api/contact', { friendUserId: user2._id, message: customMessage }).respond(200); + it('displays a confirmation waiting success message', function () { ContactAddController.add(); $httpBackend.flush(); - expect(ContactAddController.success).toBe('Done! We sent an email to your contact and he/she still needs to confirm it.'); + expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); }); + }); - describe('when unconfirmed contact conflict', function () { - - beforeEach(function () { - $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: false }); - }); - - it('displays a confirmation waiting success message', function () { - ContactAddController.add(); - $httpBackend.flush(); - expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); - }); + describe('with confirmed contact conflict', function () { + beforeEach(function () { + $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: true }); }); - describe('with confirmed contact conflict', function () { - - beforeEach(function () { - $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: true }); - }); - - it('displays an already connected success message', function () { - ContactAddController.add(); - $httpBackend.flush(); - expect(ContactAddController.success).toBe('You two are already connected. Great!'); - }); - + it('displays an already connected success message', function () { + ContactAddController.add(); + $httpBackend.flush(); + expect(ContactAddController.success).toBe('You two are already connected. Great!'); }); }); @@ -168,4 +165,5 @@ import AppConfig from '@/modules/core/client/app/config'; }); }); -}()); + +}); diff --git a/modules/contacts/tests/client/contacts.client.routes.tests.js b/modules/contacts/tests/client/contacts.client.routes.tests.js index b1d16526bd..a5a9b21ff6 100644 --- a/modules/contacts/tests/client/contacts.client.routes.tests.js +++ b/modules/contacts/tests/client/contacts.client.routes.tests.js @@ -1,107 +1,105 @@ import '@/modules/contacts/client/contacts.client.module'; import AppConfig from '@/modules/core/client/app/config'; -(function () { - describe('Contact Route Tests', function () { - // Initialize global variables - let $httpBackend; - - // We can start by loading the main application module - beforeEach(angular.mock.module(AppConfig.appModuleName)); - - // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). - // This allows us to inject a service but then attach it to a variable - // with the same name as the service. - beforeEach(inject(function ($rootScope, _$httpBackend_) { - $httpBackend = _$httpBackend_; - })); - - describe('Route Config for add contact', function () { - describe('Add contact Route', function () { - let mainstate; - beforeEach(inject(function ($state) { - // Test expected GET request - $httpBackend.when('GET', '/api/contact-by/123').respond(200, ''); - $httpBackend.expectGET('/api/contact-by/123'); - - mainstate = $state.get('contactAdd'); - })); - - it('Should have the correct URL', function () { - expect(mainstate.url).toEqual('/contact-add/:userId'); - }); - - it('Should not be abstract', function () { - expect(mainstate.abstract).toBe(undefined); - }); - - it('Should have templateUrl', function () { - expect(mainstate.templateUrl).toBe('/modules/contacts/views/add-contact.client.view.html'); - }); +describe('Contact Route Tests', function () { + // Initialize global variables + let $httpBackend; + + // We can start by loading the main application module + beforeEach(angular.mock.module(AppConfig.appModuleName)); + + // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). + // This allows us to inject a service but then attach it to a variable + // with the same name as the service. + beforeEach(inject(function ($rootScope, _$httpBackend_) { + $httpBackend = _$httpBackend_; + })); + + describe('Route Config for add contact', function () { + describe('Add contact Route', function () { + let mainstate; + beforeEach(inject(function ($state) { + // Test expected GET request + $httpBackend.when('GET', '/api/contact-by/123').respond(200, ''); + $httpBackend.expectGET('/api/contact-by/123'); + + mainstate = $state.get('contactAdd'); + })); + + it('Should have the correct URL', function () { + expect(mainstate.url).toEqual('/contact-add/:userId'); }); - describe('Handle Trailing Slash', function () { - beforeEach(inject(function ($state, $rootScope) { - // Test expected GET request - $httpBackend.when('GET', '/api/contact-by/123').respond(200, ''); - $httpBackend.expectGET('/api/contact-by/123'); - $httpBackend.when('GET', '/api/users/mini/123').respond(200, ''); - $httpBackend.expectGET('/api/users/mini/123'); + it('Should not be abstract', function () { + expect(mainstate.abstract).toBe(undefined); + }); - $state.go('contactAdd', { userId: '123' }); - $rootScope.$digest(); - })); + it('Should have templateUrl', function () { + expect(mainstate.templateUrl).toBe('/modules/contacts/views/add-contact.client.view.html'); + }); + }); - it('Should remove trailing slash', inject(function ($state, $location, $rootScope) { - $location.path('/contact-add/123/'); - $rootScope.$digest(); + describe('Handle Trailing Slash', function () { + beforeEach(inject(function ($state, $rootScope) { + // Test expected GET request + $httpBackend.when('GET', '/api/contact-by/123').respond(200, ''); + $httpBackend.expectGET('/api/contact-by/123'); + $httpBackend.when('GET', '/api/users/mini/123').respond(200, ''); + $httpBackend.expectGET('/api/users/mini/123'); - expect($location.path()).toBe('/contact-add/123'); - })); - }); + $state.go('contactAdd', { userId: '123' }); + $rootScope.$digest(); + })); + it('Should remove trailing slash', inject(function ($state, $location, $rootScope) { + $location.path('/contact-add/123/'); + $rootScope.$digest(); + + expect($location.path()).toBe('/contact-add/123'); + })); }); - describe('Route Config for confirm contact', function () { - describe('Confirm contact Route', function () { - let mainstate; - beforeEach(inject(function ($state) { - mainstate = $state.get('contactConfirm'); - })); + }); - it('Should have the correct URL', function () { - expect(mainstate.url).toEqual('/contact-confirm/:contactId'); - }); + describe('Route Config for confirm contact', function () { + describe('Confirm contact Route', function () { + let mainstate; + beforeEach(inject(function ($state) { + mainstate = $state.get('contactConfirm'); + })); - it('Should not be abstract', function () { - expect(mainstate.abstract).toBe(undefined); - }); + it('Should have the correct URL', function () { + expect(mainstate.url).toEqual('/contact-confirm/:contactId'); + }); - it('Should have templateUrl', function () { - expect(mainstate.templateUrl).toBe('/modules/contacts/views/confirm-contact.client.view.html'); - }); + it('Should not be abstract', function () { + expect(mainstate.abstract).toBe(undefined); }); - describe('Handle Trailing Slash', function () { - beforeEach(inject(function ($state, $rootScope) { - // Test expected GET request - $httpBackend.when('GET', '/api/contact/123').respond(200, ''); - $httpBackend.expectGET('/api/contact/123'); + it('Should have templateUrl', function () { + expect(mainstate.templateUrl).toBe('/modules/contacts/views/confirm-contact.client.view.html'); + }); + }); - $state.go('contactConfirm', { contactId: '123' }); - $rootScope.$digest(); - })); + describe('Handle Trailing Slash', function () { + beforeEach(inject(function ($state, $rootScope) { + // Test expected GET request + $httpBackend.when('GET', '/api/contact/123').respond(200, ''); + $httpBackend.expectGET('/api/contact/123'); - it('Should remove trailing slash', inject(function ($state, $location, $rootScope) { - $location.path('/contact-confirm/123/'); - $rootScope.$digest(); + $state.go('contactConfirm', { contactId: '123' }); + $rootScope.$digest(); + })); - expect($location.path()).toBe('/contact-confirm/123'); - })); - }); + it('Should remove trailing slash', inject(function ($state, $location, $rootScope) { + $location.path('/contact-confirm/123/'); + $rootScope.$digest(); + expect($location.path()).toBe('/contact-confirm/123'); + })); }); - }); -}()); + + +}); diff --git a/modules/contacts/tests/client/remove-contact.client.controller.tests.js b/modules/contacts/tests/client/remove-contact.client.controller.tests.js index be43ed44ba..105c2702a6 100644 --- a/modules/contacts/tests/client/remove-contact.client.controller.tests.js +++ b/modules/contacts/tests/client/remove-contact.client.controller.tests.js @@ -2,96 +2,94 @@ import '@/modules/contacts/client/contacts.client.module'; import AppConfig from '@/modules/core/client/app/config'; -(function () { - describe('ContactRemoveController', function () { - // Initialize global variables - let $httpBackend; - let Authentication; - let $rootScope; - let $scope; - let $uibModalInstance; - let messageCenterService; - let ContactRemoveController; - - const user1 = { - _id: 'user1', - displayName: 'User One', +describe('ContactRemoveController', function () { + // Initialize global variables + let $httpBackend; + let Authentication; + let $rootScope; + let $scope; + let $uibModalInstance; + let messageCenterService; + let ContactRemoveController; + + const user1 = { + _id: 'user1', + displayName: 'User One', + }; + + const contactToRemove = { + _id: 'contact1', + }; + + // Load the main application module + beforeEach(angular.mock.module(AppConfig.appModuleName)); + + beforeEach(inject(function (_$httpBackend_, _Authentication_, _$rootScope_, _messageCenterService_) { + $httpBackend = _$httpBackend_; + Authentication = _Authentication_; + + $rootScope = _$rootScope_; + spyOn($rootScope, '$broadcast').and.callThrough(); + + messageCenterService = _messageCenterService_; + spyOn(messageCenterService, 'add').and.callThrough(); + + $uibModalInstance = { + close: jest.fn(), + dismiss: jest.fn(), }; - const contactToRemove = { - _id: 'contact1', - }; - - // Load the main application module - beforeEach(angular.mock.module(AppConfig.appModuleName)); - - beforeEach(inject(function (_$httpBackend_, _Authentication_, _$rootScope_, _messageCenterService_) { - $httpBackend = _$httpBackend_; - Authentication = _Authentication_; - - $rootScope = _$rootScope_; - spyOn($rootScope, '$broadcast').and.callThrough(); - - messageCenterService = _messageCenterService_; - spyOn(messageCenterService, 'add').and.callThrough(); + $scope = $rootScope.$new(); + $scope.contactToRemove = contactToRemove; + })); - $uibModalInstance = { - close: jest.fn(), - dismiss: jest.fn(), - }; - - $scope = $rootScope.$new(); - $scope.contactToRemove = contactToRemove; - })); + afterEach(function () { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); - afterEach(function () { - $httpBackend.verifyNoOutstandingExpectation(); - $httpBackend.verifyNoOutstandingRequest(); - }); + describe('logged in', function () { - describe('logged in', function () { - - beforeEach(function (done) { - inject(function ($controller) { - Authentication.user = user1; - ContactRemoveController = $controller('ContactRemoveController', { - $scope: $scope, - $uibModalInstance: $uibModalInstance, - messageCenterService: messageCenterService, - }); - done(); + beforeEach(function (done) { + inject(function ($controller) { + Authentication.user = user1; + ContactRemoveController = $controller('ContactRemoveController', { + $scope: $scope, + $uibModalInstance: $uibModalInstance, + messageCenterService: messageCenterService, }); + done(); }); + }); - it('sets the contact', function () { - expect(ContactRemoveController.contact).toBe(contactToRemove); - }); - - it('can remove the contact', function () { - $httpBackend.expect('DELETE', '/api/contact/' + contactToRemove._id).respond(200); - expect(ContactRemoveController.removeContact).toBeDefined(); - ContactRemoveController.removeContact(); - $httpBackend.flush(); - expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); - expect($rootScope.$broadcast).toHaveBeenCalledWith('contactRemoved', contactToRemove); - }); + it('sets the contact', function () { + expect(ContactRemoveController.contact).toBe(contactToRemove); + }); - it('can be cancelled', function () { - expect(ContactRemoveController.cancelContactRemoval).toBeDefined(); - ContactRemoveController.cancelContactRemoval(); - expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); - expect($rootScope.$broadcast).not.toHaveBeenCalled(); - }); + it('can remove the contact', function () { + $httpBackend.expect('DELETE', '/api/contact/' + contactToRemove._id).respond(200); + expect(ContactRemoveController.removeContact).toBeDefined(); + ContactRemoveController.removeContact(); + $httpBackend.flush(); + expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); + expect($rootScope.$broadcast).toHaveBeenCalledWith('contactRemoved', contactToRemove); + }); - it('handles backend errors gracefully', function () { - $httpBackend.expect('DELETE', '/api/contact/' + contactToRemove._id).respond(400); - ContactRemoveController.removeContact(); - $httpBackend.flush(); - expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); - expect(messageCenterService.add).toHaveBeenCalledWith('danger', 'Oops! Something went wrong. Try again later.', { timeout: 7000 }); - }); + it('can be cancelled', function () { + expect(ContactRemoveController.cancelContactRemoval).toBeDefined(); + ContactRemoveController.cancelContactRemoval(); + expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); + expect($rootScope.$broadcast).not.toHaveBeenCalled(); + }); + it('handles backend errors gracefully', function () { + $httpBackend.expect('DELETE', '/api/contact/' + contactToRemove._id).respond(400); + ContactRemoveController.removeContact(); + $httpBackend.flush(); + expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); + expect(messageCenterService.add).toHaveBeenCalledWith('danger', 'Oops! Something went wrong. Try again later.', { timeout: 7000 }); }); }); -}()); + +}); diff --git a/modules/core/client/config/core.client.config.js b/modules/core/client/config/core.client.config.js index 191309ddc6..2185e07f44 100644 --- a/modules/core/client/config/core.client.config.js +++ b/modules/core/client/config/core.client.config.js @@ -1,24 +1,22 @@ -(function () { - angular - .module('core') - .config(CoreConfig); +angular + .module('core') + .config(CoreConfig); - /* @ngInject */ - function CoreConfig($httpProvider) { - // Config HTTP Error Handling - // Set the httpProvider "not authorized" interceptor - $httpProvider.interceptors.push(CoreServiceUnavailable); - } +/* @ngInject */ +function CoreConfig($httpProvider) { + // Config HTTP Error Handling + // Set the httpProvider "not authorized" interceptor + $httpProvider.interceptors.push(CoreServiceUnavailable); +} - /* @ngInject */ - function CoreServiceUnavailable($q, $rootScope) { - return { - responseError: function (rejection) { - if (rejection.status === 503) { - $rootScope.$broadcast('serviceUnavailable'); - } - return $q.reject(rejection); - }, - }; - } -}()); +/* @ngInject */ +function CoreServiceUnavailable($q, $rootScope) { + return { + responseError: function (rejection) { + if (rejection.status === 503) { + $rootScope.$broadcast('serviceUnavailable'); + } + return $q.reject(rejection); + }, + }; +} diff --git a/modules/core/client/config/core.client.routes.js b/modules/core/client/config/core.client.routes.js index 950491e61e..9bbab5c8c6 100644 --- a/modules/core/client/config/core.client.routes.js +++ b/modules/core/client/config/core.client.routes.js @@ -1,38 +1,36 @@ import templateUrl from '@/modules/core/client/views/404.client.view.html'; -(function () { - angular - .module('core') - .config(CoreRoutes); +angular + .module('core') + .config(CoreRoutes); - /* @ngInject */ - function CoreRoutes($stateProvider, $urlRouterProvider) { +/* @ngInject */ +function CoreRoutes($stateProvider, $urlRouterProvider) { - // Remove trailing slash from routes - $urlRouterProvider.rule(function ($injector, $location) { - const path = $location.path(); - const hasTrailingSlash = path.length > 1 && path[path.length - 1] === '/'; + // Remove trailing slash from routes + $urlRouterProvider.rule(function ($injector, $location) { + const path = $location.path(); + const hasTrailingSlash = path.length > 1 && path[path.length - 1] === '/'; - if (hasTrailingSlash) { + if (hasTrailingSlash) { - // If last character is a slash, return the same url without the slash - const newPath = path.substr(0, path.length - 1); - $location.replace().path(newPath); - } - }); + // If last character is a slash, return the same url without the slash + const newPath = path.substr(0, path.length - 1); + $location.replace().path(newPath); + } + }); - // Redirect to 404 when route not found - $urlRouterProvider.otherwise('not-found'); + // Redirect to 404 when route not found + $urlRouterProvider.otherwise('not-found'); - $stateProvider. - state('not-found', { - url: '/not-found', - templateUrl, - footerHidden: true, - headerHidden: true, - data: { - pageTitle: 'Not found', - }, - }); - } -}()); + $stateProvider. + state('not-found', { + url: '/not-found', + templateUrl, + footerHidden: true, + headerHidden: true, + data: { + pageTitle: 'Not found', + }, + }); +} diff --git a/modules/core/client/config/core.client.run.js b/modules/core/client/config/core.client.run.js index 84c8081bb8..754130edc7 100644 --- a/modules/core/client/config/core.client.run.js +++ b/modules/core/client/config/core.client.run.js @@ -1,19 +1,17 @@ -(function () { - angular - .module('core') - .run(coreRun); +angular + .module('core') + .run(coreRun); - /* @ngInject */ - function coreRun(Facebook, push) { +/* @ngInject */ +function coreRun(Facebook, push) { - // Attempt to initialize Facebook SDK on first page load - // If this fails, we'll try this again on successfull login - Facebook.init(); + // Attempt to initialize Facebook SDK on first page load + // If this fails, we'll try this again on successfull login + Facebook.init(); - // Initialize the push service if available - // It will check if user intended to enable push for this browser - // and setup the service-worker and backend registration accordingly - push.init(); + // Initialize the push service if available + // It will check if user intended to enable push for this browser + // and setup the service-worker and backend registration accordingly + push.init(); - } -}()); +} diff --git a/modules/core/client/controllers/app.client.controller.js b/modules/core/client/controllers/app.client.controller.js index 83bf344c6c..335d7f12ed 100644 --- a/modules/core/client/controllers/app.client.controller.js +++ b/modules/core/client/controllers/app.client.controller.js @@ -1,282 +1,280 @@ import '@/modules/users/client/users.client.module'; import '@/modules/messages/client/messages.client.module'; -(function () { +/** + * Application wide view controller + */ +angular + .module('core') + .controller('AppController', AppController); + +/* @ngInject */ +function AppController( + $location, + $scope, + $rootScope, + $uibModal, + $window, + $state, + $analytics, + Authentication, + SettingsFactory, + Languages, + locker, + PollMessagesCount, + push, + trNativeAppBridge) { + + // ViewModel + const vm = this; + + // Exposed to the view + vm.user = Authentication.user; + vm.appSettings = SettingsFactory.get(); + vm.languageNames = Languages.get('object'); + vm.pageTitle = $window.title; + vm.goHome = goHome; + vm.signout = signout; + vm.onWindowBlur = onWindowBlur; + vm.onWindowFocus = onWindowFocus; + vm.photoCredits = {}; + vm.photoCreditsCount = 0; + vm.isFooterHidden = false; + vm.isHeaderHidden = false; + vm.isAboutPage = false; + /** - * Application wide view controller + * Handle the window blur event */ - angular - .module('core') - .controller('AppController', AppController); - - /* @ngInject */ - function AppController( - $location, - $scope, - $rootScope, - $uibModal, - $window, - $state, - $analytics, - Authentication, - SettingsFactory, - Languages, - locker, - PollMessagesCount, - push, - trNativeAppBridge) { - - // ViewModel - const vm = this; - - // Exposed to the view - vm.user = Authentication.user; - vm.appSettings = SettingsFactory.get(); - vm.languageNames = Languages.get('object'); - vm.pageTitle = $window.title; - vm.goHome = goHome; - vm.signout = signout; - vm.onWindowBlur = onWindowBlur; - vm.onWindowFocus = onWindowFocus; - vm.photoCredits = {}; - vm.photoCreditsCount = 0; - vm.isFooterHidden = false; - vm.isHeaderHidden = false; - vm.isAboutPage = false; + function onWindowBlur() { + PollMessagesCount.setFrequency('low'); + } + + /** + * handle window focus event + */ + function onWindowFocus() { + PollMessagesCount.setFrequency('high'); + } + + // Default options for Medium-Editor directive used site wide + // @link https://github.com/yabwe/medium-editor/blob/master/OPTIONS.md + vm.editorOptions = { + disableReturn: false, + disableDoubleReturn: false, + disableExtraSpaces: false, + // Automatically turns URLs entered into + // the text field into HTML anchor tags + autoLink: false, + paste: { + // Forces pasting as plain text + forcePlainText: false, + // Cleans pasted content from different sources, like google docs etc + cleanPastedHTML: true, + // List of element attributes to remove during + // paste when `cleanPastedHTML` is `true` + cleanAttrs: [ + 'class', 'style', 'dir', 'id', 'title', 'target', 'tabindex', + 'onclick', 'oncontextmenu', 'ondblclick', 'onmousedown', 'onmouseenter', + 'onmouseleave', 'onmousemove', 'onmouseover', 'onmouseout', 'onmouseup', + 'onwheel', 'onmousewheel', 'onmessage', 'ontouchstart', 'ontouchmove', + 'ontouchend', 'ontouchcancel', 'onload', 'onscroll', + ], + // list of element tag names to remove during + // paste when `cleanPastedHTML` is `true` + cleanTags: [ + 'link', 'iframe', 'frameset', 'noframes', 'object', 'video', 'audio', + 'track', 'source', 'base', 'basefont', 'applet', 'param', 'embed', + 'script', 'meta', 'head', 'title', 'svg', 'script', 'style', + 'input', 'textarea', 'form', 'hr', 'select', 'optgroup', 'label', + 'img', 'canvas', 'area', 'map', 'figure', 'picture', 'figcaption', + 'noscript', + ], + // list of element tag names to unwrap (remove the element tag but retain + // its child elements) during paste when `cleanPastedHTML` is `true` + unwrapTags: [ + '!DOCTYPE', 'html', 'body', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'table', 'th', 'tr', 'td', 'tbody', 'thead', 'tfoot', 'article', + 'header', 'footer', 'section', 'aside', 'font', 'center', 'big', + 'code', 'pre', 'small', 'button', 'label', 'fieldset', 'legend', + 'datalist', 'keygen', 'output', 'nav', 'main', 'div', 'span', + ], + }, + // Toolbar buttons which appear when highlighting text + toolbar: { + buttons: [{ + name: 'bold', + contentDefault: '', + }, { + name: 'italic', + contentDefault: '', + }, { + name: 'underline', + contentDefault: '', + }, { + name: 'anchor', + contentDefault: '', + }, { + name: 'quote', + contentDefault: '', + }, { + name: 'unorderedlist', + contentDefault: '', + }], + }, + }; + + activate(); + + /** + * Initialize controller + */ + function activate() { /** - * Handle the window blur event + * Show "service unavailable" badge if http interceptor sends us this signal */ - function onWindowBlur() { - PollMessagesCount.setFrequency('low'); - } + $rootScope.$on('serviceUnavailable', function () { + $uibModal.open({ + ariaLabelledBy: 'Service unavailable', + template: + '' + + '', + }); + }); /** - * handle window focus event + * Snif and apply user changes */ - function onWindowFocus() { - PollMessagesCount.setFrequency('high'); - } - - // Default options for Medium-Editor directive used site wide - // @link https://github.com/yabwe/medium-editor/blob/master/OPTIONS.md - vm.editorOptions = { - disableReturn: false, - disableDoubleReturn: false, - disableExtraSpaces: false, - // Automatically turns URLs entered into - // the text field into HTML anchor tags - autoLink: false, - paste: { - // Forces pasting as plain text - forcePlainText: false, - // Cleans pasted content from different sources, like google docs etc - cleanPastedHTML: true, - // List of element attributes to remove during - // paste when `cleanPastedHTML` is `true` - cleanAttrs: [ - 'class', 'style', 'dir', 'id', 'title', 'target', 'tabindex', - 'onclick', 'oncontextmenu', 'ondblclick', 'onmousedown', 'onmouseenter', - 'onmouseleave', 'onmousemove', 'onmouseover', 'onmouseout', 'onmouseup', - 'onwheel', 'onmousewheel', 'onmessage', 'ontouchstart', 'ontouchmove', - 'ontouchend', 'ontouchcancel', 'onload', 'onscroll', - ], - // list of element tag names to remove during - // paste when `cleanPastedHTML` is `true` - cleanTags: [ - 'link', 'iframe', 'frameset', 'noframes', 'object', 'video', 'audio', - 'track', 'source', 'base', 'basefont', 'applet', 'param', 'embed', - 'script', 'meta', 'head', 'title', 'svg', 'script', 'style', - 'input', 'textarea', 'form', 'hr', 'select', 'optgroup', 'label', - 'img', 'canvas', 'area', 'map', 'figure', 'picture', 'figcaption', - 'noscript', - ], - // list of element tag names to unwrap (remove the element tag but retain - // its child elements) during paste when `cleanPastedHTML` is `true` - unwrapTags: [ - '!DOCTYPE', 'html', 'body', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', - 'table', 'th', 'tr', 'td', 'tbody', 'thead', 'tfoot', 'article', - 'header', 'footer', 'section', 'aside', 'font', 'center', 'big', - 'code', 'pre', 'small', 'button', 'label', 'fieldset', 'legend', - 'datalist', 'keygen', 'output', 'nav', 'main', 'div', 'span', - ], - }, - // Toolbar buttons which appear when highlighting text - toolbar: { - buttons: [{ - name: 'bold', - contentDefault: '', - }, { - name: 'italic', - contentDefault: '', - }, { - name: 'underline', - contentDefault: '', - }, { - name: 'anchor', - contentDefault: '', - }, { - name: 'quote', - contentDefault: '', - }, { - name: 'unorderedlist', - contentDefault: '', - }], - }, - }; - - activate(); + $scope.$on('userUpdated', function () { + vm.user = Authentication.user; + }); /** - * Initialize controller + * Before page change */ - function activate() { - - /** - * Show "service unavailable" badge if http interceptor sends us this signal - */ - $rootScope.$on('serviceUnavailable', function () { - $uibModal.open({ - ariaLabelledBy: 'Service unavailable', - template: - '' + - '', - }); - }); - - /** - * Snif and apply user changes - */ - $scope.$on('userUpdated', function () { - vm.user = Authentication.user; - }); + $scope.$on('$stateChangeStart', function (event, toState, toParams) { - /** - * Before page change - */ - $scope.$on('$stateChangeStart', function (event, toState, toParams) { - - if (toState.requiresRole) { - if (!Authentication.user) { - toState.requiresAuth = true; - } - // Check if user has the required role - else if (Authentication.user && !Authentication.user.roles.includes(toState.requiresRole)) { - event.preventDefault(); - $window.alert('This page would require you to be a Trustroots volunteer. Wanna help us build Trustroots?'); - $state.go('volunteering'); - } + if (toState.requiresRole) { + if (!Authentication.user) { + toState.requiresAuth = true; } - - // Redirect to login page if no user - if (toState.requiresAuth && !Authentication.user) { - // Cancel stateChange + // Check if user has the required role + else if (Authentication.user && !Authentication.user.roles.includes(toState.requiresRole)) { event.preventDefault(); - - // Save previous state - // See modules/users/client/controllers/authentication.client.controller.js for how they're used - $rootScope.signinState = toState.name; - $rootScope.signinStateParams = toParams; - - // Show a special signup ad for certain pages if user isn't authenticated - // (Normally we just splash a signup page at this point) - if (toState.name === 'profile') { - $state.go('profile-signup'); - } else if (toState.name === 'search' || toState.name === 'search.map') { - $state.go('search-signin', toParams || {}); - } else { - // Or just continue to the signup page... - $state.go('signin', { 'continue': true }); - } + $window.alert('This page would require you to be a Trustroots volunteer. Wanna help us build Trustroots?'); + $state.go('volunteering'); } + } - }); - - /** - * After page change - */ - $scope.$on('$stateChangeSuccess', function (event, toState) { - - // Footer is hidden on these pages - vm.isFooterHidden = (angular.isDefined(toState.footerHidden) && toState.footerHidden === true); + // Redirect to login page if no user + if (toState.requiresAuth && !Authentication.user) { + // Cancel stateChange + event.preventDefault(); + + // Save previous state + // See modules/users/client/controllers/authentication.client.controller.js for how they're used + $rootScope.signinState = toState.name; + $rootScope.signinStateParams = toParams; + + // Show a special signup ad for certain pages if user isn't authenticated + // (Normally we just splash a signup page at this point) + if (toState.name === 'profile') { + $state.go('profile-signup'); + } else if (toState.name === 'search' || toState.name === 'search.map') { + $state.go('search-signin', toParams || {}); + } else { + // Or just continue to the signup page... + $state.go('signin', { 'continue': true }); + } + } - // Header is hidden on these pages - vm.isHeaderHidden = (angular.isDefined(toState.headerHidden) && toState.headerHidden === true); + }); - // Indicate we are browsing primary landing page - vm.isHomePage = toState.name === 'home'; + /** + * After page change + */ + $scope.$on('$stateChangeSuccess', function (event, toState) { - // Reset photo copyrights on each page change - // trBoards directive hits in after this and we'll fill this with potential photo credits - vm.photoCredits = {}; - vm.photoCreditsCount = 0; + // Footer is hidden on these pages + vm.isFooterHidden = (angular.isDefined(toState.footerHidden) && toState.footerHidden === true); - // Reset page scroll on page change - $window.scrollTo(0, 0); - }); + // Header is hidden on these pages + vm.isHeaderHidden = (angular.isDefined(toState.headerHidden) && toState.headerHidden === true); - /** - * Sniff and apply photo credit changes - */ - $scope.$on('photoCreditsUpdated', function (scope, photo) { - angular.extend(vm.photoCredits, photo); - vm.photoCreditsCount++; - }); + // Indicate we are browsing primary landing page + vm.isHomePage = toState.name === 'home'; - } + // Reset photo copyrights on each page change + // trBoards directive hits in after this and we'll fill this with potential photo credits + vm.photoCredits = {}; + vm.photoCreditsCount = 0; - /** - * Determine where to direct user from "home" links - */ - function goHome() { - if (Authentication.user) { - $state.go('search.map'); - } else { - $state.go('home'); - } - } + // Reset page scroll on page change + $window.scrollTo(0, 0); + }); /** - * Sign out authenticated user + * Sniff and apply photo credit changes */ - function signout($event) { - if ($event) { - $event.preventDefault(); - } + $scope.$on('photoCreditsUpdated', function (scope, photo) { + angular.extend(vm.photoCredits, photo); + vm.photoCreditsCount++; + }); - $analytics.eventTrack('signout', { - category: 'authentication', - label: 'Sign out', - }); + } - // Clear out session/localstorage - // @link https://github.com/tymondesigns/angular-locker#removing-items-from-locker - if (locker.supported()) { - locker.clean(); - } + /** + * Determine where to direct user from "home" links + */ + function goHome() { + if (Authentication.user) { + $state.go('search.map'); + } else { + $state.go('home'); + } + } - push.disable().finally(function () { - // Do the signout and refresh the page - $window.top.location.href = '/api/auth/signout'; - }); + /** + * Sign out authenticated user + */ + function signout($event) { + if ($event) { + $event.preventDefault(); + } - // This will tell Mobile apps wrapping the site to disable push notifications at the device - if (angular.isFunction($window.postMessage)) { - $window.postMessage('unAuthenticated', $location.protocol() + '://' + $location.host()); - } + $analytics.eventTrack('signout', { + category: 'authentication', + label: 'Sign out', + }); - // Signal native mobile app we've unauthenticated - trNativeAppBridge.signalUnAuthenticated(); + // Clear out session/localstorage + // @link https://github.com/tymondesigns/angular-locker#removing-items-from-locker + if (locker.supported()) { + locker.clean(); } + push.disable().finally(function () { + // Do the signout and refresh the page + $window.top.location.href = '/api/auth/signout'; + }); + + // This will tell Mobile apps wrapping the site to disable push notifications at the device + if (angular.isFunction($window.postMessage)) { + $window.postMessage('unAuthenticated', $location.protocol() + '://' + $location.host()); + } + // Signal native mobile app we've unauthenticated + trNativeAppBridge.signalUnAuthenticated(); } -}()); + + +} diff --git a/modules/core/client/directives/message-center.client.directive.js b/modules/core/client/directives/message-center.client.directive.js index ea2929a0f5..ffd3581e1f 100644 --- a/modules/core/client/directives/message-center.client.directive.js +++ b/modules/core/client/directives/message-center.client.directive.js @@ -10,50 +10,48 @@ * See usage instructions from https://github.com/e0ipso/message-center */ -(function () { - /** - * Directive for error/success/info etc notifications - */ - angular - .module('core') - .directive('mcMessages', mcMessages); +/** + * Directive for error/success/info etc notifications + */ +angular + .module('core') + .directive('mcMessages', mcMessages); - /* @ngInject */ - function mcMessages($rootScope, messageCenterService) { - const templateString = '\ -
\ -
\ - \ - \ - \ - \ - \ - \ - {{ message.message }}\ - \ +/* @ngInject */ +function mcMessages($rootScope, messageCenterService) { + const templateString = '\ +
\ +
\ + \ + \ + \ + \ + \ + \ + {{ message.message }}\ \ -
\ + \
\ - '; - return { - restrict: 'EA', - template: templateString, - link: function (scope, element, attrs) { - // Bind the messages from the service to the root scope. +
\ + '; + return { + restrict: 'EA', + template: templateString, + link: function (scope, element, attrs) { + // Bind the messages from the service to the root scope. + messageCenterService.flush(); + const changeReaction = function () { // event, to, from + // Update 'unseen' messages to be marked as 'shown'. + messageCenterService.markShown(); + // Remove the messages that have been shown. + messageCenterService.removeShown(); + $rootScope.mcMessages = messageCenterService.mcMessages; messageCenterService.flush(); - const changeReaction = function () { // event, to, from - // Update 'unseen' messages to be marked as 'shown'. - messageCenterService.markShown(); - // Remove the messages that have been shown. - messageCenterService.removeShown(); - $rootScope.mcMessages = messageCenterService.mcMessages; - messageCenterService.flush(); - }; - if (angular.isUndefined(messageCenterService.offlistener)) { - messageCenterService.offlistener = $rootScope.$on('$locationChangeSuccess', changeReaction); - } - scope.animation = attrs.animation || 'fade in'; - }, - }; - } -}()); + }; + if (angular.isUndefined(messageCenterService.offlistener)) { + messageCenterService.offlistener = $rootScope.$on('$locationChangeSuccess', changeReaction); + } + scope.animation = attrs.animation || 'fade in'; + }, + }; +} diff --git a/modules/core/client/directives/tr-board-credits.client.directive.js b/modules/core/client/directives/tr-board-credits.client.directive.js index 4635ec61ed..6e2cd12f1e 100644 --- a/modules/core/client/directives/tr-board-credits.client.directive.js +++ b/modules/core/client/directives/tr-board-credits.client.directive.js @@ -1,25 +1,23 @@ -(function () { - /** - * Print out credits for photos used at the page by tr-boards directive - */ - angular - .module('core') - .directive('trBoardCredits', trBoardCreditsDirective); +/** + * Print out credits for photos used at the page by tr-boards directive + */ +angular + .module('core') + .directive('trBoardCredits', trBoardCreditsDirective); - /* @ngInject */ - function trBoardCreditsDirective() { - return { - template: - '' + - ' Photo by' + - ' Photos by' + - ' ' + - ' ' + - ' ()' + - ' , ' + - ' ' + - '', - restrict: 'A', - }; - } -}()); +/* @ngInject */ +function trBoardCreditsDirective() { + return { + template: + '' + + ' Photo by' + + ' Photos by' + + ' ' + + ' ' + + ' ()' + + ' , ' + + ' ' + + '', + restrict: 'A', + }; +} diff --git a/modules/core/client/directives/tr-boards.client.directive.js b/modules/core/client/directives/tr-boards.client.directive.js index f4721e2368..7d95fcd92f 100644 --- a/modules/core/client/directives/tr-boards.client.directive.js +++ b/modules/core/client/directives/tr-boards.client.directive.js @@ -1,65 +1,63 @@ import photos from '@/modules/core/client/services/photos.service'; -(function () { - /** - * Directive that simply picks a background image given element and emits copyright info down the scope. - * - * Usage: - *
- * - * Or from many: - *
- * - * To stop cover image being set for small screens (<= 480px width), - * use `tr-boards-ignore-small` attribute. - * - */ - angular - .module('core') - .directive('trBoards', trBoardsDirective); - - /* @ngInject */ - function trBoardsDirective($window) { - return { - restrict: 'A', - replace: false, - scope: { - trBoards: '=', - }, - link: function (scope, elem, attrs) { - - // Don't set background images for mobile screens if defined so via attribute - if (angular.isDefined(attrs.trBoardsIgnoreSmall) && $window.innerWidth <= 480) { - return; - } - - // If requested photo is missing or request is invalid, rely on this photo - const defaultPhoto = 'bokeh'; - - // scope.trBoards might be an array (therefore just pick one key from it) or a string (thus just use it as is) - const key = angular.isArray(scope.trBoards) ? scope.trBoards[Math.floor(Math.random() * (scope.trBoards.length))] : scope.trBoards; - - // Pick the photo - const photo = photos[key] || photos[defaultPhoto]; - - // Add photo as a background to the element - elem.addClass('board-' + key); - - // For small screens, if mobile image exists, use it - const file = ($window.innerWidth <= 480 && photo.file_mobile) ? photo.file_mobile : photo.file; - - elem.css({ - 'background-image': 'url(/img/board/' + file + ')', - }); - - // To prevent key being literally `key`: `{key: ...}`, we want it to be actual keyname such as `hitchroad`. - const photoObject = {}; - photoObject[key] = photo; - - // Send copyright info down the scope... something will pick it up! (pst, core/app-controller) - scope.$emit('photoCreditsUpdated', photoObject); - - }, - }; - } -}()); +/** + * Directive that simply picks a background image given element and emits copyright info down the scope. + * + * Usage: + *
+ * + * Or from many: + *
+ * + * To stop cover image being set for small screens (<= 480px width), + * use `tr-boards-ignore-small` attribute. + * + */ +angular + .module('core') + .directive('trBoards', trBoardsDirective); + +/* @ngInject */ +function trBoardsDirective($window) { + return { + restrict: 'A', + replace: false, + scope: { + trBoards: '=', + }, + link: function (scope, elem, attrs) { + + // Don't set background images for mobile screens if defined so via attribute + if (angular.isDefined(attrs.trBoardsIgnoreSmall) && $window.innerWidth <= 480) { + return; + } + + // If requested photo is missing or request is invalid, rely on this photo + const defaultPhoto = 'bokeh'; + + // scope.trBoards might be an array (therefore just pick one key from it) or a string (thus just use it as is) + const key = angular.isArray(scope.trBoards) ? scope.trBoards[Math.floor(Math.random() * (scope.trBoards.length))] : scope.trBoards; + + // Pick the photo + const photo = photos[key] || photos[defaultPhoto]; + + // Add photo as a background to the element + elem.addClass('board-' + key); + + // For small screens, if mobile image exists, use it + const file = ($window.innerWidth <= 480 && photo.file_mobile) ? photo.file_mobile : photo.file; + + elem.css({ + 'background-image': 'url(/img/board/' + file + ')', + }); + + // To prevent key being literally `key`: `{key: ...}`, we want it to be actual keyname such as `hitchroad`. + const photoObject = {}; + photoObject[key] = photo; + + // Send copyright info down the scope... something will pick it up! (pst, core/app-controller) + scope.$emit('photoCreditsUpdated', photoObject); + + }, + }; +} diff --git a/modules/core/client/directives/tr-date-select.client.directive.js b/modules/core/client/directives/tr-date-select.client.directive.js index e77038933c..a1fe6e9b34 100644 --- a/modules/core/client/directives/tr-date-select.client.directive.js +++ b/modules/core/client/directives/tr-date-select.client.directive.js @@ -1,147 +1,145 @@ -(function () { - /** - * @ngdoc directive - * - * @name trustroots:trDateSelect - * - * Fork of https://github.com/sambs/angular-sb-date-select with additional features: - * - allows choosing empty values - * - allows passing our own templates - * - * Relies on MomentJS - * @link http://momentjs.com/ - * - */ - angular.module('core') - - .run(['$templateCache', function ($templateCache) { - - const template = [ - '
', - ' ', - ' ', - ' ', - '
', - ]; - - $templateCache.put('tr-date-select.html', template.join('')); - - }]) - - .directive('trDateSelect', [function () { - - return { - restrict: 'A', - replace: true, - templateUrl: function ($element, $attrs) { - return $attrs.templateUrl || 'tr-date-select.html'; - }, - require: 'ngModel', - scope: { - disabled: '=ngDisabled', - selectClass: '@trSelectClass', - }, - - link: function (scope, elem, attrs, ngModel) { - scope.val = {}; - - const min = scope.min = moment(attrs.min || '1900-01-01'); - const max = scope.max = moment(attrs.max); // Defaults to now - - scope.years = []; - - for (let i = max.year(); i >= min.year(); i--) { - scope.years.push(i); - } - - scope.$watch('val.year', function () { - updateMonthOptions(); - }); - - scope.$watchCollection('[val.month, val.year]', function () { - updateDateOptions(); - }); - - scope.$watchCollection('[val.date, val.month, val.year]', function (newDate, oldDate) { - if (scope.val.year && scope.val.month && scope.val.date) { - if (!angular.equals(newDate, oldDate)) { - const m = moment([scope.val.year, scope.val.month - 1, scope.val.date]); - ngModel.$setViewValue(m.format('YYYY-MM-DD')); - } - } else { - ngModel.$setViewValue(null); +/** + * @ngdoc directive + * + * @name trustroots:trDateSelect + * + * Fork of https://github.com/sambs/angular-sb-date-select with additional features: + * - allows choosing empty values + * - allows passing our own templates + * + * Relies on MomentJS + * @link http://momentjs.com/ + * + */ +angular.module('core') + + .run(['$templateCache', function ($templateCache) { + + const template = [ + '
', + ' ', + ' ', + ' ', + '
', + ]; + + $templateCache.put('tr-date-select.html', template.join('')); + + }]) + + .directive('trDateSelect', [function () { + + return { + restrict: 'A', + replace: true, + templateUrl: function ($element, $attrs) { + return $attrs.templateUrl || 'tr-date-select.html'; + }, + require: 'ngModel', + scope: { + disabled: '=ngDisabled', + selectClass: '@trSelectClass', + }, + + link: function (scope, elem, attrs, ngModel) { + scope.val = {}; + + const min = scope.min = moment(attrs.min || '1900-01-01'); + const max = scope.max = moment(attrs.max); // Defaults to now + + scope.years = []; + + for (let i = max.year(); i >= min.year(); i--) { + scope.years.push(i); + } + + scope.$watch('val.year', function () { + updateMonthOptions(); + }); + + scope.$watchCollection('[val.month, val.year]', function () { + updateDateOptions(); + }); + + scope.$watchCollection('[val.date, val.month, val.year]', function (newDate, oldDate) { + if (scope.val.year && scope.val.month && scope.val.date) { + if (!angular.equals(newDate, oldDate)) { + const m = moment([scope.val.year, scope.val.month - 1, scope.val.date]); + ngModel.$setViewValue(m.format('YYYY-MM-DD')); } - }); + } else { + ngModel.$setViewValue(null); + } + }); - function updateMonthOptions() { - // Values begin at 1 to permit easier boolean testing - scope.months = []; + function updateMonthOptions() { + // Values begin at 1 to permit easier boolean testing + scope.months = []; - const minMonth = scope.val.year && min.isSame([scope.val.year], 'year') ? min.month() : 0; - const maxMonth = scope.val.year && max.isSame([scope.val.year], 'year') ? max.month() : 11; + const minMonth = scope.val.year && min.isSame([scope.val.year], 'year') ? min.month() : 0; + const maxMonth = scope.val.year && max.isSame([scope.val.year], 'year') ? max.month() : 11; - const monthNames = moment.months(); + const monthNames = moment.months(); - for (let j = minMonth; j <= maxMonth; j++) { - scope.months.push({ - name: monthNames[j], - value: j + 1, - }); - } + for (let j = minMonth; j <= maxMonth; j++) { + scope.months.push({ + name: monthNames[j], + value: j + 1, + }); + } - if (scope.val.month - 1 > maxMonth || scope.val.month - 1 < minMonth) { - delete scope.val.month; - } + if (scope.val.month - 1 > maxMonth || scope.val.month - 1 < minMonth) { + delete scope.val.month; } + } - function updateDateOptions() { - let minDate; - let maxDate; + function updateDateOptions() { + let minDate; + let maxDate; - if (scope.val.year && scope.val.month && min.isSame([scope.val.year, scope.val.month - 1], 'month')) { - minDate = min.date(); - } else { - minDate = 1; - } + if (scope.val.year && scope.val.month && min.isSame([scope.val.year, scope.val.month - 1], 'month')) { + minDate = min.date(); + } else { + minDate = 1; + } - if (scope.val.year && scope.val.month && max.isSame([scope.val.year, scope.val.month - 1], 'month')) { - maxDate = max.date(); - } else if (scope.val.year && scope.val.month) { - maxDate = moment([scope.val.year, scope.val.month - 1]).daysInMonth(); - } else { - maxDate = 31; - } + if (scope.val.year && scope.val.month && max.isSame([scope.val.year, scope.val.month - 1], 'month')) { + maxDate = max.date(); + } else if (scope.val.year && scope.val.month) { + maxDate = moment([scope.val.year, scope.val.month - 1]).daysInMonth(); + } else { + maxDate = 31; + } - scope.dates = []; + scope.dates = []; - for (let i = minDate; i <= maxDate; i++) { - scope.dates.push(i); - } - if (scope.val.date < minDate || scope.val.date > maxDate) { - delete scope.val.date; - } + for (let i = minDate; i <= maxDate; i++) { + scope.dates.push(i); + } + if (scope.val.date < minDate || scope.val.date > maxDate) { + delete scope.val.date; } + } - // ngModel -> view - ngModel.$render = function () { - if (!ngModel.$viewValue) return; + // ngModel -> view + ngModel.$render = function () { + if (!ngModel.$viewValue) return; - const m = moment(new Date(ngModel.$viewValue)); + const m = moment(new Date(ngModel.$viewValue)); - // Always use a dot in ng-model attrs... - scope.val = { - year: m.year(), - month: m.month() + 1, - date: m.date(), - }; + // Always use a dot in ng-model attrs... + scope.val = { + year: m.year(), + month: m.month() + 1, + date: m.date(), }; - }, - }; - }]); -}()); + }; + }, + }; + }]); diff --git a/modules/core/client/directives/tr-editor.client.directive.js b/modules/core/client/directives/tr-editor.client.directive.js index 636e1c408c..477549673e 100644 --- a/modules/core/client/directives/tr-editor.client.directive.js +++ b/modules/core/client/directives/tr-editor.client.directive.js @@ -1,123 +1,121 @@ import MediumEditor from 'medium-editor/dist/js/medium-editor'; -(function () { - /** - * Directive to embed Medium Editor instances - * - * Medium editor: https://github.com/yabwe/medium-editor - * - * Fork of https://github.com/thijsw/angular-medium-editor - * Original By Thijs Wijnmaalen (The MIT License) - * - * - * Use as an attribute: - * ```html - *

- * ``` - * - * Pass options with `tr-editor-options` attribute: - * ```html - *

- * ``` - * - * See MediumEditor's options documentation for details: - * @link https://github.com/yabwe/medium-editor#mediumeditor-options - * - * ## Examples - * - * #### Single line, no toolbar - * Header example limited to one line and no toolbar - * ```html - *

- * ``` - * - * #### Multiline with custom toolbar - * Paragraph with support for multiple lines and customized toolbar buttons - * ```html - *

- * ``` - * - * #### Apply function on control+enter - * ```html - *

- *

- * ``` - * - */ - angular - .module('core') - .directive('trEditor', trEditorDirective); +/** + * Directive to embed Medium Editor instances + * + * Medium editor: https://github.com/yabwe/medium-editor + * + * Fork of https://github.com/thijsw/angular-medium-editor + * Original By Thijs Wijnmaalen (The MIT License) + * + * + * Use as an attribute: + * ```html + *

+ * ``` + * + * Pass options with `tr-editor-options` attribute: + * ```html + *

+ * ``` + * + * See MediumEditor's options documentation for details: + * @link https://github.com/yabwe/medium-editor#mediumeditor-options + * + * ## Examples + * + * #### Single line, no toolbar + * Header example limited to one line and no toolbar + * ```html + *

+ * ``` + * + * #### Multiline with custom toolbar + * Paragraph with support for multiple lines and customized toolbar buttons + * ```html + *

+ * ``` + * + * #### Apply function on control+enter + * ```html + *

+ *

+ * ``` + * + */ +angular + .module('core') + .directive('trEditor', trEditorDirective); - /* @ngInject */ - function trEditorDirective($parse) { +/* @ngInject */ +function trEditorDirective($parse) { - function toInnerText(value) { - // eslint-disable-next-line angular/document-service - const tempEl = document.createElement('div'); - tempEl.innerHTML = value; - const text = tempEl.textContent || ''; - return text.trim(); - } - - return { - require: 'ngModel', - restrict: 'AE', - scope: { - trEditorOptions: '=', - }, - link: function (scope, iElement, iAttrs, ngModel) { - - const angularIElement = angular.element(iElement); + function toInnerText(value) { + // eslint-disable-next-line angular/document-service + const tempEl = document.createElement('div'); + tempEl.innerHTML = value; + const text = tempEl.textContent || ''; + return text.trim(); + } - angularIElement.addClass('tr-editor'); + return { + require: 'ngModel', + restrict: 'AE', + scope: { + trEditorOptions: '=', + }, + link: function (scope, iElement, iAttrs, ngModel) { - ngModel.editor = new MediumEditor(iElement, scope.trEditorOptions); + const angularIElement = angular.element(iElement); - ngModel.$render = function () { - iElement.html(ngModel.$viewValue || ''); + angularIElement.addClass('tr-editor'); - const placeholder = ngModel.editor.getExtensionByName('placeholder'); - if (placeholder) { - placeholder.updatePlaceholder(iElement[0]); - } - }; + ngModel.editor = new MediumEditor(iElement, scope.trEditorOptions); - ngModel.$isEmpty = function (value) { - if (/[<>]/.test(value)) { - return toInnerText(value).length === 0; - } else if (value) { - return value.length === 0; - } else { - return true; - } - }; + ngModel.$render = function () { + iElement.html(ngModel.$viewValue || ''); - ngModel.editor.subscribe('editableInput', function (event, editable) { - ngModel.$setViewValue(editable.innerHTML.trim()); - }); + const placeholder = ngModel.editor.getExtensionByName('placeholder'); + if (placeholder) { + placeholder.updatePlaceholder(iElement[0]); + } + }; - // On ctrl+enter - if (iAttrs.trEditorOnCtrlEnter) { - ngModel.editor.subscribe('editableKeydownEnter', function (event) { - if (event.ctrlKey) { - event.preventDefault(); - // Apply linked function - $parse(iAttrs.trEditorOnCtrlEnter)(scope.$parent); - } - }); + ngModel.$isEmpty = function (value) { + if (/[<>]/.test(value)) { + return toInnerText(value).length === 0; + } else if (value) { + return value.length === 0; + } else { + return true; } + }; + + ngModel.editor.subscribe('editableInput', function (event, editable) { + ngModel.$setViewValue(editable.innerHTML.trim()); + }); - scope.$watch('trEditorOptions', function (trEditorOptions) { - ngModel.editor.init(iElement, trEditorOptions); + // On ctrl+enter + if (iAttrs.trEditorOnCtrlEnter) { + ngModel.editor.subscribe('editableKeydownEnter', function (event) { + if (event.ctrlKey) { + event.preventDefault(); + // Apply linked function + $parse(iAttrs.trEditorOnCtrlEnter)(scope.$parent); + } }); - }, - }; - } -}()); + } + + scope.$watch('trEditorOptions', function (trEditorOptions) { + ngModel.editor.init(iElement, trEditorOptions); + }); + }, + }; +} diff --git a/modules/core/client/directives/tr-flashcards.client.directive.js b/modules/core/client/directives/tr-flashcards.client.directive.js index 3e264edd3b..6de2d1e0b1 100644 --- a/modules/core/client/directives/tr-flashcards.client.directive.js +++ b/modules/core/client/directives/tr-flashcards.client.directive.js @@ -1,53 +1,51 @@ -(function () { - /** - * Directive to embed Trustroots host guide flashcards - * - * See also `guide` page under `pages` module. - * - * Use as an attribute: - * ```html - *

- * ``` - * - */ - angular - .module('core') - .directive('trFlashcards', trFlashcardsDirective); +/** + * Directive to embed Trustroots host guide flashcards + * + * See also `guide` page under `pages` module. + * + * Use as an attribute: + * ```html + *

+ * ``` + * + */ +angular + .module('core') + .directive('trFlashcards', trFlashcardsDirective); - /* @ngInject */ - function trFlashcardsDirective() { - return { - restrict: 'A', - template: '' + - ' Tip' + - '

' + - '

' + - '
', - link: function (scope) { +/* @ngInject */ +function trFlashcardsDirective() { + return { + restrict: 'A', + template: '' + + ' Tip' + + '

' + + '

' + + '
', + link: function (scope) { - const flashcards = [{ - title: 'Make sure your profile is complete', - content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.', - }, { - title: 'Tell a little bit about yourself', - content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.', - }, { - title: 'Explain to them why you are choosing them', - content: '...explaining that you are interested in meeting them, not just looking for free accommodation.', - }, { - title: 'Tell your host why you\'re on a trip', - content: 'What are your expectations in regards with going through their town?', - }, { - title: 'Trustroots is very much about spontaneous travel', - content: 'Don\'t write to people 2 months ahead.', - }]; + const flashcards = [{ + title: 'Make sure your profile is complete', + content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.', + }, { + title: 'Tell a little bit about yourself', + content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.', + }, { + title: 'Explain to them why you are choosing them', + content: '...explaining that you are interested in meeting them, not just looking for free accommodation.', + }, { + title: 'Tell your host why you\'re on a trip', + content: 'What are your expectations in regards with going through their town?', + }, { + title: 'Trustroots is very much about spontaneous travel', + content: 'Don\'t write to people 2 months ahead.', + }]; - const randomFlashcard = flashcards[Math.floor(Math.random() * flashcards.length)]; + const randomFlashcard = flashcards[Math.floor(Math.random() * flashcards.length)]; - scope.flashTitle = randomFlashcard.title; - scope.flashContent = randomFlashcard.content; + scope.flashTitle = randomFlashcard.title; + scope.flashContent = randomFlashcard.content; - }, - }; - } -}()); + }, + }; +} diff --git a/modules/core/client/directives/tr-focustip.client.directive.js b/modules/core/client/directives/tr-focustip.client.directive.js index 5fa1ca3db7..4fed397edf 100644 --- a/modules/core/client/directives/tr-focustip.client.directive.js +++ b/modules/core/client/directives/tr-focustip.client.directive.js @@ -1,43 +1,41 @@ -(function () { - /** - * Directive that simply Adds a helper text under the input and shows/hides it on focus/blur - * - * Usage: - * - * - * Note that currently this directive uses isolated scope, so you can't combine it with other isolate scope directives. - */ - angular - .module('core') - .directive('trFocustip', trFocustipDirective); +/** + * Directive that simply Adds a helper text under the input and shows/hides it on focus/blur + * + * Usage: + * + * + * Note that currently this directive uses isolated scope, so you can't combine it with other isolate scope directives. + */ +angular + .module('core') + .directive('trFocustip', trFocustipDirective); - /* @ngInject */ - function trFocustipDirective($compile) { - return { - restrict: 'A', - replace: false, - scope: { - trFocustip: '=', - }, - link: function (scope, element) { +/* @ngInject */ +function trFocustipDirective($compile) { + return { + restrict: 'A', + replace: false, + scope: { + trFocustip: '=', + }, + link: function (scope, element) { - // Compiled template - // after() requires jQuery - const template = $compile('
' + scope.trFocustip + '
')(scope); - element.after(template); + // Compiled template + // after() requires jQuery + const template = $compile('
' + scope.trFocustip + '
')(scope); + element.after(template); - element - .bind('focus', function () { - // Enable only if there's some text to show - scope.enabled = (angular.isString(scope.trFocustip) && scope.trFocustip !== ''); - scope.$apply(); - }) - .bind('blur', function () { - scope.enabled = false; - scope.$apply(); - }); + element + .bind('focus', function () { + // Enable only if there's some text to show + scope.enabled = (angular.isString(scope.trFocustip) && scope.trFocustip !== ''); + scope.$apply(); + }) + .bind('blur', function () { + scope.enabled = false; + scope.$apply(); + }); - }, - }; - } -}()); + }, + }; +} diff --git a/modules/core/client/directives/tr-highlight-on-focus.client.directive.js b/modules/core/client/directives/tr-highlight-on-focus.client.directive.js index 5235e58a39..991892b08a 100644 --- a/modules/core/client/directives/tr-highlight-on-focus.client.directive.js +++ b/modules/core/client/directives/tr-highlight-on-focus.client.directive.js @@ -1,29 +1,27 @@ -(function () { - /** - * Directive that selects/highlights all text on input when clicking it. - * - * Usage: - * - * - * Thanks to Martin: - * @link http://stackoverflow.com/a/14996261/1984644 - */ - angular - .module('core') - .directive('trSelectOnClick', trSelectOnClickDirective); +/** + * Directive that selects/highlights all text on input when clicking it. + * + * Usage: + * + * + * Thanks to Martin: + * @link http://stackoverflow.com/a/14996261/1984644 + */ +angular + .module('core') + .directive('trSelectOnClick', trSelectOnClickDirective); - /* @ngInject */ - function trSelectOnClickDirective($window) { - return { - restrict: 'A', - link: function (scope, element) { - element.on('click', function () { - if (!$window.getSelection().toString()) { - // Required for mobile Safari - this.setSelectionRange(0, this.value.length); - } - }); - }, - }; - } -}()); +/* @ngInject */ +function trSelectOnClickDirective($window) { + return { + restrict: 'A', + link: function (scope, element) { + element.on('click', function () { + if (!$window.getSelection().toString()) { + // Required for mobile Safari + this.setSelectionRange(0, this.value.length); + } + }); + }, + }; +} diff --git a/modules/core/client/directives/tr-languages.client.directive.js b/modules/core/client/directives/tr-languages.client.directive.js index 44df1b127f..81fc0fb692 100644 --- a/modules/core/client/directives/tr-languages.client.directive.js +++ b/modules/core/client/directives/tr-languages.client.directive.js @@ -1,118 +1,116 @@ -(function () { - /** - * Directive to select languages - * - * Accepts and ouputs a list of language keys: - * `['fi_FI', 'fr_FR', ...]` - * - * Usage: - * ``` - *
- * ``` - * - * Since directive is transcluded, you can do so: - * ``` - *
- * ``` - */ - angular - .module('core') - .directive('trLanguages', trLanguagesDirective); +/** + * Directive to select languages + * + * Accepts and ouputs a list of language keys: + * `['fi_FI', 'fr_FR', ...]` + * + * Usage: + * ``` + *
+ * ``` + * + * Since directive is transcluded, you can do so: + * ``` + *
+ * ``` + */ +angular + .module('core') + .directive('trLanguages', trLanguagesDirective); - /* @ngInject */ - function trLanguagesDirective() { - const directive = { - restrict: 'A', - replace: true, - transclude: true, - template: '', - scope: { - output: '=trLanguages', - onChange: '@trLanguagesOnChange', - }, - controller: trLanguagesDirectiveController, - controllerAs: 'trLanguages', - }; - - return directive; - - /* @ngInject */ - function trLanguagesDirectiveController($scope, Languages) { +/* @ngInject */ +function trLanguagesDirective() { + const directive = { + restrict: 'A', + replace: true, + transclude: true, + template: '', + scope: { + output: '=trLanguages', + onChange: '@trLanguagesOnChange', + }, + controller: trLanguagesDirectiveController, + controllerAs: 'trLanguages', + }; - // View model - const vm = this; + return directive; - // Exposed to the view - vm.languages = Languages.get('array'); - vm.selectedLanguages = []; + /* @ngInject */ + function trLanguagesDirectiveController($scope, Languages) { - activate(); + // View model + const vm = this; - /** - * Initialize controller - */ - function activate() { + // Exposed to the view + vm.languages = Languages.get('array'); + vm.selectedLanguages = []; - // Ensure output is always an array, even on initialization - if (!$scope.output || !angular.isArray($scope.output)) { - $scope.output = []; - } + activate(); - // Pick previously populated languages - decodeSelectedLanguages(); + /** + * Initialize controller + */ + function activate() { - // Watch for changes in select and encode to array on changes - $scope.$watch('trLanguages.selectedLanguages', function (newValue, oldValue) { - if (newValue.length !== oldValue.length) { - encodeSelectedLanguages(); - } - }); + // Ensure output is always an array, even on initialization + if (!$scope.output || !angular.isArray($scope.output)) { + $scope.output = []; } - /** - * Formats array for Chosen selector: - * `[{'fi_FI': 'Finnish'}, {'fr_FR': 'French'}, ... }]` - * - * This array is used only internally for this directive. - */ - function decodeSelectedLanguages() { - const selections = []; - if ($scope.output.length > 0) { - $scope.output.forEach(function (key) { - if (angular.isString(key)) { - this.push({ - 'key': key, - 'name': vm.languages[key], - }); - } - }, selections); - vm.selectedLanguages = selections; + // Pick previously populated languages + decodeSelectedLanguages(); + + // Watch for changes in select and encode to array on changes + $scope.$watch('trLanguages.selectedLanguages', function (newValue, oldValue) { + if (newValue.length !== oldValue.length) { + encodeSelectedLanguages(); } - } + }); + } - /** - * Formats array of language keys from Chosen array: - * `['fi_FI', 'fr_FR', ...]` - * - * This is the output format for this directive. - */ - function encodeSelectedLanguages() { - const keys = []; - angular.forEach(vm.selectedLanguages, function (language) { - this.push(String(language.key)); - }, keys); - $scope.output = keys; + /** + * Formats array for Chosen selector: + * `[{'fi_FI': 'Finnish'}, {'fr_FR': 'French'}, ... }]` + * + * This array is used only internally for this directive. + */ + function decodeSelectedLanguages() { + const selections = []; + if ($scope.output.length > 0) { + $scope.output.forEach(function (key) { + if (angular.isString(key)) { + this.push({ + 'key': key, + 'name': vm.languages[key], + }); + } + }, selections); + vm.selectedLanguages = selections; } } + /** + * Formats array of language keys from Chosen array: + * `['fi_FI', 'fr_FR', ...]` + * + * This is the output format for this directive. + */ + function encodeSelectedLanguages() { + const keys = []; + angular.forEach(vm.selectedLanguages, function (language) { + this.push(String(language.key)); + }, keys); + $scope.output = keys; + } } -}()); + +} diff --git a/modules/core/client/directives/tr-location.client.directive.js b/modules/core/client/directives/tr-location.client.directive.js index bc95fc560c..c76c79720c 100644 --- a/modules/core/client/directives/tr-location.client.directive.js +++ b/modules/core/client/directives/tr-location.client.directive.js @@ -1,151 +1,149 @@ -(function () { - /** - * Directive to extend to have location auto suggestions - * - * Based on Typeahead (ui.bootstrap.typeahead) - * @link http://angular-ui.github.io/bootstrap/#!#typeahead - * - * Usage: - * `` - * - * Usage with Angular-UI-Leaflet: - * `` - * - * You can also pass custom minimum length and delay options for Typeahead: - * `` - * - * Defaults for these are - * - typeahead-min-length: 3 - * - typeahead-wait-ms: 300 - * - * Note that this directive will re-render input element using $compile. - */ - angular - .module('core') - .directive('trLocation', trLocationDirective); - - /* @ngInject */ - function trLocationDirective($compile, $timeout, LocationService) { - return { - restrict: 'A', - require: 'ngModel', - scope: { - value: '=ngModel', - // `?` makes these optional - limitLocationTypes: '=?', - trLocationChange: '=?', - trLocationNotfound: '=?', - trLocationCenter: '=?', - trLocationBounds: '=?', - }, - replace: false, - link: function (scope, element, attr, ngModel) { - - // Event handler to stop submitting the surrounding form - element.bind('keydown keypress focus', function ($event) { - scope.trLocationNotfound = false; - - // On enter - if ($event.which === 13) { - // Signal to controller that enter was pressed - scope.skipSuggestions = true; - $event.preventDefault(); +/** + * Directive to extend to have location auto suggestions + * + * Based on Typeahead (ui.bootstrap.typeahead) + * @link http://angular-ui.github.io/bootstrap/#!#typeahead + * + * Usage: + * `` + * + * Usage with Angular-UI-Leaflet: + * `` + * + * You can also pass custom minimum length and delay options for Typeahead: + * `` + * + * Defaults for these are + * - typeahead-min-length: 3 + * - typeahead-wait-ms: 300 + * + * Note that this directive will re-render input element using $compile. + */ +angular + .module('core') + .directive('trLocation', trLocationDirective); + +/* @ngInject */ +function trLocationDirective($compile, $timeout, LocationService) { + return { + restrict: 'A', + require: 'ngModel', + scope: { + value: '=ngModel', + // `?` makes these optional + limitLocationTypes: '=?', + trLocationChange: '=?', + trLocationNotfound: '=?', + trLocationCenter: '=?', + trLocationBounds: '=?', + }, + replace: false, + link: function (scope, element, attr, ngModel) { + + // Event handler to stop submitting the surrounding form + element.bind('keydown keypress focus', function ($event) { + scope.trLocationNotfound = false; + + // On enter + if ($event.which === 13) { + // Signal to controller that enter was pressed + scope.skipSuggestions = true; + $event.preventDefault(); + } else { + scope.skipSuggestions = false; + } + }); + + // Attach Angular UI Bootstrap TypeAhead + // @link http://angular-ui.github.io/bootstrap/#!#typeahead + element.attr('typeahead-min-length', attr.typeaheadMinLength ? parseInt(attr.typeaheadMinLength, 10) : 3); + element.attr('typeahead-wait-ms', attr.typeaheadWaitMs ? parseInt(attr.typeaheadWaitMs, 10) : 300); + element.attr('typeahead-on-select', 'trLocation.onSelect($item, $model, $label, $event)'); + element.attr('uib-typeahead', 'trTitle as address.trTitle for address in trLocation.searchSuggestions(' + + getQueryParameters(scope.limitLocationTypes) + ')'); + + function getQueryParameters(limitLocationTypes) { + return limitLocationTypes ? '$viewValue, "country,region,place,locality,neighborhood"' : '$viewValue'; + } + + // Stop infinite rendering on $compile + element.removeAttr('tr-location'); + + $compile(element)(scope); + + // Without this input value would be left empty due $compile + // @todo: any better way of handling this? + $timeout(function () { + ngModel.$setViewValue(scope.value); + ngModel.$render(); + }); + + }, + controllerAs: 'trLocation', + controller: function ($scope, $timeout) { + + // View Model + const vm = this; + + vm.searchSuggestions = searchSuggestions; + vm.onSelect = onSelect; + + /** + * Get geolocation suggestions + */ + function searchSuggestions(query, types) { + $scope.trLocationNotfound = false; + return LocationService.suggestions(query, types).then(function (suggestions) { + // Enter was pressed before we got these results, thus just pick first + if ($scope.skipSuggestions) { + $scope.skipSuggestions = false; + if (suggestions.length) { + locate(suggestions[0]); + $scope.value = suggestions[0].trTitle; + } else { + // Don't return suggestions list + $scope.trLocationNotfound = query; + } + // Don't return suggestions list + return []; } else { - scope.skipSuggestions = false; + // Return suggestions list + return suggestions; } }); + } - // Attach Angular UI Bootstrap TypeAhead - // @link http://angular-ui.github.io/bootstrap/#!#typeahead - element.attr('typeahead-min-length', attr.typeaheadMinLength ? parseInt(attr.typeaheadMinLength, 10) : 3); - element.attr('typeahead-wait-ms', attr.typeaheadWaitMs ? parseInt(attr.typeaheadWaitMs, 10) : 300); - element.attr('typeahead-on-select', 'trLocation.onSelect($item, $model, $label, $event)'); - element.attr('uib-typeahead', 'trTitle as address.trTitle for address in trLocation.searchSuggestions(' - + getQueryParameters(scope.limitLocationTypes) + ')'); - - function getQueryParameters(limitLocationTypes) { - return limitLocationTypes ? '$viewValue, "country,region,place,locality,neighborhood"' : '$viewValue'; - } - - // Stop infinite rendering on $compile - element.removeAttr('tr-location'); - - $compile(element)(scope); - - // Without this input value would be left empty due $compile - // @todo: any better way of handling this? + /** + * When selecting autosuggested location + */ + function onSelect($item, $model, $label) { $timeout(function () { - ngModel.$setViewValue(scope.value); - ngModel.$render(); + $scope.value = $label; }); - - }, - controllerAs: 'trLocation', - controller: function ($scope, $timeout) { - - // View Model - const vm = this; - - vm.searchSuggestions = searchSuggestions; - vm.onSelect = onSelect; - - /** - * Get geolocation suggestions - */ - function searchSuggestions(query, types) { - $scope.trLocationNotfound = false; - return LocationService.suggestions(query, types).then(function (suggestions) { - // Enter was pressed before we got these results, thus just pick first - if ($scope.skipSuggestions) { - $scope.skipSuggestions = false; - if (suggestions.length) { - locate(suggestions[0]); - $scope.value = suggestions[0].trTitle; - } else { - // Don't return suggestions list - $scope.trLocationNotfound = query; - } - // Don't return suggestions list - return []; - } else { - // Return suggestions list - return suggestions; - } - }); + locate($item); + } + + /** + * Modify `trLocationCenter` or `trLocationBounds` objects + */ + function locate(location) { + + // Set center bounds and center coordinates for (Angular-UI-Leaflet) model + const bounds = LocationService.getBounds(location); + const center = LocationService.getCenter(location); + + if (angular.isObject($scope.trLocationBounds) && bounds) { + $scope.trLocationBounds = bounds; + } else if (angular.isObject($scope.trLocationCenter) && center) { + angular.extend($scope.trLocationCenter, center); + } else if (angular.isFunction($scope.trLocationChange) && bounds) { + $scope.trLocationChange(bounds, 'bounds'); + } else if (angular.isFunction($scope.trLocationChange) && center) { + $scope.trLocationChange(center, 'center'); } - /** - * When selecting autosuggested location - */ - function onSelect($item, $model, $label) { - $timeout(function () { - $scope.value = $label; - }); - locate($item); - } - - /** - * Modify `trLocationCenter` or `trLocationBounds` objects - */ - function locate(location) { - - // Set center bounds and center coordinates for (Angular-UI-Leaflet) model - const bounds = LocationService.getBounds(location); - const center = LocationService.getCenter(location); - - if (angular.isObject($scope.trLocationBounds) && bounds) { - $scope.trLocationBounds = bounds; - } else if (angular.isObject($scope.trLocationCenter) && center) { - angular.extend($scope.trLocationCenter, center); - } else if (angular.isFunction($scope.trLocationChange) && bounds) { - $scope.trLocationChange(bounds, 'bounds'); - } else if (angular.isFunction($scope.trLocationChange) && center) { - $scope.trLocationChange(center, 'center'); - } - - } + } - }, - }; - } -}()); + }, + }; +} diff --git a/modules/core/client/directives/tr-page-title.client.directive.js b/modules/core/client/directives/tr-page-title.client.directive.js index 07755076b2..ab204b11cd 100644 --- a/modules/core/client/directives/tr-page-title.client.directive.js +++ b/modules/core/client/directives/tr-page-title.client.directive.js @@ -1,27 +1,25 @@ -(function () { - angular.module('core') - .directive('trPageTitle', trPageTitle); +angular.module('core') + .directive('trPageTitle', trPageTitle); - /* @ngInject */ - function trPageTitle($rootScope, $interpolate, $state, $window) { - const directive = { - restrict: 'A', - link: link, - }; +/* @ngInject */ +function trPageTitle($rootScope, $interpolate, $state, $window) { + const directive = { + restrict: 'A', + link: link, + }; - return directive; + return directive; - function link(scope, element) { - $rootScope.$on('$stateChangeSuccess', listener); + function link(scope, element) { + $rootScope.$on('$stateChangeSuccess', listener); - function listener(event, toState) { - if (toState.data && toState.data.pageTitle) { - const stateTitle = $interpolate(toState.data.pageTitle)($state.$current.locals.globals); - element.html(stateTitle + ' - Trustroots'); - } else { - element.html($window.title); - } + function listener(event, toState) { + if (toState.data && toState.data.pageTitle) { + const stateTitle = $interpolate(toState.data.pageTitle)($state.$current.locals.globals); + element.html(stateTitle + ' - Trustroots'); + } else { + element.html($window.title); } } } -}()); +} diff --git a/modules/core/client/directives/tr-placeholder.client.directive.js b/modules/core/client/directives/tr-placeholder.client.directive.js index f6aa50882b..2a501958de 100644 --- a/modules/core/client/directives/tr-placeholder.client.directive.js +++ b/modules/core/client/directives/tr-placeholder.client.directive.js @@ -1,19 +1,17 @@ -(function () { - angular - .module('core') - .directive('trPlaceholder', trPlaceholderDirective); +angular + .module('core') + .directive('trPlaceholder', trPlaceholderDirective); - function trPlaceholderDirective() { - return { - restrict: 'A', - replace: true, - scope: false, - template: - '
' + - 'Lorem ipsum
' + - 'Lorem ipsum Lorem ipsum Lorem
' + - 'Lorem ipsum Lorem ipsum.' + - '
', - }; - } -}()); +function trPlaceholderDirective() { + return { + restrict: 'A', + replace: true, + scope: false, + template: + '
' + + 'Lorem ipsum
' + + 'Lorem ipsum Lorem ipsum Lorem
' + + 'Lorem ipsum Lorem ipsum.' + + '
', + }; +} diff --git a/modules/core/client/directives/tr-share-fb.client.directive.js b/modules/core/client/directives/tr-share-fb.client.directive.js index 19fc6dbcc9..d09b6c6b85 100644 --- a/modules/core/client/directives/tr-share-fb.client.directive.js +++ b/modules/core/client/directives/tr-share-fb.client.directive.js @@ -1,71 +1,69 @@ /* global FB */ -(function () { - /** - * FB share button for current URL - * - * Usage: - * ``` - *
- * ``` - */ - angular - .module('core') - .directive('trShareFb', trShareFbDirective); +/** + * FB share button for current URL + * + * Usage: + * ``` + *
+ * ``` + */ +angular + .module('core') + .directive('trShareFb', trShareFbDirective); - /* @ngInject */ - function trShareFbDirective($rootScope, $window, Authentication) { +/* @ngInject */ +function trShareFbDirective($rootScope, $window, Authentication) { - return { - restrict: 'A', - replace: true, - scope: false, - link: trShareFbDirectiveLink, - }; + return { + restrict: 'A', + replace: true, + scope: false, + link: trShareFbDirectiveLink, + }; - function trShareFbDirectiveLink(scope, element) { + function trShareFbDirectiveLink(scope, element) { - // Don't show share button if user isn't connected to FB - if (!Authentication.user || !Authentication.user.additionalProvidersData || !Authentication.user.additionalProvidersData.facebook) { - return; - } + // Don't show share button if user isn't connected to FB + if (!Authentication.user || !Authentication.user.additionalProvidersData || !Authentication.user.additionalProvidersData.facebook) { + return; + } - // FB API ready, activate - if (angular.isDefined($window.FB)) { + // FB API ready, activate + if (angular.isDefined($window.FB)) { + activate(); + } else { + // FB API was not ready, wait for the ready event + const watch = $rootScope.$on('facebookReady', function () { activate(); - } else { - // FB API was not ready, wait for the ready event - const watch = $rootScope.$on('facebookReady', function () { - activate(); - // Removes watch: - watch(); - }); - } - - /** - * Activate directive - * https://developers.facebook.com/docs/plugins/share-button - */ - function activate() { + // Removes watch: + watch(); + }); + } - const button = '
' + - ' ' + - ' Share' + - ' ' + - '
'; + /** + * Activate directive + * https://developers.facebook.com/docs/plugins/share-button + */ + function activate() { - element.html(button); + const button = '
' + + ' ' + + ' Share' + + ' ' + + '
'; - // Parse XFBML code - FB.XFBML.parse(element[0]); - } + element.html(button); + // Parse XFBML code + FB.XFBML.parse(element[0]); } + } -}()); +} diff --git a/modules/core/client/directives/tr-share-twitter.client.directive.js b/modules/core/client/directives/tr-share-twitter.client.directive.js index 0c76eef9c7..21d0df993c 100644 --- a/modules/core/client/directives/tr-share-twitter.client.directive.js +++ b/modules/core/client/directives/tr-share-twitter.client.directive.js @@ -1,98 +1,96 @@ /* global twttr */ -(function () { - /** - * Twitter share button for current URL - * - * Usage: - * ``` - *
- * ``` - * - * With predefined tweet text: - * ``` - *
- * ``` - */ - angular - .module('core') - .directive('trShareTwitter', trShareTwitterDirective); - - /* @ngInject */ - function trShareTwitterDirective($window, $document) { - - return { - restrict: 'A', - replace: true, - scope: false, - link: trShareTwitterDirectiveLink, - }; - - function trShareTwitterDirectiveLink(scope, element, attrs) { - - activate(); - - /** - * Activate directive - * @link https://dev.twitter.com/web/tweet-button - */ - function activate() { - - let button = '