Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Submissions header #631

Merged
merged 54 commits into from
Dec 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6019d28
Add submissions css file
Dec 9, 2015
3a07a8e
Move intro JS CSS overrides to appropriate place
Dec 11, 2015
dd6f7cd
Add submit file method controller and jade
Dec 11, 2015
5c76f7e
Clean up CSS while building new panels in styeguide
Dec 11, 2015
187fdff
Use BEM structure
Dec 11, 2015
013b574
Fix routes
Dec 11, 2015
9c06fe0
Update to new structure
Dec 12, 2015
157e672
Reduce min-height on view container and resize mobile page container …
Dec 14, 2015
8edd9dd
New dependencies from ui-components
Dec 15, 2015
9e69697
Merge branch 'dev' into submissions-header
Dec 15, 2015
2d140a3
Add ui components
Dec 16, 2015
8d7ee98
Add ui components
Dec 16, 2015
174a154
Rename tc-input to topcoder-input since that name needs to be used in…
Dec 16, 2015
3a76c7a
Move from style guide to vendor css file
Dec 16, 2015
c5b402f
Add filter to add space before a string
Dec 17, 2015
1fb9b6f
Add form field for file input plus button and label
Dec 19, 2015
986fc13
Add directive for textarea with label and count
Dec 19, 2015
c175bd8
Use correct quotes
Dec 19, 2015
f329a44
Add new form directives
Dec 19, 2015
343f26d
Add zepto
Dec 19, 2015
111fe00
Use branch for styles repo
Dec 19, 2015
9199d1d
Use correct quotes
Dec 19, 2015
bc2803b
Get file references and make post call
Dec 19, 2015
f3f35c4
Add markup for submissions page
Dec 19, 2015
2aa14cc
Add styles for mobile page
Dec 19, 2015
03c006f
Add submissions service
Dec 19, 2015
0bdcc0d
Add submit-file specific css
Dec 19, 2015
47d32d5
Merge branch 'dev' into submissions-header
Dec 21, 2015
601afef
Rename to tc-file-input directive
Dec 22, 2015
23c6b09
Add new directive for simple label and input
Dec 22, 2015
a3d1b77
Add new files
Dec 22, 2015
8c39920
Refactor
Dec 22, 2015
e9d709d
Get presigned url POST working
Dec 22, 2015
51fe2c2
Add other future functions for processing files
Dec 23, 2015
bf78ec1
Add check for submission phase and submitter role
Dec 23, 2015
e22414b
Form
Dec 23, 2015
e490dcf
Name wrapper placeholders
Dec 28, 2015
17a6e28
Call s3 upload from presigned url success callback
Dec 28, 2015
7ea5256
Add data to header
Dec 28, 2015
107c8b2
Work on stock art form fields
Dec 28, 2015
f498d60
Remove unused request interceptor
Dec 29, 2015
7362c77
Handle the case where no challenges appear
Dec 29, 2015
d075e11
Upload to S3
Dec 29, 2015
f88b544
Add type button so it doesn't resubmit form
Dec 29, 2015
5d54d7b
Add type button for fonts too
Dec 30, 2015
188a71c
Add callbacks for updating and processing endpoints
Dec 30, 2015
cfd3e6f
Get updated ng-ui-components
Dec 30, 2015
ecffea2
Install dependencies for ng-ui-components
Dec 30, 2015
d38911e
Multiple dropdowns yay
Dec 30, 2015
78b31cc
Pass phasetype and id down to controller
Dec 31, 2015
f0e1acf
save for update
Dec 31, 2015
610f561
Wrap submission posts and puts in param
Dec 31, 2015
23e0bcb
Make updating and processing calls
Dec 31, 2015
82a9a05
Send empty arrays for fonts and stockarts if nothing to send
Dec 31, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/directives/on-file-change.directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
return {
restrict: 'A',
link: function(scope, element, attr, ctrl) {
element.bind("change", function() {
element.bind('change', function() {
scope.vm.onFileChange(element[0].files[0]);
this.value = '';
});
Expand Down
43 changes: 43 additions & 0 deletions app/directives/tc-file-input/tc-file-input.directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
(function() {
'use strict';

angular.module('tcUIComponents').directive('tcFileInput', tcFileInput);

function tcFileInput() {
return {
restrict: 'E',
templateUrl: 'directives/tc-file-input/tc-file-input.html',
scope: {
labelText: '@',
fieldId: '@',
placeholder: '@',
fileType: '@',
mandatory: '=',
buttonText: '@',
setFileReference: '&'
},
link: function(scope, element, attrs) {
scope.selectFile = selectFile;

// fieldId is not set on element at this point, so grabbing with class .none
// which exists on the element right away
var fileInput = $(element[0]).find('.none');
var fileNameInput = $(element[0]).find('input[type=text]');

fileInput.bind('change', function() {
var file = fileInput[0].files[0];

// Pass file object up through callback into controller
scope.setFileReference({file: file, fieldId: scope.fieldId});

// Set the file name as the value of the disabled input
fileNameInput[0].value = file.name;
});

function selectFile() {
fileInput.click();
}
}
}
}
})();
12 changes: 12 additions & 0 deletions app/directives/tc-file-input/tc-file-input.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.tc-file-field__label
label.tc-label {{labelText}}
span.lowercase(ng-if="fileType") {{fileType | addBeginningSpace}}

span.tc-label__mandatory.lowercase(ng-if="mandatory") #[span *]mandatory

.tc-file-field__inputs
input.tc-file-field__input(type="text", placeholder="{{placeholder}}", required)

button.tc-btn(ng-click="selectFile()") {{buttonText}}

input.none(type="file", id="{{fieldId}}")
19 changes: 19 additions & 0 deletions app/directives/tc-file-input/tc-file-input.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* jshint -W117, -W030 */
describe('Topcoder File Input Directive', function() {
var scope;

// USE AS TEMPLATE FOR DIRECTIVES

beforeEach(function() {
bard.appModule('tcUIComponents');
bard.inject(this, '$compile', '$rootScope');
});

bard.verifyNoOutstandingHttpRequests();

xdescribe('', function() {
beforeEach(function() {});

it('', function() {});
});
});
17 changes: 17 additions & 0 deletions app/directives/tc-input/tc-input.directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(function() {
'use strict';

angular.module('tcUIComponents').directive('tcInput', tcInput);

function tcInput() {
return {
restrict: 'E',
templateUrl: 'directives/tc-input/tc-input.html',
scope: {
labelText: '@',
placeholder: '@',
inputValue: '='
}
}
}
})();
3 changes: 3 additions & 0 deletions app/directives/tc-input/tc-input.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
label.tc-label {{labelText}}

input(type="text", placeholder="{{placeholder}}", ng-model="inputValue")
19 changes: 19 additions & 0 deletions app/directives/tc-textarea/tc-textarea.directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(function() {
'use strict';

angular.module('tcUIComponents').directive('tcTextarea', tcTextarea);

function tcTextarea() {
return {
restrict: 'E',
templateUrl: 'directives/tc-textarea/tc-textarea.html',
scope: {
labelText: '@',
placeholder: '@',
characterCount: '=',
characterCountMax: '@',
value: '='
}
}
}
})();
7 changes: 7 additions & 0 deletions app/directives/tc-textarea/tc-textarea.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
label.tc-label.tc-textarea__label {{labelText}}
span.tc-textarea__char-count(ng-if="characterCount")
span.tc-textarea__char-count--current {{value.length || 0}}

span {{' / ' + characterCountMax}}

textarea(placeholder="{{placeholder}}", ng-model="value", maxlength="{{characterCountMax}}")
11 changes: 11 additions & 0 deletions app/filters/add-beginning-space.filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(function() {
'use strict';

angular.module('topcoder').filter('addBeginningSpace', addBeginningSpace);

function addBeginningSpace() {
return function(input) {
return ' ' + input;
};
};
})();
10 changes: 8 additions & 2 deletions app/filters/filters.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('filters', function() {

beforeEach(function() {
bard.appModule('topcoder');
bard.inject(this, 'CONSTANTS', 'roleFilter', 'percentageFilter', 'ordinalFilter', 'displayLocationFilter', 'listRolesFilter', 'trackFilter', 'challengeLinksFilter', 'externalLinkColorFilter', 'emptyFilter', 'ternaryFilter', 'urlProtocolFilter');
bard.inject(this, 'CONSTANTS', 'roleFilter', 'percentageFilter', 'ordinalFilter', 'displayLocationFilter', 'listRolesFilter', 'trackFilter', 'challengeLinksFilter', 'externalLinkColorFilter', 'emptyFilter', 'ternaryFilter', 'urlProtocolFilter', 'addBeginningSpaceFilter');
domain = CONSTANTS.domain;
});

Expand Down Expand Up @@ -100,7 +100,7 @@ describe('filters', function() {
});

describe('externalLinkColorFilter', function() {

it('should handle twitter and linkedin correctly', function() {
expect(externalLinkColorFilter('el-twitter')).to.be.equal('#62AADC');
expect(externalLinkColorFilter('el-linkedin')).to.be.equal('#127CB5');
Expand Down Expand Up @@ -150,4 +150,10 @@ describe('filters', function() {
expect(urlProtocolFilter('https://google.com')).to.be.equal('https://google.com');
});
});

describe('addBeginningSpaceFilter', function() {
it('should add a space to the beginning of the input', function() {
expect(addBeginningSpaceFilter('some text')).to.equal(' some text');
});
});
});
22 changes: 21 additions & 1 deletion app/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ html
link(rel='stylesheet', href='../bower_components/angular-dropdowns/dist/angular-dropdowns.css')
link(rel='stylesheet', href='../bower_components/intro.js/introjs.css')
link(rel='stylesheet', href='../bower_components/angularjs-toaster/toaster.css')
link(rel='stylesheet', href='../bower_components/react-select/dist/react-select.min.css')
link(rel='stylesheet', href='../bower_components/fontawesome/css/font-awesome.css')
link(rel='stylesheet', href='../bower_components/ng-notifications-bar/dist/ngNotificationsBar.min.css')
link(rel='stylesheet', href='../bower_components/ngDialog/css/ngDialog.css')
Expand All @@ -26,8 +27,11 @@ html

// build:css /styles/app.css
//- inject:css
link(rel="stylesheet", href="assets/css/vendors/introjs.css")
link(rel="stylesheet", href="assets/css/vendors/angucomplete.css")
link(rel="stylesheet", href="assets/css/topcoder.css")
link(rel="stylesheet", href="assets/css/submissions/submit-file.css")
link(rel="stylesheet", href="assets/css/submissions/submissions.css")
link(rel="stylesheet", href="assets/css/skill-picker/skill-picker.css")
link(rel="stylesheet", href="assets/css/sitemap/sitemap.css")
link(rel="stylesheet", href="assets/css/settings/update-password.css")
Expand Down Expand Up @@ -124,6 +128,7 @@ html

// build:js /js/vendor.js
//- bower:js
script(src='../bower_components/zepto/zepto.js')
script(src='../bower_components/angular/angular.js')
script(src='../bower_components/a0-angular-storage/dist/angular-storage.js')
script(src='../bower_components/angucomplete-alt/angucomplete-alt.js')
Expand All @@ -143,9 +148,18 @@ html
script(src='../bower_components/angular-animate/angular-animate.js')
script(src='../bower_components/angularjs-toaster/toaster.js')
script(src='../bower_components/appirio-tech-ng-iso-constants/dist/ng-iso-constants.js')
script(src='../bower_components/angular-resource/angular-resource.js')
script(src='../bower_components/moment/moment.js')
script(src='../bower_components/angular-scroll/angular-scroll.js')
script(src='../bower_components/react/react.js')
script(src='../bower_components/react/react-dom.js')
script(src='../bower_components/classnames/index.js')
script(src='../bower_components/react-input-autosize/dist/react-input-autosize.min.js')
script(src='../bower_components/react-select/dist/react-select.min.js')
script(src='../bower_components/ngReact/ngReact.js')
script(src='../bower_components/appirio-tech-ng-ui-components/dist/main.js')
script(src='../bower_components/d3/d3.js')
script(src='../bower_components/jstzdetect/jstz.min.js')
script(src='../bower_components/moment/moment.js')
script(src='../bower_components/ng-busy/build/angular-busy.js')
script(src='../bower_components/ng-notifications-bar/dist/ngNotificationsBar.min.js')
script(src='../bower_components/ngDialog/js/ngDialog.js')
Expand Down Expand Up @@ -212,13 +226,17 @@ html
script(src="directives/slideable.directive.js")
script(src="directives/srm-tile/srm-tile.directive.js")
script(src="directives/tc-endless-paginator/tc-endless-paginator.directive.js")
script(src="directives/tc-file-input/tc-file-input.directive.js")
script(src="directives/tc-input/tc-input.directive.js")
script(src="directives/tc-paginator/tc-paginator.directive.js")
script(src="directives/tc-section/tc-section.directive.js")
script(src="directives/tc-sticky/tc-sticky.directive.js")
script(src="directives/tc-tabs/tc-tabs.directive.js")
script(src="directives/tc-textarea/tc-textarea.directive.js")
script(src="directives/tc-transclude.directive.js")
script(src="directives/track-toggle/track-toggle.directive.js")
script(src="topcoder.module.js")
script(src="filters/add-beginning-space.filter.js")
script(src="filters/challengeLinks.filter.js")
script(src="filters/deadline-msg.filter.js")
script(src="filters/empty.filter.js")
Expand Down Expand Up @@ -291,6 +309,7 @@ html
script(src="services/scorecard.service.js")
script(src="services/srm.service.js")
script(src="services/statistics.service.js")
script(src="services/submissions.service.js")
script(src="services/tags.service.js")
script(src="services/tcAuth.service.js")
script(src="services/user.service.js")
Expand All @@ -309,6 +328,7 @@ html
script(src="submissions/submissions.module.js")
script(src="submissions/submissions.controller.js")
script(src="submissions/submissions.routes.js")
script(src="submissions/submit-file/submit-file.controller.js")
script(src="topcoder.constants.js")
script(src="topcoder.controller.js")
script(src="topcoder.interceptors.js")
Expand Down
7 changes: 7 additions & 0 deletions app/services/api.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@
param: element
};
}

if (url.indexOf('submissions') > -1 && (operation.toLowerCase() === 'put' || operation.toLowerCase() === 'post')) {
return {
param: element
};
}

return element;
})
.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
Expand Down
118 changes: 118 additions & 0 deletions app/services/submissions.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
(function() {
'use strict';

angular.module('tc.services').factory('SubmissionsService', SubmissionsService);

SubmissionsService.$inject = ['CONSTANTS', 'ApiService', '$q', '$log', 'toaster'];

function SubmissionsService(CONSTANTS, ApiService, $q, $log, toaster) {
var api = ApiService.restangularV3;

var service = {
getPresignedURL: getPresignedURL,
uploadSubmissionFileToS3: uploadSubmissionFileToS3,
updateSubmissionStatus: updateSubmissionStatus,
recordCompletedSubmission: recordCompletedSubmission
};

return service;

function getPresignedURL(body, files) {
console.log('Body of request for presigned url: ', body);

return api.all('submissions').customPOST(body)
.then(function(response) {
console.log('POST/Presigned URL Response: ', response.plain());

uploadSubmissionFileToS3(response, response.data.files, files);
})
.catch(function(err) {
console.log(err);
$log.info('Error getting presigned url');
toaster.pop('error', 'Whoops!', 'There was an error uploading your submissions. Please try again later.');
});
}

function uploadSubmissionFileToS3(presignedURLResponse, files) {
var filesWithPresignedURL = presignedURLResponse.data.files;

var promises = filesWithPresignedURL.map(function(fileWithPresignedURL) {
var deferred = $q.defer();
var xhr = new XMLHttpRequest();

xhr.open('PUT', fileWithPresignedURL.preSignedUploadUrl, true);
xhr.setRequestHeader('Content-Type', fileWithPresignedURL.mediaType);

// xhr version of the success callback
xhr.onreadystatechange = function() {
var status = xhr.status;
if (((status >= 200 && status < 300) || status === 304) && xhr.readyState === 4) {
$log.info('Successfully uploaded file');
console.log('xhr response: ', xhr.responseText);

// updateSubmissionStatus and then resolve?
deferred.resolve();

} else if (status >= 400) {
$log.error('Error uploading to S3 with status: ' + status);
toaster.pop('error', 'Whoops!', 'There was an error uploading your files. Please try again later.');
deferred.reject(err);
}
};

xhr.onerror = function(err) {
$log.info('Error uploading to s3');
toaster.pop('error', 'Whoops!', 'There was an error uploading your files. Please try again later.');
deferred.reject(err);
}

xhr.send(files[fileWithPresignedURL.type]);

return deferred.promise;
});

return $q.all(promises)
.then(function(response) {
console.log('response from S3: ', response);
console.log('response to use .save restnagular with: ', presignedURLResponse);

// Update and start processing
updateSubmissionStatus(presignedURLResponse.plain());

})
.catch(function(err) {
console.log('error uploading to S3: ', err);
});
}

function updateSubmissionStatus(body) {
// Pass data from upload to S3
body.data.files.forEach(function(file) {
file.status = 'UPLOADED';
});

return api.one('submissions', body.id).customPUT(body)
.then(function(response) {
$log.info('Successfully updated file statuses');
recordCompletedSubmission(response.plain());
})
.catch(function(err) {
$log.info('Error updating file statuses');
$log.error(err);
});
}

function recordCompletedSubmission(body) {
// Once all uploaded, make record and begin processing
return api.one('submissions', body.id).customPOST(body, 'process')
.then(function(response) {
$log.info('Successfully made file record. Beginning processing');
console.log('response from process call: ', response);
})
.catch(function(err) {
$log.info('Error in starting processing');
$log.error(err);
});
}
};
})();
Loading