...
 
Commits (2)
......@@ -280,7 +280,7 @@ import { HorizontalInfiniteScroll } from "./components/infinite-scroll/horizonta
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [Session, Client, Upload]
deps: [Session, Client, Upload, HttpClient ]
},
{
provide: UpdateMarkersService,
......
......@@ -32,11 +32,7 @@ import { map } from "rxjs/operators";
},
templateUrl: 'comment.component.html',
providers: [
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [Session, Client, Upload]
},
AttachmentService,
{
provide: CommentsListComponent,
useValue: forwardRef(() => CommentsListComponent),
......
......@@ -74,12 +74,12 @@
</div>
<!-- Attachment preview -->
<div class="post-preview" *ngIf="attachment.hasFile() || attachment.getUploadProgress() > 0" (click)="removeAttachment(file)">
<div class="post-preview" *ngIf="attachment.hasFile() || (attachment.progress | async) > 0" (click)="removeAttachment(file)">
<div class="mdl-progress mdl-js-progress"
[mdlUpload]
[progress]="attachment.getUploadProgress()"
[hidden]="attachment.getUploadProgress() == 0"
[ngClass]="{ 'complete': attachment.getUploadProgress() == 100 }"
[progress]="attachment.progress | async"
[hidden]="(attachment.progress | async) == 0"
[ngClass]="{ 'complete': (attachment.progress | async) == 100 }"
></div>
<div *ngIf="attachment.getMime() == 'video'" class="attachment-preview video-placeholder mdl-color--blue-grey-600">
<i class="material-icons">videocam</i>
......
......@@ -20,13 +20,7 @@ import { SocketsService } from '../../../services/sockets';
@Component({
selector: 'm-comment__poster',
templateUrl: 'poster.component.html',
providers: [
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [Session, Client, Upload]
}
],
providers: [ AttachmentService ],
changeDetection: ChangeDetectionStrategy.OnPush
})
......
......@@ -27,11 +27,7 @@ import { CommentsService } from '../comments.service';
selector: 'm-comments__tree',
templateUrl: 'tree.component.html',
providers: [
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [Session, Client, Upload]
},
AttachmentService,
{
provide: CommentsService,
useFactory: (_route, _client) => { return new CommentsService(_route, _client); },
......
......@@ -111,15 +111,15 @@
<!-- Attachment preview -->
<div
class="post-preview" *ngIf="attachment.hasFile() || attachment.getUploadProgress() > 0"
class="post-preview" *ngIf="attachment.hasFile() || (attachment.progress | async) > 0"
(click)="removeAttachment(file)"
>
<div
class="mdl-progress mdl-js-progress"
[mdlUpload]
[progress]="attachment.getUploadProgress()"
[hidden]="attachment.getUploadProgress() == 0"
[ngClass]="{ 'complete': attachment.getUploadProgress() == 100 }"
[progress]="attachment.progress | async"
[hidden]="(attachment.progress | async) == 0"
[ngClass]="{ 'complete': (attachment.progress | async) == 100 }"
></div>
<div *ngIf="attachment.getMime() == 'video'" class="attachment-preview video-placeholder mdl-color--blue-grey-600">
<i class="material-icons" *ngIf="!attachment.isPendingDelete()">videocam</i>
......
......@@ -26,6 +26,7 @@ import {TopbarHashtagsService} from "../../hashtags/service/topbar.service";
import {topbarHashtagsServiceMock} from "../../../mocks/modules/hashtags/service/topbar.service.mock";
import { InMemoryStorageService } from "../../../services/in-memory-storage.service";
import { inMemoryStorageServiceMock } from "../../../../tests/in-memory-storage-service-mock.spec";
import { HttpClientTestingModule } from '@angular/common/http/testing';
@Component({
selector: 'minds-third-party-networks-selector',
......@@ -89,6 +90,7 @@ describe('PosterComponent', () => {
FormsModule,
ReactiveFormsModule,
TextInputAutocompleteModule,
HttpClientTestingModule,
],
providers: [
{ provide: Session, useValue: sessionMock },
......
......@@ -17,13 +17,7 @@ import { InMemoryStorageService } from "../../../services/in-memory-storage.serv
selector: 'minds-newsfeed-poster',
inputs: ['_container_guid: containerGuid', 'accessId', 'message'],
outputs: ['load'],
providers: [
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [Session, Client, Upload]
}
],
providers: [ AttachmentService ],
templateUrl: 'poster.component.html',
})
......
import { AttachmentService } from './attachment';
import { HttpClient } from "@angular/common/http";
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Inject } from '@angular/core';
import { Client, Upload } from './api';
import { Session } from './session';
......@@ -13,20 +16,25 @@ import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core
describe('Service: Attachment Service', () => {
let service: AttachmentService;
let mockObject;
let httpMock;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AttachmentService ],
imports: [
HttpClientTestingModule,
],
//declarations: [ AttachmentService ],
providers: [
{ provide: Session, useValue: sessionMock },
{ provide: Upload, useValue: uploadMock },
{ provide: Client, useValue: clientMock }
{ provide: Client, useValue: clientMock },
]
});
clientMock.response = {};
clientMock.response[`/api/v1/newsfeed/preview`] = { 'status': 'success' };
service = new AttachmentService(sessionMock, clientMock, uploadMock);
httpMock = TestBed.get(HttpTestingController);
service = new AttachmentService(sessionMock, clientMock, uploadMock, httpMock);
clientMock.get.calls.reset();
clientMock.post.calls.reset();
......
import { Inject } from '@angular/core';
import { Inject, Injectable } from '@angular/core';
import {
HttpClient,
HttpHeaders,
HttpRequest,
HttpEvent,
HttpEventType,
} from "@angular/common/http";
import { BehaviorSubject } from 'rxjs';
import { map, tap, last } from 'rxjs/operators';
import { Client, Upload } from './api';
import { Session } from './session';
@Injectable()
export class AttachmentService {
private meta: any = {};
private attachment: any = {};
public progress: BehaviorSubject<number> = new BehaviorSubject(0);
private container: any = {};
private accessId: any = 2;
......@@ -16,11 +29,16 @@ export class AttachmentService {
private xhr: XMLHttpRequest = null;
static _(session: Session, client: Client, upload: Upload) {
return new AttachmentService(session, client, upload);
static _(session: Session, client: Client, upload: Upload, http: HttpClient) {
return new AttachmentService(session, client, upload, http);
}
constructor(@Inject(Session) public session: Session, @Inject(Client) public clientService: Client, @Inject(Upload) public uploadService: Upload) {
constructor(
public session: Session,
public clientService: Client,
public uploadService: Upload,
private http: HttpClient,
) {
this.reset();
}
......@@ -114,9 +132,10 @@ export class AttachmentService {
this.meta.nsfw = nsfw.map(reason => reason.value);
}
upload(fileInput: HTMLInputElement, detectChangesFn?: Function) {
async upload(fileInput: HTMLInputElement, detectChangesFn?: Function) {
this.reset();
this.progress.next(0);
this.attachment.progress = 0;
this.attachment.mime = '';
......@@ -131,34 +150,86 @@ export class AttachmentService {
}
this.xhr = new XMLHttpRequest();
return this.checkFileType(file)
.then(() => {
// Set the mimetype of the attachment (this.attachment.mime)
await this.checkFileType(file);
try {
if (this.attachment.mime === 'video') {
let response = await <any>this.uploadToS3(file);
this.meta.attachment_guid = response.guid ? response.guid : null;
} else {
// Upload and return the GUID
return this.uploadService.post('api/v1/media', [file], this.meta, (progress) => {
let response = await <any>this.uploadService.post('api/v1/media', [file], this.meta, (progress) => {
this.attachment.progress = progress;
this.progress.next(progress);
if (detectChangesFn) {
detectChangesFn();
}
}, this.xhr);
})
.then((response: any) => {
this.meta.attachment_guid = response.guid ? response.guid : null;
}
if (!this.meta.attachment_guid) {
throw 'No GUID';
}
if (!this.meta.attachment_guid) {
throw 'No GUID';
}
return Promise.resolve(this.meta.attachment_guid);
})
.catch(e => {
this.meta.attachment_guid = null;
this.attachment.progress = 0;
this.attachment.preview = null;
return this.meta.attachment_guid;
} catch(e) {
this.meta.attachment_guid = null;
this.attachment.progress = 0;
this.progress.next(0);
this.attachment.preview = null;
return Promise.reject(e);
}
}
async uploadToS3(file) {
// Prepare the upload
let { lease } = await <any>this.clientService.put(`api/v2/media/upload/prepare/${this.attachment.mime}`);
return Promise.reject(e);
const headers = new HttpHeaders({
'Content-Type': file.type,
});
const req = new HttpRequest(
'PUT',
lease.presigned_url,
file,
{
headers: headers,
reportProgress: true, //This is required for track upload process
});
// Upload directly to S3
const response = this.http.request(req);
// Track upload progress && wait for completion
await response.pipe(
map((event: HttpEvent<any>, file) => {
switch (event.type) {
case HttpEventType.Sent:
return 0;
case HttpEventType.UploadProgress:
return Math.round(100 * event.loaded / event.total);
case HttpEventType.Response:
return 100;
default:
return -1;
}
}),
tap(pct => {
if (pct >= 0)
this.progress.next(pct);
}),
last(),
).toPromise();
// Complete the upload
await this.clientService.put(`api/v2/media/upload/complete/${lease.media_type}/${lease.guid}`);
return lease;
}
abort() {
......@@ -166,6 +237,7 @@ export class AttachmentService {
this.xhr.abort();
this.xhr = null;
this.progress.next(0);
this.attachment.progress = 0;
this.attachment.mime = '';
this.attachment.preview = null;
......@@ -173,6 +245,7 @@ export class AttachmentService {
}
remove(fileInput: HTMLInputElement) {
this.progress.next(0);
this.attachment.progress = 0;
this.attachment.mime = '';
this.attachment.preview = null;
......@@ -233,6 +306,7 @@ export class AttachmentService {
}
reset() {
this.progress.next(0);
this.attachment = {
preview: null,
progress: 0,
......
......@@ -126,7 +126,7 @@ export const MINDS_PROVIDERS : any[] = [
{
provide: AttachmentService,
useFactory: AttachmentService._,
deps: [ Session, Client, Upload ]
deps: [ Session, Client, Upload, HttpClient ]
},
{
provide: Sidebar,
......