Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions .angular-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"styles.css",
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/froala-editor/css/froala_editor.pkgd.min.css",
"../node_modules/cropperjs/dist/cropper.css",
"../node_modules/cropperjs/dist/cropper.js",
"lighthouse.theme.scss"
],
"scripts": [
Expand Down
18 changes: 14 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
"@angular/router": "^5.0.0",
"angular2-froala-wysiwyg": "^2.6.0",
"core-js": "^2.5.1",
"cropperjs": "^1.1.3",
"file-type": "^7.2.0",
"hammerjs": "^2.0.8",
"rxjs": "^5.5.1",
"zone.js": "^0.8.18"
Expand Down
4 changes: 4 additions & 0 deletions src/app/_models/Image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class Image {
src: any;
aspectRatio: number;
}
9 changes: 5 additions & 4 deletions src/app/_services/author.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/forkJoin';
import 'rxjs/add/observable/zip';

import { AuthenticationService } from '../_services/authentication.service';
import { Article } from '../_models/Article';
Expand Down Expand Up @@ -50,12 +50,13 @@ export class AuthorService {
}

if (profilePicture) {
return Observable.forkJoin(
return Observable.zip(
this.http.put<any>(this.authorUrl + username, body),
this.http.post<any>(this.authorUrl + username, profilePicture)
this.http.post<any>(this.authorUrl + username, profilePicture),
(r1, r2) => r2
);
} else {
return Observable.forkJoin(
return Observable.zip(
this.http.put<any>(this.authorUrl + username, body)
);
}
Expand Down
53 changes: 34 additions & 19 deletions src/app/article-portal/editor/editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export class EditorComponent implements OnInit {
const src = $img.attr('src');
this.imagesService.deleteImage(src)
.subscribe(result => {

})
}
},
Expand Down Expand Up @@ -134,35 +133,42 @@ export class EditorComponent implements OnInit {
const coverPhoto = formValue['coverPhoto'];
const tags = Array.from(this.selectedTags);

if (coverPhoto.target) {
if (coverPhoto) {
const formData = new FormData();
const file = coverPhoto.target.files[0];
const file = this.getCoverPhoto(coverPhoto);
formData.append('coverPhoto', file);

this.editorService.saveArticle(this.content, articleTitle, articleDescription, tags, formData)
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully saved article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to save this article', 4000);
});
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully saved article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to save this article', 4000);
});
} else {
this.editorService.saveArticle(this.content, articleTitle, articleDescription, tags)
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully saved article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to save this article', 4000);
});
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully saved article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to save this article', 4000);
});
}
}
}

getCoverPhoto(coverPhoto: any) {
if (coverPhoto.target) {
return coverPhoto.target.files[0];
}
return coverPhoto;
}

publishArticle() {
this.editorService.publishArticle()
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully published article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to publish this article', 4000);
});
.subscribe(result => {
this.snackbarMessageService.displayError('Successfully published article', 4000);
}, error => {
this.snackbarMessageService.displayError('There was an error while attempting to publish this article', 4000);
});
}

