20 Commits

Author SHA1 Message Date
Willem Dantuma
b5d00f5619 Merge branch 'develop'
All checks were successful
FarmMaps/FarmMapsLib/pipeline/head This commit looks good
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-25 08:19:12 +02:00
Willem Dantuma
89a0fb13a5 AW-2757
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-19 15:25:22 +02:00
Willem Dantuma
2861ba220e Revert "Help menu invisible in release sep 2021."
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
This reverts commit a454f2306d.
2021-08-18 14:37:41 +02:00
Willem Dantuma
45e0d5e836 Revert "Hide help menu"
This reverts commit 4c1d4137ea.
2021-08-18 14:37:31 +02:00
Willem Dantuma
312611cdc1 Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop 2021-08-18 14:34:53 +02:00
Willem Dantuma
54b8a3bf24 AW-1855 2021-08-18 14:34:45 +02:00
4c1d4137ea Hide help menu
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-18 14:31:28 +02:00
a454f2306d Help menu invisible in release sep 2021.
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-18 14:21:02 +02:00
Willem Dantuma
52a72b042c Fix build
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-17 19:41:20 +02:00
Willem Dantuma
c0c9864b07 AW-2714
Some checks failed
FarmMaps.Develop/FarmMapsLib/pipeline/head There was a failure building this commit
2021-08-17 19:36:30 +02:00
Willem Dantuma
e0f36b043f Oops
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-12 21:40:40 +02:00
Willem Dantuma
b52bfd4f57 Fix icon
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-12 21:02:55 +02:00
Willem Dantuma
6ff3c0ec96 Fix device geometry update
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-12 17:13:40 +02:00
Willem Dantuma
eb1157d608 Fix thumbnail editing, add blobtodataurl method
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-05 16:33:31 +02:00
Willem Dantuma
1daa8e257f make Observable
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-04 16:12:22 +02:00
Willem Dantuma
5db24cc63d Add geolocator service
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-04 16:01:41 +02:00
ff018d9db1 Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2021-08-04 12:05:09 +02:00
8c49965df8 Fix optional has package check/ 2021-08-04 12:05:02 +02:00
9c19595597 Revert "Patch lib"
Some checks failed
FarmMaps/FarmMapsLib/pipeline/head There was a failure building this commit
This reverts commit ea1b22ed41.
2021-06-23 13:52:52 +02:00
ea1b22ed41 Patch lib
All checks were successful
FarmMaps/FarmMapsLib/pipeline/head This commit looks good
2021-06-23 13:18:46 +02:00
18 changed files with 149 additions and 57 deletions

View File

