Fix feature highlighting
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good

This commit is contained in:
Willem Dantuma 2020-04-16 13:19:06 +02:00
parent 9fbc946c68
commit d34a2069d6
14 changed files with 101 additions and 79 deletions

View File

@ -35,6 +35,7 @@ export class ItemVectorSourceComponent extends SourceVectorComponent implements
@Input() selectedItem: IItem; @Input() selectedItem: IItem;
@Input() styles:IStyles; @Input() styles:IStyles;
@Output() onFeaturesSelected: EventEmitter<Feature> = new EventEmitter<Feature>(); @Output() onFeaturesSelected: EventEmitter<Feature> = new EventEmitter<Feature>();
@Output() onFeatureHover: EventEmitter<Feature> = new EventEmitter<Feature>();
private stylesCache:IStyles = {}; private stylesCache:IStyles = {};
constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, @Host() private map: MapComponent, private itemTypeService: ItemTypeService,private featureIconService$:FeatureIconService) { constructor(@Host() private layer: LayerVectorComponent, private itemService: ItemService, @Host() private map: MapComponent, private itemTypeService: ItemTypeService,private featureIconService$:FeatureIconService) {
@ -77,14 +78,12 @@ export class ItemVectorSourceComponent extends SourceVectorComponent implements
this.strategy = loadingstrategy.bbox; this.strategy = loadingstrategy.bbox;
this.format = new GeoJSON(); this.format = new GeoJSON();
this._select = new Select({ this._select = new Select({
style: (feature) => { style:null,
return this.getSelectedStyle(feature);
},
hitTolerance: 10, hitTolerance: 10,
layers: [this.layer.instance as Layer] layers: [this.layer.instance as Layer]
}); });
this._hoverSelect = new Select({ this._hoverSelect = new Select({
style: (feature) => { style: (feature) => {
return this.getSelectedStyle(feature); return this.getSelectedStyle(feature);
}, },
hitTolerance: 10, hitTolerance: 10,
@ -102,6 +101,13 @@ export class ItemVectorSourceComponent extends SourceVectorComponent implements
this.onFeaturesSelected.emit(null); this.onFeaturesSelected.emit(null);
} }
}); });
this._hoverSelect.on('select', (e) => {
if (e.selected.length > 0 && e.selected[0]) {
this.onFeatureHover.emit(e.selected[0]);
} else {
this.onFeatureHover.emit(null);
}
});
this.instance = new Vector(this); this.instance = new Vector(this);
this.host.instance.setSource(this.instance); this.host.instance.setSource(this.instance);
@ -153,7 +159,7 @@ export class ItemVectorSourceComponent extends SourceVectorComponent implements
} }
if (changes["selectedFeature"] && this.instance) { if (changes["selectedFeature"] && this.instance) {
var features = this._select.getFeatures(); var features = this._hoverSelect.getFeatures();
var feature = changes["selectedFeature"].currentValue var feature = changes["selectedFeature"].currentValue
//this.instance.clear(false); //this.instance.clear(false);
//this.instance.addFeatures(features.getArray()); //this.instance.addFeatures(features.getArray());

View File

@ -7,7 +7,7 @@
user-select: none; user-select: none;
} }
.row:hover { .row.selected {
background-color: gray('100'); background-color: gray('100');
} }

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit, ComponentFactoryResolver, ViewChild, SimpleChanges, ComponentFactory, Inject, Type} from '@angular/core'; import { Component, Input, OnInit, ComponentFactoryResolver, ViewChild, SimpleChanges, ComponentFactory, Inject} from '@angular/core';
import { Feature } from 'ol'; import { Feature } from 'ol';
import { FeatureListComponent,AbstractFeatureListComponent } from '../feature-list/feature-list.component'; import { FeatureListComponent,AbstractFeatureListComponent } from '../feature-list/feature-list.component';
import { WidgetHostDirective } from '../widget-host/widget-host.directive'; import { WidgetHostDirective } from '../widget-host/widget-host.directive';
@ -20,8 +20,10 @@ export class FeatureListContainerComponent {
@Input() features: Array<Feature> @Input() features: Array<Feature>
@Input() queryState: IQueryState; @Input() queryState: IQueryState;
@Input() selectedFeature: Feature;
@ViewChild(WidgetHostDirective, { static: true }) widgetHost: WidgetHostDirective; @ViewChild(WidgetHostDirective, { static: true }) widgetHost: WidgetHostDirective;
componentRef:any;
loadComponent(queryState:IQueryState) { loadComponent(queryState:IQueryState) {
var componentFactory: ComponentFactory<AbstractFeatureListComponent> = this.componentFactoryResolver.resolveComponentFactory(FeatureListComponent); // default var componentFactory: ComponentFactory<AbstractFeatureListComponent> = this.componentFactoryResolver.resolveComponentFactory(FeatureListComponent); // default
@ -44,16 +46,20 @@ export class FeatureListContainerComponent {
const viewContainerRef = this.widgetHost.viewContainerRef; const viewContainerRef = this.widgetHost.viewContainerRef;
viewContainerRef.clear(); viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory); this.componentRef = viewContainerRef.createComponent(componentFactory);
(<AbstractFeatureListComponent>componentRef.instance).features = this.features; (<AbstractFeatureListComponent>this.componentRef.instance).features = this.features;
(<AbstractFeatureListComponent>componentRef.instance).queryState = this.queryState; (<AbstractFeatureListComponent>this.componentRef.instance).queryState = this.queryState;
(<AbstractFeatureListComponent>this.componentRef.instance).selectedFeature = this.selectedFeature;
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (changes["features"] && changes["features"].currentValue) { if ((changes["features"] && changes["features"].currentValue)) {
if (this.queryState) { if (this.queryState) {
this.loadComponent(this.queryState); this.loadComponent(this.queryState);
} }
} }
if(changes["selectedFeature"]) {
(<AbstractFeatureListComponent>this.componentRef.instance).selectedFeature = changes["selectedFeature"].currentValue;
}
} }
} }