filterTags(text: string): Observable<string[]> {
Expand Down Expand Up @@ -202,6 +208,7 @@ export class EditorComponent implements OnInit {
}

fileChangeListener($event) {
const image = new Image();
const file = $event.target.files[0];
const myReader = new FileReader();
myReader.onloadend = (loadEvent: any) => {
Expand All @@ -213,10 +220,18 @@ export class EditorComponent implements OnInit {

openPreview() {
const dialogRef = this.dialog.open(ImagePreviewComponent, {
data: this.image
data: {
src: this.image,
aspectRatio: 16 / 9
}
});

dialogRef.afterClosed().subscribe(result => {
if (result) {
this.formGroup.patchValue({
coverPhoto: result
});
}
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,25 @@
<img [src]="image">
<div>
<div *ngIf="showingCroppingTools" class="options-row">
<button mat-icon-button title="Save changes" (click)="save()">
<mat-icon aria-label="Save Changes" [style.color]="'green'">save</mat-icon>
</button>
<button mat-icon-button title="Crop Image" (click)="cropImage()">
<mat-icon aria-label="Crop Image" [style.color]="'green'">done</mat-icon>
</button>
<button mat-icon-button title="Discard Changes" (click)="restore()">
<mat-icon aria-label="Discard Changes" [style.color]="'red'">delete</mat-icon>
</button>
<button mat-icon-button class="end" title="Close" (click)="stop()">
<mat-icon aria-label="Discard Changes">close</mat-icon>
</button>
</div>
<img id="image" [src]="image.src">
<div *ngIf="!showingCroppingTools">
<button mat-icon-button (click)="showCropperTool()" class="right">
<mat-icon aria-label="Show Cropping Tools">crop</mat-icon>
</button>
<button mat-icon-button (click)="saveImage()" class="right">
<mat-icon aria-label="Save Changes">save</mat-icon>
</button>
</div>
</div>
17 changes: 17 additions & 0 deletions src/app/article-portal/image-preview/image-preview.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#image {
max-width: 100%;
}

.right {
float: right;
}

.options-row {
display: flex;
align-items: flex-end;
justify-content: center;
}

.end {
align-self: flex-end;
}
81 changes: 78 additions & 3 deletions src/app/article-portal/image-preview/image-preview.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,94 @@
import { Component, Inject } from '@angular/core';
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import Cropper from 'cropperjs'
import { SnackbarMessagingService } from 'app/_services/snackbar-messaging.service';
import { Image } from 'app/_models/Image';

@Component({
selector: 'app-image-preview',
templateUrl: './image-preview.component.html',
styleUrls: ['./image-preview.component.scss']
})
export class ImagePreviewComponent {
export class ImagePreviewComponent implements OnInit, OnDestroy {

private cropper: Cropper;
private originalImage: any;
private imageBlob: any;
private cropped: boolean;
private croppedCanvas: any;
private aspectRatio: number = 16 / 9;

public showingCroppingTools: boolean;

constructor(
public dialogRef: MatDialogRef<ImagePreviewComponent>,
@Inject(MAT_DIALOG_DATA) public image: any
private snackbarMessagingService: SnackbarMessagingService,
@Inject(MAT_DIALOG_DATA) public image: Image
) {
this.originalImage = image.src;
this.aspectRatio = image.aspectRatio;
this.cropped = false;
}

ngOnInit() {
this.showingCroppingTools = false;
}

ngOnDestroy() {
this.cropper = null;
}

showCropperTool() {
const image = document.getElementById('image');
this.cropper = new Cropper(image, {
aspectRatio: this.aspectRatio
});
this.showingCroppingTools = true;
}

cropImage() {
this.cropped = true;
this.croppedCanvas = this.cropper.getCroppedCanvas();
const imageData = this.croppedCanvas.toDataURL();
this.cropper.replace(imageData);
}

save() {
if (this.cropped) {
const image = document.getElementById('image').getAttribute('src');
const imageData = this.croppedCanvas.toBlob((blob) => {
this.imageBlob = blob;
this.stop();
document.getElementById('image').setAttribute('src', image);
});
} else {
this.snackbarMessagingService.displayError('No changes detected', 2000);
}
}

stop() {
if (this.cropper) {
this.cropper.destroy();
this.cropper = null;
this.showingCroppingTools = false;
}
}

restore() {
this.cropper.replace(this.originalImage);
this.cropped = false;
}

saveImage() {
if (this.cropped) {
this.dialogRef.close(this.imageBlob);
} else {
this.snackbarMessagingService.displayError('No changes detected', 2000);
}
}

onNoClick(): void {
this.stop();
this.dialogRef.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<button mat-mini-fab *ngIf="previewImage()" type="button" (click)="openPreview()" color="primary">
<mat-icon aria-label="Preview profile picture" title="Preview profile picture">picture_in_picture</mat-icon>
</button>
<button mat-raised-button type="submit" [disabled]="!f.valid || !f.dirty || !f.touched" color="accent"> Save Settings </button>
<button mat-raised-button type="submit" [disabled]="!f.valid" color="accent"> Save Settings </button>
</mat-card-actions>
</form>
</mat-card>
Loading