@@ -6,12 +6,14 @@ import { ILayervalue } from '../models/layer.value';
import { IQueryState } from '@farmmaps/common'; import { IQueryState } from '@farmmaps/common';
import { IItem } from '@farmmaps/common'; import { IItem } from '@farmmaps/common';
import { Feature,Style } from 'ol'; import { Feature,Style } from 'ol';
import { IPeriodState } from '../models/period.state';
export const SETSTATE = '[Map] SetState'; export const SETSTATE = '[Map] SetState';
export const SETMAPSTATE = '[Map] MapState'; export const SETMAPSTATE = '[Map] MapState';
export const SETVIEWEXTENT = '[Map] SetViewExtent'; export const SETVIEWEXTENT = '[Map] SetViewExtent';
export const INIT = '[Map] Init'; export const INIT = '[Map] Init';
export const SETPARENT = '[Map] SetParent'; export const SETPARENT = '[Map] SetParent';
export const SETPERIOD = '[Map] SetPeriod';
export const STARTSEARCH = '[Map] StartSearch'; export const STARTSEARCH = '[Map] StartSearch';
export const STARTSEARCHSUCCESS = '[Map] StartSearchSuccess'; export const STARTSEARCHSUCCESS = '[Map] StartSearchSuccess';
export const SELECTFEATURE = '[Map] SelectFeature'; export const SELECTFEATURE = '[Map] SelectFeature';
@@ -86,6 +88,12 @@ export class SetParent implements Action {
constructor(public parentCode:string) { } constructor(public parentCode:string) { }
} }
export class SetPeriod implements Action {
readonly type = SETPERIOD;
constructor(public period:IPeriodState) { }
}
export class StartSearch implements Action { export class StartSearch implements Action {
readonly type = STARTSEARCH; readonly type = STARTSEARCH;
@@ -348,5 +356,6 @@ export type Actions = SetMapState
| SetLayerValuesLocation | SetLayerValuesLocation
| ToggleLayerValuesEnabled | ToggleLayerValuesEnabled
| GetLayerValueSuccess | GetLayerValueSuccess
| GetLayerValue; | GetLayerValue
| SetPeriod;

View File

@@ -82,10 +82,18 @@ export function LocalStorageSync(reducer: ActionReducer<any>): ActionReducer<any
if(ms) { if(ms) {
r2["mapState"] = JSON.parse(ms); r2["mapState"] = JSON.parse(ms);
} }
let sp = window.localStorage.getItem(MODULE_NAME+"_searchPeriod");
if(sp) {
let p = JSON.parse(sp);
r2["period"] = { startDate: new Date(Date.parse(p.startDate)),endDate:new Date(Date.parse(p.endDate))};
}
} }
if(action.type == "[Map] MapState" || action.type == "[Map] SetState") { if(action.type == "[Map] MapState" || action.type == "[Map] SetState") {
window.localStorage.setItem(MODULE_NAME + "_mapState",JSON.stringify(r2["mapState"])); window.localStorage.setItem(MODULE_NAME + "_mapState",JSON.stringify(r2["mapState"]));
} }
if(action.type == "[Map] SetPeriod" ) {
window.localStorage.setItem(MODULE_NAME + "_searchPeriod",JSON.stringify(r2["period"]));
}
return r2; return r2;
}; };

View File

