From c68b8e5fd060f4850e3ba6263d2e8a105f2b60b3 Mon Sep 17 00:00:00 2001 From: Daniel Bisgrove Date: Wed, 11 Oct 2023 09:02:24 -0400 Subject: [PATCH 1/6] Updating ESLint and Prettier rules --- .eslintrc.json | 55 +++++++++++++++++++++++++++++++++----------------- .prettierrc.js | 4 ++++ package.json | 4 ++++ 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 273feb0838..bb2829b83c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,7 +7,13 @@ "env": { "browser": true }, - "extends": ["angular"], + "extends": [ + "eslint:recommended", + "plugin:prettier/recommended", + "angular", + "standard", + "prettier" + ], "overrides": [ { "files": ["app/assets/javascripts/angular/**/*.spec.js"], @@ -25,18 +31,39 @@ ], "plugins": ["import"], "rules": { + "angular/definedundefined": "off", + "angular/typecheck-string": "off", + "angular/no-service-method": "off", + "angular/window-service": "off", "block-scoped-var": "error", + "consistent-this": ["error", "_this", "vm"], "dot-notation": "error", "eqeqeq": ["error", "smart"], + "max-len": [ + "error", + { + "code": 120, + "ignoreRegExpLiterals": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true, + "ignoreTrailingComments": true, + "ignoreUrls": true + } + ], "import/order": [ 2, { "newlines-between": "always" } ], + "new-cap": "error", + "new-parens": "error", "no-alert": "warn", + "no-array-constructor": "error", + "no-bitwise": "error", "no-caller": "error", "no-case-declarations": "error", + "no-continue": "error", "no-eval": "error", "no-extend-native": "error", "no-extra-bind": "error", @@ -44,13 +71,16 @@ "no-global-assign": "error", "no-implied-eval": "error", "no-iterator": "error", + "no-lonely-if": "error", "no-label-var": "error", "no-labels": "error", "no-lone-blocks": "error", "no-loop-func": "error", "no-multi-str": "error", + "no-negated-condition": "error", "no-new": "error", "no-new-func": "error", + "no-new-object": "error", "no-new-wrappers": "error", "no-octal-escape": "error", "no-param-reassign": "error", @@ -61,6 +91,7 @@ "no-shadow-restricted-names": "error", "no-throw-literal": "error", "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", "no-unsafe-negation": "error", "no-useless-call": "error", "no-useless-concat": "error", @@ -68,25 +99,13 @@ "no-useless-return": "error", "no-void": "error", "no-with": "error", + "prettier/prettier": [ + "error", + { "singleQuote": true, "tabWidth": 2 } + ], "radix": "error", "strict": ["error", "function"], "wrap-iife": ["error", "inside"], - "yoda": "error", - - "consistent-this": ["error", "_this", "vm"], - "new-cap": "error", - "new-parens": "error", - "no-array-constructor": "error", - "no-bitwise": "error", - "no-continue": "error", - "no-lonely-if": "error", - "no-negated-condition": "error", - "no-new-object": "error", - "no-unneeded-ternary": "error", - - "angular/definedundefined": "off", - "angular/typecheck-string": "off", - "angular/no-service-method": "off", - "angular/window-service": "off" + "yoda": "error" } } diff --git a/.prettierrc.js b/.prettierrc.js index af572f2c0d..250a8e9c99 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,4 +1,8 @@ module.exports = { singleQuote: true, trailingComma: 'all', + arrowParens: 'always', + semi: true, + printWidth: 120, + tabWidth: 2, }; diff --git a/package.json b/package.json index 0ecd8535d2..d8c75b9b1c 100644 --- a/package.json +++ b/package.json @@ -70,10 +70,14 @@ "eslint": "^7.13.0", "eslint-config-angular": "^0.5.0", "eslint-config-prettier": "^6.15.0", + "eslint-config-standard": "^17.1.0", "eslint-loader": "^4.0.2", "eslint-plugin-angular": "^4.0.1", "eslint-plugin-import": "^2.20.2", + "eslint-plugin-n": "^16.2.0", "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-standard": "^5.0.0", "favicons-webpack-plugin": "^4.2.0", "file-loader": "^6.0.0", "html-loader": "^1.3.2", From db16220854526830894b914d448d4faf9c5f5dbc Mon Sep 17 00:00:00 2001 From: Daniel Bisgrove Date: Wed, 11 Oct 2023 09:02:40 -0400 Subject: [PATCH 2/6] Ran ESLint:fix and Prettier:fix --- app/app.component.js | 56 +- app/app.html | 48 +- .../javascripts/angular/all-tests.spec.js | 37 +- .../angular/campusContactsApp.config.js | 280 ++- .../angular/campusContactsApp.constants.js | 10 +- .../angular/campusContactsApp.module.js | 30 +- .../angular/campusContactsApp.routes.js | 1209 +++++----- .../angular/campusContactsApp.run.js | 108 +- .../aboutModal/aboutModal.component.js | 50 +- .../components/aboutModal/aboutModal.html | 56 +- .../accordion/accordion.component.js | 40 +- .../components/accordion/accordion.html | 10 +- .../accordionToggle.component.js | 22 +- .../accordionToggle/accordionToggle.html | 18 +- .../answerSheet/answerSheet.component.js | 46 +- .../components/answerSheet/answerSheet.html | 24 +- .../editAnswerSheetModal.component.js | 72 +- .../answerSheet/editAnswerSheetModal.html | 134 +- .../assignedLabelSelect.component.js | 66 +- .../assignedLabelSelect.html | 22 +- .../assignedLabelSelect.service.js | 40 +- .../assignedPeopleSelect.component.js | 74 +- .../assignedPeopleSelect.html | 40 +- .../assignedPeopleSelect.service.js | 72 +- .../assignedPeopleSelect.service.spec.js | 42 +- .../asyncContent/asyncContent.component.js | 10 +- .../contactActions.component.js | 22 +- .../contactActions/contactActions.html | 148 +- .../copySurvey/copySurvey.component.js | 88 +- .../components/copySurvey/copySurvey.html | 69 +- .../createSurvey/createSurvey.component.js | 69 +- .../components/createSurvey/createSurvey.html | 47 +- .../dashboard/dashboard.component.js | 35 +- .../subnav/dashboard-subnav.component.js | 16 +- .../dashboard/subnav/dashboard-subnav.html | 156 +- .../editAddress/editAddress.component.js | 183 +- .../components/editAddress/editAddress.html | 158 +- .../editAddress/editAddress.service.js | 131 +- .../editAddress/editAddress.service.spec.js | 323 ++- .../editGroup/editGroup.component.js | 138 +- .../components/editGroup/editGroup.html | 185 +- .../components/editGroup/editGroup.service.js | 16 +- .../editGroupOrLabelAssignments.component.js | 201 +- .../editGroupOrLabelAssignments.html | 47 +- .../editGroupOrLabelAssignments.service.js | 225 +- .../editLabel/editLabel.component.js | 84 +- .../editLabel/editLabel.component.spec.js | 212 +- .../components/editLabel/editLabel.html | 49 +- .../groupMembersModal.component.js | 259 +- .../groupMembersModal/groupMembersModal.html | 102 +- .../groupMembersModal.service.js | 108 +- .../groupMembersModal.service.spec.js | 116 +- .../iconButton/iconButton.component.js | 28 +- .../components/iconButton/iconButton.html | 8 +- .../iconModal/iconModal.component.js | 12 +- .../components/iconModal/iconModal.html | 72 +- .../interaction/interaction.component.js | 112 +- .../interaction/interaction.component.spec.js | 185 +- .../components/interaction/interaction.html | 89 +- .../loadingSpinner.component.js | 8 +- .../loadingSpinner/loadingSpinner.html | 2 +- .../components/massEdit/massEdit.component.js | 136 +- .../angular/components/massEdit/massEdit.html | 84 +- .../components/massEdit/massEdit.service.js | 895 ++++--- .../massEdit/massEdit.service.spec.js | 1153 ++++----- .../messageModal/messageModal.component.js | 268 +- .../components/messageModal/messageModal.html | 68 +- .../messageModal/messageModal.service.js | 62 +- .../ministryViewGroup.component.js | 138 +- .../ministryViewGroup/ministryViewGroup.html | 44 +- .../ministryViewGroup.service.js | 86 +- .../ministryViewGroup.service.spec.js | 120 +- .../ministryViewLabel.component.js | 71 +- .../ministryViewLabel.component.spec.js | 193 +- .../ministryViewLabel/ministryViewLabel.html | 25 +- .../ministryViewPerson.component.js | 159 +- .../ministryViewPerson.html | 159 +- .../multiselectList.component.js | 102 +- .../multiselectList/multiselectList.html | 30 +- .../multiselectList.service.js | 145 +- .../multiselectList.service.spec.js | 363 ++- .../myOrganizationsDashboard.component.js | 8 +- .../myOrganizationsDashboard.html | 7 +- .../myOrganizationsDashboard.service.js | 45 +- .../myOrganizationsDashboardList.component.js | 46 +- .../myOrganizationsDashboardList.html | 22 +- .../myPeopleDashboard.component.js | 308 ++- .../myPeopleDashboard.component.spec.js | 55 +- .../myPeopleDashboard/myPeopleDashboard.html | 161 +- .../myPeopleDashboard.service.js | 71 +- .../myPeopleDashboard.service.spec.js | 242 +- .../orgManagement/orgManagement.component.js | 10 +- .../orgManagement/orgManagement.html | 13 +- .../orgManagementEdit.component.js | 58 +- .../orgManagement/orgManagementEdit.html | 162 +- .../orgManagementSubOrg.component.js | 150 +- .../orgManagement/orgManagementSubOrg.html | 101 +- .../organization/organization.component.js | 157 +- .../components/organization/organization.html | 167 +- .../organizationBreadcrumbs.component.js | 70 +- .../organizationBreadcrumbs.html | 14 +- .../organizationCleanup.component.js | 151 +- .../organizationCleanup.html | 133 +- .../organizationContactImport.component.js | 68 +- .../organizationContactImport.html | 92 +- ...rganizationContactImportStep1.component.js | 146 +- .../organizationContactImportStep1.html | 200 +- ...rganizationContactImportStep2.component.js | 93 +- .../organizationContactImportStep2.html | 170 +- ...rganizationContactImportStep3.component.js | 262 +- .../organizationContactImportStep3.html | 113 +- ...rganizationContactImportStep4.component.js | 18 +- .../organizationContactImportStep4.html | 38 +- .../organizationOverview.component.js | 175 +- .../organizationOverview.html | 272 +-- .../organizationOverview.service.js | 98 +- .../organizationOverview.service.spec.js | 259 +- .../organizationOverviewGroups.component.js | 44 +- .../organizationOverviewGroups.html | 37 +- .../organizationOverviewLabels.component.js | 34 +- ...ganizationOverviewLabels.component.spec.js | 90 +- .../organizationOverviewLabels.html | 25 +- .../organizationOverviewPeople.component.js | 16 +- .../organizationOverviewPeople.html | 6 +- .../organizationOverviewSuborgs.component.js | 116 +- .../organizationOverviewSuborgs.html | 25 +- .../organizationOverviewSuborgs.service.js | 85 +- ...rganizationOverviewSuborgs.service.spec.js | 115 +- ...zationOverviewSurveyResponses.component.js | 56 +- .../organizationOverviewSurveyResponses.html | 41 +- .../organizationOverviewSurveys.component.js | 176 +- .../organizationOverviewSurveys.html | 236 +- .../organizationOverviewTeam.component.js | 92 +- ...organizationOverviewTeam.component.spec.js | 138 +- .../organizationOverviewTeam.html | 22 +- .../organizationOverviewTeam.service.js | 72 +- .../organizationSignatures.component.js | 217 +- .../organizationSignatures.html | 249 +- .../organizationSignaturesSign.component.js | 158 +- .../organizationSignaturesSign.html | 119 +- .../organizationalStats.component.js | 36 +- .../organizationalStats.html | 32 +- .../peopleFiltersPanel.component.js | 373 ++- .../peopleFiltersPanel.html | 466 ++-- .../peopleFiltersPanel.service.js | 38 +- .../peopleFiltersPanel.service.spec.js | 106 +- .../peopleScreen/peopleScreen.component.js | 915 ++++--- .../peopleScreen.component.spec.js | 44 +- .../components/peopleScreen/peopleScreen.html | 399 ++- .../peopleScreen/peopleScreen.service.js | 440 ++-- .../peopleScreen/peopleScreen.service.spec.js | 111 +- .../peopleViewPerson.component.js | 184 +- .../peopleViewPerson/peopleViewPerson.html | 149 +- .../personActivity.component.js | 76 +- .../personActivity/personActivity.html | 53 +- .../personAssigned.component.js | 28 +- .../personAssigned/personAssigned.html | 19 +- .../personAssigned/personAssigned.service.js | 47 +- .../personHistory/personHistory.component.js | 210 +- .../personHistory.component.spec.js | 98 +- .../personHistory/personHistory.html | 159 +- .../personHistory/personHistory.service.js | 93 +- .../personHistory.service.spec.js | 151 +- .../personMultiselect.component.js | 183 +- .../personMultiselect/personMultiselect.html | 43 +- .../personPage/personPage.component.js | 356 ++- .../components/personPage/personPage.html | 141 +- .../personPage/personPage.service.js | 156 +- .../personProfile/personProfile.component.js | 710 +++--- .../personProfile/personProfile.html | 681 +++--- .../personProfile/personProfile.service.js | 466 ++-- .../personProfile.service.spec.js | 832 +++---- .../preloadState/preloadState.component.js | 37 +- .../publicPhoneNumberValidation.component.js | 8 +- .../publicPhoneNumberValidation.html | 63 +- .../publicSurvey/publicSurvey.component.js | 10 +- .../components/publicSurvey/publicSurvey.html | 131 +- .../confirmMovementIndicators.component.js | 392 ++- .../confirmMovementIndicators.html | 138 +- .../tooltip/tooltip.component.js | 8 +- .../tooltip/tooltip.html | 11 +- .../reportMovementIndicators.component.js | 62 +- .../reportMovementIndicators.html | 30 +- .../suggestedActionsAccordion.component.js | 48 +- .../accordion/suggestedActionsAccordion.html | 130 +- .../suggestedActions.component.js | 156 +- .../suggestedActions/suggestedActions.html | 62 +- .../reportPeriod/reportPeriod.component.js | 12 +- .../components/reportPeriod/reportPeriod.html | 24 +- .../statsHeader/statsHeader.component.js | 16 +- .../components/statsHeader/statsHeader.html | 34 +- .../surveyOverview.component.js | 44 +- .../surveyOverview/surveyOverview.html | 86 +- .../surveyOverviewKeyword.component.js | 214 +- .../surveyOverviewKeyword.html | 264 +- .../autoAssignLabelNotifyModal.component.js | 44 +- .../autoAssignLabelNotifyModal.html | 116 +- .../predefinedQuestionsModal.component.js | 57 +- .../predefinedQuestionsModal.html | 76 +- .../surveyOverviewQuestions.component.js | 948 ++++---- .../surveyOverviewQuestions.html | 383 ++- .../surveyOverviewSettings.component.js | 188 +- .../surveyOverviewSettings.html | 303 +-- .../addSurveyResponseModal.component.js | 12 +- .../addSurveyResponseModal.html | 61 +- .../surveyResponses.component.js | 68 +- .../surveyResponses/surveyResponses.html | 37 +- .../surveyTypeformModal.component.js | 32 +- .../surveyTypeformModal.html | 62 +- .../surveys/surveyForm.component.js | 209 +- .../components/surveys/surveyFormPublic.html | 148 +- .../components/surveys/surveyFormUser.html | 87 +- .../transferModal/transferModal.component.js | 140 +- .../transferModal/transferModal.html | 110 +- .../transferModal/transferModal.service.js | 54 +- .../unsubscribe/unsubscribe.component.js | 52 +- .../components/unsubscribe/unsubscribe.html | 40 +- .../user-preferences.component.js | 64 +- .../user-preferences.component.spec.js | 76 +- .../user-preferences/user-preferences.html | 142 +- .../user-preferences.service.js | 62 +- .../user-preferences.service.spec.js | 8 +- .../angular/decorators/templateRequest.js | 60 +- .../angular/directives/autoGrow.directive.js | 98 +- .../angular/directives/exposeSelect.js | 14 +- .../javascripts/angular/directives/focus.js | 18 +- .../directives/onClickAway.directive.js | 44 +- .../directives/safeSubmit.directive.js | 72 +- .../angular/filters/mailto.filter.js | 6 +- .../angular/filters/personName.filter.js | 26 +- .../angular/filters/phone.filter.js | 80 +- .../angular/filters/translation.filter.js | 10 +- app/assets/javascripts/angular/main.js | 6 +- .../javascripts/angular/rollbar.config.js | 280 +-- .../angular/services/analyticsService.js | 295 ++- .../angular/services/asyncBindings.service.js | 87 +- .../services/authentication.service.js | 401 ++- .../angular/services/confirmModal.service.js | 64 +- .../angular/services/error.service.spec.js | 231 +- .../angular/services/error/error.service.js | 236 +- .../errorRetryToastTemplate.directive.js | 12 +- .../angular/services/facebookService.js | 82 +- .../angular/services/geoData.service.js | 38 +- .../angular/services/geoData.service.spec.js | 46 +- .../angular/services/groups.service.js | 508 ++-- .../angular/services/groups.service.spec.js | 716 +++--- .../angular/services/httpProxy.service.js | 456 ++-- .../services/httpProxy.service.spec.js | 711 +++--- .../angular/services/interactions.service.js | 335 ++- .../services/interactions.service.spec.js | 500 ++-- .../angular/services/labels.service.js | 167 +- .../angular/services/labels.service.spec.js | 376 ++- .../angular/services/localStorage.service.js | 32 +- .../services/loggedInPerson.service.js | 164 +- .../services/loggedInPerson.service.spec.js | 174 +- .../services/ministryViewTabs.service.js | 16 +- .../angular/services/models.service.js | 220 +- .../angular/services/models.service.spec.js | 42 +- .../angular/services/oktaService.js | 65 +- .../angular/services/organization.service.js | 283 +-- .../services/organization.service.spec.js | 203 +- .../angular/services/peopleSearch.service.js | 38 +- .../services/peopleSearch.service.spec.js | 100 +- .../angular/services/period.service.js | 109 +- .../angular/services/permission.service.js | 16 +- .../angular/services/person.service.js | 661 +++-- .../angular/services/person.service.spec.js | 584 +++-- .../angular/services/personSelection.js | 96 +- .../services/personSelection.service.spec.js | 224 +- .../angular/services/personTabs.service.js | 7 +- .../services/progressiveListLoader.service.js | 121 +- .../progressiveListLoader.service.spec.js | 231 +- .../angular/services/reports.service.js | 338 ++- .../angular/services/reports.service.spec.js | 551 ++--- .../services/requestDeduper.service.js | 66 +- .../services/requestDeduper.service.spec.js | 164 +- .../angular/services/routes.service.js | 157 +- .../services/sessionStorage.service.js | 32 +- .../angular/services/state.service.js | 8 +- .../angular/services/survey.service.js | 621 +++-- .../angular/services/survey.service.spec.js | 133 +- .../angular/services/urlHashParserService.js | 36 +- .../services/userPreferences.service.js | 163 +- .../services/userPreferences.service.spec.js | 278 +-- .../angular/workboxServiceWorker.ts | 20 +- .../authentication/authLanding.component.js | 2 +- .../authentication/authLanding.html | 10 +- .../impersonateUser.component.js | 26 +- .../authentication/inviteLink.component.js | 111 +- app/components/authentication/inviteLink.html | 16 +- .../authentication/mergeAccount.component.js | 97 +- .../authentication/mergeAccount.html | 71 +- .../authentication/signIn.component.js | 50 +- app/components/authentication/signIn.html | 60 +- .../navigation/navHeader.component.js | 33 +- app/components/navigation/navHeader.html | 193 +- .../navigation/navSearch.component.js | 10 +- app/components/navigation/navSearch.html | 117 +- babel.config.js | 6 +- bin/oneskyDownload.js | 41 +- bin/oneskyUpload.js | 38 +- karma.conf.js | 103 +- src/i18n/i18next.config.js | 34 +- src/i18n/locales/en-US.js | 2145 ++++++++--------- webpack.config.js | 347 ++- yarn.lock | 119 + 306 files changed, 20702 insertions(+), 25153 deletions(-) diff --git a/app/app.component.js b/app/app.component.js index 74d914f04f..0b406bd0b9 100644 --- a/app/app.component.js +++ b/app/app.component.js @@ -3,43 +3,37 @@ import './components/navigation/navHeader.component'; import './app.scss'; angular.module('campusContactsApp').component('app', { - controller: appController, - template: template, - bindings: { - hideHeader: '<', - hideFooter: '<', - hideMenuLinks: '<', - }, + controller: appController, + template, + bindings: { + hideHeader: '<', + hideFooter: '<', + hideMenuLinks: '<', + }, }); function appController(periodService, $rootScope, analyticsService) { - let deregisterEditOrganizationsEvent; - let deregisterStateChangedEvent; + let deregisterEditOrganizationsEvent; + let deregisterStateChangedEvent; - this.editOrganizations = false; - this.getPeriod = periodService.getPeriod; + this.editOrganizations = false; + this.getPeriod = periodService.getPeriod; - this.$onInit = () => { - this.year = new Date(); + this.$onInit = () => { + this.year = new Date(); - deregisterStateChangedEvent = $rootScope.$on( - 'state:changed', - (event, { loggedIn }) => { - if (loggedIn) analyticsService.setupAuthenitcatedAnalyticData(); - else analyticsService.clearAuthenticatedData(); - }, - ); + deregisterStateChangedEvent = $rootScope.$on('state:changed', (event, { loggedIn }) => { + if (loggedIn) analyticsService.setupAuthenitcatedAnalyticData(); + else analyticsService.clearAuthenticatedData(); + }); - deregisterEditOrganizationsEvent = $rootScope.$on( - 'editOrganizations', - (event, value) => { - this.editOrganizations = value; - }, - ); - }; + deregisterEditOrganizationsEvent = $rootScope.$on('editOrganizations', (event, value) => { + this.editOrganizations = value; + }); + }; - this.$onDestroy = () => { - deregisterEditOrganizationsEvent(); - deregisterStateChangedEvent(); - }; + this.$onDestroy = () => { + deregisterEditOrganizationsEvent(); + deregisterStateChangedEvent(); + }; } diff --git a/app/app.html b/app/app.html index d88b27d499..ffc2b69be6 100644 --- a/app/app.html +++ b/app/app.html @@ -1,34 +1,26 @@
- - - + + +
- +
diff --git a/app/assets/javascripts/angular/all-tests.spec.js b/app/assets/javascripts/angular/all-tests.spec.js index cdbeed68e1..64009db5b7 100644 --- a/app/assets/javascripts/angular/all-tests.spec.js +++ b/app/assets/javascripts/angular/all-tests.spec.js @@ -3,12 +3,13 @@ import angular from 'angular'; import 'angular-mocks'; class OktaAuth { - constructor(config) { - this.token = ''; - this.tokenManager = {}; - } - start() {} - signOut() {} + constructor(config) { + this.token = ''; + this.tokenManager = {}; + } + + start() {} + signOut() {} } window.OktaAuth = OktaAuth; @@ -16,19 +17,17 @@ window.OktaAuth = OktaAuth; beforeEach(angular.mock.module('campusContactsApp')); beforeEach( - angular.mock.module({ - analyticsService: { - init: jasmine.createSpy('init'), - track: jasmine.createSpy('track'), - }, - authenticationService: { - storeJwtToken: jasmine.createSpy('storeJwtToken'), - removeAccess: jasmine.createSpy('removeAccess'), - isTokenValid: jasmine - .createSpy('isTokenValid') - .and.returnValue(false), - }, - }), + angular.mock.module({ + analyticsService: { + init: jasmine.createSpy('init'), + track: jasmine.createSpy('track'), + }, + authenticationService: { + storeJwtToken: jasmine.createSpy('storeJwtToken'), + removeAccess: jasmine.createSpy('removeAccess'), + isTokenValid: jasmine.createSpy('isTokenValid').and.returnValue(false), + }, + }), ); /* global require */ diff --git a/app/assets/javascripts/angular/campusContactsApp.config.js b/app/assets/javascripts/angular/campusContactsApp.config.js index 40ce19501e..8bec653b58 100644 --- a/app/assets/javascripts/angular/campusContactsApp.config.js +++ b/app/assets/javascripts/angular/campusContactsApp.config.js @@ -1,145 +1,143 @@ angular - .module('campusContactsApp') - .config((envServiceProvider) => { - envServiceProvider.config({ - domains: { - development: ['localhost'], - production: ['campuscontacts.cru.org', 'ccontacts.app'], - staging: [ - // These wildcards need to be the last domains so they don't override matches above - '*.campuscontacts.cru.org', - '*.ccontacts.app', - '*.d23um2gb8xlk6n.amplifyapp.com', - ], - }, - vars: { - development: { - apiUrl: 'https://campus-contacts-api-stage.cru.org/apis/v4', - publicUri: 'https://localhost:8080', - oktaClientId: '0oa1oqxpke9BXTbhp0h8', - facebookAppId: '264148437992398', - surveyLinkPrefix: 'http://localhost:8080/s/', - }, - staging: { - apiUrl: 'https://campus-contacts-api-stage.cru.org/apis/v4', - publicUri: 'https://stage.campuscontacts.cru.org', - oktaClientId: '0oa1oqxpke9BXTbhp0h8', - facebookAppId: '264148437992398', - surveyLinkPrefix: 'https://stage.ccontacts.app/s/', - }, - production: { - apiUrl: 'https://campus-contacts-api.cru.org/apis/v4', - publicUri: 'https://campuscontacts.cru.org', - oktaClientId: '0oa1oqxpke9BXTbhp0h8', - facebookAppId: '264148437992398', - surveyLinkPrefix: 'https://ccontacts.app/s/', - googleAnalytics: 'UA-325725-21', - }, - defaults: { - oktaUrl: 'https://signon.okta.com', - googleAnalytics: 'UA-XXXXXX-XX', - }, - }, - }); + .module('campusContactsApp') + .config((envServiceProvider) => { + envServiceProvider.config({ + domains: { + development: ['localhost'], + production: ['campuscontacts.cru.org', 'ccontacts.app'], + staging: [ + // These wildcards need to be the last domains so they don't override matches above + '*.campuscontacts.cru.org', + '*.ccontacts.app', + '*.d23um2gb8xlk6n.amplifyapp.com', + ], + }, + vars: { + development: { + apiUrl: 'https://campus-contacts-api-stage.cru.org/apis/v4', + publicUri: 'https://localhost:8080', + oktaClientId: '0oa1oqxpke9BXTbhp0h8', + facebookAppId: '264148437992398', + surveyLinkPrefix: 'http://localhost:8080/s/', + }, + staging: { + apiUrl: 'https://campus-contacts-api-stage.cru.org/apis/v4', + publicUri: 'https://stage.campuscontacts.cru.org', + oktaClientId: '0oa1oqxpke9BXTbhp0h8', + facebookAppId: '264148437992398', + surveyLinkPrefix: 'https://stage.ccontacts.app/s/', + }, + production: { + apiUrl: 'https://campus-contacts-api.cru.org/apis/v4', + publicUri: 'https://campuscontacts.cru.org', + oktaClientId: '0oa1oqxpke9BXTbhp0h8', + facebookAppId: '264148437992398', + surveyLinkPrefix: 'https://ccontacts.app/s/', + googleAnalytics: 'UA-325725-21', + }, + defaults: { + oktaUrl: 'https://signon.okta.com', + googleAnalytics: 'UA-XXXXXX-XX', + }, + }, + }); - // run the environment check, so the comprobation is made - // before controllers and services are built - envServiceProvider.check(); - }) - .config(($compileProvider) => { - // Customized in order to add sms. Can retrieve original whitelist by calling it with no arguments. https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist - $compileProvider.aHrefSanitizationWhitelist( - /^\s*(https?|ftp|mailto|tel|sms|webcal|local|file|data|blob):/, - ); - }) - .config(($analyticsProvider) => { - $analyticsProvider.firstPageview(false); - $analyticsProvider.virtualPageviews(false); - }) - .config((ngMdIconServiceProvider, $qProvider) => { - /* eslint-disable max-len */ - ngMdIconServiceProvider - .addViewBox('holySpirit', '0 0 48 48') - .addViewBox('uncontactedPerson', '0 0 48 48') - .addViewBox('assignedPeople', '0 0 48 48') - .addViewBox('unassignedPerson', '0 0 48 48') - .addViewBox('spiritualConversation', '0 0 48 48') - .addViewBox('evangelism', '0 0 48 48') - .addViewBox('personalDecision', '0 0 48 48') - .addViewBox('discipleship', '0 0 48 48') - .addViewBox('archive', '0 0 48 48') - .addViewBox('addPerson', '0 0 48 48') - .addViewBox('email', '0 0 48 48') - .addViewBox('add', '0 0 48 48') - .addViewBox('phone', '0 0 48 48') - .addViewBox('close', '0 0 48 48') - .addViewBox('edit', '0 0 48 48') - .addViewBox('note', '0 0 48 48') - .addShapes({ - edit: - '', - unassignedPerson: - '', - phone: - '', - close: - '', - dashboard: - '' + - '' + - '', - discipleship: - '', - assignedPeople: - '', - uncontactedPerson: - '', - holySpirit: - '', - personalDecision: - '', - evangelism: - '', - survey: - '' + - '' + - '', - add: - '', - addPerson: - '', - snooze: - '' + - '' + - '', - dragHandle: - '' + - '' + - '', - visibilityOn: - '' + - '' + - '', - visibilityOff: - '' + - '' + - '', - editOrder: - '' + - '' + - '', - email: - '' + - '', - spiritualConversation: - '', - note: - '', - archive: - '', - }); + // run the environment check, so the comprobation is made + // before controllers and services are built + envServiceProvider.check(); + }) + .config(($compileProvider) => { + // Customized in order to add sms. Can retrieve original whitelist by calling it with no arguments. https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|sms|webcal|local|file|data|blob):/); + }) + .config(($analyticsProvider) => { + $analyticsProvider.firstPageview(false); + $analyticsProvider.virtualPageviews(false); + }) + .config((ngMdIconServiceProvider, $qProvider) => { + /* eslint-disable max-len */ + ngMdIconServiceProvider + .addViewBox('holySpirit', '0 0 48 48') + .addViewBox('uncontactedPerson', '0 0 48 48') + .addViewBox('assignedPeople', '0 0 48 48') + .addViewBox('unassignedPerson', '0 0 48 48') + .addViewBox('spiritualConversation', '0 0 48 48') + .addViewBox('evangelism', '0 0 48 48') + .addViewBox('personalDecision', '0 0 48 48') + .addViewBox('discipleship', '0 0 48 48') + .addViewBox('archive', '0 0 48 48') + .addViewBox('addPerson', '0 0 48 48') + .addViewBox('email', '0 0 48 48') + .addViewBox('add', '0 0 48 48') + .addViewBox('phone', '0 0 48 48') + .addViewBox('close', '0 0 48 48') + .addViewBox('edit', '0 0 48 48') + .addViewBox('note', '0 0 48 48') + .addShapes({ + edit: + '', + unassignedPerson: + '', + phone: + '', + close: + '', + dashboard: + '' + + '' + + '', + discipleship: + '', + assignedPeople: + '', + uncontactedPerson: + '', + holySpirit: + '', + personalDecision: + '', + evangelism: + '', + survey: + '' + + '' + + '', + add: + '', + addPerson: + '', + snooze: + '' + + '' + + '', + dragHandle: + '' + + '' + + '', + visibilityOn: + '' + + '' + + '', + visibilityOff: + '' + + '' + + '', + editOrder: + '' + + '' + + '', + email: + '' + + '', + spiritualConversation: + '', + note: + '', + archive: + '', + }); - /* eslint-enable max-len */ + /* eslint-enable max-len */ - $qProvider.errorOnUnhandledRejections(false); - }); + $qProvider.errorOnUnhandledRejections(false); + }); diff --git a/app/assets/javascripts/angular/campusContactsApp.constants.js b/app/assets/javascripts/angular/campusContactsApp.constants.js index 0f13a86da2..ce50fa3755 100644 --- a/app/assets/javascripts/angular/campusContactsApp.constants.js +++ b/app/assets/javascripts/angular/campusContactsApp.constants.js @@ -2,8 +2,8 @@ import _ from 'lodash'; import moment from 'moment'; angular - .module('campusContactsApp') - .constant('_', _) - .constant('moment', moment) - .constant('p2cOrgId', '8411') - .constant('rollbarAccessToken', 'e749b290a241465b9e70c9cf93124721'); + .module('campusContactsApp') + .constant('_', _) + .constant('moment', moment) + .constant('p2cOrgId', '8411') + .constant('rollbarAccessToken', 'e749b290a241465b9e70c9cf93124721'); diff --git a/app/assets/javascripts/angular/campusContactsApp.module.js b/app/assets/javascripts/angular/campusContactsApp.module.js index b213ac6bb6..e67f4a914e 100644 --- a/app/assets/javascripts/angular/campusContactsApp.module.js +++ b/app/assets/javascripts/angular/campusContactsApp.module.js @@ -20,19 +20,19 @@ import 'moment'; import 'angular-smart-table'; export default angular.module('campusContactsApp', [ - ngAnimate, - ngMdIcons, - 'beauby.jsonApiDataStore', - ngEnvironment, - uiRouter, - uiSelect, - 'ng-sortable', - uiBootstrap, - ngFileUpload, - ngInfiniteScroll, - 'toaster', - ngScrollGlue, - angulartics, - angularticsGoogle, - 'smart-table', + ngAnimate, + ngMdIcons, + 'beauby.jsonApiDataStore', + ngEnvironment, + uiRouter, + uiSelect, + 'ng-sortable', + uiBootstrap, + ngFileUpload, + ngInfiniteScroll, + 'toaster', + ngScrollGlue, + angulartics, + angularticsGoogle, + 'smart-table', ]); diff --git a/app/assets/javascripts/angular/campusContactsApp.routes.js b/app/assets/javascripts/angular/campusContactsApp.routes.js index 48e2c81e64..9b1a29df3d 100644 --- a/app/assets/javascripts/angular/campusContactsApp.routes.js +++ b/app/assets/javascripts/angular/campusContactsApp.routes.js @@ -1,678 +1,595 @@ angular - .module('campusContactsApp') - .config(function ( - $stateProvider, - $locationProvider, - $urlServiceProvider, - $uibResolveProvider, - asyncBindingsServiceProvider, - ministryViewTabs, - ministryViewDefaultTab, - personTabs, - personDefaultTab, - _, - ) { - // Instantiate factories - var asyncBindingsService = asyncBindingsServiceProvider.$get(); + .module('campusContactsApp') + .config(function ( + $stateProvider, + $locationProvider, + $urlServiceProvider, + $uibResolveProvider, + asyncBindingsServiceProvider, + ministryViewTabs, + ministryViewDefaultTab, + personTabs, + personDefaultTab, + _, + ) { + // Instantiate factories + const asyncBindingsService = asyncBindingsServiceProvider.$get(); - // Convenience alias - var lazyLoadedResolve = asyncBindingsService.lazyLoadedResolve; + // Convenience alias + const lazyLoadedResolve = asyncBindingsService.lazyLoadedResolve; - // Hack $stateProvider.state to support a custom state property "modal" that turns the state into a modal - // dialog. An Angular decorator would be preferable, but there is no way of decorating a provider. - var originalState = $stateProvider.state; - $stateProvider.state = function (state) { - var transform = state.modal ? modalState : _.identity; - return originalState(transform(state)); - }; + // Hack $stateProvider.state to support a custom state property "modal" that turns the state into a modal + // dialog. An Angular decorator would be preferable, but there is no way of decorating a provider. + const originalState = $stateProvider.state; + $stateProvider.state = function (state) { + const transform = state.modal ? modalState : _.identity; + return originalState(transform(state)); + }; - // Add a states helper method that defines an array of states all at once - $stateProvider.states = function (states) { - states.forEach(function (state) { - $stateProvider.state(state); - }); - return $stateProvider; - }; + // Add a states helper method that defines an array of states all at once + $stateProvider.states = function (states) { + states.forEach(function (state) { + $stateProvider.state(state); + }); + return $stateProvider; + }; - // Use the ui-router resolver so that we can correctly resolve ui-router injectables like $transition$ in - // $uibModal resolve blocks. - $uibResolveProvider.setResolver('$resolve'); + // Use the ui-router resolver so that we can correctly resolve ui-router injectables like $transition$ in + // $uibModal resolve blocks. + $uibResolveProvider.setResolver('$resolve'); - // Return the parent state name of a ui-router state name - function getParentState(stateName) { - // Drop the last part of the state to get the parent state - return _.chain(stateName).split('.').initial().join('.').value(); - } + // Return the parent state name of a ui-router state name + function getParentState(stateName) { + // Drop the last part of the state to get the parent state + return _.chain(stateName).split('.').initial().join('.').value(); + } - // Convert a normal ui-router state definition into a state representing a modal dialog - function modalState(state) { - var modalInstance = null; - var closedByRouteChange; - return { - name: state.name, - url: state.url, - abstract: state.abstract, - params: state.params, - onEnter: /* @ngInject */ function ($state, $uibModal) { - closedByRouteChange = false; + // Convert a normal ui-router state definition into a state representing a modal dialog + function modalState(state) { + let modalInstance = null; + let closedByRouteChange; + return { + name: state.name, + url: state.url, + abstract: state.abstract, + params: state.params, + onEnter: /* @ngInject */ function ($state, $uibModal) { + closedByRouteChange = false; - // The final generated template will look like this: - // - var injectedProps = _.keys(state.resolve); - var attributes = injectedProps.map(function (property) { - return ( - _.kebabCase(property) + '="$ctrl.' + property + '"' - ); - }); - var directive = _.kebabCase(state.component); - var template = - '<' + - directive + - ' ' + - attributes.join(' ') + - '>'; + // The final generated template will look like this: + // + const injectedProps = _.keys(state.resolve); + const attributes = injectedProps.map(function (property) { + return _.kebabCase(property) + '="$ctrl.' + property + '"'; + }); + const directive = _.kebabCase(state.component); + const template = '<' + directive + ' ' + attributes.join(' ') + '>'; - modalInstance = $uibModal.open({ - animation: true, - template: template, + modalInstance = $uibModal.open({ + animation: true, + template, - // Explicitly inject the injected properties as dependencies - controller: injectedProps.concat([ - function () { - var vm = this; + // Explicitly inject the injected properties as dependencies + controller: injectedProps.concat([ + function () { + const vm = this; - var injectedValues = arguments; - var injections = _.zipObject( - injectedProps, - injectedValues, - ); - _.extend(vm, injections); - }, - ]), - controllerAs: '$ctrl', - resolve: state.resolve, - windowClass: 'dashboard_panels pivot_theme', - }); + const injectedValues = arguments; + const injections = _.zipObject(injectedProps, injectedValues); + _.extend(vm, injections); + }, + ]), + controllerAs: '$ctrl', + resolve: state.resolve, + windowClass: 'dashboard_panels pivot_theme', + }); - modalInstance.result.finally(function () { - modalInstance = null; + modalInstance.result.finally(function () { + modalInstance = null; - if (closedByRouteChange) { - // The modal was closed as a result of a route change, so we should not modify the route - return; - } + if (closedByRouteChange) { + // The modal was closed as a result of a route change, so we should not modify the route + return; + } - $state.go(getParentState(state.name)); - }); - }, - onExit: function () { - if (modalInstance) { - closedByRouteChange = true; - modalInstance.close(); - } - }, - }; - } + $state.go(getParentState(state.name)); + }); + }, + onExit: function () { + if (modalInstance) { + closedByRouteChange = true; + modalInstance.close(); + } + }, + }; + } - // A dictionary of extra resolves needed by each component - // The key is the tab name and the name is a dictionary of extra resolves - var personTabResolves = { - history: { - history: lazyLoadedResolve( - /* @ngInject */ function ($uiRouter, routesService) { - var $transition$ = $uiRouter.globals.transition; - return routesService.getHistory( - $transition$.params().personId, - ); - }, - ), - }, - }; + // A dictionary of extra resolves needed by each component + // The key is the tab name and the name is a dictionary of extra resolves + const personTabResolves = { + history: { + history: lazyLoadedResolve( + /* @ngInject */ function ($uiRouter, routesService) { + const $transition$ = $uiRouter.globals.transition; + return routesService.getHistory($transition$.params().personId); + }, + ), + }, + }; - // Generate and return an array of the states needed for the personPage component - // The "state" parameter is the state definition that will contain the person page, including its tabs - function generatePersonPageStates(state) { - var states = []; + // Generate and return an array of the states needed for the personPage component + // The "state" parameter is the state definition that will contain the person page, including its tabs + function generatePersonPageStates(state) { + const states = []; - // Generate the container state - states.push({ - name: state.name, - url: state.url, - component: 'personPage', - abstract: true, - params: _.extend( - { - assignToMe: { type: 'bool', value: false }, - }, - state.params, - ), - modal: state.modal, - resolve: { - // We have to send the state name to the personPage component so that route links will work when - // the person page is in a modal. Relative ui-state directives work fine when the person page is - // a component. However, when it is a modal, apparently the component created by uib-modal does - // not know the state that it was created from, so those relative links will all be broken. To - // solve this, we send the state name to the component so that it can generate absolute links - // based on its current state. - stateName: _.constant(state.name), - person: lazyLoadedResolve( - /* @ngInject */ function ( - $state, - $uiRouter, - routesService, - personService, - ) { - // Ideally, we would inject $transition$, an object representing that ui-router makes - // available to states' resolves. However, when the state is refers to a state in a modal, - // the resolve will not have access to that transition, so we have to get it from the - // a ui-router global that is injectable everywhere. - var $transition$ = $uiRouter.globals.transition; - var params = $transition$.params(); + // Generate the container state + states.push({ + name: state.name, + url: state.url, + component: 'personPage', + abstract: true, + params: _.extend( + { + assignToMe: { type: 'bool', value: false }, + }, + state.params, + ), + modal: state.modal, + resolve: { + // We have to send the state name to the personPage component so that route links will work when + // the person page is in a modal. Relative ui-state directives work fine when the person page is + // a component. However, when it is a modal, apparently the component created by uib-modal does + // not know the state that it was created from, so those relative links will all be broken. To + // solve this, we send the state name to the component so that it can generate absolute links + // based on its current state. + stateName: _.constant(state.name), + person: lazyLoadedResolve( + /* @ngInject */ function ($state, $uiRouter, routesService, personService) { + // Ideally, we would inject $transition$, an object representing that ui-router makes + // available to states' resolves. However, when the state is refers to a state in a modal, + // the resolve will not have access to that transition, so we have to get it from the + // a ui-router global that is injectable everywhere. + const $transition$ = $uiRouter.globals.transition; + const params = $transition$.params(); - if (params.personId === 'new') { - // We are creating a new person instead of editing an existing one, so generate that - // new person model - return personService.getNewPerson(params.orgId); - } + if (params.personId === 'new') { + // We are creating a new person instead of editing an existing one, so generate that + // new person model + return personService.getNewPerson(params.orgId); + } - return routesService - .getPerson(params.personId) - .catch(function () { - // Go back to the parent state if the person could not be found - $state.go(getParentState(state.name), { - orgId: params.orgId, - }); + return routesService.getPerson(params.personId).catch(function () { + // Go back to the parent state if the person could not be found + $state.go(getParentState(state.name), { + orgId: params.orgId, + }); - throw new Error( - 'Person could not be loaded', - ); - }); - }, - ), + throw new Error('Person could not be loaded'); + }); + }, + ), - organizationId: /* @ngInject */ ($uiRouter) => { - const $transition$ = $uiRouter.globals.transition; - return $transition$.params().orgId - ? $transition$.params().orgId - : false; - }, + organizationId: /* @ngInject */ ($uiRouter) => { + const $transition$ = $uiRouter.globals.transition; + return $transition$.params().orgId ? $transition$.params().orgId : false; + }, - options: /* @ngInject */ function ($uiRouter) { - var $transition$ = $uiRouter.globals.transition; - return { - assignToMe: $transition$.params().assignToMe, - }; - }, - }, - }); + options: /* @ngInject */ function ($uiRouter) { + const $transition$ = $uiRouter.globals.transition; + return { + assignToMe: $transition$.params().assignToMe, + }; + }, + }, + }); - // Generate a state for each tab - personTabs.forEach(function (tab) { - var personTabView = { - component: 'person' + _.capitalize(tab), - }; - states.push({ - name: state.name + '.' + tab, - url: '/' + tab, - resolve: personTabResolves[tab], - views: state.modal - ? { 'personTab@': personTabView } - : { personTab: personTabView }, - }); - }); + // Generate a state for each tab + personTabs.forEach(function (tab) { + const personTabView = { + component: 'person' + _.capitalize(tab), + }; + states.push({ + name: state.name + '.' + tab, + url: '/' + tab, + resolve: personTabResolves[tab], + views: state.modal ? { 'personTab@': personTabView } : { personTab: personTabView }, + }); + }); - // Generate the default tab state - states.push({ - name: state.name + '.defaultTab', - redirectTo: state.name + '.' + personDefaultTab, - }); + // Generate the default tab state + states.push({ + name: state.name + '.defaultTab', + redirectTo: state.name + '.' + personDefaultTab, + }); - return states; - } + return states; + } - $stateProvider - .state({ - name: 'app', - url: '', - abstract: true, - component: 'app', - resolve: { - hideHeader: () => false, - hideFooter: () => false, - hideMenuLinks: () => false, - }, - }) - .state({ - name: 'appWithoutMenus', - url: '', - abstract: true, - component: 'app', - resolve: { - hideHeader: () => true, - hideFooter: () => true, - hideMenuLinks: () => false, - }, - }) - .state({ - name: 'appWithoutMenuLinks', - url: '', - abstract: true, - component: 'app', - resolve: { - hideHeader: () => false, - hideFooter: () => false, - hideMenuLinks: () => true, - }, - }) - .state({ - name: 'app.signIn', - url: '/sign-in?previousUri', - component: 'signIn', - data: { - isPublic: true, - }, - }) - .state({ - name: 'appWithoutMenus.unsubscribe', - url: '/unsubscribe', - component: 'unsubscribe', - data: { - isPublic: true, - }, - resolve: { - token: ($location) => $location.search().token, - organizationId: ($location) => - $location.search().organization_id, - organizationName: ($location) => - $location.search().organization_name, - }, - }) - .state({ - name: 'appWithoutMenuLinks.auth', - url: '/auth-web?access_token', - component: 'signIn', - resolve: { - accessToken: ($location, urlHashParserService) => { - return urlHashParserService.param('access_token'); - }, - }, - data: { - isPublic: true, - }, - }) - .state({ - name: 'appWithoutMenuLinks.authLanding', - url: '/auth', - component: 'authLanding', - data: { - isPublic: true, - }, - }) - .state({ - name: 'appWithoutMenus.mergeAccount', - url: '/merge-account/:rememberCode/:orgId/:userId', - component: 'mergeAccount', - resolve: { - rememberCode: ($transition$) => - $transition$.params().rememberCode, - userId: ($transition$) => $transition$.params().userId, - orgId: ($transition$) => $transition$.params().orgId, - loggedInUser: (loggedInPerson) => loggedInPerson.load(), - }, - }) - .state({ - name: 'app.impersonateUser', - url: '/impersonate-user/:userId', - component: 'impersonateUser', - resolve: { - userId: ($state, $transition$) => - $transition$.params().userId, - }, - }) - .state({ - name: 'app.stopImpersonatingUser', - url: '/stop-impersonation', - component: 'impersonateUser', - }) - .state({ - name: 'admin', - url: '/admin', - resolve: { - adminRedirect: (authenticationService) => - authenticationService.adminRedirect(), - }, - }) - .state({ - name: 'app.people', - url: '/people', - template: - '', - }) - .states( - generatePersonPageStates({ - name: 'app.people.new', - url: '/new?orgId', - modal: true, - params: { - orgId: { value: null }, - personId: { value: 'new' }, - }, - }), - ) - .state({ - name: 'app.ministries', - url: '/ministries', - abstract: true, - template: - '', - }) - .state({ - name: 'app.ministries.root', - url: '/root', - component: 'myOrganizationsDashboardList', - resolve: { - rootOrgs: function ( - myOrganizationsDashboardService, - userPreferencesService, - $q, - $state, - ) { - return myOrganizationsDashboardService - .getRootOrganizations() - .then( - userPreferencesService.applyUserOrgDisplayPreferences, - ) - .then((orgs) => { - if (orgs.length === 1) { - $state.go( - 'app.ministries.ministry.' + - ministryViewDefaultTab, - { orgId: orgs[0].id }, - ); - return $q.reject( - 'cancel transition, re-route user to root org.', - ); - } - return orgs; - }); - }, - }, - }) - .state({ - name: 'app.ministries.signAgreements', - url: '/sign-agreements', - component: 'organizationSignaturesSign', - }) - .state({ - name: 'app.ministries.ministry', - url: '/:orgId', - component: 'organizationOverview', - abstract: true, - resolve: { - org: lazyLoadedResolve( - /* @ngInject */ function ( - $state, - $transition$, - routesService, - ) { - return routesService - .getOrganization($transition$.params().orgId) - .catch(function () { - // Go to the root organization if the organization could not be loaded - $state.go('app.ministries.root'); - - throw new Error( - 'Organization could not be loaded', - ); - }); - }, - ), - }, - }) - .state({ - name: 'app.ministries.ministry.import', - url: '/import', - component: 'organizationContactImport', - params: { - surveyId: null, - }, - resolve: { - surveyId: ($state, $transition$) => - $transition$.params().surveyId, - }, - }) - .state({ - name: 'app.ministries.ministry.management', - url: '/management', - component: 'orgManagement', - }) - .state({ - name: 'app.ministries.ministry.cleanup', - url: '/organization-cleanup', - component: 'organizationCleanup', - resolve: { - orgId: ($transition$) => $transition$.params().orgId, - }, - }) - .state({ - name: 'app.ministries.ministry.signatures', - url: '/organization-signatures', - component: 'organizationSignatures', - resolve: { - orgId: ($transition$) => $transition$.params().orgId, - }, - }) - .state({ - name: 'app.ministries.ministry.reportMovementIndicators', - url: '/report-movement-indicators', - component: 'reportMovementIndicators', - resolve: { - orgId: ($transition$) => $transition$.params().orgId, - }, - }) - .state({ - name: 'app.ministries.ministry.defaultTab', - redirectTo: 'app.ministries.ministry.' + ministryViewDefaultTab, - }) - .states( - generatePersonPageStates({ - name: 'app.ministries.ministry.people.new', - url: '/new', - modal: true, - params: { - personId: { value: 'new' }, - }, - }), - ) - .states( - ministryViewTabs.map(function (tab) { - const formatArrayForFilter = (filter) => { - if (!filter) return {}; + $stateProvider + .state({ + name: 'app', + url: '', + abstract: true, + component: 'app', + resolve: { + hideHeader: () => false, + hideFooter: () => false, + hideMenuLinks: () => false, + }, + }) + .state({ + name: 'appWithoutMenus', + url: '', + abstract: true, + component: 'app', + resolve: { + hideHeader: () => true, + hideFooter: () => true, + hideMenuLinks: () => false, + }, + }) + .state({ + name: 'appWithoutMenuLinks', + url: '', + abstract: true, + component: 'app', + resolve: { + hideHeader: () => false, + hideFooter: () => false, + hideMenuLinks: () => true, + }, + }) + .state({ + name: 'app.signIn', + url: '/sign-in?previousUri', + component: 'signIn', + data: { + isPublic: true, + }, + }) + .state({ + name: 'appWithoutMenus.unsubscribe', + url: '/unsubscribe', + component: 'unsubscribe', + data: { + isPublic: true, + }, + resolve: { + token: ($location) => $location.search().token, + organizationId: ($location) => $location.search().organization_id, + organizationName: ($location) => $location.search().organization_name, + }, + }) + .state({ + name: 'appWithoutMenuLinks.auth', + url: '/auth-web?access_token', + component: 'signIn', + resolve: { + accessToken: ($location, urlHashParserService) => { + return urlHashParserService.param('access_token'); + }, + }, + data: { + isPublic: true, + }, + }) + .state({ + name: 'appWithoutMenuLinks.authLanding', + url: '/auth', + component: 'authLanding', + data: { + isPublic: true, + }, + }) + .state({ + name: 'appWithoutMenus.mergeAccount', + url: '/merge-account/:rememberCode/:orgId/:userId', + component: 'mergeAccount', + resolve: { + rememberCode: ($transition$) => $transition$.params().rememberCode, + userId: ($transition$) => $transition$.params().userId, + orgId: ($transition$) => $transition$.params().orgId, + loggedInUser: (loggedInPerson) => loggedInPerson.load(), + }, + }) + .state({ + name: 'app.impersonateUser', + url: '/impersonate-user/:userId', + component: 'impersonateUser', + resolve: { + userId: ($state, $transition$) => $transition$.params().userId, + }, + }) + .state({ + name: 'app.stopImpersonatingUser', + url: '/stop-impersonation', + component: 'impersonateUser', + }) + .state({ + name: 'admin', + url: '/admin', + resolve: { + adminRedirect: (authenticationService) => authenticationService.adminRedirect(), + }, + }) + .state({ + name: 'app.people', + url: '/people', + template: '', + }) + .states( + generatePersonPageStates({ + name: 'app.people.new', + url: '/new?orgId', + modal: true, + params: { + orgId: { value: null }, + personId: { value: 'new' }, + }, + }), + ) + .state({ + name: 'app.ministries', + url: '/ministries', + abstract: true, + template: '', + }) + .state({ + name: 'app.ministries.root', + url: '/root', + component: 'myOrganizationsDashboardList', + resolve: { + rootOrgs: function (myOrganizationsDashboardService, userPreferencesService, $q, $state) { + return myOrganizationsDashboardService + .getRootOrganizations() + .then(userPreferencesService.applyUserOrgDisplayPreferences) + .then((orgs) => { + if (orgs.length === 1) { + $state.go('app.ministries.ministry.' + ministryViewDefaultTab, { orgId: orgs[0].id }); + return $q.reject('cancel transition, re-route user to root org.'); + } + return orgs; + }); + }, + }, + }) + .state({ + name: 'app.ministries.signAgreements', + url: '/sign-agreements', + component: 'organizationSignaturesSign', + }) + .state({ + name: 'app.ministries.ministry', + url: '/:orgId', + component: 'organizationOverview', + abstract: true, + resolve: { + org: lazyLoadedResolve( + /* @ngInject */ function ($state, $transition$, routesService) { + return routesService.getOrganization($transition$.params().orgId).catch(function () { + // Go to the root organization if the organization could not be loaded + $state.go('app.ministries.root'); - return filter - .split(',') - .reduce( - (acc, value) => ({ ...acc, [value]: true }), - {}, - ); - }; + throw new Error('Organization could not be loaded'); + }); + }, + ), + }, + }) + .state({ + name: 'app.ministries.ministry.import', + url: '/import', + component: 'organizationContactImport', + params: { + surveyId: null, + }, + resolve: { + surveyId: ($state, $transition$) => $transition$.params().surveyId, + }, + }) + .state({ + name: 'app.ministries.ministry.management', + url: '/management', + component: 'orgManagement', + }) + .state({ + name: 'app.ministries.ministry.cleanup', + url: '/organization-cleanup', + component: 'organizationCleanup', + resolve: { + orgId: ($transition$) => $transition$.params().orgId, + }, + }) + .state({ + name: 'app.ministries.ministry.signatures', + url: '/organization-signatures', + component: 'organizationSignatures', + resolve: { + orgId: ($transition$) => $transition$.params().orgId, + }, + }) + .state({ + name: 'app.ministries.ministry.reportMovementIndicators', + url: '/report-movement-indicators', + component: 'reportMovementIndicators', + resolve: { + orgId: ($transition$) => $transition$.params().orgId, + }, + }) + .state({ + name: 'app.ministries.ministry.defaultTab', + redirectTo: 'app.ministries.ministry.' + ministryViewDefaultTab, + }) + .states( + generatePersonPageStates({ + name: 'app.ministries.ministry.people.new', + url: '/new', + modal: true, + params: { + personId: { value: 'new' }, + }, + }), + ) + .states( + ministryViewTabs.map(function (tab) { + const formatArrayForFilter = (filter) => { + if (!filter) return {}; - if (tab === 'people') { - return { - name: 'app.ministries.ministry.' + tab, - url: '/people?statuses=&assigned_to=', - component: - 'organizationOverview' + _.upperFirst(tab), - resolve: { - queryFilters: /* @ngInject */ ( - $transition$, - $location, - ) => { - const filters = $location.search(); + return filter.split(',').reduce((acc, value) => ({ ...acc, [value]: true }), {}); + }; - return { - ...(filters.assigned_to - ? { - assigned_tos: formatArrayForFilter( - filters.assigned_to, - ), - } - : {}), - ...(filters.statuses - ? { - statuses: formatArrayForFilter( - filters.statuses, - ), - } - : {}), - }; - }, - }, - }; - } + if (tab === 'people') { + return { + name: 'app.ministries.ministry.' + tab, + url: '/people?statuses=&assigned_to=', + component: 'organizationOverview' + _.upperFirst(tab), + resolve: { + queryFilters: /* @ngInject */ ($transition$, $location) => { + const filters = $location.search(); - return { - name: 'app.ministries.ministry.' + tab, - url: '/' + tab, - component: 'organizationOverview' + _.upperFirst(tab), - }; - }), - ) - .states( - generatePersonPageStates({ - name: 'app.people.person', - url: '/:personId/organization/:orgId', - modal: true, - params: { - orgId: { value: null }, - }, - }), - ) - .states( - generatePersonPageStates({ - name: 'app.people.myProfile', - url: '/:personId', - modal: true, - }), - ) - .states( - generatePersonPageStates({ - name: 'app.ministries.ministry.team.person', - url: '/:personId', - modal: true, - }), - ) - .states( - generatePersonPageStates({ - name: 'app.ministries.ministry.people.person', - url: '/:personId', - modal: false, - }), - ) - .states( - generatePersonPageStates({ - name: 'app.ministries.ministry.survey.responses.person', - url: '/:personId', - modal: false, - }), - ) - .state({ - name: 'app.userPreferences', - url: '/user-preferences', - template: '', - whiteBackground: true, - }) - .state({ - name: 'publicPhoneNumberValidation', - url: '/p/:code/:id', - component: 'publicPhoneNumberValidation', - data: { - isPublic: true, - }, - resolve: { - phoneNumberValidation: ( - $state, - $transition$, - routesService, - ) => { - return routesService - .getPhoneNumberValidation( - $transition$.params().code, - $transition$.params().id, - ) - .catch((e) => null); - }, - }, - }) - .state({ - name: 'appWithoutMenus.publicSurvey', - url: '/s/:surveyId?preview', - component: 'publicSurvey', - data: { - isPublic: true, - }, - resolve: { - survey: ($state, $transition$, routesService) => { - return routesService - .getSurvey($transition$.params().surveyId) - .catch((e) => null); - }, - preview: ($state, $transition$) => - !!$transition$.params().preview, - }, - }) - .state({ - name: 'appWithoutMenus.previewSurvey', - url: '/previewSurvey/:surveyId', - component: 'publicSurvey', - resolve: { - survey: ($state, $transition$, routesService) => - routesService.getSurvey($transition$.params().surveyId), - preview: () => true, - }, - }) - .state({ - name: 'appWithoutMenus.inviteLink', - url: '/l/:rememberCode/:orgId/:userId', - component: 'inviteLink', - data: { - isPublic: true, - }, - resolve: { - rememberCode: ($transition$) => - $transition$.params().rememberCode, - userId: ($transition$) => $transition$.params().userId, - orgId: ($transition$) => $transition$.params().orgId, - }, - }) - .state({ - name: 'app.ministries.ministry.survey', - url: '/survey/:surveyId', - abstract: true, - template: '', - resolve: { - survey: ($state, $transition$, routesService) => { - return routesService.getSurvey( - $transition$.params().surveyId, - ); - }, + return { + ...(filters.assigned_to + ? { + assigned_tos: formatArrayForFilter(filters.assigned_to), + } + : {}), + ...(filters.statuses + ? { + statuses: formatArrayForFilter(filters.statuses), + } + : {}), + }; }, - }) - .state({ - name: 'app.ministries.ministry.survey.manage', - url: '/', - component: 'surveyOverview', - }) - .state({ - name: 'app.ministries.ministry.survey.responses', - url: '/responses', - component: 'surveyResponses', - }); + }, + }; + } + + return { + name: 'app.ministries.ministry.' + tab, + url: '/' + tab, + component: 'organizationOverview' + _.upperFirst(tab), + }; + }), + ) + .states( + generatePersonPageStates({ + name: 'app.people.person', + url: '/:personId/organization/:orgId', + modal: true, + params: { + orgId: { value: null }, + }, + }), + ) + .states( + generatePersonPageStates({ + name: 'app.people.myProfile', + url: '/:personId', + modal: true, + }), + ) + .states( + generatePersonPageStates({ + name: 'app.ministries.ministry.team.person', + url: '/:personId', + modal: true, + }), + ) + .states( + generatePersonPageStates({ + name: 'app.ministries.ministry.people.person', + url: '/:personId', + modal: false, + }), + ) + .states( + generatePersonPageStates({ + name: 'app.ministries.ministry.survey.responses.person', + url: '/:personId', + modal: false, + }), + ) + .state({ + name: 'app.userPreferences', + url: '/user-preferences', + template: '', + whiteBackground: true, + }) + .state({ + name: 'publicPhoneNumberValidation', + url: '/p/:code/:id', + component: 'publicPhoneNumberValidation', + data: { + isPublic: true, + }, + resolve: { + phoneNumberValidation: ($state, $transition$, routesService) => { + return routesService + .getPhoneNumberValidation($transition$.params().code, $transition$.params().id) + .catch((e) => null); + }, + }, + }) + .state({ + name: 'appWithoutMenus.publicSurvey', + url: '/s/:surveyId?preview', + component: 'publicSurvey', + data: { + isPublic: true, + }, + resolve: { + survey: ($state, $transition$, routesService) => { + return routesService.getSurvey($transition$.params().surveyId).catch((e) => null); + }, + preview: ($state, $transition$) => !!$transition$.params().preview, + }, + }) + .state({ + name: 'appWithoutMenus.previewSurvey', + url: '/previewSurvey/:surveyId', + component: 'publicSurvey', + resolve: { + survey: ($state, $transition$, routesService) => routesService.getSurvey($transition$.params().surveyId), + preview: () => true, + }, + }) + .state({ + name: 'appWithoutMenus.inviteLink', + url: '/l/:rememberCode/:orgId/:userId', + component: 'inviteLink', + data: { + isPublic: true, + }, + resolve: { + rememberCode: ($transition$) => $transition$.params().rememberCode, + userId: ($transition$) => $transition$.params().userId, + orgId: ($transition$) => $transition$.params().orgId, + }, + }) + .state({ + name: 'app.ministries.ministry.survey', + url: '/survey/:surveyId', + abstract: true, + template: '', + resolve: { + survey: ($state, $transition$, routesService) => { + return routesService.getSurvey($transition$.params().surveyId); + }, + }, + }) + .state({ + name: 'app.ministries.ministry.survey.manage', + url: '/', + component: 'surveyOverview', + }) + .state({ + name: 'app.ministries.ministry.survey.responses', + url: '/responses', + component: 'surveyResponses', + }); - // This is the default URL if the URL does not match any routes - $urlServiceProvider.rules.otherwise('/people'); - $locationProvider.html5Mode(true); - }); + // This is the default URL if the URL does not match any routes + $urlServiceProvider.rules.otherwise('/people'); + $locationProvider.html5Mode(true); + }); diff --git a/app/assets/javascripts/angular/campusContactsApp.run.js b/app/assets/javascripts/angular/campusContactsApp.run.js index dea1082cee..c1cc4f3873 100644 --- a/app/assets/javascripts/angular/campusContactsApp.run.js +++ b/app/assets/javascripts/angular/campusContactsApp.run.js @@ -1,68 +1,64 @@ angular - .module('campusContactsApp') - .run(function ( - $window, - $rootScope, - $analytics, - $transitions, - localStorageService, - authenticationService, - loggedInPerson, - facebookService, - oktaService, - analyticsService, - state, - $location, - envService, - ) { - $rootScope.whiteBackground = false; - $transitions.onSuccess({}, (transition) => { - $rootScope.whiteBackground = !!transition.to().whiteBackground; - }); + .module('campusContactsApp') + .run(function ( + $window, + $rootScope, + $analytics, + $transitions, + localStorageService, + authenticationService, + loggedInPerson, + facebookService, + oktaService, + analyticsService, + state, + $location, + envService, + ) { + $rootScope.whiteBackground = false; + $transitions.onSuccess({}, (transition) => { + $rootScope.whiteBackground = !!transition.to().whiteBackground; + }); - $window.fbAsyncInit = function () { - facebookService.init(); - }; - oktaService.init(); + $window.fbAsyncInit = function () { + facebookService.init(); + }; + oktaService.init(); - if (authenticationService.isTokenValid()) - authenticationService.setupAuthenticationState(); + if (authenticationService.isTokenValid()) authenticationService.setupAuthenticationState(); - facebookService.loadSDK()(document); + facebookService.loadSDK()(document); - analyticsService.init(); + analyticsService.init(); - $transitions.onBefore({}, (transition) => { - if (transition.to().data && transition.to().data.isPublic) - return true; + $transitions.onBefore({}, (transition) => { + if (transition.to().data && transition.to().data.isPublic) return true; - if ($location.host().includes('ccontacts.app')) { - $window.location.href = envService.read('publicUri'); - return false; - } + if ($location.host().includes('ccontacts.app')) { + $window.location.href = envService.read('publicUri'); + return false; + } - if (!authenticationService.isTokenValid()) { - authenticationService.removeAccess(); - return transition.router.stateService.target('app.signIn', { - previousUri: $location.path(), - }); - } + if (!authenticationService.isTokenValid()) { + authenticationService.removeAccess(); + return transition.router.stateService.target('app.signIn', { + previousUri: $location.path(), + }); + } - if ( - transition.to().name !== 'app.ministries.signAgreements' && - state && - state.organization_with_missing_signatures_ids && - state.organization_with_missing_signatures_ids.length > 0 - ) { - return transition.router.stateService.target( - 'app.ministries.signAgreements', - ); - } + if ( + transition.to().name !== 'app.ministries.signAgreements' && + state && + state.organization_with_missing_signatures_ids && + state.organization_with_missing_signatures_ids.length > 0 + ) { + return transition.router.stateService.target('app.ministries.signAgreements'); + } - return loggedInPerson.loadOnce(); - }); + return loggedInPerson.loadOnce(); + }); - $transitions.onFinish({}, (transition) => { - analyticsService.track(transition); - }); + $transitions.onFinish({}, (transition) => { + analyticsService.track(transition); }); + }); diff --git a/app/assets/javascripts/angular/components/aboutModal/aboutModal.component.js b/app/assets/javascripts/angular/components/aboutModal/aboutModal.component.js index 584bc312c2..6a8e05560c 100644 --- a/app/assets/javascripts/angular/components/aboutModal/aboutModal.component.js +++ b/app/assets/javascripts/angular/components/aboutModal/aboutModal.component.js @@ -2,34 +2,34 @@ import template from './aboutModal.html'; import './aboutModal.scss'; angular - .module('campusContactsApp') - .component('aboutModal', { - controller: aboutModalController, - template: template, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - }) - .run( - /* @ngInject */ function ($rootScope, $uibModal) { - $rootScope.openAboutModal = function () { - $uibModal.open({ - component: 'aboutModal', - windowClass: 'pivot_theme', - size: 'md', - }); - }; - }, - ); + .module('campusContactsApp') + .component('aboutModal', { + controller: aboutModalController, + template, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + }) + .run( + /* @ngInject */ function ($rootScope, $uibModal) { + $rootScope.openAboutModal = function () { + $uibModal.open({ + component: 'aboutModal', + windowClass: 'pivot_theme', + size: 'md', + }); + }; + }, + ); function aboutModalController() { - var vm = this; + const vm = this; - vm.year = new Date().getFullYear(); + vm.year = new Date().getFullYear(); - vm.$onInit = activate; + vm.$onInit = activate; - function activate() {} + function activate() {} } diff --git a/app/assets/javascripts/angular/components/aboutModal/aboutModal.html b/app/assets/javascripts/angular/components/aboutModal/aboutModal.html index 913787dce4..dc13179ed4 100644 --- a/app/assets/javascripts/angular/components/aboutModal/aboutModal.html +++ b/app/assets/javascripts/angular/components/aboutModal/aboutModal.html @@ -1,42 +1,26 @@ diff --git a/app/assets/javascripts/angular/components/accordion/accordion.component.js b/app/assets/javascripts/angular/components/accordion/accordion.component.js index 64897eb00a..6ac662f34a 100644 --- a/app/assets/javascripts/angular/components/accordion/accordion.component.js +++ b/app/assets/javascripts/angular/components/accordion/accordion.component.js @@ -2,30 +2,30 @@ import template from './accordion.html'; import './accordion.scss'; angular.module('campusContactsApp').component('accordion', { - controller: accordionController, - bindings: { - collapsed: '=?', - collapsible: '=?', - accordionDisabled: '<', - }, - template: template, - transclude: { - header: 'accordionHeader', - content: 'accordionContent', - }, + controller: accordionController, + bindings: { + collapsed: '=?', + collapsible: '=?', + accordionDisabled: '<', + }, + template, + transclude: { + header: 'accordionHeader', + content: 'accordionContent', + }, }); function accordionController(_) { - var vm = this; + const vm = this; - vm.toggleVisibility = toggleVisibility; + vm.toggleVisibility = toggleVisibility; - _.defaults(vm, { - collapsed: true, - collapsible: true, - }); + _.defaults(vm, { + collapsed: true, + collapsible: true, + }); - function toggleVisibility() { - vm.collapsed = !vm.collapsed; - } + function toggleVisibility() { + vm.collapsed = !vm.collapsed; + } } diff --git a/app/assets/javascripts/angular/components/accordion/accordion.html b/app/assets/javascripts/angular/components/accordion/accordion.html index 346fae753e..6641fca562 100644 --- a/app/assets/javascripts/angular/components/accordion/accordion.html +++ b/app/assets/javascripts/angular/components/accordion/accordion.html @@ -1,9 +1,5 @@
-
+
diff --git a/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.component.js b/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.component.js index 55c567b9db..4eb65c2bd2 100644 --- a/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.component.js +++ b/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.component.js @@ -2,20 +2,20 @@ import template from './accordionToggle.html'; import './accordionToggle.scss'; angular.module('campusContactsApp').component('accordionToggle', { - controller: accordionToggleController, - require: { - accordion: '^', - }, - template: template, - transclude: true, + controller: accordionToggleController, + require: { + accordion: '^', + }, + template, + transclude: true, }); function accordionToggleController() { - var vm = this; + const vm = this; - vm.toggleVisibility = toggleVisibility; + vm.toggleVisibility = toggleVisibility; - function toggleVisibility() { - vm.accordion.collapsed = !vm.accordion.collapsed; - } + function toggleVisibility() { + vm.accordion.collapsed = !vm.accordion.collapsed; + } } diff --git a/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.html b/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.html index 6d94eccd1d..6de15bd8a5 100644 --- a/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.html +++ b/app/assets/javascripts/angular/components/accordionToggle/accordionToggle.html @@ -1,11 +1,11 @@ - - - + + + diff --git a/app/assets/javascripts/angular/components/answerSheet/answerSheet.component.js b/app/assets/javascripts/angular/components/answerSheet/answerSheet.component.js index 9e0a002892..aede161260 100644 --- a/app/assets/javascripts/angular/components/answerSheet/answerSheet.component.js +++ b/app/assets/javascripts/angular/components/answerSheet/answerSheet.component.js @@ -4,33 +4,31 @@ import template from './answerSheet.html'; import './answerSheet.scss'; angular.module('campusContactsApp').component('answerSheet', { - template: template, - bindings: { - answerSheet: '<', - organizationId: '<', - }, - controller: answerSheetController, + template, + bindings: { + answerSheet: '<', + organizationId: '<', + }, + controller: answerSheetController, }); function answerSheetController($uibModal, loggedInPerson) { - this.moment = moment; + this.moment = moment; - this.editResponse = () => { - $uibModal.open({ - component: 'editAnswerSheetModal', - resolve: { - answerSheet: () => this.answerSheet, - organizationId: () => this.organizationId, - }, - windowClass: 'pivot_theme', - backdrop: 'static', - keyboard: false, - }); - }; + this.editResponse = () => { + $uibModal.open({ + component: 'editAnswerSheetModal', + resolve: { + answerSheet: () => this.answerSheet, + organizationId: () => this.organizationId, + }, + windowClass: 'pivot_theme', + backdrop: 'static', + keyboard: false, + }); + }; - this.$onInit = () => { - this.directAdminPrivileges = loggedInPerson.isDirectAdminAt( - this.answerSheet.survey.organization, - ); - }; + this.$onInit = () => { + this.directAdminPrivileges = loggedInPerson.isDirectAdminAt(this.answerSheet.survey.organization); + }; } diff --git a/app/assets/javascripts/angular/components/answerSheet/answerSheet.html b/app/assets/javascripts/angular/components/answerSheet/answerSheet.html index fc94e124be..0c17c7dbf5 100644 --- a/app/assets/javascripts/angular/components/answerSheet/answerSheet.html +++ b/app/assets/javascripts/angular/components/answerSheet/answerSheet.html @@ -1,18 +1,18 @@
- +
-
- {{$ctrl.moment($ctrl.answerSheet.updated_at).fromNow()}} -
-
{{$ctrl.answerSheet.survey.title}}
-
-
{{answer.question.label}}
-
{{answer.value}}
-
+
+ {{$ctrl.moment($ctrl.answerSheet.updated_at).fromNow()}} +
+
{{$ctrl.answerSheet.survey.title}}
+
+
{{answer.question.label}}
+
{{answer.value}}
+
diff --git a/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.component.js b/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.component.js index 6e743b4a38..4173e50ce7 100644 --- a/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.component.js +++ b/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.component.js @@ -3,48 +3,46 @@ import template from './editAnswerSheetModal.html'; import './editAnswerSheetModal.scss'; angular.module('campusContactsApp').component('editAnswerSheetModal', { - bindings: { - resolve: '<', - dismiss: '&', - close: '&', - }, - template: template, - controller: editAnswerSheetModalController, + bindings: { + resolve: '<', + dismiss: '&', + close: '&', + }, + template, + controller: editAnswerSheetModalController, }); function editAnswerSheetModalController(httpProxy, modelsService) { - this.save = async (answerId) => { - const answers = this.resolve.answerSheet.answers; + this.save = async (answerId) => { + const answers = this.resolve.answerSheet.answers; - const includedAnswers = answers.map((a) => { - return { - type: 'answer', - attributes: { - question_id: a.question.id, - value: a.value, - }, - }; - }); + const includedAnswers = answers.map((a) => { + return { + type: 'answer', + attributes: { + question_id: a.question.id, + value: a.value, + }, + }; + }); - const url = modelsService - .getModelMetadata('answer_sheet') - .url.single(this.resolve.answerSheet.id); + const url = modelsService.getModelMetadata('answer_sheet').url.single(this.resolve.answerSheet.id); - const { data } = await httpProxy.put( - url, - { - data: { - type: 'answer_sheet', - attributes: {}, - }, - included: includedAnswers, - }, - { - params: { include: 'answers' }, - errorMessage: 'surveyTab:errors.updateSurvey', - }, - ); + const { data } = await httpProxy.put( + url, + { + data: { + type: 'answer_sheet', + attributes: {}, + }, + included: includedAnswers, + }, + { + params: { include: 'answers' }, + errorMessage: 'surveyTab:errors.updateSurvey', + }, + ); - this.close(); - }; + this.close(); + }; } diff --git a/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.html b/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.html index 69b94081c6..3f7c25125a 100644 --- a/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.html +++ b/app/assets/javascripts/angular/components/answerSheet/editAnswerSheetModal.html @@ -1,88 +1,64 @@
-
-
{{answer.question.label}}
+
+
{{answer.question.label}}
-
-
- -
-
-
- -
-
-
-
- -
-
-
- - {{ content }} -
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + {{ content }} +
+
diff --git a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.component.js b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.component.js index a4e5fa0c4b..c0a1f4f508 100644 --- a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.component.js +++ b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.component.js @@ -2,43 +2,39 @@ import template from './assignedLabelSelect.html'; import './assignedLabelSelect.scss'; angular.module('campusContactsApp').component('assignedLabelSelect', { - bindings: { - assigned: '=', - organizationId: '<', - disabled: '<', - actionAfterSelect: '&', - }, - controller: assignedLabelSelectController, - template: template, + bindings: { + assigned: '=', + organizationId: '<', + disabled: '<', + actionAfterSelect: '&', + }, + controller: assignedLabelSelectController, + template, }); function assignedLabelSelectController($scope, assignedLabelSelectService) { - this.labels = []; - this.originalLabels = []; - this.$onInit = () => { - // When this loads, get all the labels and set this.originalLabels to all the labels. We do this once instead of every time the user types. - assignedLabelSelectService - .searchLabels(this.organizationId) - .then((labels) => { - this.originalLabels = labels; - }); - // This will happen everytime the user types - $scope.$watch('$select.search', (search) => { - if (search === '') { - // Set this.labels to the original list of labels we fetched - this.labels = [...this.originalLabels]; - return; - } - // Here we filter out all the labels from the originalLabels array that do not include what the user is currently typing - this.labels = this.originalLabels.filter((label) => - label.name.toLowerCase().includes(search.toLowerCase()), - ); - }); + this.labels = []; + this.originalLabels = []; + this.$onInit = () => { + // When this loads, get all the labels and set this.originalLabels to all the labels. We do this once instead of every time the user types. + assignedLabelSelectService.searchLabels(this.organizationId).then((labels) => { + this.originalLabels = labels; + }); + // This will happen everytime the user types + $scope.$watch('$select.search', (search) => { + if (search === '') { + // Set this.labels to the original list of labels we fetched + this.labels = [...this.originalLabels]; + return; + } + // Here we filter out all the labels from the originalLabels array that do not include what the user is currently typing + this.labels = this.originalLabels.filter((label) => label.name.toLowerCase().includes(search.toLowerCase())); + }); - $scope.$watch('$ctrl.assigned', (o, n) => { - if (this.actionAfterSelect && o !== n) { - this.actionAfterSelect(); - } - }); - }; + $scope.$watch('$ctrl.assigned', (o, n) => { + if (this.actionAfterSelect && o !== n) { + this.actionAfterSelect(); + } + }); + }; } diff --git a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.html b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.html index db07587e3c..2417e1bd6a 100644 --- a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.html +++ b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.html @@ -1,16 +1,8 @@ - - - {{ $item.name }} - - - {{ label.name }} - + + + {{ $item.name }} + + + {{ label.name }} + diff --git a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.service.js b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.service.js index 6b942225ce..3997d5f024 100644 --- a/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.service.js +++ b/app/assets/javascripts/angular/components/assignedLabelSelect/assignedLabelSelect.service.js @@ -1,24 +1,22 @@ -angular - .module('campusContactsApp') - .factory('assignedLabelSelectService', assignedLabelSelectService); +angular.module('campusContactsApp').factory('assignedLabelSelectService', assignedLabelSelectService); function assignedLabelSelectService(httpProxy) { - return { - // Get all the labels from the current organizations - searchLabels: (organizationId) => { - return httpProxy - .get( - `/organizations/${organizationId}`, - { - include: 'labels', - }, - { - errorMessage: 'error.messages.surveys.loadQuestions', - }, - ) - .then((data) => { - return data.data.labels; - }); - }, - }; + return { + // Get all the labels from the current organizations + searchLabels: (organizationId) => { + return httpProxy + .get( + `/organizations/${organizationId}`, + { + include: 'labels', + }, + { + errorMessage: 'error.messages.surveys.loadQuestions', + }, + ) + .then((data) => { + return data.data.labels; + }); + }, + }; } diff --git a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.component.js b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.component.js index 520c5eadac..53a9abecf6 100644 --- a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.component.js +++ b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.component.js @@ -2,49 +2,39 @@ import template from './assignedPeopleSelect.html'; import './assignedPeopleSelect.scss'; angular.module('campusContactsApp').component('assignedPeopleSelect', { - bindings: { - assigned: '=', - ruleCode: '<', - organizationId: '<', - disabled: '<', - actionAfterSelect: '&', - }, - controller: assignedPeopleSelectController, - template: template, + bindings: { + assigned: '=', + ruleCode: '<', + organizationId: '<', + disabled: '<', + actionAfterSelect: '&', + }, + controller: assignedPeopleSelectController, + template, }); -function assignedPeopleSelectController( - $scope, - assignedPeopleSelectService, - RequestDeduper, -) { - this.people = []; - this.isMe = assignedPeopleSelectService.isMe; - this.$onInit = () => { - const requestDeduper = new RequestDeduper(); - // Refresh the person list whenever the search term changes - $scope.$watch('$select.search', (search) => { - assignedPeopleSelectService - .searchPeople(search, this.organizationId, requestDeduper) - .then((people) => { - if (this.assigned === null) { - this.people = people; - } else { - const assignedPeopleIds = this.assigned.map( - ({ id }) => id, - ); - // Find all the current people in this.assigned - this.people = people.filter( - (person) => !assignedPeopleIds.includes(person.id), - ); - } - }); - }); +function assignedPeopleSelectController($scope, assignedPeopleSelectService, RequestDeduper) { + this.people = []; + this.isMe = assignedPeopleSelectService.isMe; + this.$onInit = () => { + const requestDeduper = new RequestDeduper(); + // Refresh the person list whenever the search term changes + $scope.$watch('$select.search', (search) => { + assignedPeopleSelectService.searchPeople(search, this.organizationId, requestDeduper).then((people) => { + if (this.assigned === null) { + this.people = people; + } else { + const assignedPeopleIds = this.assigned.map(({ id }) => id); + // Find all the current people in this.assigned + this.people = people.filter((person) => !assignedPeopleIds.includes(person.id)); + } + }); + }); - $scope.$watch('$ctrl.assigned', (o, n) => { - if (this.actionAfterSelect && o !== n) { - this.actionAfterSelect(); - } - }); - }; + $scope.$watch('$ctrl.assigned', (o, n) => { + if (this.actionAfterSelect && o !== n) { + this.actionAfterSelect(); + } + }); + }; } diff --git a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.html b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.html index ac8cd36b7f..9f821d280c 100644 --- a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.html +++ b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.html @@ -1,30 +1,20 @@ - - + - - {{ $item | personName }} - ({{ 'application.assign_search.me' | t }}) - - - - - {{ person | personName }} - ({{ 'application.assign_search.me' | t }}) - - + > + + {{ $item | personName }} + ({{ 'application.assign_search.me' | t }}) + + + + + {{ person | personName }} + ({{ 'application.assign_search.me' | t }}) + + diff --git a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.js b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.js index da0158017e..d07eb77382 100644 --- a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.js +++ b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.js @@ -1,44 +1,34 @@ -angular - .module('campusContactsApp') - .factory('assignedPeopleSelectService', assignedPeopleSelectService); +angular.module('campusContactsApp').factory('assignedPeopleSelectService', assignedPeopleSelectService); -function assignedPeopleSelectService( - httpProxy, - modelsService, - loggedInPerson, - permissionService, -) { - return { - // Search for people in a particular organization that match the query - searchPeople: function (query, organizationId, deduper) { - if (!query || query.length < 2) { - return Promise.resolve([]); - } +function assignedPeopleSelectService(httpProxy, modelsService, loggedInPerson, permissionService) { + return { + // Search for people in a particular organization that match the query + searchPeople: function (query, organizationId, deduper) { + if (!query || query.length < 2) { + return Promise.resolve([]); + } - return httpProxy - .get( - modelsService.getModelMetadata('person').url.all, - { - 'filters[name]': query, - 'filters[organization_ids]': organizationId, - 'filters[permission_ids]': permissionService.adminAndUserIds.join( - ',', - ), - 'fields[person]': 'first_name,last_name', - include: '', - }, - { - deduper: deduper, - errorMessage: - 'error.messages.assigned_select.search_people', - bypassStore: true, - }, - ) - .then(httpProxy.extractModels); - }, - // Determine whether a person is the currently logged-in person - isMe: function (person) { - return loggedInPerson.person === person; - }, - }; + return httpProxy + .get( + modelsService.getModelMetadata('person').url.all, + { + 'filters[name]': query, + 'filters[organization_ids]': organizationId, + 'filters[permission_ids]': permissionService.adminAndUserIds.join(','), + 'fields[person]': 'first_name,last_name', + include: '', + }, + { + deduper, + errorMessage: 'error.messages.assigned_select.search_people', + bypassStore: true, + }, + ) + .then(httpProxy.extractModels); + }, + // Determine whether a person is the currently logged-in person + isMe: function (person) { + return loggedInPerson.person === person; + }, + }; } diff --git a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.spec.js b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.spec.js index c3469f31b5..2ad74a8295 100644 --- a/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.spec.js +++ b/app/assets/javascripts/angular/components/assignedPeopleSelect/assignedPeopleSelect.service.spec.js @@ -1,32 +1,32 @@ import 'angular-mocks'; // Constants -var assignedPeopleSelectService; +let assignedPeopleSelectService; describe('assignedPeopleSelectService', function () { - beforeEach(function () { - var _this = this; - angular.mock.module(function ($provide) { - $provide.factory('loggedInPerson', function () { - return { - get person() { - return _this.person; - }, - }; - }); - }); + beforeEach(function () { + const _this = this; + angular.mock.module(function ($provide) { + $provide.factory('loggedInPerson', function () { + return { + get person() { + return _this.person; + }, + }; + }); }); + }); - beforeEach(inject(function (_assignedPeopleSelectService_) { - assignedPeopleSelectService = _assignedPeopleSelectService_; + beforeEach(inject(function (_assignedPeopleSelectService_) { + assignedPeopleSelectService = _assignedPeopleSelectService_; - this.person = { id: 123 }; - })); + this.person = { id: 123 }; + })); - describe('isMe', function () { - it('should check whether the person matches the logged in person', function () { - expect(assignedPeopleSelectService.isMe(this.person)).toBe(true); - expect(assignedPeopleSelectService.isMe({ id: 456 })).toBe(false); - }); + describe('isMe', function () { + it('should check whether the person matches the logged in person', function () { + expect(assignedPeopleSelectService.isMe(this.person)).toBe(true); + expect(assignedPeopleSelectService.isMe({ id: 456 })).toBe(false); }); + }); }); diff --git a/app/assets/javascripts/angular/components/asyncContent/asyncContent.component.js b/app/assets/javascripts/angular/components/asyncContent/asyncContent.component.js index b3b5046881..78650ae86d 100644 --- a/app/assets/javascripts/angular/components/asyncContent/asyncContent.component.js +++ b/app/assets/javascripts/angular/components/asyncContent/asyncContent.component.js @@ -2,9 +2,9 @@ import template from './asyncContent.html'; import './asyncContent.scss'; angular.module('campusContactsApp').component('asyncContent', { - bindings: { - ready: '<', - }, - template: template, - transclude: true, + bindings: { + ready: '<', + }, + template, + transclude: true, }); diff --git a/app/assets/javascripts/angular/components/contactActions/contactActions.component.js b/app/assets/javascripts/angular/components/contactActions/contactActions.component.js index 568832d36a..1f1095a04e 100644 --- a/app/assets/javascripts/angular/components/contactActions/contactActions.component.js +++ b/app/assets/javascripts/angular/components/contactActions/contactActions.component.js @@ -2,20 +2,20 @@ import template from './contactActions.html'; import './contactActions.scss'; angular.module('campusContactsApp').component('contactActions', { - bindings: { - phone: '<', - email: '<', - }, - template: template, - controller: contactActionsController, + bindings: { + phone: '<', + email: '<', + }, + template, + controller: contactActionsController, }); function contactActionsController() { - this.actionsVisible = false; + this.actionsVisible = false; - this.toggleActions = () => { - this.actionsVisible = !this.actionsVisible; - }; + this.toggleActions = () => { + this.actionsVisible = !this.actionsVisible; + }; - this.copyText = (text) => navigator.clipboard.writeText(text); + this.copyText = (text) => navigator.clipboard.writeText(text); } diff --git a/app/assets/javascripts/angular/components/contactActions/contactActions.html b/app/assets/javascripts/angular/components/contactActions/contactActions.html index 392d19feba..1464c9d1e8 100644 --- a/app/assets/javascripts/angular/components/contactActions/contactActions.html +++ b/app/assets/javascripts/angular/components/contactActions/contactActions.html @@ -1,92 +1,76 @@
-
-
- - -
-
- - -
+
+
+ +
-
- - - +
+ +
+
+
+ + + +
diff --git a/app/assets/javascripts/angular/components/copySurvey/copySurvey.component.js b/app/assets/javascripts/angular/components/copySurvey/copySurvey.component.js index b74bc5988e..328af13964 100644 --- a/app/assets/javascripts/angular/components/copySurvey/copySurvey.component.js +++ b/app/assets/javascripts/angular/components/copySurvey/copySurvey.component.js @@ -1,55 +1,47 @@ import template from './copySurvey.html'; angular.module('campusContactsApp').component('copySurvey', { - controller: copySurveyController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: copySurveyController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); function copySurveyController(surveyService, loggedInPerson) { - this.saving = false; - this.survey = {}; - - this.$onInit = () => { - this.survey.id = this.resolve.survey.id; - this.survey.title = this.resolve.survey.title; - - this.orgs = loggedInPerson.person.organizational_permissions.map( - (orgPermission) => orgPermission.organization, - ); - this.orgs = this.orgs.filter((org) => { - return loggedInPerson.isAdminAt(org); - }); - - //default to current org - this.survey.parent_organization = this.resolve.organizationId; - }; - - this.valid = () => { - return this.survey.parent_organization && this.survey.title; - }; - - this.save = () => { - this.saving = true; - - surveyService - .copySurvey( - this.survey.id, - this.survey.parent_organization, - this.survey.title, - ) - .then( - (newSurvey) => { - this.close(newSurvey); - }, - (response) => { - this.saving = false; - this.error = response.data.error; - }, - ); - }; + this.saving = false; + this.survey = {}; + + this.$onInit = () => { + this.survey.id = this.resolve.survey.id; + this.survey.title = this.resolve.survey.title; + + this.orgs = loggedInPerson.person.organizational_permissions.map((orgPermission) => orgPermission.organization); + this.orgs = this.orgs.filter((org) => { + return loggedInPerson.isAdminAt(org); + }); + + // default to current org + this.survey.parent_organization = this.resolve.organizationId; + }; + + this.valid = () => { + return this.survey.parent_organization && this.survey.title; + }; + + this.save = () => { + this.saving = true; + + surveyService.copySurvey(this.survey.id, this.survey.parent_organization, this.survey.title).then( + (newSurvey) => { + this.close(newSurvey); + }, + (response) => { + this.saving = false; + this.error = response.data.error; + }, + ); + }; } diff --git a/app/assets/javascripts/angular/components/copySurvey/copySurvey.html b/app/assets/javascripts/angular/components/copySurvey/copySurvey.html index 426db6cf11..e432e41954 100644 --- a/app/assets/javascripts/angular/components/copySurvey/copySurvey.html +++ b/app/assets/javascripts/angular/components/copySurvey/copySurvey.html @@ -1,51 +1,34 @@ diff --git a/app/assets/javascripts/angular/components/createSurvey/createSurvey.component.js b/app/assets/javascripts/angular/components/createSurvey/createSurvey.component.js index 6e364b5c82..5526ed6ff3 100644 --- a/app/assets/javascripts/angular/components/createSurvey/createSurvey.component.js +++ b/app/assets/javascripts/angular/components/createSurvey/createSurvey.component.js @@ -1,51 +1,48 @@ import template from './createSurvey.html'; angular.module('campusContactsApp').component('createSurvey', { - controller: createSurveyController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: createSurveyController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); function createSurveyController(surveyService) { - var vm = this; + const vm = this; - vm.title = null; - vm.saving = false; - vm.survey = {}; + vm.title = null; + vm.saving = false; + vm.survey = {}; - vm.valid = valid; - vm.save = save; - vm.cancel = cancel; + vm.valid = valid; + vm.save = save; + vm.cancel = cancel; - vm.$onInit = activate; + vm.$onInit = activate; - function activate() { - vm.orgId = vm.resolve.organizationId; - } + function activate() { + vm.orgId = vm.resolve.organizationId; + } - function valid() { - return vm.survey.title; - } + function valid() { + return vm.survey.title; + } - async function save() { - vm.saving = true; - - try { - const newSurvey = await surveyService.createSurvey( - vm.survey.title, - vm.orgId, - ); - vm.close({ $value: newSurvey }); - } catch (err) { - vm.saving = false; - } - } + async function save() { + vm.saving = true; - function cancel() { - vm.dismiss(); + try { + const newSurvey = await surveyService.createSurvey(vm.survey.title, vm.orgId); + vm.close({ $value: newSurvey }); + } catch (err) { + vm.saving = false; } + } + + function cancel() { + vm.dismiss(); + } } diff --git a/app/assets/javascripts/angular/components/createSurvey/createSurvey.html b/app/assets/javascripts/angular/components/createSurvey/createSurvey.html index 67d0de9ee7..29de86e74d 100644 --- a/app/assets/javascripts/angular/components/createSurvey/createSurvey.html +++ b/app/assets/javascripts/angular/components/createSurvey/createSurvey.html @@ -1,38 +1,21 @@ diff --git a/app/assets/javascripts/angular/components/dashboard/dashboard.component.js b/app/assets/javascripts/angular/components/dashboard/dashboard.component.js index 0f221c56ab..9577d6fff8 100644 --- a/app/assets/javascripts/angular/components/dashboard/dashboard.component.js +++ b/app/assets/javascripts/angular/components/dashboard/dashboard.component.js @@ -1,29 +1,26 @@ import template from './dashboard.html'; angular.module('campusContactsApp').component('dashboard', { - controller: DashboardController, - template: template, + controller: DashboardController, + template, }); function DashboardController(periodService, $rootScope) { - const vm = this; - let deregisterEditOrganizationsEvent; + const vm = this; + let deregisterEditOrganizationsEvent; - vm.editOrganizations = false; - vm.getPeriod = periodService.getPeriod; - vm.$onInit = activate; - vm.$onDestroy = deactivate; + vm.editOrganizations = false; + vm.getPeriod = periodService.getPeriod; + vm.$onInit = activate; + vm.$onDestroy = deactivate; - function activate() { - deregisterEditOrganizationsEvent = $rootScope.$on( - 'editOrganizations', - function (event, value) { - vm.editOrganizations = value; - }, - ); - } + function activate() { + deregisterEditOrganizationsEvent = $rootScope.$on('editOrganizations', function (event, value) { + vm.editOrganizations = value; + }); + } - function deactivate() { - deregisterEditOrganizationsEvent(); - } + function deactivate() { + deregisterEditOrganizationsEvent(); + } } diff --git a/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.component.js b/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.component.js index 8136855eab..fd4ada102a 100644 --- a/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.component.js +++ b/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.component.js @@ -2,16 +2,16 @@ import './dashboard-subnav.scss'; import template from './dashboard-subnav.html'; angular.module('campusContactsApp').component('dashboardSubnav', { - controller: DashboardSubnavController, - template: template, + controller: DashboardSubnavController, + template, }); function DashboardSubnavController($rootScope, $state) { - this.$state = $state; - this.editOrganizations = false; + this.$state = $state; + this.editOrganizations = false; - this.toggleEditOrganizations = () => { - this.editOrganizations = !this.editOrganizations; - $rootScope.$broadcast('editOrganizations', this.editOrganizations); - }; + this.toggleEditOrganizations = () => { + this.editOrganizations = !this.editOrganizations; + $rootScope.$broadcast('editOrganizations', this.editOrganizations); + }; } diff --git a/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.html b/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.html index d0d07008de..88fb6563ce 100644 --- a/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.html +++ b/app/assets/javascripts/angular/components/dashboard/subnav/dashboard-subnav.html @@ -1,104 +1,88 @@
- - diff --git a/app/assets/javascripts/angular/components/editAddress/editAddress.component.js b/app/assets/javascripts/angular/components/editAddress/editAddress.component.js index 324c71f039..8928cac71e 100644 --- a/app/assets/javascripts/angular/components/editAddress/editAddress.component.js +++ b/app/assets/javascripts/angular/components/editAddress/editAddress.component.js @@ -2,103 +2,94 @@ import template from './editAddress.html'; import './editAddress.scss'; angular.module('campusContactsApp').component('editAddress', { - controller: editAddressController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: editAddressController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); function editAddressController(editAddressService, personProfileService, _) { - var vm = this; - - vm.saving = false; - vm.addressTypes = editAddressService.getAddressTypes(); - - vm.valid = valid; - vm.loadRegions = loadRegions; - vm.isAddressTypeValid = isAddressTypeValid; - vm.save = save; - vm.cancel = cancel; - - vm.$onInit = activate; - - function activate() { - vm.person = vm.resolve.person; - - // This will be true if we are creating a new contact and false if we are editing an existing contact - vm.isNewAddress = vm.resolve.address === null; - - // Copy the address so that the changes can be discard if the user does not save - var address = vm.resolve.address; - vm.address = address - ? _.clone(address) - : editAddressService.getAddressTemplate(vm.person); - - // Get the list of the user's other addresses - vm.otherAddresses = _.without(vm.person.addresses, address); - - loadCountries().then(function () { - // For now, US regions are the only valid region choices - loadRegions('US'); - }); - } - - function valid() { - return editAddressService.isAddressValid(vm.address); - } - - // Populate vm.countries with the valid country choices - function loadCountries() { - return editAddressService - .getCountryOptions() - .then(function (countries) { - vm.countries = countries; - }); - } - - // Populate vm.countries with the valid region choices - function loadRegions(countryCode) { - return editAddressService - .getRegionOptions(countryCode) - .then(function (regions) { - vm.regions = regions; - }); - } - - function isAddressTypeValid(addressType) { - return editAddressService.isAddressTypeValid( - addressType, - vm.otherAddresses, - ); - } - - // Persist the changes to the address to the server - function save() { - vm.saving = true; - personProfileService - .saveAttribute(vm.person.id, vm.address, _.keys(vm.address)) - .then(function () { - if (vm.person.id === null && vm.isNewAddress) { - // The person is not saved on the server, so manually add the new address to the person - vm.person.addresses.push(vm.address); - } - - if (!vm.isNewAddress) { - // Apply the changes to the original address - _.extend(vm.resolve.address, vm.address); - } - - vm.close({ $value: vm.address }); - }) - .catch(function () { - vm.saving = false; - }); - } - - function cancel() { - vm.dismiss(); - } + const vm = this; + + vm.saving = false; + vm.addressTypes = editAddressService.getAddressTypes(); + + vm.valid = valid; + vm.loadRegions = loadRegions; + vm.isAddressTypeValid = isAddressTypeValid; + vm.save = save; + vm.cancel = cancel; + + vm.$onInit = activate; + + function activate() { + vm.person = vm.resolve.person; + + // This will be true if we are creating a new contact and false if we are editing an existing contact + vm.isNewAddress = vm.resolve.address === null; + + // Copy the address so that the changes can be discard if the user does not save + const address = vm.resolve.address; + vm.address = address ? _.clone(address) : editAddressService.getAddressTemplate(vm.person); + + // Get the list of the user's other addresses + vm.otherAddresses = _.without(vm.person.addresses, address); + + loadCountries().then(function () { + // For now, US regions are the only valid region choices + loadRegions('US'); + }); + } + + function valid() { + return editAddressService.isAddressValid(vm.address); + } + + // Populate vm.countries with the valid country choices + function loadCountries() { + return editAddressService.getCountryOptions().then(function (countries) { + vm.countries = countries; + }); + } + + // Populate vm.countries with the valid region choices + function loadRegions(countryCode) { + return editAddressService.getRegionOptions(countryCode).then(function (regions) { + vm.regions = regions; + }); + } + + function isAddressTypeValid(addressType) { + return editAddressService.isAddressTypeValid(addressType, vm.otherAddresses); + } + + // Persist the changes to the address to the server + function save() { + vm.saving = true; + personProfileService + .saveAttribute(vm.person.id, vm.address, _.keys(vm.address)) + .then(function () { + if (vm.person.id === null && vm.isNewAddress) { + // The person is not saved on the server, so manually add the new address to the person + vm.person.addresses.push(vm.address); + } + + if (!vm.isNewAddress) { + // Apply the changes to the original address + _.extend(vm.resolve.address, vm.address); + } + + vm.close({ $value: vm.address }); + }) + .catch(function () { + vm.saving = false; + }); + } + + function cancel() { + vm.dismiss(); + } } diff --git a/app/assets/javascripts/angular/components/editAddress/editAddress.html b/app/assets/javascripts/angular/components/editAddress/editAddress.html index 2a6e290d50..0d549bbeb1 100644 --- a/app/assets/javascripts/angular/components/editAddress/editAddress.html +++ b/app/assets/javascripts/angular/components/editAddress/editAddress.html @@ -1,101 +1,73 @@ + + + + + +
diff --git a/app/assets/javascripts/angular/components/editAddress/editAddress.service.js b/app/assets/javascripts/angular/components/editAddress/editAddress.service.js index 5747a3a500..0f1f1764d8 100644 --- a/app/assets/javascripts/angular/components/editAddress/editAddress.service.js +++ b/app/assets/javascripts/angular/components/editAddress/editAddress.service.js @@ -1,76 +1,61 @@ -angular - .module('campusContactsApp') - .factory('editAddressService', editAddressService); +angular.module('campusContactsApp').factory('editAddressService', editAddressService); function editAddressService(geoDataService, JsonApiDataStore, _) { - var editAddressService = { - // Return an array of valid address types - getAddressTypes: function () { - return ['current', 'permanent', 'emergency1', 'emergency2']; - }, - - // Return a boolean indicating whether a particular address type is valid for a particular person's address - isAddressTypeValid: function (addressType, otherAddresses) { - // The address type is valid if no other addresses already have the address type - return !_.find(otherAddresses, { address_type: addressType }); - }, - - // Determine whether an address has valid field values - isAddressValid: function (address) { - return Boolean(address.address_type); - }, - - // Return an address for the specific with default field values - getAddressTemplate: function (person) { - // Find the first unused address type - var addressType = _.chain(editAddressService.getAddressTypes()) - .difference(_.map(person.addresses, 'address_type')) - .first() - .defaultTo(null) - .value(); - - var address = new JsonApiDataStore.Model('address'); - address.setAttribute('person_id', person.id); - address.setAttribute('address_type', addressType); - [ - 'address1', - 'address2', - 'address3', - 'address4', - 'city', - 'state', - 'zip', - 'country', - ].forEach(function (attribute) { - address.setAttribute(attribute, ''); - }); - return address; - }, - - // Return an array that resolves to the list of country options - getCountryOptions: function () { - return geoDataService.getCountries().then(function (countries) { - // Remove the priority countries and then add them back to the front of the list - var priorityCountryCodes = ['US', 'CA']; - var priorityCountries = priorityCountryCodes.map(function ( - countryCode, - ) { - return _.find(countries, { shortCode: countryCode }); - }); - return priorityCountries.concat( - _.difference(countries, priorityCountries), - ); - }); - }, - - // Return an array that resolves to the list of region options for a given country - getRegionOptions: function (countryCode) { - return geoDataService.getCountries().then(function (countries) { - var country = _.find(countries, { shortCode: countryCode }); - return country ? country.regions : []; - }); - }, - }; - - return editAddressService; + var editAddressService = { + // Return an array of valid address types + getAddressTypes: function () { + return ['current', 'permanent', 'emergency1', 'emergency2']; + }, + + // Return a boolean indicating whether a particular address type is valid for a particular person's address + isAddressTypeValid: function (addressType, otherAddresses) { + // The address type is valid if no other addresses already have the address type + return !_.find(otherAddresses, { address_type: addressType }); + }, + + // Determine whether an address has valid field values + isAddressValid: function (address) { + return Boolean(address.address_type); + }, + + // Return an address for the specific with default field values + getAddressTemplate: function (person) { + // Find the first unused address type + const addressType = _.chain(editAddressService.getAddressTypes()) + .difference(_.map(person.addresses, 'address_type')) + .first() + .defaultTo(null) + .value(); + + const address = new JsonApiDataStore.Model('address'); + address.setAttribute('person_id', person.id); + address.setAttribute('address_type', addressType); + ['address1', 'address2', 'address3', 'address4', 'city', 'state', 'zip', 'country'].forEach(function (attribute) { + address.setAttribute(attribute, ''); + }); + return address; + }, + + // Return an array that resolves to the list of country options + getCountryOptions: function () { + return geoDataService.getCountries().then(function (countries) { + // Remove the priority countries and then add them back to the front of the list + const priorityCountryCodes = ['US', 'CA']; + const priorityCountries = priorityCountryCodes.map(function (countryCode) { + return _.find(countries, { shortCode: countryCode }); + }); + return priorityCountries.concat(_.difference(countries, priorityCountries)); + }); + }, + + // Return an array that resolves to the list of region options for a given country + getRegionOptions: function (countryCode) { + return geoDataService.getCountries().then(function (countries) { + const country = _.find(countries, { shortCode: countryCode }); + return country ? country.regions : []; + }); + }, + }; + + return editAddressService; } diff --git a/app/assets/javascripts/angular/components/editAddress/editAddress.service.spec.js b/app/assets/javascripts/angular/components/editAddress/editAddress.service.spec.js index 09ececcac8..f83bc965bf 100644 --- a/app/assets/javascripts/angular/components/editAddress/editAddress.service.spec.js +++ b/app/assets/javascripts/angular/components/editAddress/editAddress.service.spec.js @@ -1,211 +1,160 @@ import 'angular-mocks'; // Constants -var editAddressService, $q, $rootScope, _; +let editAddressService, $q, $rootScope, _; // Add better asynchronous support to a test function // The test function must return a promise // The promise will automatically be bound to "done" and the $rootScope will be automatically digested function asynchronous(fn) { - return function (done) { - var returnValue = fn.call(this, done); - returnValue - .then(function () { - done(); - }) - .catch(function (err) { - done.fail(err); - }); - $rootScope.$apply(); - return returnValue; - }; + return function (done) { + const returnValue = fn.call(this, done); + returnValue + .then(function () { + done(); + }) + .catch(function (err) { + done.fail(err); + }); + $rootScope.$apply(); + return returnValue; + }; } describe('editAddressService', function () { - beforeEach(inject(function ( - _editAddressService_, - _$q_, - _$rootScope_, - geoDataService, - ___, - ) { - editAddressService = _editAddressService_; - $q = _$q_; - $rootScope = _$rootScope_; - _ = ___; - - this.address1 = { id: 1, address_type: 'type1' }; - this.address2 = { id: 2, address_type: 'type2' }; - this.address3 = { id: 3, address_type: 'type3' }; - - var countries = [ - { shortCode: 'AA' }, - { shortCode: 'BA' }, - { shortCode: 'CA' }, - { - shortCode: 'US', - regions: [ - { shortCode: 'AL' }, - { shortCode: 'AK' }, - { shortCode: 'AZ' }, - ], - }, - ]; - spyOn(geoDataService, 'getCountries').and.returnValue( - $q.resolve(countries), - ); - })); - - describe('getAddressTypes', function () { - it('should return an array', function () { - expect(editAddressService.getAddressTypes()).toEqual( - jasmine.any(Array), - ); - }); + beforeEach(inject(function (_editAddressService_, _$q_, _$rootScope_, geoDataService, ___) { + editAddressService = _editAddressService_; + $q = _$q_; + $rootScope = _$rootScope_; + _ = ___; + + this.address1 = { id: 1, address_type: 'type1' }; + this.address2 = { id: 2, address_type: 'type2' }; + this.address3 = { id: 3, address_type: 'type3' }; + + const countries = [ + { shortCode: 'AA' }, + { shortCode: 'BA' }, + { shortCode: 'CA' }, + { + shortCode: 'US', + regions: [{ shortCode: 'AL' }, { shortCode: 'AK' }, { shortCode: 'AZ' }], + }, + ]; + spyOn(geoDataService, 'getCountries').and.returnValue($q.resolve(countries)); + })); + + describe('getAddressTypes', function () { + it('should return an array', function () { + expect(editAddressService.getAddressTypes()).toEqual(jasmine.any(Array)); }); + }); - describe('isAddressTypeValid', function () { - beforeEach(function () { - this.otherAddresses = [this.address1, this.address2]; - spyOn(editAddressService, 'getAddressTypes').and.returnValue([ - 'type1', - 'type2', - 'type3', - ]); - }); - - it('should treat unused address types as valid', function () { - expect( - editAddressService.isAddressTypeValid( - 'type3', - this.otherAddresses, - ), - ).toBe(true); - }); - - it('should treat used address types as invalid', function () { - expect( - editAddressService.isAddressTypeValid( - 'type1', - this.otherAddresses, - ), - ).toBe(false); - }); + describe('isAddressTypeValid', function () { + beforeEach(function () { + this.otherAddresses = [this.address1, this.address2]; + spyOn(editAddressService, 'getAddressTypes').and.returnValue(['type1', 'type2', 'type3']); }); - describe('isAddressValid', function () { - it('should treat addresses without a type as invalid', function () { - expect( - editAddressService.isAddressValid({ address_type: null }), - ).toBe(false); - }); - - it('should treat addresses with a type as valid', function () { - expect( - editAddressService.isAddressValid({ address_type: 'type' }), - ).toBe(true); - }); + it('should treat unused address types as valid', function () { + expect(editAddressService.isAddressTypeValid('type3', this.otherAddresses)).toBe(true); }); - describe('getAddressTemplate', function () { - it('should set the required address fields', function () { - var person = { - id: 1, - }; - expect(editAddressService.getAddressTemplate(person)).toEqual( - jasmine.objectContaining({ - _type: 'address', - person_id: person.id, - address_type: jasmine.any(String), - }), - ); - }); + it('should treat used address types as invalid', function () { + expect(editAddressService.isAddressTypeValid('type1', this.otherAddresses)).toBe(false); + }); + }); - it('should choose the first available address type', function () { - spyOn(editAddressService, 'getAddressTypes').and.returnValue([ - 'type1', - 'type2', - 'type3', - ]); - - expect( - editAddressService.getAddressTemplate({ - id: 1, - addresses: [], - }), - ).toEqual( - jasmine.objectContaining({ - address_type: 'type1', - }), - ); - - expect( - editAddressService.getAddressTemplate({ - id: 1, - addresses: [this.address1, this.address3], - }), - ).toEqual( - jasmine.objectContaining({ - address_type: 'type2', - }), - ); - - expect( - editAddressService.getAddressTemplate({ - id: 1, - addresses: [this.address1, this.address2, this.address3], - }), - ).toEqual( - jasmine.objectContaining({ - address_type: null, - }), - ); - }); + describe('isAddressValid', function () { + it('should treat addresses without a type as invalid', function () { + expect(editAddressService.isAddressValid({ address_type: null })).toBe(false); }); - describe('getCountryOptions', function () { - it( - 'should prioritize certain countries', - asynchronous(function () { - return editAddressService - .getCountryOptions() - .then(function (countryOptions) { - expect(_.map(countryOptions, 'shortCode')).toEqual([ - 'US', - 'CA', - 'AA', - 'BA', - ]); - }); - }), - ); + it('should treat addresses with a type as valid', function () { + expect(editAddressService.isAddressValid({ address_type: 'type' })).toBe(true); + }); + }); + + describe('getAddressTemplate', function () { + it('should set the required address fields', function () { + const person = { + id: 1, + }; + expect(editAddressService.getAddressTemplate(person)).toEqual( + jasmine.objectContaining({ + _type: 'address', + person_id: person.id, + address_type: jasmine.any(String), + }), + ); }); - describe('getRegionOptions', function () { - it( - "should return the country's regions", - asynchronous(function () { - return editAddressService - .getRegionOptions('US') - .then(function (regionOptions) { - expect(_.map(regionOptions, 'shortCode')).toEqual([ - 'AL', - 'AK', - 'AZ', - ]); - }); - }), - ); - - it( - 'should return an empty array for an invalid country', - asynchronous(function () { - return editAddressService - .getRegionOptions('foo') - .then(function (regionOptions) { - expect(_.map(regionOptions, 'shortCode')).toEqual([]); - }); - }), - ); + it('should choose the first available address type', function () { + spyOn(editAddressService, 'getAddressTypes').and.returnValue(['type1', 'type2', 'type3']); + + expect( + editAddressService.getAddressTemplate({ + id: 1, + addresses: [], + }), + ).toEqual( + jasmine.objectContaining({ + address_type: 'type1', + }), + ); + + expect( + editAddressService.getAddressTemplate({ + id: 1, + addresses: [this.address1, this.address3], + }), + ).toEqual( + jasmine.objectContaining({ + address_type: 'type2', + }), + ); + + expect( + editAddressService.getAddressTemplate({ + id: 1, + addresses: [this.address1, this.address2, this.address3], + }), + ).toEqual( + jasmine.objectContaining({ + address_type: null, + }), + ); }); + }); + + describe('getCountryOptions', function () { + it( + 'should prioritize certain countries', + asynchronous(function () { + return editAddressService.getCountryOptions().then(function (countryOptions) { + expect(_.map(countryOptions, 'shortCode')).toEqual(['US', 'CA', 'AA', 'BA']); + }); + }), + ); + }); + + describe('getRegionOptions', function () { + it( + "should return the country's regions", + asynchronous(function () { + return editAddressService.getRegionOptions('US').then(function (regionOptions) { + expect(_.map(regionOptions, 'shortCode')).toEqual(['AL', 'AK', 'AZ']); + }); + }), + ); + + it( + 'should return an empty array for an invalid country', + asynchronous(function () { + return editAddressService.getRegionOptions('foo').then(function (regionOptions) { + expect(_.map(regionOptions, 'shortCode')).toEqual([]); + }); + }), + ); + }); }); diff --git a/app/assets/javascripts/angular/components/editGroup/editGroup.component.js b/app/assets/javascripts/angular/components/editGroup/editGroup.component.js index 4489225b60..f66cb25cda 100644 --- a/app/assets/javascripts/angular/components/editGroup/editGroup.component.js +++ b/app/assets/javascripts/angular/components/editGroup/editGroup.component.js @@ -2,93 +2,85 @@ import template from './editGroup.html'; import './editGroup.scss'; angular.module('campusContactsApp').component('editGroup', { - controller: editGroupController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: editGroupController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); function editGroupController(groupsService, editGroupService, tFilter, _) { - var vm = this; + const vm = this; - vm.title = null; - vm.saving = false; - vm.meetingFrequencyOptions = ['weekly', 'monthly', 'sporadically']; - vm.weekDayOptions = _.range(0, 7).map(function (day) { - return { value: day, label: tFilter('date.day_names.' + day) }; - }); - vm.monthDayOptions = _.range(1, 32).map(function (day) { - return { value: day, label: day.toString() }; - }); + vm.title = null; + vm.saving = false; + vm.meetingFrequencyOptions = ['weekly', 'monthly', 'sporadically']; + vm.weekDayOptions = _.range(0, 7).map(function (day) { + return { value: day, label: tFilter('date.day_names.' + day) }; + }); + vm.monthDayOptions = _.range(1, 32).map(function (day) { + return { value: day, label: day.toString() }; + }); - vm.valid = valid; - vm.save = save; - vm.cancel = cancel; + vm.valid = valid; + vm.save = save; + vm.cancel = cancel; - vm.$onInit = activate; + vm.$onInit = activate; - function activate() { - vm.orgId = vm.resolve.organizationId; - var groupTemplate = groupsService.getGroupTemplate(vm.orgId); - vm.group = _.clone(vm.resolve.group || groupTemplate); - vm.leaders = groupsService.getMembersWithRole(vm.group, 'leader'); + function activate() { + vm.orgId = vm.resolve.organizationId; + const groupTemplate = groupsService.getGroupTemplate(vm.orgId); + vm.group = _.clone(vm.resolve.group || groupTemplate); + vm.leaders = groupsService.getMembersWithRole(vm.group, 'leader'); - // The uib-timepicker needs the start and end times to be Date instances - // Default the start and end times to the values set on their default values in a new group template - vm.startTimeDate = groupsService.timeToDate( - vm.group.start_time || groupTemplate.start_time, - ); - vm.endTimeDate = groupsService.timeToDate( - vm.group.end_time || groupTemplate.end_time, - ); + // The uib-timepicker needs the start and end times to be Date instances + // Default the start and end times to the values set on their default values in a new group template + vm.startTimeDate = groupsService.timeToDate(vm.group.start_time || groupTemplate.start_time); + vm.endTimeDate = groupsService.timeToDate(vm.group.end_time || groupTemplate.end_time); - // Track the meeting time when it is a day of the week and when it is a day of the month separately - vm.meetingDayOfWeek = - vm.group.meets === 'weekly' ? vm.group.meeting_day : 0; - vm.meetingDayOfMonth = - vm.group.meets === 'monthly' ? vm.group.meeting_day : 1; + // Track the meeting time when it is a day of the week and when it is a day of the month separately + vm.meetingDayOfWeek = vm.group.meets === 'weekly' ? vm.group.meeting_day : 0; + vm.meetingDayOfMonth = vm.group.meets === 'monthly' ? vm.group.meeting_day : 1; - vm.title = vm.group.id - ? 'groups.edit.edit_group' - : 'groups.new.new_group'; - } - - function valid() { - return editGroupService.isGroupValid(vm.group); - } + vm.title = vm.group.id ? 'groups.edit.edit_group' : 'groups.new.new_group'; + } - function save() { - vm.saving = true; + function valid() { + return editGroupService.isGroupValid(vm.group); + } - // Update the start and end times with the uib-timepicker values - vm.group.start_time = groupsService.dateToTime(vm.startTimeDate); - vm.group.end_time = groupsService.dateToTime(vm.endTimeDate); + function save() { + vm.saving = true; - // Copy the meeting time to the group - if (vm.group.meets === 'weekly') { - vm.group.meeting_day = vm.meetingDayOfWeek; - } else if (vm.group.meets === 'monthly') { - vm.group.meeting_day = vm.meetingDayOfMonth; - } else if (vm.group.meets === 'sporadically') { - vm.group.meeting_day = null; - vm.group.start_time = null; - vm.group.end_time = null; - } + // Update the start and end times with the uib-timepicker values + vm.group.start_time = groupsService.dateToTime(vm.startTimeDate); + vm.group.end_time = groupsService.dateToTime(vm.endTimeDate); - groupsService - .saveGroup(vm.group, vm.leaders) - .then(function (newGroup) { - vm.close({ $value: newGroup }); - }) - .catch(function () { - vm.saving = false; - }); + // Copy the meeting time to the group + if (vm.group.meets === 'weekly') { + vm.group.meeting_day = vm.meetingDayOfWeek; + } else if (vm.group.meets === 'monthly') { + vm.group.meeting_day = vm.meetingDayOfMonth; + } else if (vm.group.meets === 'sporadically') { + vm.group.meeting_day = null; + vm.group.start_time = null; + vm.group.end_time = null; } - function cancel() { - vm.dismiss(); - } + groupsService + .saveGroup(vm.group, vm.leaders) + .then(function (newGroup) { + vm.close({ $value: newGroup }); + }) + .catch(function () { + vm.saving = false; + }); + } + + function cancel() { + vm.dismiss(); + } } diff --git a/app/assets/javascripts/angular/components/editGroup/editGroup.html b/app/assets/javascripts/angular/components/editGroup/editGroup.html index 4887ae1485..929aa4e9f4 100644 --- a/app/assets/javascripts/angular/components/editGroup/editGroup.html +++ b/app/assets/javascripts/angular/components/editGroup/editGroup.html @@ -1,119 +1,86 @@ diff --git a/app/assets/javascripts/angular/components/editGroup/editGroup.service.js b/app/assets/javascripts/angular/components/editGroup/editGroup.service.js index dfde79fa3f..84a0e31801 100644 --- a/app/assets/javascripts/angular/components/editGroup/editGroup.service.js +++ b/app/assets/javascripts/angular/components/editGroup/editGroup.service.js @@ -1,12 +1,10 @@ -angular - .module('campusContactsApp') - .factory('editGroupService', editGroupService); +angular.module('campusContactsApp').factory('editGroupService', editGroupService); function editGroupService() { - return { - // Determine whether a group has valid field values - isGroupValid: function (group) { - return group.name && group.location; - }, - }; + return { + // Determine whether a group has valid field values + isGroupValid: function (group) { + return group.name && group.location; + }, + }; } diff --git a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.component.js b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.component.js index 4ea7ec8bbc..3476166b25 100644 --- a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.component.js +++ b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.component.js @@ -2,125 +2,112 @@ import template from './editGroupOrLabelAssignments.html'; import './editGroupOrLabelAssignments.scss'; angular.module('campusContactsApp').component('editGroupOrLabelAssignments', { - controller: editGroupOrLabelAssignmentsController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: editGroupOrLabelAssignmentsController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); -function editGroupOrLabelAssignmentsController( - editGroupOrLabelAssignmentsService, - JsonApiDataStore, - _, -) { - var vm = this; - - vm.saving = false; - vm.entryOptions = []; - vm.selectedEntries = {}; - vm.addedEntries = []; - vm.removedEntries = []; - - vm.save = save; - vm.cancel = cancel; - - vm.$onInit = activate; - - function activate() { - loadEntryOptions(); - buildSelectedDict(); - - const title = isOrgLabelsMode() - ? 'people.show.apply_labels' - : 'people.show.apply_groups'; - vm.title = vm.resolve.person.first_name ? title : `${title}_undefined`; - vm.subtitle = isOrgLabelsMode() ? 'people.index.labels' : 'nav.groups'; - } +function editGroupOrLabelAssignmentsController(editGroupOrLabelAssignmentsService, JsonApiDataStore, _) { + const vm = this; - function isOrgLabelsMode() { - return vm.resolve.relationship === 'organizational_labels'; - } + vm.saving = false; + vm.entryOptions = []; + vm.selectedEntries = {}; + vm.addedEntries = []; + vm.removedEntries = []; - function orgRelationship() { - return isOrgLabelsMode() ? 'labels' : 'groups'; - } + vm.save = save; + vm.cancel = cancel; - function relatedModel() { - return isOrgLabelsMode() ? 'label' : 'group'; - } + vm.$onInit = activate; - function sortFunction() { - if (isOrgLabelsMode()) { - return function (organization) { - return parseInt(organization.id, 10); - }; - } - return 'name'; - } + function activate() { + loadEntryOptions(); + buildSelectedDict(); - function orgFilterExpression() { - if (isOrgLabelsMode()) { - return { organization_id: vm.resolve.organizationId }; - } - return ['group.organization.id', vm.resolve.organizationId]; - } + const title = isOrgLabelsMode() ? 'people.show.apply_labels' : 'people.show.apply_groups'; + vm.title = vm.resolve.person.first_name ? title : `${title}_undefined`; + vm.subtitle = isOrgLabelsMode() ? 'people.index.labels' : 'nav.groups'; + } - function errorMessage() { - return isOrgLabelsMode() - ? 'error.messages.edit_group_or_label_assignments.load_labels' - : 'error.messages.edit_group_or_label_assignments.load_groups'; - } + function isOrgLabelsMode() { + return vm.resolve.relationship === 'organizational_labels'; + } - function loadEntryOptions() { - var entries = JsonApiDataStore.store.find( - 'organization', - vm.resolve.organizationId, - )[orgRelationship()]; - vm.entryOptions = _.sortBy(entries, sortFunction()); - editGroupOrLabelAssignmentsService.loadPlaceholderEntries( - entries, - vm.resolve.organizationId, - errorMessage(), - ); - } + function orgRelationship() { + return isOrgLabelsMode() ? 'labels' : 'groups'; + } - function buildSelectedDict() { - vm.selectedEntries = _.chain(vm.resolve.person[vm.resolve.relationship]) - .filter(orgFilterExpression()) - .map(function (entry) { - return [entry[relatedModel()].id, true]; - }) - .fromPairs() - .value(); - } + function relatedModel() { + return isOrgLabelsMode() ? 'label' : 'group'; + } - function save() { - var savingPromise; - vm.saving = true; - if (isOrgLabelsMode()) { - savingPromise = editGroupOrLabelAssignmentsService.saveOrganizationalLabels( - vm.resolve.person, - vm.resolve.organizationId, - vm.addedEntries, - vm.removedEntries, - ); - } else { - savingPromise = editGroupOrLabelAssignmentsService.saveGroupMemberships( - vm.resolve.person, - vm.addedEntries, - vm.removedEntries, - ); - } - - savingPromise.then(vm.close).catch(function () { - vm.saving = false; - }); + function sortFunction() { + if (isOrgLabelsMode()) { + return function (organization) { + return parseInt(organization.id, 10); + }; } + return 'name'; + } - function cancel() { - vm.dismiss(); + function orgFilterExpression() { + if (isOrgLabelsMode()) { + return { organization_id: vm.resolve.organizationId }; } + return ['group.organization.id', vm.resolve.organizationId]; + } + + function errorMessage() { + return isOrgLabelsMode() + ? 'error.messages.edit_group_or_label_assignments.load_labels' + : 'error.messages.edit_group_or_label_assignments.load_groups'; + } + + function loadEntryOptions() { + const entries = JsonApiDataStore.store.find('organization', vm.resolve.organizationId)[orgRelationship()]; + vm.entryOptions = _.sortBy(entries, sortFunction()); + editGroupOrLabelAssignmentsService.loadPlaceholderEntries(entries, vm.resolve.organizationId, errorMessage()); + } + + function buildSelectedDict() { + vm.selectedEntries = _.chain(vm.resolve.person[vm.resolve.relationship]) + .filter(orgFilterExpression()) + .map(function (entry) { + return [entry[relatedModel()].id, true]; + }) + .fromPairs() + .value(); + } + + function save() { + let savingPromise; + vm.saving = true; + if (isOrgLabelsMode()) { + savingPromise = editGroupOrLabelAssignmentsService.saveOrganizationalLabels( + vm.resolve.person, + vm.resolve.organizationId, + vm.addedEntries, + vm.removedEntries, + ); + } else { + savingPromise = editGroupOrLabelAssignmentsService.saveGroupMemberships( + vm.resolve.person, + vm.addedEntries, + vm.removedEntries, + ); + } + + savingPromise.then(vm.close).catch(function () { + vm.saving = false; + }); + } + + function cancel() { + vm.dismiss(); + } } diff --git a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.html b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.html index 7ca60747f3..521833434f 100644 --- a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.html +++ b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.html @@ -1,36 +1,23 @@ diff --git a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.service.js b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.service.js index 9df7d6e492..5886b02e72 100644 --- a/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.service.js +++ b/app/assets/javascripts/angular/components/editGroupOrLabelAssignments/editGroupOrLabelAssignments.service.js @@ -1,161 +1,92 @@ -angular - .module('campusContactsApp') - .factory( - 'editGroupOrLabelAssignmentsService', - editGroupOrLabelAssignmentsService, - ); +angular.module('campusContactsApp').factory('editGroupOrLabelAssignmentsService', editGroupOrLabelAssignmentsService); -function editGroupOrLabelAssignmentsService( - $q, - httpProxy, - modelsService, - JsonApiDataStore, - personProfileService, - _, -) { - function pushNew(modelType, person, newIds, organizationId) { - var relationships = _.map(newIds, function (labelId) { - return buildRelationshipModel(modelType, labelId, organizationId); - }); +function editGroupOrLabelAssignmentsService($q, httpProxy, modelsService, JsonApiDataStore, personProfileService, _) { + function pushNew(modelType, person, newIds, organizationId) { + const relationships = _.map(newIds, function (labelId) { + return buildRelationshipModel(modelType, labelId, organizationId); + }); - return personProfileService.saveRelationships( - person, - relationships, - personRelationshipName(modelType), - ); - } + return personProfileService.saveRelationships(person, relationships, personRelationshipName(modelType)); + } - function buildRelationshipModel(modelType, relatedId, organizationId) { - var model = new JsonApiDataStore.Model(modelType); - if (modelType === 'organizational_label') { - model.setAttribute('label_id', relatedId); - model.setAttribute('organization_id', organizationId); - model.setRelationship( - 'label', - JsonApiDataStore.store.find('label', relatedId), - ); - } else { - model.setAttribute('group_id', relatedId); - model.setRelationship( - 'group', - JsonApiDataStore.store.find('group', relatedId), - ); - } - return model; + function buildRelationshipModel(modelType, relatedId, organizationId) { + const model = new JsonApiDataStore.Model(modelType); + if (modelType === 'organizational_label') { + model.setAttribute('label_id', relatedId); + model.setAttribute('organization_id', organizationId); + model.setRelationship('label', JsonApiDataStore.store.find('label', relatedId)); + } else { + model.setAttribute('group_id', relatedId); + model.setRelationship('group', JsonApiDataStore.store.find('group', relatedId)); } + return model; + } - function personRelationshipName(modelType) { - // accept either a string type or an object - return modelType === 'organizational_label' - ? 'organizational_labels' - : 'group_memberships'; - } + function personRelationshipName(modelType) { + // accept either a string type or an object + return modelType === 'organizational_label' ? 'organizational_labels' : 'group_memberships'; + } - function relatedModel(type) { - return type === 'organizational_label' ? 'label' : 'group'; - } + function relatedModel(type) { + return type === 'organizational_label' ? 'label' : 'group'; + } - function deleteByRelatedId(type, relatedId, person) { - var relationshipName = personRelationshipName(type); - var relatedType = relatedModel(type); - var relationship = _.find(person[relationshipName], [ - relatedType + '.id', - relatedId, - ]); - return personProfileService.deleteRelationship( - person, - relationship, - relationshipName, - ); - } + function deleteByRelatedId(type, relatedId, person) { + const relationshipName = personRelationshipName(type); + const relatedType = relatedModel(type); + const relationship = _.find(person[relationshipName], [relatedType + '.id', relatedId]); + return personProfileService.deleteRelationship(person, relationship, relationshipName); + } - function saveRelationshipChanges( - type, - person, - addedRelationshipIds, - removedRelationshipIds, - organizationId, - ) { - var promises = _.map(removedRelationshipIds, function (relatedId) { - return deleteByRelatedId(type, relatedId, person); - }); - if (addedRelationshipIds.length > 0) { - promises.push( - pushNew(type, person, addedRelationshipIds, organizationId), - ); - } - return $q.all(promises); + function saveRelationshipChanges(type, person, addedRelationshipIds, removedRelationshipIds, organizationId) { + const promises = _.map(removedRelationshipIds, function (relatedId) { + return deleteByRelatedId(type, relatedId, person); + }); + if (addedRelationshipIds.length > 0) { + promises.push(pushNew(type, person, addedRelationshipIds, organizationId)); } + return $q.all(promises); + } - function updateGroupMemberships(person, addedGroupIds, removedGroupIds) { - _.each(addedGroupIds, function (groupId) { - var group = JsonApiDataStore.store.find('group', groupId); - var membership = _.find(person.group_memberships, [ - 'group.id', - groupId, - ]); - group.group_memberships.push(membership); - }); - _.each(removedGroupIds, function (groupId) { - var group = JsonApiDataStore.store.find('group', groupId); - var membership = _.find(group.group_memberships, [ - 'person.id', - person.id, - ]); - _.remove(group.group_memberships, membership); - }); - } + function updateGroupMemberships(person, addedGroupIds, removedGroupIds) { + _.each(addedGroupIds, function (groupId) { + const group = JsonApiDataStore.store.find('group', groupId); + const membership = _.find(person.group_memberships, ['group.id', groupId]); + group.group_memberships.push(membership); + }); + _.each(removedGroupIds, function (groupId) { + const group = JsonApiDataStore.store.find('group', groupId); + const membership = _.find(group.group_memberships, ['person.id', person.id]); + _.remove(group.group_memberships, membership); + }); + } - return { - saveOrganizationalLabels: function ( - person, - organizationId, - addedLabelIds, - removedLabelIds, - ) { - return saveRelationshipChanges( - 'organizational_label', - person, - addedLabelIds, - removedLabelIds, - organizationId, - ); - }, + return { + saveOrganizationalLabels: function (person, organizationId, addedLabelIds, removedLabelIds) { + return saveRelationshipChanges('organizational_label', person, addedLabelIds, removedLabelIds, organizationId); + }, - saveGroupMemberships: function ( - person, - addedGroupIds, - removedGroupIds, - ) { - var savePromise = saveRelationshipChanges( - 'group_membership', - person, - addedGroupIds, - removedGroupIds, - ); - return savePromise.then(function (resp) { - updateGroupMemberships(person, addedGroupIds, removedGroupIds); - return resp; - }); - }, + saveGroupMemberships: function (person, addedGroupIds, removedGroupIds) { + const savePromise = saveRelationshipChanges('group_membership', person, addedGroupIds, removedGroupIds); + return savePromise.then(function (resp) { + updateGroupMemberships(person, addedGroupIds, removedGroupIds); + return resp; + }); + }, - loadPlaceholderEntries: function (entries, orgId, errorMessage) { - if (_.find(entries, { _placeHolder: true })) { - httpProxy.get( - modelsService - .getModelMetadata('organization') - .url.single(orgId), - { - include: modelsService.getModelMetadata( - entries[0]._type, - ).include, - 'filters[user_created]': false, - }, - { - errorMessage: errorMessage, - }, - ); - } - }, - }; + loadPlaceholderEntries: function (entries, orgId, errorMessage) { + if (_.find(entries, { _placeHolder: true })) { + httpProxy.get( + modelsService.getModelMetadata('organization').url.single(orgId), + { + include: modelsService.getModelMetadata(entries[0]._type).include, + 'filters[user_created]': false, + }, + { + errorMessage, + }, + ); + } + }, + }; } diff --git a/app/assets/javascripts/angular/components/editLabel/editLabel.component.js b/app/assets/javascripts/angular/components/editLabel/editLabel.component.js index d7a783c388..52bf4e0ec1 100644 --- a/app/assets/javascripts/angular/components/editLabel/editLabel.component.js +++ b/app/assets/javascripts/angular/components/editLabel/editLabel.component.js @@ -1,50 +1,48 @@ import template from './editLabel.html'; angular.module('campusContactsApp').component('editLabel', { - controller: editLabelController, - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - template: template, + controller: editLabelController, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + template, }); function editLabelController(labelsService, _) { - var vm = this; - - vm.title = null; - vm.saving = false; - - vm.valid = valid; - vm.save = save; - - vm.$onInit = activate; - - function activate() { - vm.orgId = vm.resolve.organizationId; - var labelTemplate = labelsService.getLabelTemplate(vm.orgId); - vm.label = _.clone(vm.resolve.label || labelTemplate); - - vm.title = vm.label.id - ? 'labels.edit.edit_label' - : 'labels.new.new_label'; - } - - function valid() { - return Boolean(vm.label.name); - } - - function save() { - vm.saving = true; - - return labelsService - .saveLabel(vm.label) - .then(function (newLabel) { - vm.close({ $value: newLabel }); - }) - .catch(function () { - vm.saving = false; - }); - } + const vm = this; + + vm.title = null; + vm.saving = false; + + vm.valid = valid; + vm.save = save; + + vm.$onInit = activate; + + function activate() { + vm.orgId = vm.resolve.organizationId; + const labelTemplate = labelsService.getLabelTemplate(vm.orgId); + vm.label = _.clone(vm.resolve.label || labelTemplate); + + vm.title = vm.label.id ? 'labels.edit.edit_label' : 'labels.new.new_label'; + } + + function valid() { + return Boolean(vm.label.name); + } + + function save() { + vm.saving = true; + + return labelsService + .saveLabel(vm.label) + .then(function (newLabel) { + vm.close({ $value: newLabel }); + }) + .catch(function () { + vm.saving = false; + }); + } } diff --git a/app/assets/javascripts/angular/components/editLabel/editLabel.component.spec.js b/app/assets/javascripts/angular/components/editLabel/editLabel.component.spec.js index 9149f651f7..424760bf2f 100644 --- a/app/assets/javascripts/angular/components/editLabel/editLabel.component.spec.js +++ b/app/assets/javascripts/angular/components/editLabel/editLabel.component.spec.js @@ -1,132 +1,118 @@ import 'angular-mocks'; // Constants -var $ctrl, $q, $rootScope, JsonApiDataStore; +let $ctrl, $q, $rootScope, JsonApiDataStore; // Add better asynchronous support to a test function // The test function must return a promise // The promise will automatically be bound to "done" and the $rootScope will be automatically digested function asynchronous(fn) { - return function (done) { - var returnValue = fn.call(this, done); - returnValue - .then(function () { - done(); - }) - .catch(function (err) { - done.fail(err); - }); - $rootScope.$apply(); - return returnValue; - }; + return function (done) { + const returnValue = fn.call(this, done); + returnValue + .then(function () { + done(); + }) + .catch(function (err) { + done.fail(err); + }); + $rootScope.$apply(); + return returnValue; + }; } describe('editLabel component', function () { - beforeEach(inject(function ( - $componentController, - _$q_, - _$rootScope_, - _JsonApiDataStore_, - ) { - $q = _$q_; - $rootScope = _$rootScope_; - JsonApiDataStore = _JsonApiDataStore_; - - this.labelsService = jasmine.createSpyObj('labelsService', [ - 'getLabelTemplate', - 'saveLabel', - ]); - this.close = jasmine.createSpy('close'); - this.dismiss = jasmine.createSpy('dismiss'); - - this.label = new JsonApiDataStore.Model('label'); - this.label.setAttribute('id', 1); - this.label.setAttribute('name', 'Test label'); - - $ctrl = $componentController( - 'editLabel', - { - labelsService: this.labelsService, - }, - { - resolve: { - organizationId: 1, - label: this.label, - }, - close: this.close, - dismiss: this.dismiss, - }, - ); - })); - - describe('$onInit', function () { - it("should initialize and create a label if one doesn't exist", function () { - delete $ctrl.resolve.label; - this.labelsService.getLabelTemplate.and.returnValue({ - name: 'New Label', - }); - - $ctrl.$onInit(); - - expect($ctrl.orgId).toEqual(1); - expect($ctrl.label).toEqual({ name: 'New Label' }); - expect($ctrl.title).toEqual('labels.new.new_label'); - }); + beforeEach(inject(function ($componentController, _$q_, _$rootScope_, _JsonApiDataStore_) { + $q = _$q_; + $rootScope = _$rootScope_; + JsonApiDataStore = _JsonApiDataStore_; + + this.labelsService = jasmine.createSpyObj('labelsService', ['getLabelTemplate', 'saveLabel']); + this.close = jasmine.createSpy('close'); + this.dismiss = jasmine.createSpy('dismiss'); + + this.label = new JsonApiDataStore.Model('label'); + this.label.setAttribute('id', 1); + this.label.setAttribute('name', 'Test label'); + + $ctrl = $componentController( + 'editLabel', + { + labelsService: this.labelsService, + }, + { + resolve: { + organizationId: 1, + label: this.label, + }, + close: this.close, + dismiss: this.dismiss, + }, + ); + })); + + describe('$onInit', function () { + it("should initialize and create a label if one doesn't exist", function () { + delete $ctrl.resolve.label; + this.labelsService.getLabelTemplate.and.returnValue({ + name: 'New Label', + }); + + $ctrl.$onInit(); + + expect($ctrl.orgId).toEqual(1); + expect($ctrl.label).toEqual({ name: 'New Label' }); + expect($ctrl.title).toEqual('labels.new.new_label'); }); + }); - describe('valid', function () { - beforeEach(function () { - $ctrl.$onInit(); - }); - - it('should return true if the edited label has a name', function () { - expect($ctrl.valid()).toEqual(true); - }); + describe('valid', function () { + beforeEach(function () { + $ctrl.$onInit(); + }); - it('should return false if the edited label is empty', function () { - $ctrl.label.name = ''; - expect($ctrl.valid()).toEqual(false); - }); + it('should return true if the edited label has a name', function () { + expect($ctrl.valid()).toEqual(true); }); - describe('save', function () { - beforeEach(function () { - $ctrl.$onInit(); - }); + it('should return false if the edited label is empty', function () { + $ctrl.label.name = ''; + expect($ctrl.valid()).toEqual(false); + }); + }); - it( - 'should save the edited label', - asynchronous(function () { - var _this = this; - this.labelsService.saveLabel.and.returnValue( - $q.resolve({ name: 'Saved Label' }), - ); - - return $ctrl.save().then(function () { - expect(_this.labelsService.saveLabel).toHaveBeenCalledWith( - _this.label, - ); - expect(_this.close).toHaveBeenCalledWith({ - $value: { name: 'Saved Label' }, - }); - expect($ctrl.saving).toEqual(true); - }); - }), - ); - - it( - 'should handle an error saving the edited label', - asynchronous(function () { - var _this = this; - this.labelsService.saveLabel.and.returnValue($q.reject()); - - return $ctrl.save().then(function () { - expect(_this.labelsService.saveLabel).toHaveBeenCalledWith( - _this.label, - ); - expect($ctrl.saving).toEqual(false); - }); - }), - ); + describe('save', function () { + beforeEach(function () { + $ctrl.$onInit(); }); + + it( + 'should save the edited label', + asynchronous(function () { + const _this = this; + this.labelsService.saveLabel.and.returnValue($q.resolve({ name: 'Saved Label' })); + + return $ctrl.save().then(function () { + expect(_this.labelsService.saveLabel).toHaveBeenCalledWith(_this.label); + expect(_this.close).toHaveBeenCalledWith({ + $value: { name: 'Saved Label' }, + }); + expect($ctrl.saving).toEqual(true); + }); + }), + ); + + it( + 'should handle an error saving the edited label', + asynchronous(function () { + const _this = this; + this.labelsService.saveLabel.and.returnValue($q.reject()); + + return $ctrl.save().then(function () { + expect(_this.labelsService.saveLabel).toHaveBeenCalledWith(_this.label); + expect($ctrl.saving).toEqual(false); + }); + }), + ); + }); }); diff --git a/app/assets/javascripts/angular/components/editLabel/editLabel.html b/app/assets/javascripts/angular/components/editLabel/editLabel.html index d9e9227abb..3dfe299d22 100644 --- a/app/assets/javascripts/angular/components/editLabel/editLabel.html +++ b/app/assets/javascripts/angular/components/editLabel/editLabel.html @@ -1,40 +1,21 @@ diff --git a/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.component.js b/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.component.js index 4218b86429..5987a0a192 100644 --- a/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.component.js +++ b/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.component.js @@ -2,142 +2,137 @@ import template from './groupMembersModal.html'; import './groupMembersModal.scss'; angular.module('campusContactsApp').component('groupMembersModal', { - bindings: { - resolve: '<', - close: '&', - dismiss: '&', - }, - controller: groupMembersModalController, - template: template, + bindings: { + resolve: '<', + close: '&', + dismiss: '&', + }, + controller: groupMembersModalController, + template, }); function groupMembersModalController( - $scope, - $uibModal, - confirmModalService, - RequestDeduper, - ProgressiveListLoader, - groupsService, - groupMembersModalService, - tFilter, - _, + $scope, + $uibModal, + confirmModalService, + RequestDeduper, + ProgressiveListLoader, + groupsService, + groupMembersModalService, + tFilter, + _, ) { - var vm = this; - - vm.memberships = []; - vm.loadedAll = false; - vm.busy = false; - vm.memberAdderVisible = false; - vm.loadMemberPage = loadMemberPage; - vm.toggleMemberAdderVisibility = toggleMemberAdderVisibility; - vm.messageGroup = messageGroup; - vm.emailPerson = emailPerson; - vm.addMember = addMember; - vm.removeMember = removeMember; - - vm.close = close; - vm.$onInit = activate; - - var requestDeduper = new RequestDeduper(); - var listLoader = new ProgressiveListLoader({ - modelType: 'person', - requestDeduper: requestDeduper, - errorMessage: 'error.messages.group_members.load_member_chunk', + const vm = this; + + vm.memberships = []; + vm.loadedAll = false; + vm.busy = false; + vm.memberAdderVisible = false; + vm.loadMemberPage = loadMemberPage; + vm.toggleMemberAdderVisibility = toggleMemberAdderVisibility; + vm.messageGroup = messageGroup; + vm.emailPerson = emailPerson; + vm.addMember = addMember; + vm.removeMember = removeMember; + + vm.close = close; + vm.$onInit = activate; + + const requestDeduper = new RequestDeduper(); + const listLoader = new ProgressiveListLoader({ + modelType: 'person', + requestDeduper, + errorMessage: 'error.messages.group_members.load_member_chunk', + }); + + function activate() { + vm.group = vm.resolve.group; + + $scope.$watchCollection('$ctrl.group.group_memberships', function () { + vm.members = groupsService.getAllMembers(vm.group); }); - - function activate() { - vm.group = vm.resolve.group; - - $scope.$watchCollection('$ctrl.group.group_memberships', function () { - vm.members = groupsService.getAllMembers(vm.group); - }); - } - - // Load another page of members - function loadMemberPage() { - vm.busy = true; - - return groupMembersModalService - .loadMoreGroupMembers(vm.group, listLoader) - .then(function (res) { - // Convert members to memberships - vm.memberships = res.list.map(function (member) { - return groupsService.findMember(vm.group, member); - }); - vm.loadedAll = res.loadedAll; - }) - .finally(function () { - vm.busy = false; - }); - } - - function toggleMemberAdderVisibility() { - vm.memberAdderVisible = !vm.memberAdderVisible; - } - - // Generate a selection object from an array of people - function generateSelection(members) { - return { - orgId: vm.group.organization.id, - filters: { - groups: [vm.group.id], - }, - selectedPeople: _.map(members, 'id'), - unselectedPeople: [], - totalSelectedPeople: members.length, - allSelected: true, - allIncluded: true, - }; - } - - function messageGroup(medium) { - var members = groupsService.getAllMembers(vm.group); - $uibModal.open({ - component: 'messageModal', - resolve: { - medium: _.constant(medium), - selection: _.constant(generateSelection(members)), - }, - windowClass: 'pivot_theme', - size: 'md', - }); - } - - function emailPerson(person) { - $uibModal.open({ - component: 'messageModal', - resolve: { - medium: _.constant('email'), - selection: _.constant(generateSelection([person])), - }, - windowClass: 'pivot_theme', - size: 'md', + } + + // Load another page of members + function loadMemberPage() { + vm.busy = true; + + return groupMembersModalService + .loadMoreGroupMembers(vm.group, listLoader) + .then(function (res) { + // Convert members to memberships + vm.memberships = res.list.map(function (member) { + return groupsService.findMember(vm.group, member); }); - } - - function addMember(person) { - groupMembersModalService - .addMember(vm.group, person) - .then(function (membership) { - vm.memberships.push(membership); - }); - } - - function removeMember(membership) { - confirmModalService - .create(tFilter('groups.members.remove_confirm')) - .then(function () { - return groupMembersModalService.removeMember( - vm.group, - membership, - ); - }) - .then(function () { - _.pull(vm.memberships, membership); - }); - } - - function close() { - vm.close(); - } + vm.loadedAll = res.loadedAll; + }) + .finally(function () { + vm.busy = false; + }); + } + + function toggleMemberAdderVisibility() { + vm.memberAdderVisible = !vm.memberAdderVisible; + } + + // Generate a selection object from an array of people + function generateSelection(members) { + return { + orgId: vm.group.organization.id, + filters: { + groups: [vm.group.id], + }, + selectedPeople: _.map(members, 'id'), + unselectedPeople: [], + totalSelectedPeople: members.length, + allSelected: true, + allIncluded: true, + }; + } + + function messageGroup(medium) { + const members = groupsService.getAllMembers(vm.group); + $uibModal.open({ + component: 'messageModal', + resolve: { + medium: _.constant(medium), + selection: _.constant(generateSelection(members)), + }, + windowClass: 'pivot_theme', + size: 'md', + }); + } + + function emailPerson(person) { + $uibModal.open({ + component: 'messageModal', + resolve: { + medium: _.constant('email'), + selection: _.constant(generateSelection([person])), + }, + windowClass: 'pivot_theme', + size: 'md', + }); + } + + function addMember(person) { + groupMembersModalService.addMember(vm.group, person).then(function (membership) { + vm.memberships.push(membership); + }); + } + + function removeMember(membership) { + confirmModalService + .create(tFilter('groups.members.remove_confirm')) + .then(function () { + return groupMembersModalService.removeMember(vm.group, membership); + }) + .then(function () { + _.pull(vm.memberships, membership); + }); + } + + function close() { + vm.close(); + } } diff --git a/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.html b/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.html index 4e38fb4c96..5eade3f415 100644 --- a/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.html +++ b/app/assets/javascripts/angular/components/groupMembersModal/groupMembersModal.html @@ -1,67 +1,55 @@