Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workspace - enabling table view for vector layers #667

Merged
merged 101 commits into from
Sep 21, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
f45ed42
feat(layer) feature layer stored in a store now have a inMapExtent state
pelord Jun 9, 2020
9cdb867
feat(workspace-state) active widget subscription
pelord Jun 9, 2020
c554e66
feat(workspace) monitor a tool to activate on workspace
pelord Jun 9, 2020
3d72d7f
feat(workspace) Feature datasource (imported or url based) now get a …
pelord Jun 9, 2020
5d9f41d
feat(workspace) adjust actions/widget for wfs
pelord Jun 9, 2020
676d5d5
wip
pelord Jun 9, 2020
8fd6ae3
feat(workspace) Add a table template if no sourceFields provided
pelord Jun 9, 2020
fa266e8
refactor(loading-layer) adjust store for cluster datasource
pelord Jun 9, 2020
af8d03e
wip
pelord Jun 9, 2020
227db73
feat(workspace) creation of a workspace button
pelord Jun 10, 2020
a2dee6d
feat(map integration) adding the workspace button
pelord Jun 10, 2020
ac1e989
wip
pelord Jun 10, 2020
60394aa
wip
pelord Jun 10, 2020
a5f2dfc
refactor(workspace-button) moving from package geo to integration
pelord Jun 10, 2020
d9c49c8
wip
pelord Jun 10, 2020
0fbbba2
refactor(workspace-selector) review
pelord Jun 10, 2020
a19bc84
wip
pelord Jun 12, 2020
0d8756e
feat(featureStore) in map extent state strategy
pelord Jun 12, 2020
6fef828
wip
pelord Jun 12, 2020
8dd8a46
wip
pelord Jun 12, 2020
f00d259
refactor(workspace) tableTemplate in wfs/feature workspace
pelord Jun 12, 2020
a63e103
fix(cluster) cluster base style creation.
pelord Jun 16, 2020
f4fd4fb
Merge remote-tracking branch 'origin/next' into workspace3
pelord Jul 20, 2020
84c26d9
wip
pelord Jul 20, 2020
a67e37f
feat(workspace) new directive to monitor if workspaces are available.
pelord Jul 22, 2020
1945537
wip review
pelord Jul 24, 2020
898e37b
Merge remote-tracking branch 'origin/master' into workspace3
pelord Aug 10, 2020
795d172
travis
mbarbeau Aug 5, 2020
263a093
feat(libs): upgrade librairies (#696)
mbarbeau Aug 5, 2020
f1a5b3b
chore(utils): bowser version
mbarbeau Aug 5, 2020
2eed017
fix(spatial-filter): fix spatial filter 1.4 (#697)
PhilippeLafreniere18 Aug 6, 2020
ad990c4
fix(layer-list-tool) alphaSort icon name tooltip (#700)
Aug 12, 2020
4f092fe
feat(interactiveTour + welcomeWindows): add new component and service…
Aug 12, 2020
10006bc
Merge remote-tracking branch 'origin/next' into workspace3
pelord Aug 12, 2020
06253c1
wip
pelord Aug 12, 2020
e8ad3d4
wip
pelord Aug 12, 2020
3f0d16a
wip handling zoom auto on row selection in table
pelord Aug 13, 2020
cbe705a
wip review on tool to activate by workspace
pelord Aug 13, 2020
d67019e
wip
pelord Aug 13, 2020
9205140
wip
pelord Aug 13, 2020
4387e2a
wip
pelord Aug 14, 2020
415eab0
wip
pelord Aug 14, 2020
59fd497
fix(layer-legend.component) Fix param legendOptions.display: false (#…
Aug 17, 2020
89bb35a
feature(geo) Moving two common vector styling function into geo/utils…
pelord Aug 17, 2020
52099c7
feat(workspace) applying vector style to selected entities
pelord Aug 18, 2020
a717af9
feat((workspace) clear selection button
pelord Aug 18, 2020
bb06445
feat(workspace) allow multiple selection by dragbox
pelord Aug 18, 2020
25dfe33
feat(workspace) action to show only selected record
pelord Aug 19, 2020
3e7c48b
Merge remote-tracking branch 'origin/next' into workspace3
pelord Aug 20, 2020
3764f73
feat(entity-table): add pagination (#707)
pelord Aug 20, 2020
0985311
Merge remote-tracking branch 'origin/next' into workspace3
pelord Aug 20, 2020
b6e4bbb
wip
pelord Aug 20, 2020
210cc3c
fix(entity-table-paginator) missing subscription & lifecycle hook oni…
pelord Aug 25, 2020
c0d1945
refactor(exportOptions) Renaming from layer to layers
pelord Aug 25, 2020
d1388fa
feat(catalog): arcgis rest data catalog (#709)
PhilippeLafreniere18 Aug 27, 2020
bfe9107
fix(interactive-tour): css fix for interactive tour (#708)
PhilippeLafreniere18 Aug 27, 2020
a38d6fa
feat(import-export) vector - allow export selected features only IF w…
pelord Aug 28, 2020
a66fb82
feat(import-export) export - shorten selected layers in ui
pelord Aug 28, 2020
2727de7
fix(import-export) export - locale for select layers + style
pelord Aug 28, 2020
71ee75b
(entity-table-paginator) button display in mobile
Aug 31, 2020
8c5b6bb
Merge branch 'workspace3' of https://github.com/infra-geo-ouverte/igo…
Aug 31, 2020
68a92e9
feat(igoQuery) Allow drag box selection with ctrl down
pelord Aug 31, 2020
dff7477
Merge remote-tracking branch 'origin/next' into workspace3
pelord Aug 31, 2020
a67e9ed
feat(query) allow dragbox event to select vector
pelord Sep 1, 2020
1edbc9b
fix(query) handling results from layers built from same feature
pelord Sep 1, 2020
0248a71
feat(storage) observable on key change/addition/deletion
pelord Sep 1, 2020
df3dec0
feat(action) checkCondition is now an observable
pelord Sep 1, 2020
895b7bb
refactor(workspace) moving workspace action into integration
pelord Sep 1, 2020
e4135ed
feat(integration) new state for storage
pelord Sep 1, 2020
4dd3207
wip
pelord Sep 1, 2020
7109cb4
wip
pelord Sep 1, 2020
0cf2586
refactor(workspace) tooltoactivate from geo package to toolstate (int…
pelord Sep 1, 2020
4c6a07d
feat(tool-state) method to activate tool and options and opensidenav …
pelord Sep 1, 2020
23369b8
wip
pelord Sep 2, 2020
89b5dd9
merge next
Sep 8, 2020
1618713
fix(workspace) remove wms workspace creation
pelord Sep 9, 2020
9158e5e
fix(tool.state) All 'constructor' signatures should be adjacent
pelord Sep 9, 2020
1c64216
Merge remote-tracking branch 'origin/next' into workspace3
pelord Sep 9, 2020
6ef8a44
wip - merge conflict resolution
pelord Sep 9, 2020
e84fec3
fix(entity-table-paginator) fix the paginaor on input change
pelord Sep 11, 2020
7848c42
refactor(*) usign mediaservice.ismobile method instead of media value.
pelord Sep 11, 2020
d96ffc6
refactor(workspace) function name in lowercase
pelord Sep 11, 2020
d6f919e
typo
pelord Sep 11, 2020
886c114
Update entity-table-paginator.component.scss
mbarbeau Sep 11, 2020
9a88f47
fix(entity-table) table datasource was not refeshed on store change.
pelord Sep 14, 2020
23ab0c8
fix(entity-table) on store change subscription and management
pelord Sep 14, 2020
0831f37
feat(entity-table) change the pageIndex if the selected entity is not…
pelord Sep 14, 2020
9042faf
wip lint
pelord Sep 14, 2020
ae606ce
refactor(workspace) reorder the action list
pelord Sep 16, 2020
9a072e6
wip
pelord Sep 16, 2020
b815d67
padding
Sep 16, 2020
1ff9844
Merge branch 'workspace3' of github.com:infra-geo-ouverte/igo2-lib in…
Sep 16, 2020
6dbeb03
Merge remote-tracking branch 'origin/next' into workspace3
pelord Sep 16, 2020
d5c17e0
feat(spatial-filter) add a table view on results
pelord Sep 17, 2020
532c267
fix(workspace) inMapExtent strategy deletion on layer deletion.
pelord Sep 17, 2020
56fcac4
fix(context-import-export) only show to user the layers shown in laye…
pelord Sep 17, 2020
ca33ee3
typo
pelord Sep 17, 2020
7f638d7
wip
pelord Sep 17, 2020
167167c
fix(layer add) preview conflict with layer add (1st attempt to fix)
pelord Sep 17, 2020
b2edef5
refactor(entity-table-paginator) removing icons for mobile
pelord Sep 18, 2020
4094e9f
lint
Sep 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/common/src/lib/workspace/shared/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export class Workspace<E extends object = object> {
get active(): boolean { return this.active$.value; }
readonly active$: BehaviorSubject<boolean> = new BehaviorSubject(false);

toolToActivate$: BehaviorSubject<{ toolbox: string; options: {[key: string]: any} }> = new BehaviorSubject(undefined);
pelord marked this conversation as resolved.
Show resolved Hide resolved

/**
* Activate the workspace. By doing that, the workspace will observe
* the selected entity (from the store) and update the actions availability.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms';
import { Subscription, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, take, skipWhile } from 'rxjs/operators';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';

import olFeature from 'ol/Feature';
import OlGeoJSON from 'ol/format/GeoJSON';
Expand Down
30 changes: 28 additions & 2 deletions packages/geo/src/lib/feature/shared/strategies/loading-layer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { unByKey } from 'ol/Observable';
import { OlEvent } from 'ol/events/Event';
import * as olextent from 'ol/extent';

import { EntityStoreStrategy } from '@igo2/common';

import { FeatureStore } from '../store';
import { FeatureStoreLoadingLayerStrategyOptions } from '../feature.interfaces';
import { FeatureStoreLoadingLayerStrategyOptions, Feature } from '../feature.interfaces';
import { Subscription } from 'rxjs';
import { ClusterDataSource } from '../../../datasource/shared/datasources/cluster-datasource';

/**
* This strategy loads a layer's features into it's store counterpart.
Expand All @@ -20,6 +23,7 @@ export class FeatureStoreLoadingLayerStrategy extends EntityStoreStrategy {
* Subscription to the store's OL source changes
*/
private stores$$ = new Map<FeatureStore, string>();
private states$$: Subscription[] = [];

constructor(protected options: FeatureStoreLoadingLayerStrategyOptions) {
super(options);
Expand Down Expand Up @@ -76,7 +80,22 @@ export class FeatureStoreLoadingLayerStrategy extends EntityStoreStrategy {
const olSource = store.layer.ol.getSource();
olSource.on('change', (event: OlEvent) => {
this.onSourceChanges(store);
this.updateEntitiesInExtent(store);
});

pelord marked this conversation as resolved.
Show resolved Hide resolved
this.states$$.push(store.layer.map.viewController.state$.subscribe(() => {
this.updateEntitiesInExtent(store);
}));
}

private updateEntitiesInExtent(store) {
store.state.updateAll({ inMapExtent: false });
const mapExtent = store.layer.map.viewController.getExtent();
const entitiesInMapExtent = store.entities$.value
.filter((entity: Feature) => olextent.intersects(entity.ol.getGeometry().getExtent(), mapExtent));
if (entitiesInMapExtent.length > 0) {
store.state.updateMany(entitiesInMapExtent, { inMapExtent: true }, true);
}
}

/**
Expand All @@ -99,6 +118,7 @@ export class FeatureStoreLoadingLayerStrategy extends EntityStoreStrategy {
unByKey(entries[1]);
});
this.stores$$.clear();
this.states$$.map(state => state.unsubscribe());
}

/**
Expand All @@ -107,7 +127,13 @@ export class FeatureStoreLoadingLayerStrategy extends EntityStoreStrategy {
* @param store Feature store
*/
private onSourceChanges(store: FeatureStore) {
const olFeatures = store.layer.ol.getSource().getFeatures();
let olFeatures = store.layer.ol.getSource().getFeatures();

if (store.layer.dataSource instanceof ClusterDataSource) {
olFeatures = (olFeatures as any).flatMap((cluster: any) =>
pelord marked this conversation as resolved.
Show resolved Hide resolved
cluster.get('features')
);
}
if (olFeatures.length === 0) {
store.clear();
} else {
Expand Down
55 changes: 55 additions & 0 deletions packages/geo/src/lib/workspace/shared/feature-actions.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Injectable } from '@angular/core';

import { Action, EntityStoreFilterCustomFuncStrategy } from '@igo2/common';

import { FeatureWorkspace } from './feature-workspace';
import { mapExtentStrategyActiveIcon, mapExtentStrategyActiveToolTip } from './workspace.utils';
import { ExportOptions } from '../../import-export/shared/export.interface';

@Injectable({
providedIn: 'root'
})
export class FeatureActionsService {

constructor() {}

loadActions(workspace: FeatureWorkspace) {
const actions = this.buildActions(workspace);
workspace.actionStore.load(actions);
}

buildActions(workspace: FeatureWorkspace): Action[] {
return [
{
id: 'filterInMapExtent',
icon: mapExtentStrategyActiveIcon(workspace),
title: 'igo.geo.workspace.inMapExtent.title',
tooltip: mapExtentStrategyActiveToolTip(workspace),
args: [workspace],
handler: (ws: FeatureWorkspace) => {
const filterStrategy = ws.entityStore
.getStrategyOfType(EntityStoreFilterCustomFuncStrategy);
if (filterStrategy.active) {
filterStrategy.deactivate();
} else {
filterStrategy.activate();
}
}
},
{
id: 'featureDownload',
icon: 'download',
title: 'igo.geo.workspace.wfsDownload.title',
tooltip: 'igo.geo.workspace.wfsDownload.tooltip',
handler: (ws: FeatureWorkspace) => {
const filterStrategy = ws.entityStore.getStrategyOfType(EntityStoreFilterCustomFuncStrategy);
ws.toolToActivate$.next({
toolbox: 'importExport',
options: { layer: ws.layer.id, featureInMapExtent: filterStrategy.active } as ExportOptions
});
},
args: [workspace]
}
];
}
}
84 changes: 84 additions & 0 deletions packages/geo/src/lib/workspace/shared/feature-workspace.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Injectable } from '@angular/core';

import {
ActionStore,
EntityTableTemplate,
EntityStoreFilterCustomFuncStrategy,
EntityRecord,
EntityStoreStrategyFuncOptions
} from '@igo2/common';

import {
FeatureStore,
FeatureStoreLoadingLayerStrategy,
FeatureStoreSelectionStrategy
} from '../../feature';
import { VectorLayer } from '../../layer';
import { IgoMap } from '../../map';
import { SourceFieldsOptionsParams } from '../../datasource';

import { FeatureWorkspace } from './feature-workspace';
import { FeatureActionsService } from './feature-actions.service';

@Injectable({
providedIn: 'root'
})
export class FeatureWorkspaceService {

constructor(private featureActionsService: FeatureActionsService) {}

createWorkspace(layer: VectorLayer, map: IgoMap): FeatureWorkspace {
const wks = new FeatureWorkspace({
id: layer.id,
title: layer.title,
layer,
map,
entityStore: this.createFeatureStore(layer, map),
actionStore: new ActionStore([]),
meta: {
tableTemplate: this.createTableTemplate(layer)
}
});
this.featureActionsService.loadActions(wks);
return wks;

}

private createFeatureStore(layer: VectorLayer, map: IgoMap): FeatureStore {
const store = new FeatureStore([], {map});
store.bindLayer(layer);

const loadingStrategy = new FeatureStoreLoadingLayerStrategy({});
const selectionStrategy = new FeatureStoreSelectionStrategy({
map,
hitTolerance: 15
});
store.addStrategy(loadingStrategy, true);
store.addStrategy(selectionStrategy, true);
store.addStrategy(this.createFilterInMapExtentStrategy(), false);
return store;
}

private createTableTemplate(layer: VectorLayer): EntityTableTemplate {
const fields = layer.dataSource.options.sourceFields || [];
const columns = fields.map((field: SourceFieldsOptionsParams) => {
return {
name: `properties.${field.name}`,
title: field.alias ? field.alias : field.name
};
});

return {
selection: true,
sort: true,
columns
};
}

private createFilterInMapExtentStrategy(): EntityStoreFilterCustomFuncStrategy {
const filterClauseFunc = (record: EntityRecord<object>) => {
return record.state.inMapExtent === true;
};
return new EntityStoreFilterCustomFuncStrategy({filterClauseFunc} as EntityStoreStrategyFuncOptions);
}
}
23 changes: 23 additions & 0 deletions packages/geo/src/lib/workspace/shared/feature-workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
Workspace,
WorkspaceOptions
} from '@igo2/common';

import { VectorLayer } from '../../layer';
import { IgoMap } from '../../map';

export interface FeatureWorkspaceOptions extends WorkspaceOptions {
layer: VectorLayer;
map: IgoMap;
}

export class FeatureWorkspace extends Workspace {

get layer(): VectorLayer { return this.options.layer; }

get map(): IgoMap { return this.options.map; }

constructor(protected options: FeatureWorkspaceOptions) {
super(options);
}
}
4 changes: 4 additions & 0 deletions packages/geo/src/lib/workspace/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export * from './wfs-workspace';
export * from './wfs-actions.service';
export * from './wfs-workspace.service';
export * from './feature-workspace';
export * from './feature-actions.service';
export * from './feature-workspace.service';
export * from './workspace.utils';
43 changes: 34 additions & 9 deletions packages/geo/src/lib/workspace/shared/wfs-actions.service.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
import { Inject, Injectable } from '@angular/core';

import { Action, Widget } from '@igo2/common';
import { Action, Widget, EntityStoreFilterCustomFuncStrategy } from '@igo2/common';

import { DownloadService } from '../../download';
import { OgcFilterWidget } from '../widgets';
import { OgcFilterWidget } from '../widgets/widgets';
import { WfsWorkspace } from './wfs-workspace';
import { mapExtentStrategyActiveIcon, mapExtentStrategyActiveToolTip } from './workspace.utils';
import { ExportOptions } from '../../import-export/shared/export.interface';

@Injectable({
providedIn: 'root'
})
export class WfsActionsService {

constructor(
@Inject(OgcFilterWidget) private ogcFilterWidget: Widget,
private downloadService: DownloadService
) {}
constructor(@Inject(OgcFilterWidget) private ogcFilterWidget: Widget) {}

loadActions(workspace: WfsWorkspace) {
const actions = this.buildActions(workspace);
workspace.actionStore.load(actions);
}

buildActions(workspace: WfsWorkspace): Action[] {
return [
{
id: 'filterInMapExtent',
icon: mapExtentStrategyActiveIcon(workspace),
title: 'igo.geo.workspace.inMapExtent.title',
tooltip: mapExtentStrategyActiveToolTip(workspace),
args: [workspace],
handler: (ws: WfsWorkspace) => {
const filterStrategy = ws.entityStore
.getStrategyOfType(EntityStoreFilterCustomFuncStrategy);
if (filterStrategy.active) {
filterStrategy.deactivate();
} else {
filterStrategy.activate();
}
}
},
{
id: 'ogcFilter',
icon: 'filter-list',
icon: 'filter',
title: 'igo.geo.workspace.ogcFilter.title',
tooltip: 'igo.geo.workspace.ogcFilter.tooltip',
handler: (widget: Widget, ws: WfsWorkspace) => {
Expand All @@ -36,7 +55,13 @@ export class WfsActionsService {
icon: 'download',
title: 'igo.geo.workspace.wfsDownload.title',
tooltip: 'igo.geo.workspace.wfsDownload.tooltip',
handler: (ws: WfsWorkspace) => this.downloadService.open(ws.layer),
handler: (ws: WfsWorkspace) => {
const filterStrategy = ws.entityStore.getStrategyOfType(EntityStoreFilterCustomFuncStrategy);
ws.toolToActivate$.next({
toolbox: 'importExport',
options: { layer: ws.layer.id, featureInMapExtent: filterStrategy.active } as ExportOptions
});
},
args: [workspace]
}
];
Expand Down
23 changes: 18 additions & 5 deletions packages/geo/src/lib/workspace/shared/wfs-workspace.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Injectable } from '@angular/core';

import {
ActionStore,
EntityTableTemplate
EntityTableTemplate,
EntityStoreFilterCustomFuncStrategy,
EntityRecord,
EntityStoreStrategyFuncOptions
} from '@igo2/common';

import {
Expand All @@ -15,16 +18,17 @@ import { IgoMap } from '../../map';
import { SourceFieldsOptionsParams } from '../../datasource';

import { WfsWorkspace } from './wfs-workspace';
import { WfsActionsService } from './wfs-actions.service';

@Injectable({
providedIn: 'root'
})
export class WfsWorkspaceService {

constructor() {}
constructor(private wfsActionsService: WfsActionsService) {}

createWorkspace(layer: VectorLayer, map: IgoMap): WfsWorkspace {
return new WfsWorkspace({
const wks = new WfsWorkspace({
id: layer.id,
title: layer.title,
layer,
Expand All @@ -35,6 +39,9 @@ export class WfsWorkspaceService {
tableTemplate: this.createTableTemplate(layer)
}
});
this.wfsActionsService.loadActions(wks);
return wks;

}

private createFeatureStore(layer: VectorLayer, map: IgoMap): FeatureStore {
Expand All @@ -44,11 +51,11 @@ export class WfsWorkspaceService {
const loadingStrategy = new FeatureStoreLoadingLayerStrategy({});
const selectionStrategy = new FeatureStoreSelectionStrategy({
map,
hitTolerance: 5
hitTolerance: 15
});
store.addStrategy(loadingStrategy, true);
store.addStrategy(selectionStrategy, true);

store.addStrategy(this.createFilterInMapExtentStrategy(), false);
return store;
}

Expand All @@ -68,4 +75,10 @@ export class WfsWorkspaceService {
};
}

private createFilterInMapExtentStrategy(): EntityStoreFilterCustomFuncStrategy {
const filterClauseFunc = (record: EntityRecord<object>) => {
return record.state.inMapExtent === true;
};
return new EntityStoreFilterCustomFuncStrategy({filterClauseFunc} as EntityStoreStrategyFuncOptions);
}
}
Loading