From 2f1c5210ea8a44421da7add4d6d511ac8573cfae Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Mon, 1 Mar 2021 22:03:18 +0100 Subject: [PATCH] Save image --- .../common/src/fm/common-service.module.ts | 2 + .../edit-image-modal.component.html | 5 ++- .../edit-image-modal.component.ts | 32 +++++++++++--- .../thumbnail/thumbnail.component.html | 2 +- .../thumbnail/thumbnail.component.ts | 12 +++-- .../common/src/fm/services/image.service.ts | 44 +++++++++++++++++++ src/configuration.json | 4 +- 7 files changed, 86 insertions(+), 15 deletions(-) create mode 100644 projects/common/src/fm/services/image.service.ts diff --git a/projects/common/src/fm/common-service.module.ts b/projects/common/src/fm/common-service.module.ts index a5e6ebd..8e8bddf 100644 --- a/projects/common/src/fm/common-service.module.ts +++ b/projects/common/src/fm/common-service.module.ts @@ -16,6 +16,7 @@ import { ItemService } from './services/item.service'; import { EventService } from './services/event.service'; import { TypeaheadService } from './services/typeahead.service'; import { UserService } from './services/user.service'; +import { ImageService } from './services/image.service'; import { WeatherService} from './services/weather.service'; import { AppConfig } from './shared/app.config'; import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor"; @@ -42,6 +43,7 @@ export { EventService, TypeaheadService, UserService, + ImageService, WeatherService, AppConfig, AccessTokenInterceptor, diff --git a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.html b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.html index 4e8be55..413e5d7 100644 --- a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.html +++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.html @@ -16,18 +16,19 @@ [maintainAspectRatio]="true" format="jpeg" [aspectRatio]="aspectRatio" - [autoCrop]="false" + [autoCrop]="true" (imageCropped)="imageCropped($event)" (imageLoaded)="imageLoaded($event)" (cropperReady)="cropperReady()" (loadImageFailed)="loadImageFailed()" + [imageURL]="imageUrl" > Select image diff --git a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.ts b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.ts index 8591dde..4f9c44c 100644 --- a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.ts +++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.ts @@ -1,6 +1,8 @@ -import { Component, OnInit,ViewChild,ElementRef } from '@angular/core'; +import { Component, OnInit,ViewChild,ElementRef,EventEmitter, Output } from '@angular/core'; +import { HttpClient, HttpParams,HttpHeaders } from "@angular/common/http"; import {NgbModal} from "@ng-bootstrap/ng-bootstrap" import { ImageCroppedEvent,LoadedImage } from 'ngx-image-cropper'; +import {ImageService } from '../../services/image.service'; @Component({ selector: 'fm-edit-image-modal', @@ -9,23 +11,28 @@ import { ImageCroppedEvent,LoadedImage } from 'ngx-image-cropper'; }) export class EditImageModalComponent implements OnInit { + @Output() changed = new EventEmitter(); @ViewChild('upload_modal') modal:ElementRef; - constructor(private modalService: NgbModal) { } + constructor(private modalService: NgbModal,public imageService:ImageService) { } + + isImageLoaded:boolean = false; + aspectRatio:number = 4/3; + imageChangedEvent: any = ''; + croppedImage: string = ''; + endpointUrl:string = null; + imageUrl:string = null; ngOnInit(): void { } open(endpoint:string,aspectRatio:number) { + this.endpointUrl = endpoint; + this.imageUrl = endpoint; this.aspectRatio= aspectRatio; this.modalService.open(this.modal,{ size: 'lg' }); } - isImageLoaded:boolean = false; - aspectRatio:number = 4/3; - imageChangedEvent: any = ''; - croppedImage: any = ''; - fileChangeEvent(event: any): void { this.imageChangedEvent = event; } @@ -41,4 +48,15 @@ export class EditImageModalComponent implements OnInit { loadImageFailed() { // show message } + + save() { + if(this.croppedImage) { + + var body = this.croppedImage.substr(23); + this.imageService.putImage(this.endpointUrl,this.imageService.b64toBlob(body,"image/jpeg")).subscribe(() => { + this.changed.emit({}); + }); + (this.modal as any).close('Save click'); + } + } } diff --git a/projects/common/src/fm/components/thumbnail/thumbnail.component.html b/projects/common/src/fm/components/thumbnail/thumbnail.component.html index 466182e..a5a560a 100644 --- a/projects/common/src/fm/components/thumbnail/thumbnail.component.html +++ b/projects/common/src/fm/components/thumbnail/thumbnail.component.html @@ -6,4 +6,4 @@ - + diff --git a/projects/common/src/fm/components/thumbnail/thumbnail.component.ts b/projects/common/src/fm/components/thumbnail/thumbnail.component.ts index bf80e2a..4caa5cc 100644 --- a/projects/common/src/fm/components/thumbnail/thumbnail.component.ts +++ b/projects/common/src/fm/components/thumbnail/thumbnail.component.ts @@ -4,6 +4,7 @@ import { Store } from '@ngrx/store'; import { IListItem } from '../../models/list.item'; import { commonReducers,ItemTypeService } from '../../../public-api' import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.component'; +import { AppConfig } from "../../shared/app.config"; @Component({ selector: 'fm-thumbnail', @@ -18,11 +19,11 @@ import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.com @ViewChild('thumbnail') el:ElementRef; @ViewChild('modal') modal:EditImageModalComponent; - constructor(public store: Store, public itemTypeService: ItemTypeService) { + constructor(public store: Store, public itemTypeService: ItemTypeService,public appConfig: AppConfig,) { } getThumbnailUrl(item:IListItem):string { - return item.url+'/thumbnail?v=' + Date.parse(item.updated); + return this.appConfig.getConfig("apiEndPoint")+item.url+'/thumbnail?v=' + Date.parse(item.updated); } getFontSize():string { @@ -47,6 +48,11 @@ import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.com } onEditClick() { - this.modal.open(this.item.url+"/thumbnail",4/3); + var endpoint = `${this.appConfig.getConfig("apiEndPoint")}/api/v1/items/${this.item.code}/thumbnail`; + this.modal.open(endpoint,4/3); + } + + onChanged() { + console.log("changed"); } } \ No newline at end of file diff --git a/projects/common/src/fm/services/image.service.ts b/projects/common/src/fm/services/image.service.ts new file mode 100644 index 0000000..24b7a96 --- /dev/null +++ b/projects/common/src/fm/services/image.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { IUser } from '../models/user'; +import { HttpClient,HttpHeaders } from "@angular/common/http"; +import { AppConfig } from "../shared/app.config"; + +@Injectable({ + providedIn: 'root', +}) +export class ImageService { + constructor(public httpClient: HttpClient, public appConfig: AppConfig) { + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); + } + + putImage(endpoint:string,blob:Blob) { + const formData = new FormData(); + formData.append('file', blob,blob.type); + return this.httpClient.put(endpoint,formData); + } + + b64toBlob(b64Data:string, contentType?:string):Blob { + const sliceSize = 512; + const byteCharacters = atob(b64Data); + const byteArrays = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize); + + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + + const blob = new Blob(byteArrays, {type: contentType}); + return blob; + } +} diff --git a/src/configuration.json b/src/configuration.json index 61c0dff..c38ec06 100644 --- a/src/configuration.json +++ b/src/configuration.json @@ -1,9 +1,9 @@ { "issuer": "https://accounts.test.farmmaps.eu", "clientId": "farmmapsdev", - "audience": "https://test.farmmaps.eu", + "audience": "http://localhost:8082", "requireHttps": true, - "apiEndPoint": "https://test.farmmaps.eu", + "apiEndPoint": "http://localhost:8082", "grantType":"code" } \ No newline at end of file