View File

@ -5,7 +5,7 @@
<h4 i18n>Farm</h4> <h4 i18n>Farm</h4>
<h3>{{schemeItem.name}}</h3> <h3>{{schemeItem.name}}</h3>
<div class="cropfields"> <div class="cropfields">
<div class="row m-0 pl-3 pr-3" *ngFor="let feature of features" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)"> <div class="row m-0 pl-3 pr-3" *ngFor="let feature of features" [ngClass]="{'selected':isFeatureSelected(feature)}" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)">
<fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container> <fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container>
</div> </div>
</div> </div>

View File

@ -11,7 +11,7 @@ fm-map-feature-list-feature-container {
padding-left:1.5rem; padding-left:1.5rem;
} }
.row:hover { .row.selected {
background-color: gray('100'); background-color: gray('100');
} }

View File

@ -1,30 +1,30 @@
import { Component, Injectable,AfterViewInit, OnInit} from '@angular/core'; import { Component, Injectable,AfterViewInit, OnInit,SimpleChanges, ChangeDetectorRef} from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { AbstractFeatureListComponent } from '../feature-list/feature-list.component'; import { AbstractFeatureListComponent } from '../feature-list/feature-list.component';
import {ForItemType } from '../for-item/for-itemtype.decorator'; import {ForItemType } from '../for-item/for-itemtype.decorator';
import {ForChild } from '../for-item/for-child.decorator'; import {ForChild } from '../for-item/for-child.decorator';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer'; import * as mapReducers from '../../reducers/map.reducer';
import { commonReducers, ItemTypeService, IItem,ItemService } from '@farmmaps/common'; import { commonReducers, ItemTypeService, IItem,ItemService } from '@farmmaps/common';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
@ForChild() @ForChild()
@ForItemType("vnd.farmmaps.itemtype.cropfield") @ForItemType("vnd.farmmaps.itemtype.cropfield")
@Injectable() @Injectable()
@Component({ @Component({
selector: 'fm-map-feature-list-cropfield', selector: 'fm-map-feature-list-cropfield',
templateUrl: './feature-list-cropfield.component.html', templateUrl: './feature-list-cropfield.component.html',
styleUrls: ['./feature-list-cropfield.component.scss'] styleUrls: ['./feature-list-cropfield.component.scss']
}) })
export class FeatureListCropfieldComponent extends AbstractFeatureListComponent implements OnInit { export class FeatureListCropfieldComponent extends AbstractFeatureListComponent implements OnInit {
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, private itemService: ItemService) { constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, private itemService: ItemService) {
super(store, itemTypeService,location); super(store, itemTypeService,location);
} }
public schemeItem: Observable<IItem> public schemeItem: Observable<IItem>
ngOnInit() { ngOnInit() {
this.schemeItem = this.itemService.getItem(this.queryState.parentCode); this.schemeItem = this.itemService.getItem(this.queryState.parentCode);
} }
} }

