From fe4f84efaac5f3edc22e74ceb6b09f8b820ade6b Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Thu, 21 Apr 2016 11:47:15 -0700 Subject: [PATCH 01/20] Remove stockart description and file number fields --- .../tc-form-stockart.directive.js | 38 +------ .../tc-form-stockart/tc-form-stockart.jade | 29 +---- .../tc-form-stockart/tc-form-stockart.spec.js | 105 ++---------------- .../submit-design-files.controller.js | 5 +- .../submit-design-files.spec.js | 34 +----- 5 files changed, 18 insertions(+), 193 deletions(-) diff --git a/app/directives/tc-form-stockart/tc-form-stockart.directive.js b/app/directives/tc-form-stockart/tc-form-stockart.directive.js index 75f25e7e1..2c5daf8f5 100644 --- a/app/directives/tc-form-stockart/tc-form-stockart.directive.js +++ b/app/directives/tc-form-stockart/tc-form-stockart.directive.js @@ -21,12 +21,7 @@ import _ from 'lodash' controller: ['$scope', function($scope) { var stockartId = 0 var emptyStockart = { - description: '', - sourceUrl: '', - fileNumber: '', - isPhotoDescriptionRequired: false, - isPhotoURLRequired: false, - isFileNumberRequired: false + sourceUrl: '' } // Initialize stockart form data @@ -45,9 +40,7 @@ import _ from 'lodash' // If only one stockart fieldset is there, just reset the values // so that ng-repeat doesn't refresh and there is no UI flickering if (Object.keys($scope.formStockarts).length === 1) { - $scope.submissionForm['photoDescription' + index].$setPristine() $scope.submissionForm['photoURL' + index].$setPristine() - $scope.submissionForm['fileNumber' + index].$setPristine() $scope.formStockarts[index] = angular.copy(emptyStockart) } else { @@ -57,36 +50,9 @@ import _ from 'lodash' $scope.isButtonDisabled = function() { return _.some($scope.formStockarts, function(stockart) { - return !stockart.description || !stockart.sourceUrl || !stockart.fileNumber + return !stockart.sourceUrl }) } - - $scope.showMandatoryMessage = function(inputValue, inputName) { - var id = inputName.slice(-1) - - var stockartSection = $scope.formStockarts[id] - - var stockartDescription = stockartSection.description - var stockartSourceUrl = stockartSection.sourceUrl - var stockartFileNumber = stockartSection.fileNumber - - if (!stockartDescription && !stockartSourceUrl && !stockartFileNumber) { - // All fields empty so required should be false - stockartSection.isPhotoDescriptionRequired = false - stockartSection.isPhotoURLRequired = false - stockartSection.isFileNumberRequired = false - } else if (stockartDescription && stockartSourceUrl && stockartFileNumber) { - // All fields filled out, so required should be false - stockartSection.isPhotoDescriptionRequired = false - stockartSection.isPhotoURLRequired = false - stockartSection.isFileNumberRequired = false - } else { - // Fields are not completely filled out or completely blank so setting required to true - stockartSection.isPhotoDescriptionRequired = true - stockartSection.isPhotoURLRequired = true - stockartSection.isFileNumberRequired = true - } - } }] } } diff --git a/app/directives/tc-form-stockart/tc-form-stockart.jade b/app/directives/tc-form-stockart/tc-form-stockart.jade index 7f10fb425..f561d1f15 100644 --- a/app/directives/tc-form-stockart/tc-form-stockart.jade +++ b/app/directives/tc-form-stockart/tc-form-stockart.jade @@ -1,44 +1,17 @@ .fieldset(ng-repeat="(stockartId, stockart) in formStockarts") button.clean.remove-section(type="button", ng-click="deleteStockartFieldset(stockartId)") - tc-input.fieldset__input( - label-text="Photo Description", - asterisk-text="Field can't be empty", - show-asterisk-text="true", - placeholder="A picture of a girl", - input-value="stockart.description", - input-name="photoDescription{{stockartId}}", - input-required="formStockarts[stockartId].isPhotoDescriptionRequired", - maxlength="100", - on-input-change="showMandatoryMessage(inputValue, inputName)" - ) - tc-input.fieldset__input( label-text="Photo URL", - asterisk-text="Field can't be empty", - show-asterisk-text="true", placeholder="www.istockphoto.com", input-value="stockart.sourceUrl", input-name="photoURL{{stockartId}}", input-required="formStockarts[stockartId].isPhotoURLRequired", input-pattern="urlRegEx", - maxlength="250", - on-input-change="showMandatoryMessage(inputValue, inputName)" + maxlength="250" ) .tc-error-messages(ng-show="submissionForm['photoURL' + stockartId].$dirty && submissionForm['photoURL' + stockartId].$invalid && submissionForm['photoURL' + stockartId].$error.pattern") p Please enter a valid url. - tc-input.fieldset__input( - label-text="File Number", - asterisk-text="Field can't be empty", - show-asterisk-text="true", - placeholder="u2434312", - input-value="stockart.fileNumber", - input-name="fileNumber{{stockartId}}", - input-required="formStockarts[stockartId].isFileNumberRequired", - maxlength="50", - on-input-change="showMandatoryMessage(inputValue, inputName)" - ) - button.fieldset__button.tc-btn.tc-btn-s(type="button", ng-click="createAdditionalStockartFieldset()", ng-disabled="isButtonDisabled()") + Add Stock Photo diff --git a/app/directives/tc-form-stockart/tc-form-stockart.spec.js b/app/directives/tc-form-stockart/tc-form-stockart.spec.js index d0be7a02c..8b92a6d46 100644 --- a/app/directives/tc-form-stockart/tc-form-stockart.spec.js +++ b/app/directives/tc-form-stockart/tc-form-stockart.spec.js @@ -29,12 +29,7 @@ describe('Topcoder Form Stockart Directive', function() { var initialStockart = isolateScope.formStockarts[0] expect(initialStockart.id).to.equal(0) - expect(initialStockart.description).to.equal('') expect(initialStockart.sourceUrl).to.equal('') - expect(initialStockart.fileNumber).to.equal('') - expect(initialStockart.isPhotoDescriptionRequired).to.equal(false) - expect(initialStockart.isPhotoURLRequired).to.equal(false) - expect(initialStockart.isFileNumberRequired).to.equal(false) }) it('a regular expression', function() { @@ -79,21 +74,21 @@ describe('Topcoder Form Stockart Directive', function() { it('resets the stockart fieldset when it\'s the only one', function() { var stockart = isolateScope.formStockarts[0] - expect(stockart.description).to.equal('') + expect(stockart.sourceUrl).to.equal('') - stockart.description = 'a funny cat picture' + stockart.sourceUrl = 'www.myURL.com' scope.$digest() - expect(stockart.description).to.equal('a funny cat picture') + expect(stockart.sourceUrl).to.equal('www.myURL.com') isolateScope.deleteStockartFieldset(0) scope.$digest() - expect(isolateScope.formStockarts[0].description).to.equal('') + expect(isolateScope.formStockarts[0].sourceUrl).to.equal('') }) }) - describe('isButtonDisabled', function() { + describe.only('isButtonDisabled', function() { var button beforeEach(function() { @@ -108,37 +103,20 @@ describe('Topcoder Form Stockart Directive', function() { expect(button.disabled).to.be.true }) - it('disables the button when 1 field is filled out', function() { - isolateScope.formStockarts[0].description = 'test description' - scope.$digest() - - expect(button.disabled).to.be.true - }) - - it('disables the button when 2 fields are filled out', function() { - isolateScope.formStockarts[0].description = 'test description' - isolateScope.formStockarts[0].sourceUrl = 'url' - scope.$digest() - + it('enables the button when the url field is filled out', function() { expect(button.disabled).to.be.true - }) - it('enables the button when all fields are filled out', function() { - isolateScope.formStockarts[0].description = 'test description' isolateScope.formStockarts[0].sourceUrl = 'url' - isolateScope.formStockarts[0].fileNumber = '123' scope.$digest() expect(button.disabled).to.be.false }) - it('disables the button when any field in any fieldset is empty', function() { + it('disables the button when any url field in any fieldset is empty', function() { expect(button.disabled).to.be.true // Fill out first fieldset - isolateScope.formStockarts[0].description = 'test description' isolateScope.formStockarts[0].sourceUrl = 'url.com' - isolateScope.formStockarts[0].fileNumber = '123' scope.$digest() expect(button.disabled).to.be.false @@ -149,81 +127,16 @@ describe('Topcoder Form Stockart Directive', function() { expect(button.disabled).to.be.true // Fill out second fieldset - isolateScope.formStockarts[1].description = 'test description2' isolateScope.formStockarts[1].sourceUrl = 'url2.com' - isolateScope.formStockarts[1].fileNumber = '1232' scope.$digest() expect(button.disabled).to.be.false - // Empty a field in the first fieldset - isolateScope.formStockarts[0].fileNumber = '' + // Empty the field in the first fieldset + isolateScope.formStockarts[0].sourceUrl = '' scope.$digest() expect(button.disabled).to.be.true }) }) - - describe('showMandatoryMessage', function() { - describe('sets the stockart required properties to false when all fields are', function() { - var stockart - - beforeEach(function() { - stockart = isolateScope.formStockarts[0] - stockart.description = 'test description' - stockart.sourceUrl = 'url.com' - stockart.fileNumber = '123' - scope.$digest() - }) - - afterEach(function() { - stockart = undefined - }) - - it('filled out', function() { - expect(stockart.isPhotoDescriptionRequired).to.be.false - expect(stockart.isPhotoURLRequired).to.be.false - expect(stockart.isFileNumberRequired).to.be.false - }) - - it('empty', function() { - // Reset stockart fields - stockart.description = '' - stockart.sourceUrl = '' - stockart.fileNumber = '' - scope.$digest() - - expect(stockart.isPhotoDescriptionRequired).to.be.false - expect(stockart.isPhotoURLRequired).to.be.false - expect(stockart.isFileNumberRequired).to.be.false - }) - }) - - - describe('sets the stockart required properties to false when all fields are', function() { - var stockart - - beforeEach(function() { - stockart = isolateScope.formStockarts[0] - stockart.description = 'test description' - stockart.sourceUrl = 'url.com' - stockart.fileNumber = '123' - scope.$digest() - }) - - afterEach(function() { - stockart = undefined - }) - - it('sets the stockart required properties to true if any field is blank', function() { - // Reset stockart fields - stockart.description = '' - scope.$digest() - - expect(stockart.isPhotoDescriptionRequired).to.be.true - expect(stockart.isPhotoURLRequired).to.be.true - expect(stockart.isFileNumberRequired).to.be.true - }) - }) - }) }) diff --git a/app/submissions/submit-design-files/submit-design-files.controller.js b/app/submissions/submit-design-files/submit-design-files.controller.js index 9825f3250..31c85a2c1 100644 --- a/app/submissions/submit-design-files/submit-design-files.controller.js +++ b/app/submissions/submit-design-files/submit-design-files.controller.js @@ -131,11 +131,8 @@ import _ from 'lodash' // Process stock art var processedStockarts = _.reduce(vm.formStockarts, function(compiledStockarts, formStockart) { - if (formStockart.description) { + if (formStockart.sourceUrl) { delete formStockart.id - delete formStockart.isPhotoDescriptionRequired - delete formStockart.isPhotoURLRequired - delete formStockart.isFileNumberRequired compiledStockarts.push(formStockart) } diff --git a/app/submissions/submit-design-files/submit-design-files.spec.js b/app/submissions/submit-design-files/submit-design-files.spec.js index 78ce53e30..42766baee 100644 --- a/app/submissions/submit-design-files/submit-design-files.spec.js +++ b/app/submissions/submit-design-files/submit-design-files.spec.js @@ -196,38 +196,14 @@ describe('Submit Design Files Controller', function() { expect(vm.submissionsBody.data.stockArts).to.deep.equal([]) }) - it('removes the required properties and id from each stockart', function() { + it('removes the id from each stockart', function() { vm.formStockarts = [ - { - id: 0, - description: 'first stockart', - sourceUrl: 'url.com', - fileNumber: '123', - isPhotoDescriptionRequired: false, - isPhotoURLRequired: false, - isFileNumberRequired: false - }, - { - id: 1, - description: 'second stockart', - sourceUrl: 'url2.com', - fileNumber: '234', - isPhotoDescriptionRequired: false, - isPhotoURLRequired: false, - isFileNumberRequired: false - } + { id: 0, sourceUrl: 'url.com' }, + { id: 1, sourceUrl: 'url2.com' } ] var processedStockart = [ - { - description: 'first stockart', - sourceUrl: 'url.com', - fileNumber: '123' - }, - { - description: 'second stockart', - sourceUrl: 'url2.com', - fileNumber: '234' - } + { sourceUrl: 'url.com' }, + { sourceUrl: 'url2.com' } ] scope.$digest() From 41b847e081ff1608fcf683852383b902af8d5e6c Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Mon, 2 May 2016 20:32:33 +0530 Subject: [PATCH 02/20] AS#118090147171048, Mail chimp Integration -- Added mail chimp angular service -- Added user to member list on page load --- app/services/api.service.js | 2 + app/services/mailchimp.service.js | 70 +++++++++++++++++++++ app/skill-picker/skill-picker.controller.js | 19 +++++- app/topcoder.constants.js | 7 +++ 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 app/services/mailchimp.service.js diff --git a/app/services/api.service.js b/app/services/api.service.js index 8881f4d4d..0c16d843e 100644 --- a/app/services/api.service.js +++ b/app/services/api.service.js @@ -74,6 +74,8 @@ import _ from 'lodash' case 'SUBMISSIONS': case 'USER': return _getRestangularV3(CONSTANTS.AUTH_API_URL) + case 'MAILCHIMP': + return _getRestangularV3(CONSTANTS.INTERNAL_API_URL) default: return _getRestangularV3() } diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js new file mode 100644 index 000000000..f9cc80ab1 --- /dev/null +++ b/app/services/mailchimp.service.js @@ -0,0 +1,70 @@ +import angular from 'angular' +import _ from 'lodash' + +(function() { + 'use strict' + + angular.module('tc.services').factory('MailchimpService', MailchimpService) + + MailchimpService.$inject = ['$http', 'logger', 'Restangular', 'CONSTANTS', 'ApiService', '$q'] + + function MailchimpService($http, logger, Restangular, CONSTANTS, ApiService, $q) { + var mailchimpApi = ApiService.getApiServiceProvider('MAILCHIMP') + var service = { + getMemberSubscription: getMemberSubscription, + addSubscription: addSubscription + } + return service + + function getMemberSubscription(user) { + return $q(function(resolve, reject) { + mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID) + .one('members', user.userId).get() + .then(function(resp) { + resolve(resp) + }) + .catch(function(err) { + logger.error('Error adding member to subscription list', err) + + var errorStatus = 'FATAL_ERROR' + reject({ + status: errorStatus, + msg: err.data.result.content + }) + }) + }) + } + + + function addSubscription(user) { + var subscription = { + userId: user.userId, + firstName: user.firstName, + lastName: user.lastName, + interests: {} + } + subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true + return $q(function(resolve, reject) { + mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID) + .customPUT(subscription, 'members') + .then(function(resp) { + resolve(resp) + }) + .catch(function(err) { + logger.error('Error adding member to subscription list', err) + + var errorStatus = 'FATAL_ERROR' + + reject({ + status: errorStatus, + msg: err.data.result.content + }) + }) + }) + } + } +})() diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js index 75b0668d0..39aa6a5c4 100644 --- a/app/skill-picker/skill-picker.controller.js +++ b/app/skill-picker/skill-picker.controller.js @@ -6,9 +6,9 @@ import _ from 'lodash' angular.module('tc.skill-picker').controller('SkillPickerController', SkillPickerController) - SkillPickerController.$inject = ['$scope', 'CONSTANTS', 'ProfileService', '$state', 'userProfile', 'featuredSkills', 'logger', 'toaster', 'MemberCertService', '$q'] + SkillPickerController.$inject = ['$scope', 'CONSTANTS', 'ProfileService', '$state', 'userProfile', 'featuredSkills', 'logger', 'toaster', 'MemberCertService', '$q', 'MailchimpService'] - function SkillPickerController($scope, CONSTANTS, ProfileService, $state, userProfile, featuredSkills, logger, toaster, MemberCertService, $q) { + function SkillPickerController($scope, CONSTANTS, ProfileService, $state, userProfile, featuredSkills, logger, toaster, MemberCertService, $q, MailchimpService) { var vm = this vm.ASSET_PREFIX = CONSTANTS.ASSET_PREFIX vm.IOS_PROGRAM_ID = CONSTANTS.SWIFT_PROGRAM_ID @@ -32,6 +32,7 @@ import _ from 'lodash' * Activates the controller. */ function activate() { + addToMailingList() initCommunities() checkCommunityStatus() } @@ -137,6 +138,20 @@ import _ from 'lodash' } } + function addToMailingList() { + return MailchimpService.getMemberSubscription(userProfile).then(function(subscription) { + console.log(subscription) + if (!subscription) { + return MailchimpService.addSubscription(userProfile).then(function(resp) { + console.log(resp) + }) + } + }).catch(function(err) { + //TODO some error alert to community admin + console.log('error in adding user to member list') + }) + } + /** * Persists the user's altered information. */ diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js index cab991847..98dacbb52 100644 --- a/app/topcoder.constants.js +++ b/app/topcoder.constants.js @@ -4,6 +4,7 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', { 'API_URL' : process.env.API_URL, 'AUTH_API_URL' : process.env.AUTH_API_URL, 'API_URL_V2' : process.env.API_URL_V2, + 'INTERNAL_API_URL' : process.env.INTERNAL_API_URL, 'ASSET_PREFIX' : process.env.ASSET_PREFIX || '', 'auth0Callback' : process.env.auth0Callback, 'auth0Domain' : process.env.auth0Domain, @@ -19,6 +20,12 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', { 'PHOTO_LINK_LOCATION' : process.env.PHOTO_LINK_LOCATION, 'SWIFT_PROGRAM_URL' : process.env.SWIFT_PROGRAM_URL, 'TCO16_URL' : process.env.TCO16_URL, + 'MAILCHIMP_LIST_ID' : process.env.MAILCHIMP_LIST_ID, + 'MAILCHIMP_NL_TCO' : process.env.MAILCHIMP_NL_TCO, + 'MAILCHIMP_NL_IOS' : process.env.MAILCHIMP_NL_IOS, + 'MAILCHIMP_NL_DEV' : process.env.MAILCHIMP_NL_DEV, + 'MAILCHIMP_NL_DESIGN' : process.env.MAILCHIMP_NL_DESIGN, + 'MAILCHIMP_NL_DATA' : process.env.MAILCHIMP_NL_DATA, 'NEW_CHALLENGES_URL' : 'https://www.topcoder.com/challenges/develop/upcoming/', 'SWIFT_PROGRAM_ID' : 3445, From a2ce169687e7db83b73b0cee24c907d9bfd05e2a Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Tue, 3 May 2016 11:36:08 +0530 Subject: [PATCH 03/20] AS#118090147171048, Mail chimp Integration -- Fixed lint errors -- Updated webpack-config version --- app/services/mailchimp.service.js | 1 - app/skill-picker/skill-picker.controller.js | 6 +++--- package.json | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js index f9cc80ab1..3eec695d4 100644 --- a/app/services/mailchimp.service.js +++ b/app/services/mailchimp.service.js @@ -1,5 +1,4 @@ import angular from 'angular' -import _ from 'lodash' (function() { 'use strict' diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js index 39aa6a5c4..ec0c104fa 100644 --- a/app/skill-picker/skill-picker.controller.js +++ b/app/skill-picker/skill-picker.controller.js @@ -140,15 +140,15 @@ import _ from 'lodash' function addToMailingList() { return MailchimpService.getMemberSubscription(userProfile).then(function(subscription) { - console.log(subscription) + logger.debug(subscription) if (!subscription) { return MailchimpService.addSubscription(userProfile).then(function(resp) { - console.log(resp) + logger.debug(resp) }) } }).catch(function(err) { //TODO some error alert to community admin - console.log('error in adding user to member list') + logger.debug('error in adding user to member list') }) } diff --git a/package.json b/package.json index 97f576d82..8f93e9e96 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "devDependencies": { "angular-mocks": "^1.4.9", - "appirio-tech-webpack-config": "^0.2.0", + "appirio-tech-webpack-config": "^0.3.0", "babel-polyfill": "^6.7.2", "bardjs": "^0.1.8", "bower": "^1.6.8", From 85b1be33a6084a1c94ab9f16cab84e54ecef8dad Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Tue, 3 May 2016 11:37:51 +0530 Subject: [PATCH 04/20] AS#118090147171048, Mail chimp Integration -- Temporary travis build --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7f699e053..667e45a5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,16 @@ script: - npm run lint && npm test && npm run build sudo: false deploy: +- provider: s3 + cache_control: private, no-store, no-cache, must-revalidate, max-age=0 + detect_encoding: true + access_key_id: $AWS_KEY + secret_access_key: $AWS_SECRET + bucket: app.topcoder-dev.com + skip_cleanup: true + local_dir: dist + on: + branch: feature/mailchimp - provider: s3 cache_control: private, no-store, no-cache, must-revalidate, max-age=0 detect_encoding: true From 506b88899367a0edd4218281a9975ea77dfc91e0 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Tue, 3 May 2016 12:32:51 +0530 Subject: [PATCH 05/20] AS#118090147171048, Mail chimp Integration -- Fixed unit tests --- app/skill-picker/skill-picker.spec.js | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/app/skill-picker/skill-picker.spec.js b/app/skill-picker/skill-picker.spec.js index 7a2100fc7..70dd236c1 100644 --- a/app/skill-picker/skill-picker.spec.js +++ b/app/skill-picker/skill-picker.spec.js @@ -3,12 +3,12 @@ const mockData = require('../../tests/test-helpers/mock-data') describe('Skill Picker Controller', function() { var vm - var toasterSvc, memberCertService, profileService, state + var toasterSvc, memberCertService, profileService, mailchimpService, state var mockProfile = mockData.getMockProfile() beforeEach(function() { bard.appModule('tc.skill-picker') - bard.inject(this, '$controller', '$rootScope', '$q', 'MemberCertService', 'ProfileService', 'toaster', 'CONSTANTS') + bard.inject(this, '$controller', '$rootScope', '$q', 'MemberCertService', 'ProfileService', 'MailchimpService', 'toaster', 'CONSTANTS') memberCertService = MemberCertService profileService = ProfileService @@ -52,6 +52,29 @@ describe('Skill Picker Controller', function() { return deferred.promise }) + mailchimpService = MailchimpService + sinon.stub(mailchimpService, 'getMemberSubscription', function(user) { + var deferred = $q.defer() + if (user.userId === 10336829) { + deferred.resolve() + } else if (user.userId === 12345) { + var resp = { id: 'sdku34i5kdk', email_address: user.email} + deferred.resolve(resp) + } else { + deferred.reject() + } + return deferred.promise + }) + sinon.stub(mailchimpService, 'addSubscription', function(user) { + var deferred = $q.defer() + if (user.userId === 10336829) { + deferred.resolve() + } else { + deferred.reject() + } + return deferred.promise + }) + // mocks the toaster service toasterSvc = toaster bard.mockService(toaster, { @@ -115,6 +138,39 @@ describe('Skill Picker Controller', function() { CONSTANTS.SWIFT_PROGRAM_ID = origSwiftProgId }) + it('should call mailchimp service to add subscription', function() { + expect(vm).to.exist + // getMemberSubscription should always be called + expect(mailchimpService.getMemberSubscription).to.be.calledOnce + // addSubscription should be called once if not subscribed + // getMemberSubscription service mock returns null for mockProfile.userId + expect(mailchimpService.addSubscription).to.be.calledOnce + }) + + it('should not call mailchimp service to add subscription', function() { + // reset getMemberSubscription, addSubscription spy's called count + mailchimpService.getMemberSubscription.reset() + mailchimpService.addSubscription.reset() + var scope = $rootScope.$new() + + var profile = angular.copy(mockProfile) + // update userId to return valid object in service mock + profile.userId = 12345 + vm = $controller('SkillPickerController', { + $scope: scope, + userProfile: profile, + featuredSkills: [], + $state: state + }) + $rootScope.$digest() + expect(vm).to.exist + // getMemberSubscription should always be called + expect(mailchimpService.getMemberSubscription).to.be.calledOnce + // addSubscription should not be called if already subscribed + // getMemberSubscription service mock returns valid object for userId 12345 + expect(mailchimpService.addSubscription).not.to.be.called + }) + it('should add skill ', function() { vm.toggleSkill(409) expect(vm.mySkills).to.exist.have.length(1) From 37714596196ee30d87d3bfa753e518fde8ab2c47 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Tue, 3 May 2016 15:07:06 +0530 Subject: [PATCH 06/20] AS#118090147171048, Mail chimp Integration -- Misc fixes to get it working --- app/services/api.service.js | 4 ++++ app/services/mailchimp.service.js | 11 ++++++++--- app/skill-picker/skill-picker.controller.js | 5 +++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/services/api.service.js b/app/services/api.service.js index 0c16d843e..9f7735975 100644 --- a/app/services/api.service.js +++ b/app/services/api.service.js @@ -95,6 +95,10 @@ import _ from 'lodash' }) .setDefaultHeaders({ 'Content-Type': 'application/json' }) .addRequestInterceptor(function(element, operation, what, url) { + // for mailchimp api, don't add param field in the body + if (url.indexOf('mailchimp') > -1) { + return element + } if (url.indexOf('members') > -1 || (operation.toLowerCase() === 'post' && url.indexOf('profiles') > -1)) { return { param: element diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js index 3eec695d4..da355780c 100644 --- a/app/services/mailchimp.service.js +++ b/app/services/mailchimp.service.js @@ -23,12 +23,17 @@ import angular from 'angular' resolve(resp) }) .catch(function(err) { - logger.error('Error adding member to subscription list', err) + if (err.status === 404) { + logger.debug('Member subscription not found') + resolve() + return + } + logger.error('Error getting member to subscription list', err) var errorStatus = 'FATAL_ERROR' reject({ status: errorStatus, - msg: err.data.result.content + msg: err.errorMessage }) }) }) @@ -60,7 +65,7 @@ import angular from 'angular' reject({ status: errorStatus, - msg: err.data.result.content + msg: err.errorMessage }) }) }) diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js index ec0c104fa..a564c876c 100644 --- a/app/skill-picker/skill-picker.controller.js +++ b/app/skill-picker/skill-picker.controller.js @@ -144,9 +144,14 @@ import _ from 'lodash' if (!subscription) { return MailchimpService.addSubscription(userProfile).then(function(resp) { logger.debug(resp) + }).catch(function(err) { + // no error to user + //TODO some error alert to community admin + logger.debug('error in adding user to member list') }) } }).catch(function(err) { + // no error to user //TODO some error alert to community admin logger.debug('error in adding user to member list') }) From 18134632ef3da65ec28603c9bcd502a7b49b2177 Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Tue, 3 May 2016 14:56:10 -0700 Subject: [PATCH 07/20] April members of the month --- app/community/members.controller.js | 2 +- app/services/communityData.service.js | 28 +++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/community/members.controller.js b/app/community/members.controller.js index 1b12bd21b..92c50e0d6 100644 --- a/app/community/members.controller.js +++ b/app/community/members.controller.js @@ -12,7 +12,7 @@ import angular from 'angular' ctrl.notSearch = true ctrl.showing = 'list' ctrl.domain = CONSTANTS.domain - ctrl.currentMonth = 'March 2016' + ctrl.currentMonth = 'April 2016' ctrl.memberLeaderboard = [] ctrl.copilots = [] CommunityDataService.getMembersData() diff --git a/app/services/communityData.service.js b/app/services/communityData.service.js index 66fa59d22..9f951ca1c 100644 --- a/app/services/communityData.service.js +++ b/app/services/communityData.service.js @@ -21,29 +21,29 @@ import angular from 'angular' var data = { 'memberLeaderboard': [ { - 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/universo_march2016.png', - 'name': 'universo', + 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/toxicpixel_apr2016.png', + 'name': 'ToxicPixel', 'contestType': 'Design', - 'description': 'Won $4,500 in design challenges', + 'description': 'Won $4,200 with top prizes in LUX and Idea Gen!', 'class': 'design' }, { - 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/sdgun_march2016.png', - 'name': 'sdgun', + 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/monicamuranyi_apr2016.png', + 'name': 'MonicaMuranyi', 'contestType': 'Development', - 'description': 'Nine wins for $2,076', + 'description': 'Won $8,300 across 12 competitions', 'class': 'develop' }, { - 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/BSBandme_march2016.png', - 'name': 'BSBandme', + 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/sugina_apr2016.png', + 'name': 'Sugina', 'contestType': 'Data Science', - 'description': 'Gained 285 rating points within all 3 January SRMs', + 'description': 'Total increase of 175 points, with a jump from Div 2 to Div 1', 'class': 'data-science' }, { - 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/johan_92_march2016.png', - 'name': 'johan_92', - 'contestType': 'Design Rookie', - 'description': 'Joined end of December and has had 4 1st place wins!', - 'class': 'design' + 'avatar': '//www.topcoder.com/wp-content/uploads/2015/05/tritias_apr2016.png', + 'name': 'TiTrias', + 'contestType': 'Development Rookie', + 'description': 'Won first challenge within a month of joining!', + 'class': 'develop' } ], 'copilots': [{ From 817b69b2ed1103987d04480433525e4d4575713c Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Tue, 3 May 2016 15:00:22 -0700 Subject: [PATCH 08/20] Fix plural --- app/community/members.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/community/members.jade b/app/community/members.jade index e8c6f8dc3..037e41d57 100644 --- a/app/community/members.jade +++ b/app/community/members.jade @@ -13,13 +13,13 @@ .platform-stats-container .stat p.statVal {{ctrl.platformStats.memberCount | number : 0}} - p.statLabel ACTIVE MEMBER + p.statLabel ACTIVE MEMBERS .stat p.statVal {{ctrl.platformStats.activeMembersCount | number : 0}} p.statLabel COMPETING TODAY .stat p.statVal {{ctrl.platformStats.prizePurse | currency:undefined:0}} - p.statLabel AVAILABLE PRIZE + p.statLabel AVAILABLE PRIZES .stat p.statVal {{ctrl.platformStats.activeContestsCount | number : 0}} p.statLabel ACTIVE CHALLENGES From 4b145c7cff6f2a2c20ff4839a04638066391f2d6 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Wed, 4 May 2016 11:53:41 +0530 Subject: [PATCH 09/20] AS#118090147171050, Email settings tab UI -- Added settings tab with required functionality --- app/index.js | 1 + app/services/mailchimp.service.js | 16 ++-- app/settings/email/email.controller.js | 105 +++++++++++++++++++++++++ app/settings/email/email.jade | 30 +++++++ app/settings/settings.jade | 3 + app/settings/settings.routes.js | 17 ++++ app/topcoder.constants.js | 1 + assets/css/settings/email.scss | 92 ++++++++++++++++++++++ 8 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 app/settings/email/email.controller.js create mode 100644 app/settings/email/email.jade create mode 100644 assets/css/settings/email.scss diff --git a/app/index.js b/app/index.js index 88d8a918b..30f039869 100644 --- a/app/index.js +++ b/app/index.js @@ -63,6 +63,7 @@ require('../assets/css/sitemap/sitemap.scss') require('../assets/css/settings/update-password.scss') require('../assets/css/settings/settings.scss') require('../assets/css/settings/preferences.scss') +require('../assets/css/settings/email.scss') require('../assets/css/settings/edit-profile.scss') require('../assets/css/settings/account-info.scss') require('../assets/css/profile/subtrack.scss') diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js index da355780c..5b5cbfdbd 100644 --- a/app/services/mailchimp.service.js +++ b/app/services/mailchimp.service.js @@ -40,18 +40,22 @@ import angular from 'angular' } - function addSubscription(user) { + function addSubscription(user, preferences) { var subscription = { userId: user.userId, firstName: user.firstName, lastName: user.lastName, interests: {} } - subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true + if (!preferences) { + subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true + } else { + subscription.interests = preferences + } return $q(function(resolve, reject) { mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID) .customPUT(subscription, 'members') diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js new file mode 100644 index 000000000..0e61e861f --- /dev/null +++ b/app/settings/email/email.controller.js @@ -0,0 +1,105 @@ +import angular from 'angular' +import _ from 'lodash' + +(function () { + 'use strict' + + angular.module('tc.settings').controller('EmailSettingsController', EmailSettingsController) + + EmailSettingsController.$inject = ['$rootScope', 'userProfile', 'ProfileService', 'MailchimpService', 'logger', 'CONSTANTS', 'toaster', '$q', '$scope'] + + function EmailSettingsController($rootScope, userProfile, ProfileService, MailchimpService, logger, CONSTANTS, toaster, $q, $scope) { + var vm = this + vm.loading = false + vm.saving = false + vm.isDirty = isDirty + vm.save = save + + activate() + + function activate() { + vm.newsletters = [ + { + id: CONSTANTS.MAILCHIMP_NL_DEV, + name: 'Developer Newsletter', + desc: 'Software architecture, component assembly, application development and bug hunting', + enabled: false, + dirty: false + }, + { + id: CONSTANTS.MAILCHIMP_NL_DESIGN, + name: 'Design Newsletter', + desc: 'Website, mobile, and product design; UI and UX', + enabled: false, + dirty: false + }, + { + id: CONSTANTS.MAILCHIMP_NL_DATA, + name: 'Data Science Newsletter', + desc: 'Algorithm and data structures, statistical analysis', + enabled: false, + dirty: false + }, + { + id: CONSTANTS.MAILCHIMP_NL_TCO, + name: 'TCO Newsletter', + desc: 'Software architecture, component assembly, application development and bug hunting', + enabled: false, + dirty: false + }, + { + id: CONSTANTS.MAILCHIMP_NL_IOS, + name: 'iOS Community Newsletter', + desc: 'Software architecture, component assembly, application development and bug hunting', + enabled: false, + dirty: false + } + ] + + vm.loading = true + MailchimpService.getMemberSubscription(userProfile).then(function(resp) { + vm.loading = false + if (resp.interests) { + vm.newsletters.forEach(function(newsletter) { + if (resp.interests[newsletter.id]) { + newsletter.enabled = true + } + }) + } + }) + } + + function isDirty() { + var dirty = false + vm.newsletters.forEach(function(newsletter) { + if (newsletter.dirty){ + dirty = true + } + }) + return dirty + } + + function save() { + vm.saving = true + var preferences = {} + vm.newsletters.forEach(function(newsletter) { + preferences[newsletter.id] = newsletter.enabled + }) + MailchimpService.addSubscription(userProfile, preferences).then(function(resp) { + vm.loading = false + vm.saving = false + // reset dirty state for all newsletter options + vm.newsletters.forEach(function(newsletter) { + newsletter.dirty = false + }) + toaster.pop('success', 'Success!', 'Preferences updated.') + }).catch(function(err) { + logger.error('Could not update email preferences', err) + vm.loading = false + vm.saving = false + + toaster.pop('error', 'Whoops!', 'Something went wrong. Please try again later.') + }) + } + } +})() diff --git a/app/settings/email/email.jade b/app/settings/email/email.jade new file mode 100644 index 000000000..37977606f --- /dev/null +++ b/app/settings/email/email.jade @@ -0,0 +1,30 @@ +.email-preferences-container + .settings-section.newsletters + .section-info + h2 Always be up to date + .description Select the email notifications that you'd like to receive. We send them once every week, so you can be up to date with latest news, events and callenges. + + .section-fields + .processing(ng-show="vm.loading") + i.fa.fa-spinner.fa-spin + .newsletters(ng-hide="vm.loading") + .newsletter(ng-repeat="newsletter in vm.newsletters") + + .content(ng-class="{ disabled: !newsletter.enabled }") + .newsletter-details + .text + span.title {{newsletter.name}} + .description + span(ng-bind="newsletter.desc") + + .onoffswitch + input.onoffswitch-checkbox(type='checkbox', name='onoffswitch', checked='', ng-model="newsletter.enabled", id="{{newsletter.name}}-onoffswitch", ng-change="newsletter.dirty = !newsletter.dirty") + label.onoffswitch-label(for='{{newsletter.name}}-onoffswitch') + span.onoffswitch-inner + span.onoffswitch-switch + .save-section + button.tc-btn.tc-btn-l.done-button( + type="button", + tc-busy-button, tc-busy-when="vm.saving", + ng-click="vm.save()", + ng-disabled="!vm.isDirty()") Save diff --git a/app/settings/settings.jade b/app/settings/settings.jade index 8c3cd2d0a..8923a13f5 100644 --- a/app/settings/settings.jade +++ b/app/settings/settings.jade @@ -10,6 +10,9 @@ li a(ui-sref="settings.account", ui-sref-active="active-tab") Account + li + a(ui-sref="settings.email", ui-sref-active="active-tab") Email + li a(ui-sref="settings.preferences", ui-sref-active="active-tab") Preferences diff --git a/app/settings/settings.routes.js b/app/settings/settings.routes.js index 0dce4be57..031faed38 100644 --- a/app/settings/settings.routes.js +++ b/app/settings/settings.routes.js @@ -47,6 +47,23 @@ import angular from 'angular' title: 'Account Info' } }, + 'settings.email': { + url: 'email/', + template: require('./email/email')(), + controller: 'EmailSettingsController', + controllerAs: 'vm', + data: { + title: 'Email Preferences' + }, + resolve: { + userIdentity: ['UserService', function(UserService) { + return UserService.getUserIdentity() + }], + userProfile: ['userIdentity', 'ProfileService', function(userIdentity, ProfileService) { + return ProfileService.getUserProfile(userIdentity.handle.toLowerCase()) + }] + } + }, 'settings.preferences': { url: 'preferences/', template: require('./preferences/preferences')(), diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js index 98dacbb52..bf5f73ea4 100644 --- a/app/topcoder.constants.js +++ b/app/topcoder.constants.js @@ -21,6 +21,7 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', { 'SWIFT_PROGRAM_URL' : process.env.SWIFT_PROGRAM_URL, 'TCO16_URL' : process.env.TCO16_URL, 'MAILCHIMP_LIST_ID' : process.env.MAILCHIMP_LIST_ID, + 'MAILCHIMP_NL_CATEGORY_ID': process.env.MAILCHIMP_NL_CATEGORY_ID, 'MAILCHIMP_NL_TCO' : process.env.MAILCHIMP_NL_TCO, 'MAILCHIMP_NL_IOS' : process.env.MAILCHIMP_NL_IOS, 'MAILCHIMP_NL_DEV' : process.env.MAILCHIMP_NL_DEV, diff --git a/assets/css/settings/email.scss b/assets/css/settings/email.scss new file mode 100644 index 000000000..2dab3612b --- /dev/null +++ b/assets/css/settings/email.scss @@ -0,0 +1,92 @@ +@import 'topcoder/tc-includes'; + +.email-preferences-container { + width: 100%; + padding: 0 60px 30px; + + .processing { + display: flex; + justify-content: center; + align-items: center; + } + + .newsletters { + .newsletter { + width: 100%; + display: flex; + flex-direction: column; + align-items: left; + + .content { + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 15px 0; + border-bottom: 1px solid $gray-light; + width: 100%; + transition: background-color .15s; + + &.disabled { + background-color: $gray-lightest; + } + + .newsletter-details { + display: flex; + flex-direction: row; + align-items: center; + padding-left: 10px; + + .icon { + &.disabled { + color: #b7b7b7; + } + img { + height: 32px; + width: 32px; + } + span { + @include font-with-weight('Sofia Pro', 500); + font-size: 16px; + } + } + } + } + .text { + margin-left: 15px; + .title { + font-size: 16px; + line-height: 28px; + @include sofia-pro-medium; + text-transform: uppercase; + transition: .1s color; + &.disabled { + color: #b7b7b7; + } + } + .description { + @include merriweather-sans-regular; + font-size: 13px; + margin-top: 4px; + color: $accent-gray; + } + } + } + } + + .save-section { + width: 100%; + margin: 0 auto; + background-color: #fcfcfc; + border-top: 1px solid #f0f0f0; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + button.save { + margin-bottom: 15px; + margin-top: 15px; + width: 100px; + } + } +} \ No newline at end of file From aca36b2f8ee4e1fda3763e5f2148e8a337360a07 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Wed, 4 May 2016 12:07:23 +0530 Subject: [PATCH 10/20] AS#118090147171050, Email settings tab UI -- Fixed lint error --- app/settings/email/email.controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js index 0e61e861f..dbee69659 100644 --- a/app/settings/email/email.controller.js +++ b/app/settings/email/email.controller.js @@ -1,5 +1,4 @@ import angular from 'angular' -import _ from 'lodash' (function () { 'use strict' From 64bb8f4276ab3cf1dd31670a107236da9be0148c Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Wed, 4 May 2016 12:29:19 +0530 Subject: [PATCH 11/20] AS#118090147171050, Email settings tab UI -- Removed preferences option from preferences tab for email --- app/settings/preferences/preferences.jade | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/settings/preferences/preferences.jade b/app/settings/preferences/preferences.jade index 7e9c5f3b2..b836ce4dd 100644 --- a/app/settings/preferences/preferences.jade +++ b/app/settings/preferences/preferences.jade @@ -1,12 +1,5 @@ .preferences-container ul - li - a(href="http://thecloud.appirio.com/email_prefs_request.html", target="_blank") - .icon - i.fa.fa-envelope - span Email Preferences - .description Specify what kind of email you would like to receive from us - li a(href="https://apps.{{DOMAIN}}/forums/?module=Settings", target="_blank") .icon From 4a74ae9058c9ff370da4eb91fe14d8ced1f95cef Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Wed, 4 May 2016 13:22:26 +0530 Subject: [PATCH 12/20] AS#118090147171048, Mail chimp Integration -- Removed temporary build --- .travis.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 667e45a5d..7f699e053 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,16 +7,6 @@ script: - npm run lint && npm test && npm run build sudo: false deploy: -- provider: s3 - cache_control: private, no-store, no-cache, must-revalidate, max-age=0 - detect_encoding: true - access_key_id: $AWS_KEY - secret_access_key: $AWS_SECRET - bucket: app.topcoder-dev.com - skip_cleanup: true - local_dir: dist - on: - branch: feature/mailchimp - provider: s3 cache_control: private, no-store, no-cache, must-revalidate, max-age=0 detect_encoding: true From b0b68c7641a8097659e65b6e3b0bb266212f8d5b Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Wed, 4 May 2016 17:50:40 +0530 Subject: [PATCH 13/20] AS#118090147171050, Email settings tab UI -- Handled case where user is not in the required mailing list and opens the email settings page --- app/settings/email/email.controller.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js index dbee69659..39b59db30 100644 --- a/app/settings/email/email.controller.js +++ b/app/settings/email/email.controller.js @@ -56,14 +56,25 @@ import angular from 'angular' ] vm.loading = true - MailchimpService.getMemberSubscription(userProfile).then(function(resp) { + return MailchimpService.getMemberSubscription(userProfile).then(function(subscription) { vm.loading = false - if (resp.interests) { - vm.newsletters.forEach(function(newsletter) { - if (resp.interests[newsletter.id]) { - newsletter.enabled = true - } + if (!subscription) { + // add member to the list with empty preferences + MailchimpService.addSubscription(userProfile, {}).then(function(resp) { + logger.debug(resp) + }).catch(function(err) { + // no error to user + //TODO some error alert to community admin + logger.debug('error in adding user to member list') }) + } else { + if (subscription.interests) { + vm.newsletters.forEach(function(newsletter) { + if (subscription.interests[newsletter.id]) { + newsletter.enabled = true + } + }) + } } }) } From 00d64f2a22f1e0abbc9bf6352c95834b530bd644 Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Wed, 4 May 2016 11:34:42 -0700 Subject: [PATCH 14/20] Experiment with different cache setting --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7f699e053..23273852c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ script: sudo: false deploy: - provider: s3 - cache_control: private, no-store, no-cache, must-revalidate, max-age=0 + cache_control: max-age=300 detect_encoding: true access_key_id: $AWS_KEY secret_access_key: $AWS_SECRET From 6a5148aa73798d63d6de3b83659b3a4212904410 Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Wed, 4 May 2016 14:10:36 -0700 Subject: [PATCH 15/20] Revert test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 23273852c..7f699e053 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ script: sudo: false deploy: - provider: s3 - cache_control: max-age=300 + cache_control: private, no-store, no-cache, must-revalidate, max-age=0 detect_encoding: true access_key_id: $AWS_KEY secret_access_key: $AWS_SECRET From e3047be9f1d5fab7cd60db308d386cd7965e5656 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Thu, 5 May 2016 11:05:46 +0530 Subject: [PATCH 16/20] AS#121262308049576, Copy changes -- Done --- app/settings/email/email.controller.js | 13 ++++++++++--- app/settings/email/email.jade | 4 ++-- app/topcoder.constants.js | 1 + assets/css/settings/email.scss | 1 - 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js index 39b59db30..802058e18 100644 --- a/app/settings/email/email.controller.js +++ b/app/settings/email/email.controller.js @@ -18,10 +18,17 @@ import angular from 'angular' function activate() { vm.newsletters = [ + { + id: CONSTANTS.MAILCHIMP_NL_GEN, + name: 'General Newsletter', + desc: "News summary from all tracks and programs", + enabled: false, + dirty: false + }, { id: CONSTANTS.MAILCHIMP_NL_DEV, name: 'Developer Newsletter', - desc: 'Software architecture, component assembly, application development and bug hunting', + desc: 'Software architecture, component assembly, application development, and bug hunting', enabled: false, dirty: false }, @@ -42,14 +49,14 @@ import angular from 'angular' { id: CONSTANTS.MAILCHIMP_NL_TCO, name: 'TCO Newsletter', - desc: 'Software architecture, component assembly, application development and bug hunting', + desc: 'Our annual online and onsite tournament to celebrate and reward the community', enabled: false, dirty: false }, { id: CONSTANTS.MAILCHIMP_NL_IOS, name: 'iOS Community Newsletter', - desc: 'Software architecture, component assembly, application development and bug hunting', + desc: 'Mobile app design and development for iOS, with Swift emphasis', enabled: false, dirty: false } diff --git a/app/settings/email/email.jade b/app/settings/email/email.jade index 37977606f..63742b87b 100644 --- a/app/settings/email/email.jade +++ b/app/settings/email/email.jade @@ -1,8 +1,8 @@ .email-preferences-container .settings-section.newsletters .section-info - h2 Always be up to date - .description Select the email notifications that you'd like to receive. We send them once every week, so you can be up to date with latest news, events and callenges. + h2 Email Preferences + .description Choose the community newsletters that you would like to receive. They are sent about once a week and have the latest news on challenges, events, and special programs. .section-fields .processing(ng-show="vm.loading") diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js index bf5f73ea4..c3245842a 100644 --- a/app/topcoder.constants.js +++ b/app/topcoder.constants.js @@ -22,6 +22,7 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', { 'TCO16_URL' : process.env.TCO16_URL, 'MAILCHIMP_LIST_ID' : process.env.MAILCHIMP_LIST_ID, 'MAILCHIMP_NL_CATEGORY_ID': process.env.MAILCHIMP_NL_CATEGORY_ID, + 'MAILCHIMP_NL_GEN' : process.env.MAILCHIMP_NL_GEN, 'MAILCHIMP_NL_TCO' : process.env.MAILCHIMP_NL_TCO, 'MAILCHIMP_NL_IOS' : process.env.MAILCHIMP_NL_IOS, 'MAILCHIMP_NL_DEV' : process.env.MAILCHIMP_NL_DEV, diff --git a/assets/css/settings/email.scss b/assets/css/settings/email.scss index 2dab3612b..e8d38e568 100644 --- a/assets/css/settings/email.scss +++ b/assets/css/settings/email.scss @@ -57,7 +57,6 @@ font-size: 16px; line-height: 28px; @include sofia-pro-medium; - text-transform: uppercase; transition: .1s color; &.disabled { color: #b7b7b7; From 7fb6f5d30bf9fea32d85fb0691b7a94a8f6bd3bf Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Thu, 5 May 2016 11:55:36 +0530 Subject: [PATCH 17/20] AS#121262308049576, Copy changes -- Fixed lint errors --- app/settings/email/email.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js index 802058e18..dec412017 100644 --- a/app/settings/email/email.controller.js +++ b/app/settings/email/email.controller.js @@ -21,7 +21,7 @@ import angular from 'angular' { id: CONSTANTS.MAILCHIMP_NL_GEN, name: 'General Newsletter', - desc: "News summary from all tracks and programs", + desc: 'News summary from all tracks and programs', enabled: false, dirty: false }, From f1409d8d2b55d33dfbbcee4705226bceaf8adefd Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Thu, 5 May 2016 11:59:36 +0530 Subject: [PATCH 18/20] AS#121262308049598, Change newsletter default -- Fixed --- app/services/mailchimp.service.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js index 5b5cbfdbd..ead0d06a1 100644 --- a/app/services/mailchimp.service.js +++ b/app/services/mailchimp.service.js @@ -48,11 +48,7 @@ import angular from 'angular' interests: {} } if (!preferences) { - subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true - subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true + subscription.interests[CONSTANTS.MAILCHIMP_NL_GEN] = true } else { subscription.interests = preferences } From c44091a742d0a383ac03b65f389f7c84ad4b5249 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Thu, 5 May 2016 12:02:00 +0530 Subject: [PATCH 19/20] AS#121262308049584, Reorder newsletter options and add "General Newsletter" -- Done --- app/settings/email/email.controller.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js index dec412017..443265c54 100644 --- a/app/settings/email/email.controller.js +++ b/app/settings/email/email.controller.js @@ -26,16 +26,16 @@ import angular from 'angular' dirty: false }, { - id: CONSTANTS.MAILCHIMP_NL_DEV, - name: 'Developer Newsletter', - desc: 'Software architecture, component assembly, application development, and bug hunting', + id: CONSTANTS.MAILCHIMP_NL_DESIGN, + name: 'Design Newsletter', + desc: 'Website, mobile, and product design; UI and UX', enabled: false, dirty: false }, { - id: CONSTANTS.MAILCHIMP_NL_DESIGN, - name: 'Design Newsletter', - desc: 'Website, mobile, and product design; UI and UX', + id: CONSTANTS.MAILCHIMP_NL_DEV, + name: 'Developer Newsletter', + desc: 'Software architecture, component assembly, application development, and bug hunting', enabled: false, dirty: false }, @@ -47,16 +47,16 @@ import angular from 'angular' dirty: false }, { - id: CONSTANTS.MAILCHIMP_NL_TCO, - name: 'TCO Newsletter', - desc: 'Our annual online and onsite tournament to celebrate and reward the community', + id: CONSTANTS.MAILCHIMP_NL_IOS, + name: 'iOS Community Newsletter', + desc: 'Mobile app design and development for iOS, with Swift emphasis', enabled: false, dirty: false }, { - id: CONSTANTS.MAILCHIMP_NL_IOS, - name: 'iOS Community Newsletter', - desc: 'Mobile app design and development for iOS, with Swift emphasis', + id: CONSTANTS.MAILCHIMP_NL_TCO, + name: 'TCO Newsletter', + desc: 'Our annual online and onsite tournament to celebrate and reward the community', enabled: false, dirty: false } From 665af8ad2819f50e5e675b43356245e9ff39b7ed Mon Sep 17 00:00:00 2001 From: Mauricio Desiderio Date: Thu, 5 May 2016 10:19:43 -0500 Subject: [PATCH 20/20] adding host to npm start --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97f576d82..635846027 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Topcoder pages including login, registration, settings, dashboard, profile.", "scripts": { "build": "webpack --bail --progress --build --tc", - "start": "webpack-dev-server --history-api-fallback --dev --tc --inline --progress --port 3000", + "start": "webpack-dev-server --history-api-fallback --host 0.0.0.0 --dev --tc --inline --progress --port 3000", "lint": "eslint --ignore-path .gitignore .", "test": "karma start --tc --test" },