diff --git a/package-lock.json b/package-lock.json
index cd019a5..090ffc3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1865,25 +1865,25 @@
}
},
"@farmmaps/common": {
- "version": "0.0.1-prerelease.530",
- "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common/-/common-0.0.1-prerelease.530.tgz",
- "integrity": "sha512-cvUKFctQvl91gE5zCJvzxhcnZ35XpletqFmxOFwj6qxLr975qs/Ia9VrzwjkqoIoXlsO9xlM/0Cn1PnPsF7nIg==",
+ "version": "0.0.1-prerelease.548",
+ "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common/-/common-0.0.1-prerelease.548.tgz",
+ "integrity": "sha512-gI+5kwpdimDkJUqU51PsyfZ0My5QRrEtwHGpCivd4kHxBZJ053cz6vHFnH1HquxesIXBVmDxjyeYGCrxhXVIOA==",
"requires": {
"tslib": "^2.0.0"
}
},
"@farmmaps/common-map": {
- "version": "0.0.1-prerelease.530",
- "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common-map/-/common-map-0.0.1-prerelease.530.tgz",
- "integrity": "sha512-LU4yzsTvja85GciySpJB5LjUD7fndEsnd2KKj0q9+IFZl9jOFfVcP+/3nImsYYmV9CK6sczNdevaSxQW+lpseQ==",
+ "version": "0.0.1-prerelease.548",
+ "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common-map/-/common-map-0.0.1-prerelease.548.tgz",
+ "integrity": "sha512-rrlYUZvq4r1ANlbinucdasy5iRidOt8DI9V7ra4pKcgZqlsD5hteeosX45DnDlbSvcNzTtY3A0E28e4WXd25jA==",
"requires": {
"tslib": "^2.0.0"
}
},
"@farmmaps/common-map3d": {
- "version": "0.0.1-prerelease.530",
- "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common-map3d/-/common-map3d-0.0.1-prerelease.530.tgz",
- "integrity": "sha512-4OG3yv6vOMJZ5dLZ2e8W9P1F1qvzcYBA/zCIA+kxfS0iiOfrOIiJgDvXPhMot+swATSsWeY4Txh6ydh6KmTzlg==",
+ "version": "0.0.1-prerelease.548",
+ "resolved": "https://repository.akkerweb.nl/repository/npm-group/@farmmaps/common-map3d/-/common-map3d-0.0.1-prerelease.548.tgz",
+ "integrity": "sha512-l3XQMSclt6x0fIjKw4K9j1IAr+L+0alHLd/9p80jfCkhB0qo1jZf/TorA636PSYB9NIBioiXOKMDVqTuPi+s/w==",
"requires": {
"tslib": "^2.0.0"
}
@@ -8604,10 +8604,20 @@
"ts-md5": "^1.2.4"
}
},
- "ngx-bootstrap": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-5.6.2.tgz",
- "integrity": "sha512-6YHXtdXkGH3w0NQoaUgNYAcrj064Lv5RTO284ha/hvpNTrh55yQz2cVh0VvwBk3MjyY2tdmLH4SuCJDszYdYiw=="
+ "ngx-image-cropper": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/ngx-image-cropper/-/ngx-image-cropper-3.3.5.tgz",
+ "integrity": "sha512-0yRVKG5XAbVo3rOaj/iFDlekGsxEqXKU9iXFbjyvHvRT2DFs+AjwtyvINsHCWw+4ed9yA4Y+wLIUNqzA0bfxLw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ }
+ }
},
"ngx-openlayers": {
"version": "1.0.0-next.17",
diff --git a/package.json b/package.json
index eb5cfb9..1ad2d5b 100644
--- a/package.json
+++ b/package.json
@@ -19,9 +19,9 @@
"@angular/platform-browser": "~10.2.4",
"@angular/platform-browser-dynamic": "~10.2.4",
"@angular/router": "~10.2.4",
- "@farmmaps/common": ">=0.0.1-prerelease.530 <0.0.1",
- "@farmmaps/common-map": ">=0.0.1-prerelease.530 <0.0.1",
- "@farmmaps/common-map3d": ">=0.0.1-prerelease.530 <0.0.1",
+ "@farmmaps/common": ">=0.0.1-prerelease.548 <0.0.1",
+ "@farmmaps/common-map": ">=0.0.1-prerelease.548 <0.0.1",
+ "@farmmaps/common-map3d": ">=0.0.1-prerelease.548 <0.0.1",
"@microsoft/signalr": "^3.1.3",
"@ng-bootstrap/ng-bootstrap": "^7.0",
"@ngrx/effects": "^10.0",
@@ -31,8 +31,10 @@
"bootstrap": "^4.4.1",
"cesium": "^1.77.0",
"core-js": "^2.6.11",
+ "moment": "^2.27.0",
"ngrx-store-localstorage": "^10.0",
- "ngx-bootstrap": "^5.6.1",
+ "ngx-avatar": "^4.0.0",
+ "ngx-image-cropper": "^3.3.5",
"ngx-openlayers": "1.0.0-next.17",
"ngx-uploadx": "^3.5.1",
"ol": "6.5.0",
@@ -41,9 +43,7 @@
"rxjs": "^6.5.4",
"tassign": "^1.0.0",
"tslib": "^2.0.0",
- "zone.js": "~0.10.2",
- "moment": "^2.27.0",
- "ngx-avatar": "^4.0.0"
+ "zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-builders/custom-webpack": "~10.0.1",
diff --git a/projects/common-map/src/fm-map/components/selected-item/selected-item.component.html b/projects/common-map/src/fm-map/components/selected-item/selected-item.component.html
index e52559e..025f82f 100644
--- a/projects/common-map/src/fm-map/components/selected-item/selected-item.component.html
+++ b/projects/common-map/src/fm-map/components/selected-item/selected-item.component.html
@@ -1,9 +1,6 @@
-
-
-
-
+
diff --git a/projects/common/package.json b/projects/common/package.json
index a0e9f57..10f7777 100644
--- a/projects/common/package.json
+++ b/projects/common/package.json
@@ -18,6 +18,7 @@
"ngx-uploadx": "^3.3.4",
"angular-oauth2-oidc": "^10.0.3",
"moment": "^2.27.0",
- "ngx-avatar": "^4.0.0"
+ "ngx-avatar": "^4.0.0",
+ "ngx-image-cropper": "^3.3.5"
}
}
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/common.module.ts b/projects/common/src/fm/common.module.ts
index 23baa24..3097b6d 100644
--- a/projects/common/src/fm/common.module.ts
+++ b/projects/common/src/fm/common.module.ts
@@ -60,8 +60,11 @@ import { AppMenuComponent } from './components/app-menu/app-menu.component';
import { NotificationMenuComponent} from './components/notification-menu/notification-menu.component';
import { HelpMenuComponent} from './components/help-menu/help-menu.component';
import { BackButtonComponent } from './components/back-button/back-button.component';
+import { EditImageModalComponent } from './components/edit-image-modal/edit-image-modal.component';
import { AvatarComponent } from './components/avatar/avatar.component';
import { AvatarModule } from 'ngx-avatar';
+import { ImageCropperModule } from 'ngx-image-cropper';
+
export {
SafePipe,
@@ -119,7 +122,8 @@ export {
NgbModule,
FormsModule,
UploadxModule,
- AvatarModule
+ AvatarModule,
+ ImageCropperModule
],
declarations: [
AppComponent,
@@ -143,6 +147,7 @@ export {
HelpMenuComponent,
BackButtonComponent,
ThumbnailComponent,
+ EditImageModalComponent,
AvatarComponent
],
exports: [
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
new file mode 100644
index 0000000..413e5d7
--- /dev/null
+++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+
diff --git a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.scss b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.scss
new file mode 100644
index 0000000..be7e1fd
--- /dev/null
+++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.scss
@@ -0,0 +1,13 @@
+.cropper {
+ position: relative;
+ height: calc(60vh);
+}
+
+.no-image {
+ text-align: center;
+}
+
+.no-image i {
+ font-size: calc(50vh);
+ color: gray;
+}
\ No newline at end of file
diff --git a/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.spec.ts b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.spec.ts
new file mode 100644
index 0000000..7395ec0
--- /dev/null
+++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { EditImageModalComponent } from './edit-image-modal.component';
+
+describe('EditImageModalComponent', () => {
+ let component: EditImageModalComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ EditImageModalComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditImageModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
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
new file mode 100644
index 0000000..3b8e7fb
--- /dev/null
+++ b/projects/common/src/fm/components/edit-image-modal/edit-image-modal.component.ts
@@ -0,0 +1,62 @@
+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',
+ templateUrl: './edit-image-modal.component.html',
+ styleUrls: ['./edit-image-modal.component.scss']
+})
+export class EditImageModalComponent implements OnInit {
+
+ @Output() changed = new EventEmitter();
+ @ViewChild('upload_modal') modal:ElementRef;
+
+ 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' });
+ }
+
+ fileChangeEvent(event: any): void {
+ this.imageChangedEvent = event;
+ }
+ imageCropped(event: ImageCroppedEvent) {
+ this.croppedImage = event.base64;
+ }
+ imageLoaded(image: LoadedImage) {
+ this.isImageLoaded=true;
+ }
+ cropperReady() {
+ // cropper ready
+ }
+ 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,this.modalService.dismissAll("Save");
+ }
+ }
+}
diff --git a/projects/common/src/fm/components/thumbnail/thumbnail.component.html b/projects/common/src/fm/components/thumbnail/thumbnail.component.html
index 16a806e..a5a560a 100644
--- a/projects/common/src/fm/components/thumbnail/thumbnail.component.html
+++ b/projects/common/src/fm/components/thumbnail/thumbnail.component.html
@@ -1,6 +1,9 @@
-
-
-
-
+
+
+
+
+
-
\ No newline at end of file
+
+
+
diff --git a/projects/common/src/fm/components/thumbnail/thumbnail.component.scss b/projects/common/src/fm/components/thumbnail/thumbnail.component.scss
index e69de29..6ce8ec0 100644
--- a/projects/common/src/fm/components/thumbnail/thumbnail.component.scss
+++ b/projects/common/src/fm/components/thumbnail/thumbnail.component.scss
@@ -0,0 +1,28 @@
+.thumbnail {
+ width: 100%;
+ position: relative;
+ padding-top: 75%;
+}
+
+.content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ text-align: center;
+}
+
+.large-icon i {
+ color: white;
+}
+
+.edit {
+ position: absolute;
+ bottom: 1rem;
+ right: 1rem;
+ width: 2.5rem;
+ height: 2.5rem;
+ padding: 0;
+ line-height: 2.5rem;
+}
\ No newline at end of file
diff --git a/projects/common/src/fm/components/thumbnail/thumbnail.component.ts b/projects/common/src/fm/components/thumbnail/thumbnail.component.ts
index 9163846..075be8e 100644
--- a/projects/common/src/fm/components/thumbnail/thumbnail.component.ts
+++ b/projects/common/src/fm/components/thumbnail/thumbnail.component.ts
@@ -1,7 +1,10 @@
-import { Component,Input } from '@angular/core';
+import { Component,Input ,ViewChild,ElementRef,ChangeDetectorRef} from '@angular/core';
import { Store } from '@ngrx/store';
-import { IItem } from '../../models/item';
+
+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',
@@ -11,12 +14,48 @@ import { commonReducers,ItemTypeService } from '../../../public-api'
export class ThumbnailComponent {
- @Input() public item: IItem;
+ @Input() public item: IListItem;
+ @Input() public edit: boolean = false;
+ @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,private changeDetector:ChangeDetectorRef) {
}
- getThumbnailUrl(item:IItem):string {
- return item.url+'/thumbnail?v=' + Date.parse(item.updated);
- }
+ getThumbnailUrl(item:IListItem):string {
+ return this.appConfig.getConfig("apiEndPoint")+item.url+'/thumbnail?v=' + Date.parse(item.updated);
+ }
+
+ getFontSize():string {
+ if(this.el) {
+ var h = this.el.nativeElement.offsetHeight - (this.el.nativeElement.offsetHeight / 5 )
+ return h + "px";
+ } else {
+ return "1em";
+ }
+ }
+
+ getLineHeight():string {
+ if(this.el) {
+ return this.el.nativeElement.offsetHeight + "px";
+ } else {
+ return "1em";
+ }
+ }
+
+ canEdit():boolean {
+ return this.edit && this.item != null;
+ }
+
+ onEditClick() {
+ var endpoint = `${this.appConfig.getConfig("apiEndPoint")}/api/v1/items/${this.item.code}/thumbnail`;
+ this.modal.open(endpoint,4/3);
+ }
+
+ onChanged() {
+ if(this.item) {
+ this.item.updated = new Date(new Date().getTime()).toISOString();
+ this.changeDetector.detectChanges();
+ }
+ }
}
\ No newline at end of file
diff --git a/projects/common/src/fm/components/user-menu/user-menu.component.scss b/projects/common/src/fm/components/user-menu/user-menu.component.scss
index 481addf..0b0f03c 100644
--- a/projects/common/src/fm/components/user-menu/user-menu.component.scss
+++ b/projects/common/src/fm/components/user-menu/user-menu.component.scss
@@ -1,5 +1,4 @@
.menu-button {
- background-color: purple;
display: inline-block;
width: 2.5em;
height: 2.5em;
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