@@ -112,17 +112,18 @@ export class ItemVectorSourceComponent extends SourceVectorComponent implements
this.host.instance.setSource(this.instance); this.host.instance.setSource(this.instance);
this.host.instance.setStyle((feature) => { this.host.instance.setStyle((feature) => {
var key = feature.get('itemType') + (this.selectedItem?"_I":""); var itemType = feature.get('itemType');
var key = itemType + (this.selectedItem?"_I":"");
if (!this.stylesCache[key]) { if (!this.stylesCache[key]) {
if (this.itemTypeService.itemTypes[key]) { if (this.itemTypeService.itemTypes[itemType]) {
let itemType = this.itemTypeService.itemTypes[key]; let itemTypeEntry = this.itemTypeService.itemTypes[itemType];
let fillColor = color.asArray(itemType.iconColor); let fillColor = color.asArray(itemTypeEntry.iconColor);
fillColor[3] = 0; fillColor[3] = 0;
this.stylesCache[key] = new style.Style({ this.stylesCache[key] = new style.Style({
image: itemType.icon ? new style.Icon({ image: itemTypeEntry.icon ? new style.Icon({
anchor: [0.5, 1], anchor: [0.5, 1],
scale: 0.05, scale: 0.05,
src: this.featureIconService$.getIconImageDataUrl(itemType.icon) src: this.featureIconService$.getIconImageDataUrl(itemTypeEntry.icon)
}):null, }):null,
stroke: new style.Stroke({ stroke: new style.Stroke({
color: 'red', color: 'red',

View File

@@ -17,7 +17,7 @@
</div> </div>
<div *ngIf="itemLayer.legendVisible"> <div *ngIf="itemLayer.legendVisible">
<div class="card legend"> <div class="card legend">
<fm-map-layer-legend [layer]="firstLayer(itemLayer)" (click)="handleLegendClick($event,itemLayer);"></fm-map-layer-legend> <fm-map-layer-legend [layer]="firstLayer(itemLayer)" (click)="handleLegendClick($event,itemLayer);" [histogramenabled]="true"></fm-map-layer-legend>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,7 +7,7 @@
<li class="border-top pt-1 pb-1 value" *ngFor="let layerValue of layers"> <li class="border-top pt-1 pb-1 value" *ngFor="let layerValue of layers">
<div>{{layerValue.layerName}}</div> <div>{{layerValue.layerName}}</div>
<div>{{layerValue.date|date}}</div> <div>{{layerValue.date|date}}</div>
<div><span class="mr-1">{{layerValue.quantity}}</span> <span class="mr-1 font-weight-bold">{{layerValue.value}}</span><span>{{layerValue.unit}}</span></div> <div><span *ngIf="layerValue.quantity"><span class="mr-1">{{layerValue.quantity}}</span> </span><span class="mr-1 font-weight-bold">{{layerValue.value}}</span><span>{{layerValue.unit}}</span></div>
</li> </li>
</ul> </ul>
<ng-template #no_data> <ng-template #no_data>

View File

@@ -89,7 +89,7 @@ export class LegendComponent implements OnInit,AfterViewInit {
} }
showHistogram(): boolean { showHistogram(): boolean {
return this.histogramenabled && this.layer.renderer.band.histogram.entries && this.layer.renderer.band.histogram.entries.length > 0 && this.layer.renderer.colorMap.colormapType == "minmax"; return this.histogramenabled && this.layer.renderer.band.histogram.entries && this.layer.renderer.band.histogram.entries.length > 0 && this.layer.renderer.band.histogram.entries.length == this.layer.renderer.colorMap.entries.length;
} }
bandContainsStatistics(): boolean { bandContainsStatistics(): boolean {

View File

@@ -33,4 +33,4 @@
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
</div> </div>
<fm-map-select-period-modal [modalState]="openedModalName" (onCloseModal)="handleCloseModal()" (onSelect)="handleSelectPeriod($event)" [startDate]="startDate" [endDate]="endDate"></fm-map-select-period-modal> <fm-map-select-period-modal [modalState]="openedModalName" (onCloseModal)="handleCloseModal()" (onSelect)="handleSelectPeriod($event)" [startDate]="periodLocal.startDate" [endDate]="periodLocal.endDate"></fm-map-select-period-modal>

View File

@@ -22,7 +22,10 @@ export class MapSearchComponent {
@Input() set searchMinified(minified: boolean) { @Input() set searchMinified(minified: boolean) {
this.searchMinifiedLocal = minified; this.searchMinifiedLocal = minified;
} }
@Input() period: IPeriodState @Input() set period(period:IPeriodState) {
this.periodLocal = tassign(this.periodLocal,{startDate: period.startDate,endDate:period.endDate});
this.startEndCaption = this.timespanService.getCaption(period.startDate, period.endDate, 4)
}
@Output() onSearch = new EventEmitter<IQueryState>(); @Output() onSearch = new EventEmitter<IQueryState>();
@Output() onClear = new EventEmitter<any>(); @Output() onClear = new EventEmitter<any>();
@Output() onSearchCollapse = new EventEmitter<any>(); @Output() onSearchCollapse = new EventEmitter<any>();
@@ -30,6 +33,7 @@ export class MapSearchComponent {
@Output() onToggleMenu = new EventEmitter<any>(); @Output() onToggleMenu = new EventEmitter<any>();
@Output() onOpenModal = new EventEmitter<string>(); @Output() onOpenModal = new EventEmitter<string>();
@Output() onCloseModal = new EventEmitter<any>(); @Output() onCloseModal = new EventEmitter<any>();
@Output() onPeriodChange = new EventEmitter<IPeriodState>();
@Input() openedModalName: string; @Input() openedModalName: string;
@Input() set filterOptions(filterOptions: IQueryState) { @Input() set filterOptions(filterOptions: IQueryState) {
if (filterOptions && filterOptions.query && filterOptions.query.length > 0) { if (filterOptions && filterOptions.query && filterOptions.query.length > 0) {
@@ -43,22 +47,17 @@ export class MapSearchComponent {
} else { } else {
this.searchTextLocal = { name: filterOptions.query }; this.searchTextLocal = { name: filterOptions.query };
} }
if (this.dateFilter) {
this.filterOptionsLocal.startDate = this.startDate;
this.filterOptionsLocal.endDate = this.endDate;
}
} }
public collapsedLocal: boolean = true; public collapsedLocal: boolean = true;
public searchMinifiedLocal: boolean = false; public searchMinifiedLocal: boolean = false;
public periodLocal: IPeriodState = { startDate:new Date(new Date(Date.now()).getFullYear(), new Date(Date.now()).getMonth() - 3, 1), endDate:new Date(Date.now())};
public filterOptionsLocal: IQueryState; public filterOptionsLocal: IQueryState;
private extent: number[]; private extent: number[];
public searchTextLocal: any; public searchTextLocal: any;
public searchTextLocalOutput: string; public searchTextLocalOutput: string;
public dateFilter: boolean = true; public dateFilter: boolean = true;
public startDate: Date = new Date(new Date(Date.now()).getFullYear(), new Date(Date.now()).getMonth() - 3, 1); public startEndCaption: string = this.timespanService.getCaption(this.periodLocal.startDate, this.periodLocal.endDate, 4);
public endDate: Date = new Date(Date.now());
public startEndCaption: string = this.timespanService.getCaption(this.startDate, this.endDate, 4);
searching = false; searching = false;
searchFailed = false; searchFailed = false;
@@ -94,8 +93,8 @@ export class MapSearchComponent {
this.filterOptionsLocal.parentCode = null; this.filterOptionsLocal.parentCode = null;
this.filterOptionsLocal.query = this.searchTextLocalOutput; this.filterOptionsLocal.query = this.searchTextLocalOutput;
if (this.dateFilter) { if (this.dateFilter) {
this.filterOptionsLocal.startDate = this.startDate; this.filterOptionsLocal.startDate = this.periodLocal.startDate;
this.filterOptionsLocal.endDate = this.endDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate;
} }
this.onSearch.emit(this.filterOptionsLocal); this.onSearch.emit(this.filterOptionsLocal);
} }
@@ -117,26 +116,30 @@ export class MapSearchComponent {
this.filterOptionsLocal.parentCode = null; this.filterOptionsLocal.parentCode = null;
this.filterOptionsLocal.tags = event.item.name; this.filterOptionsLocal.tags = event.item.name;
if (this.dateFilter) { if (this.dateFilter) {
this.filterOptionsLocal.startDate = this.startDate; this.filterOptionsLocal.startDate = this.periodLocal.startDate;
this.filterOptionsLocal.endDate = this.endDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate;
} }
this.onSearch.emit(this.filterOptionsLocal); this.onSearch.emit(this.filterOptionsLocal);
this.searchTextLocal = { name: this.filterOptionsLocal.tags }; this.searchTextLocal = { name: this.filterOptionsLocal.tags };
} }
handleSelectPeriod(event: { startDate: Date, endDate: Date }) { handleSelectPeriod(event: { startDate: Date, endDate: Date }) {
this.startDate = event.startDate; this.periodLocal = { startDate: event.startDate, endDate: event.endDate}
this.endDate = event.endDate; this.onPeriodChange.emit(this.periodLocal);
this.handleCloseModal();
this.startEndCaption = this.timespanService.getCaption(event.startDate, event.endDate, 4); this.startEndCaption = this.timespanService.getCaption(event.startDate, event.endDate, 4);
if(this.dateFilter) {
this.filterOptionsLocal.startDate =event.startDate;
this.filterOptionsLocal.endDate = event.endDate;
this.onSearch.emit(this.filterOptionsLocal); this.onSearch.emit(this.filterOptionsLocal);
} }
this.handleCloseModal();
}
handleChangeEnableDateFilter(enabled) { handleChangeEnableDateFilter(enabled) {
this.dateFilter = enabled; this.dateFilter = enabled;
if (enabled) { if (enabled) {
this.filterOptionsLocal.startDate = this.startDate; this.filterOptionsLocal.startDate = this.periodLocal.startDate;
this.filterOptionsLocal.endDate = this.endDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate;
} else { } else {
this.filterOptionsLocal.startDate = null; this.filterOptionsLocal.startDate = null;
this.filterOptionsLocal.endDate = null; this.filterOptionsLocal.endDate = null;

View File

@@ -50,7 +50,7 @@
<fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target> <fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target>
<div *ngIf="noContent"> <div *ngIf="noContent">
<fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period"></fm-map-map-search> <fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period" (onPeriodChange)="handlePeriodChange($event)"></fm-map-map-search>
</div> </div>
<div class="side-panel-container"> <div class="side-panel-container">
<fm-side-panel [resizeable]="true" [visible]="state.panelVisible && noContent" [collapsed]="state.panelCollapsed" [collapsable]="false"> <fm-side-panel [resizeable]="true" [visible]="state.panelVisible && noContent" [collapsed]="state.panelCollapsed" [collapsable]="false">

View File

@@ -434,6 +434,10 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
this.store.dispatch(new mapActions.SelectOverlayLayer(itemLayer)); this.store.dispatch(new mapActions.SelectOverlayLayer(itemLayer));
} }
handlePeriodChange(period:IPeriodState) {
this.store.dispatch(new mapActions.SetPeriod(period));
}
ngOnDestroy() { ngOnDestroy() {
if (this.paramSub) this.paramSub.unsubscribe(); if (this.paramSub) this.paramSub.unsubscribe();
if (this.itemTypeSub) this.itemTypeSub.unsubscribe(); if (this.itemTypeSub) this.itemTypeSub.unsubscribe();

View File

@@ -50,15 +50,16 @@ export class MapEffects {
private _wktFormat: WKT; private _wktFormat: WKT;
private overrideSelectedItemLayer: boolean = false; private overrideSelectedItemLayer: boolean = false;
private toPointFeature(updateEvent:commonActions.DeviceUpdateEvent): Feature { private updateFeatureGeometry(feature:Feature, updateEvent:commonActions.DeviceUpdateEvent): Feature {
let newFeature = feature.clone();
var f = this._wktFormat.readFeature(updateEvent.attributes["geometry"],{ var f = this._wktFormat.readFeature(updateEvent.attributes["geometry"],{
dataProjection: 'EPSG:4326', dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857' featureProjection: 'EPSG:3857'
}); });
f.setId(updateEvent.itemCode);
var centroid = getCenter(f.getGeometry().getExtent()); var centroid = getCenter(f.getGeometry().getExtent());
f.setGeometry(new Point(centroid)); newFeature.setId(feature.getId());
return f; newFeature.setGeometry(new Point(centroid));
return newFeature;
} }
init$ = createEffect(() => this.actions$.pipe( init$ = createEffect(() => this.actions$.pipe(
@@ -263,7 +264,7 @@ export class MapEffects {
} }
} }
if (feature) { if (feature) {
return of(new mapActions.UpdateFeatureSuccess(this.toPointFeature(deviceUpdateEventAction))); return of(new mapActions.UpdateFeatureSuccess(this.updateFeatureGeometry(feature,deviceUpdateEventAction)));
} else { } else {
return []; return [];
} }
@@ -316,7 +317,7 @@ export class MapEffects {
if(v !== null) { if(v !== null) {
if(l.renderer && l.renderer.colorMap && l.renderer.colorMap.colormapType == "manual") { if(l.renderer && l.renderer.colorMap && l.renderer.colorMap.colormapType == "manual") {
l.renderer.colorMap.entries.forEach((e) => { l.renderer.colorMap.entries.forEach((e) => {
if(e.value == v) { if(e.value == v && e.label) {
v=e.label; v=e.label;
return; return;
} }

View File

@@ -310,6 +310,10 @@ export function reducer(state = initialState, action: mapActions.Actions | commo
}) })
} }
case mapActions.SETPERIOD: {
return tassign(state,{ period: action.period});
}
case mapActions.ADDFEATURESUCCESS: { case mapActions.ADDFEATURESUCCESS: {
let a = action as mapActions.AddFeatureSuccess; let a = action as mapActions.AddFeatureSuccess;
let features = state.features.slice(); let features = state.features.slice();

View File

@@ -17,6 +17,7 @@ import { EventService } from './services/event.service';
import { TypeaheadService } from './services/typeahead.service'; import { TypeaheadService } from './services/typeahead.service';
import { UserService } from './services/user.service'; import { UserService } from './services/user.service';
import { ImageService } from './services/image.service'; import { ImageService } from './services/image.service';
import { GeolocatorService } from './services/geolocator.service';
import { WeatherService} from './services/weather.service'; import { WeatherService} from './services/weather.service';
import { AppConfig } from './shared/app.config'; import { AppConfig } from './shared/app.config';
import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor"; import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor";
@@ -44,6 +45,7 @@ export {
TypeaheadService, TypeaheadService,
UserService, UserService,
ImageService, ImageService,
GeolocatorService,
WeatherService, WeatherService,
AppConfig, AppConfig,
AccessTokenInterceptor, AccessTokenInterceptor,

View File

@@ -1,9 +1,9 @@
<div #thumbnail class="thumbnail" [style.background-color]="itemTypeService.getColor(item.itemType)" > <div #thumbnail class="thumbnail" [style.background-color]="itemTypeService.getColor(item.itemType)" >
<div class="content"> <div class="content">
<img *ngIf="item.thumbnail" class="card-img-top" [src]="getThumbnailUrl(item)" /> <img *ngIf="hasThumbnail()" class="card-img-top" [src]="getThumbnailUrl(item)" />
<div *ngIf="!item.thumbnail" class="large-icon" [style.font-size]="getFontSize()" [style.line-height]="getLineHeight()"><i [ngClass]="itemTypeService.getIcon(item.itemType)"></i></div> <div *ngIf="!hasThumbnail()" class="large-icon" [style.font-size]="getFontSize()" [style.line-height]="getLineHeight()"><i [ngClass]="itemTypeService.getIcon(item.itemType)"></i></div>
<div *ngIf="canEdit()" class="edit btn btn-secondary rounded-circle" (click)="onEditClick()"><i class="fal fa-camera"></i></div> <div *ngIf="canEdit()" class="edit btn btn-secondary rounded-circle" (click)="onEditClick()"><i class="fal fa-camera"></i></div>
</div> </div>
</div> </div>
<fm-edit-image-modal #modal (changed)="onChanged()"></fm-edit-image-modal> <fm-edit-image-modal #modal (changed)="onChanged($event)"></fm-edit-image-modal>

View File

@@ -1,7 +1,8 @@
import { Component,Input ,ViewChild,ElementRef,ChangeDetectorRef} from '@angular/core'; import { Component,Input ,ViewChild,ElementRef,ChangeDetectorRef, Output,EventEmitter} from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { IListItem } from '../../models/list.item'; import { IListItem } from '../../models/list.item';
import { ImageService } from '../../services/image.service';
import { commonReducers,ItemTypeService } from '../../../public-api' import { commonReducers,ItemTypeService } from '../../../public-api'
import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.component'; import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.component';
import { AppConfig } from "../../shared/app.config"; import { AppConfig } from "../../shared/app.config";
@@ -16,14 +17,25 @@ import { AppConfig } from "../../shared/app.config";
export class ThumbnailComponent { export class ThumbnailComponent {
@Input() public item: IListItem; @Input() public item: IListItem;
@Input() public edit: boolean = false; @Input() public edit: boolean = false;
@Input() public save: boolean = true;
@Output() changed = new EventEmitter();
@ViewChild('thumbnail') el:ElementRef; @ViewChild('thumbnail') el:ElementRef;
@ViewChild('modal') modal:EditImageModalComponent; @ViewChild('modal') modal:EditImageModalComponent;
constructor(public store: Store<commonReducers.State>, public itemTypeService: ItemTypeService,public appConfig: AppConfig,private changeDetector:ChangeDetectorRef) { public image = null;
private endpoint = "";
public thumnailUrl = "";
constructor(public store: Store<commonReducers.State>, public itemTypeService: ItemTypeService,public appConfig: AppConfig,private changeDetector:ChangeDetectorRef,public imageService:ImageService) {
} }
getThumbnailUrl(item:IListItem):string { getThumbnailUrl(item:IListItem):string {
return this.appConfig.getConfig("apiEndPoint")+item.url+'/thumbnail?v=' + Date.parse(item.updated); if(this.image == null && this.item.thumbnail) {
this.thumnailUrl = this.appConfig.getConfig("apiEndPoint")+item.url+'/thumbnail?v=' + Date.parse(item.updated);
} else if (this.image == null) {
this.thumnailUrl = "";
}
return this.thumnailUrl;
} }
getFontSize():string { getFontSize():string {
@@ -47,15 +59,28 @@ import { AppConfig } from "../../shared/app.config";
return this.edit && this.item != null; return this.edit && this.item != null;
} }
onEditClick() { hasThumbnail():boolean {
var endpoint = `${this.appConfig.getConfig("apiEndPoint")}/api/v1/items/${this.item.code}/thumbnail`; return (this.item && this.item.thumbnail) || this.image != null;
this.modal.open(endpoint,4/3);
} }
onChanged() { onEditClick() {
if(this.item) { this.endpoint = `${this.appConfig.getConfig("apiEndPoint")}/api/v1/items/${this.item.code}/thumbnail`;
this.item.updated = new Date(new Date().getTime()).toISOString(); this.modal.open(this.endpoint,4/3,false,200,false);
}
onChanged(event:any) {
this.image = event.croppedImage;
this.imageService.blobToDataUrl(event.croppedImage).then(url => {
this.thumnailUrl = url
this.changeDetector.detectChanges(); this.changeDetector.detectChanges();
if(this.save) this.saveImage();
this.changed.emit(event.croppedImage);
});
}
saveImage() {
if(this.image) {
this.imageService.putImage(this.endpoint,this.image).subscribe(() => {});
} }
} }
} }

View File

@@ -0,0 +1,21 @@
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 GeolocatorService {
constructor(public httpClient: HttpClient, public appConfig: AppConfig) {
}
ApiEndpoint() {
return this.appConfig.getConfig("apiEndPoint");
}
geocode(address:string): Observable<any> {
return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/service/geocode?address=${address}`)
}
}

View File

@@ -48,4 +48,18 @@ export class ImageService {
blobToFile(blob:Blob, filename:string):File { blobToFile(blob:Blob, filename:string):File {
return new File([blob],filename,{type:blob.type}); return new File([blob],filename,{type:blob.type});
} }
blobToDataUrl(blob:File):Promise<string> {
return new Promise<string>((resolve) => {
let reader = new FileReader();
reader.addEventListener('error', () => {
resolve("");
});
reader.addEventListener("load", function () {
resolve(reader.result as string);
}, false);
reader.readAsDataURL(blob);
});
}
} }

View File

@@ -28,7 +28,7 @@ export class PackageService {
hasPackage(id:string):boolean { hasPackage(id:string):boolean {
if(!this.packages$[id]) return false; if(!this.packages$[id]) return false;
return this.packages$[id].enabled == true; return this.packages$[id].enabled ? this.packages$[id].enabled == true : true;
} }
postItemPackageTask(item: IItem, task: IItemTask): Observable<IItemTask> { postItemPackageTask(item: IItem, task: IItemTask): Observable<IItemTask> {