feat(profile): Profile picture cropping, mobile uploading and progress bar (#1443)

* Add ng-file-upload and picture cropping

* Update bower.json

Remove bower dependency for angular-file-upload
This commit is contained in:
hyperreality
2016-08-26 07:56:56 +01:00
committed by Liran Tal
parent 25bd40c3f7
commit 246c5d953c
6 changed files with 54 additions and 67 deletions

View File

@@ -7,12 +7,13 @@
"angular": "~1.5.0",
"angular-animate": "~1.5.0",
"angular-bootstrap": "~1.2.1",
"angular-file-upload": "~2.2.0",
"angular-messages": "~1.5.0",
"angular-mocks": "~1.5.0",
"angular-resource": "~1.5.0",
"angular-ui-router": "~0.2.18",
"bootstrap": "~3.3.6",
"ng-file-upload": "^12.1.0",
"ng-img-crop": "ngImgCrop#^0.3.2",
"owasp-password-strength-test": "~1.3.0"
},
"overrides": {

View File

@@ -9,6 +9,7 @@ module.exports = {
// bower:css
'public/lib/bootstrap/dist/css/bootstrap.css',
'public/lib/bootstrap/dist/css/bootstrap-theme.css',
'public/lib/ng-img-crop/compile/unminified/ng-img-crop.css'
// endbower
],
js: [
@@ -16,7 +17,8 @@ module.exports = {
'public/lib/angular/angular.js',
'public/lib/angular-animate/angular-animate.js',
'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
'public/lib/angular-file-upload/dist/angular-file-upload.min.js',
'public/lib/ng-file-upload/ng-file-upload.js',
'public/lib/ng-img-crop/compile/unminified/ng-img-crop.js',
'public/lib/angular-messages/angular-messages.js',
'public/lib/angular-mocks/angular-mocks.js',
'public/lib/angular-resource/angular-resource.js',

View File

@@ -5,7 +5,7 @@
var service = {
applicationModuleName: applicationModuleName,
applicationModuleVendorDependencies: ['ngResource', 'ngAnimate', 'ngMessages', 'ui.router', 'ui.bootstrap', 'angularFileUpload'],
applicationModuleVendorDependencies: ['ngResource', 'ngAnimate', 'ngMessages', 'ui.router', 'ui.bootstrap', 'ngFileUpload', 'ngImgCrop'],
registerModule: registerModule
};

View File

@@ -5,82 +5,52 @@
.module('users')
.controller('ChangeProfilePictureController', ChangeProfilePictureController);
ChangeProfilePictureController.$inject = ['$scope', '$timeout', '$window', 'Authentication', 'FileUploader'];
ChangeProfilePictureController.$inject = ['$timeout', 'Authentication', 'Upload'];
function ChangeProfilePictureController($scope, $timeout, $window, Authentication, FileUploader) {
function ChangeProfilePictureController($timeout, Authentication, Upload) {
var vm = this;
vm.user = Authentication.user;
vm.imageURL = vm.user.profileImageURL;
vm.uploadProfilePicture = uploadProfilePicture;
vm.fileSelected = false;
vm.cancelUpload = cancelUpload;
// Create file uploader instance
vm.uploader = new FileUploader({
url: 'api/users/picture',
alias: 'newProfilePicture',
onAfterAddingFile: onAfterAddingFile,
onSuccessItem: onSuccessItem,
onErrorItem: onErrorItem
});
vm.upload = function (dataUrl, name) {
vm.success = vm.error = null;
// Set file uploader image filter
vm.uploader.filters.push({
name: 'imageFilter',
fn: function (item, options) {
var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|';
return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1;
}
});
// Called after the user selected a new picture file
function onAfterAddingFile(fileItem) {
if ($window.FileReader) {
var fileReader = new FileReader();
fileReader.readAsDataURL(fileItem._file);
fileReader.onload = function (fileReaderEvent) {
$timeout(function () {
vm.imageURL = fileReaderEvent.target.result;
}, 0);
};
}
}
Upload.upload({
url: 'api/users/picture',
data: {
newProfilePicture: Upload.dataUrltoBlob(dataUrl, name)
}
}).then(function (response) {
$timeout(function () {
onSuccessItem(response.data);
});
}, function (response) {
if (response.status > 0) onErrorItem(response.data);
}, function (evt) {
vm.progress = parseInt(100.0 * evt.loaded / evt.total, 10);
});
};
// Called after the user has successfully uploaded a new picture
function onSuccessItem(fileItem, response, status, headers) {
function onSuccessItem(response) {
// Show success message
vm.success = true;
// Populate user object
vm.user = Authentication.user = response;
// Clear upload buttons
cancelUpload();
// Reset form
vm.fileSelected = false;
vm.progress = 0;
}
// Called after the user has failed to uploaded a new picture
function onErrorItem(fileItem, response, status, headers) {
// Clear upload buttons
cancelUpload();
function onErrorItem(response) {
vm.fileSelected = false;
// Show error message
vm.error = response.message;
}
// Change user profile picture
function uploadProfilePicture() {
// Clear messages
vm.success = vm.error = null;
// Start upload
vm.uploader.uploadAll();
}
// Cancel the upload process
function cancelUpload() {
vm.uploader.clearQueue();
vm.imageURL = vm.user.profileImageURL;
}
}
}());

View File

@@ -34,3 +34,8 @@
min-height: 150px;
max-height: 150px;
}
.cropArea {
background: #E4E4E4;
width: 300px;
height: 300px;
}

View File

@@ -2,17 +2,26 @@
<div class="col-xs-offset-1 col-xs-10 col-md-offset-3 col-md-4">
<form class="signin form-horizontal">
<fieldset>
<div ng-show="vm.fileSelected" class="text-center form-group">
<p>Crop your picture then press upload below:</p>
<div ngf-drop ng-model="picFile" ngf-pattern="image/*" class="cropArea">
<img-crop image="picFile | ngfDataUrl" result-image="croppedDataUrl" ng-init="croppedDataUrl=''"></img-crop>
</div>
</div>
<div class="form-group text-center">
<img ng-src="{{vm.imageURL}}" alt="{{vm.user.displayName}}" class="img-thumbnail user-profile-picture">
<img ng-src="{{vm.fileSelected ? croppedDataUrl : vm.user.profileImageURL}}" alt="{{vm.user.displayName}}" class="img-thumbnail user-profile-picture" ngf-drop>
</div>
<div class="text-center form-group" ng-hide="vm.uploader.queue.length">
<span class="btn btn-default btn-file">
Select Image <input type="file" nv-file-select uploader="vm.uploader">
</span>
<div ng-show="!vm.fileSelected" class="text-center form-group">
<button class="btn btn-default btn-file" ngf-select="vm.fileSelected = true; vm.success = null" ng-model="picFile" accept="image/*">Select Picture</button>
</div>
<div class="text-center form-group" ng-show="vm.uploader.queue.length">
<button class="btn btn-primary" ng-click="vm.uploadProfilePicture();">Upload</button>
<button class="btn btn-default" ng-click="vm.cancelUpload();">Cancel</button>
<div ng-show="vm.fileSelected" class="text-center form-group">
<button class="btn btn-primary" ng-click="vm.upload(croppedDataUrl, picFile.name)">Upload</button>
<button class="btn btn-default" ng-click="vm.fileSelected = false">Cancel</button>
</div>
<div ng-show="vm.fileSelected" class="progress text-center">
<div class="progress-bar" role="progressbar" aria-valuenow="{{vm.progress}}" aria-valuemin="0" aria-valuemax="100" style="width:{{vm.progress}}%" ng-bind="vm.progress + '%'">
<span class="sr-only">{{vm.progress}}% Complete</span>
</div>
</div>
<div ng-show="vm.success" class="text-center text-success">
<strong>Profile Picture Changed Successfully</strong>