View File

@ -4,7 +4,7 @@
<div><a href="#" (click)="handleBackClick($event)" i18n>Back</a></div> <div><a href="#" (click)="handleBackClick($event)" i18n>Back</a></div>
<h3><i class="fm fm-farm"></i>&nbsp;<span i18n>Farms</span></h3> <h3><i class="fm fm-farm"></i>&nbsp;<span i18n>Farms</span></h3>
<div class="farms"> <div class="farms">
<div class="row m-0 pl-3 pr-3" *ngFor="let feature of features" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)"> <div class="row m-0 pl-3 pr-3" *ngFor="let feature of features"[ngClass]="{'selected':isFeatureSelected(feature)}" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)">
<fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container> <fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container>
</div> </div>
</div> </div>

View File

@ -11,7 +11,7 @@ fm-map-feature-list-feature-container {
padding-left:1.5rem; padding-left:1.5rem;
} }
.row:hover { .row.selected {
background-color: gray('100'); background-color: gray('100');
} }

View File

@ -1,29 +1,29 @@
import { Component, Injectable } from '@angular/core'; import { Component, Injectable } from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { AbstractFeatureListComponent } from '../feature-list/feature-list.component'; import { AbstractFeatureListComponent } from '../feature-list/feature-list.component';
import { ForItemType } from '../for-item/for-itemtype.decorator'; import { ForItemType } from '../for-item/for-itemtype.decorator';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer'; import * as mapReducers from '../../reducers/map.reducer';
import { commonReducers, ItemTypeService } from '@farmmaps/common'; import { commonReducers, ItemTypeService } from '@farmmaps/common';
import * as mapActions from '../../actions/map.actions'; import * as mapActions from '../../actions/map.actions';
import { tassign } from 'tassign'; import { tassign } from 'tassign';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@ForItemType("vnd.farmmaps.itemtype.croppingscheme") @ForItemType("vnd.farmmaps.itemtype.croppingscheme")
@Injectable() @Injectable()
@Component({ @Component({
selector: 'fm-map-feature-list-croppingscheme', selector: 'fm-map-feature-list-croppingscheme',
templateUrl: './feature-list-croppingscheme.component.html', templateUrl: './feature-list-croppingscheme.component.html',
styleUrls: ['./feature-list-croppingscheme.component.scss'] styleUrls: ['./feature-list-croppingscheme.component.scss']
}) })
export class FeatureListCroppingschemeComponent extends AbstractFeatureListComponent { export class FeatureListCroppingschemeComponent extends AbstractFeatureListComponent {
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, private router: Router) { constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, private router: Router) {
super(store, itemTypeService, location); super(store, itemTypeService, location);
} }
handleFeatureClick(feature) { handleFeatureClick(feature) {
var queryState = tassign(mapReducers.initialState.queryState, { parentCode: feature.get('code'), itemType: "vnd.farmmaps.itemtype.cropfield" }); var queryState = tassign(mapReducers.initialState.queryState, { parentCode: feature.get('code'), itemType: "vnd.farmmaps.itemtype.cropfield" });
this.store.dispatch(new mapActions.DoQuery(queryState)); this.store.dispatch(new mapActions.DoQuery(queryState));
} }
} }

View File

@ -1,6 +1,6 @@
<div *ngIf="features;let features"> <div *ngIf="features;let features">
<a href="#" (click)="handleBackClick($event)">Go back</a> <a href="#" (click)="handleBackClick($event)">Go back</a>
<div class="row m-0 pl-3 pr-3" *ngFor="let feature of features" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)"> <div class="row m-0 pl-3 pr-3" *ngFor="let feature of features" [ngClass]="{'selected':isFeatureSelected(feature)}" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)">
<fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container> <fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container>
</div> </div>
</div> </div>

View File

@ -10,6 +10,6 @@ fm-map-feature-list-feature-container {
user-select: none; user-select: none;
} }
.row:hover { .row.selected {
background-color: gray('100'); background-color: gray('100');
} }

View File

@ -1,4 +1,4 @@
import { Component, Input, Injectable,Directive } from '@angular/core'; import { Component, Input, Injectable,Directive,SimpleChanges } from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { Feature } from 'ol'; import { Feature } from 'ol';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@ -16,6 +16,7 @@ import { IQueryState } from '@farmmaps/common';
export abstract class AbstractFeatureListComponent { export abstract class AbstractFeatureListComponent {
@Input() features: Array<Feature>; @Input() features: Array<Feature>;
@Input() queryState: IQueryState; @Input() queryState: IQueryState;
@Input() selectedFeature: Feature;
constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, private location: Location) { constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, private location: Location) {
} }
@ -37,6 +38,11 @@ export abstract class AbstractFeatureListComponent {
event.preventDefault(); event.preventDefault();
this.location.back(); this.location.back();
} }
isFeatureSelected(feature:Feature):boolean {
if(!this.selectedFeature) return false;
return feature.getId() == this.selectedFeature.getId();
}
} }
@Injectable() @Injectable()

View File

@ -34,7 +34,7 @@
<fm-map-item-layers [itemLayers]="state.overlayLayers"></fm-map-item-layers> <fm-map-item-layers [itemLayers]="state.overlayLayers"></fm-map-item-layers>
<fm-map-item-layers [itemLayer]="state.selectedItemLayer"></fm-map-item-layers> <fm-map-item-layers [itemLayer]="state.selectedItemLayer"></fm-map-item-layers>
<aol-layer-vector> <aol-layer-vector>
<fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeaturesSelected)="handleFeaturesSelected($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector> <fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeaturesSelected)="handleFeaturesSelected($event)" (onFeatureHover)="handleFeatureHover($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector>
</aol-layer-vector> </aol-layer-vector>
<fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="true" [heading]="state.compassHeading"></fm-map-gps-location> <fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="true" [heading]="state.compassHeading"></fm-map-gps-location>
<div class="control-container"> <div class="control-container">
@ -53,7 +53,7 @@
<div class="panel-bottom"> <div class="panel-bottom">
<div *ngIf="!(state.selectedItem)"> <div *ngIf="!(state.selectedItem)">
<fm-map-feature-list-container [features]="state.features" [queryState]="state.queryState"></fm-map-feature-list-container> <fm-map-feature-list-container [features]="state.features" [selectedFeature]="state.selectedFeature" [queryState]="state.queryState"></fm-map-feature-list-container>
</div> </div>
<div *ngIf="state.selectedItem;let item"> <div *ngIf="state.selectedItem;let item">

View File

@ -120,6 +120,10 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
} }
} }
handleFeatureHover(feature: Feature) {
this.store.dispatch(new mapActions.SelectFeature(feature));
}
handleSearch(queryState: IQueryState) { handleSearch(queryState: IQueryState) {
this.store.dispatch(new mapActions.DoQuery(queryState)); this.store.dispatch(new mapActions.DoQuery(queryState));
} }