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

feat(geo): highlight unavailable layer in map tool #1688

Open
wants to merge 3 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export class LayerContextDirective implements OnInit, OnDestroy {
}
this.contextLayers = [];

this.layerService.unavailableLayers = [];
const layersAndIndex$ = merge(
...context.layers.map((layerOptions: LayerOptions) => {
return this.layerService.createAsyncLayer(layerOptions, context.uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@ export type AnyDataSourceOptions =
| TileArcGISRestDataSourceOptions
| MVTDataSourceOptions
| ClusterDataSourceOptions;

export type AnyDataSourceOptionsWithParams =
| FeatureDataSourceOptions
| WFSDataSourceOptions
| WMSDataSourceOptions
| CartoDataSourceOptions
| ArcGISRestDataSourceOptions
| ArcGISRestImageDataSourceOptions
| TileArcGISRestDataSourceOptions;
209 changes: 125 additions & 84 deletions packages/geo/src/lib/layer/layer-item/layer-item.component.html
Original file line number Diff line number Diff line change
@@ -1,92 +1,133 @@
<mat-list-item class="igo-layer-list-item">
<mat-checkbox
*ngIf="selectionMode"
class="layerCheck"
matListItemIcon
(change)="check()"
[checked]="layerCheck"
>
</mat-checkbox>
<span
matListItemTitle
class="igo-layer-title"
[matTooltip]="tooltipText"
matTooltipShowDelay="500"
(click)="toggleLegendOnClick()"
>
{{ layer.title }}
</span>

<div matListItemMeta>
<button
*ngIf="!selectionMode"
mat-icon-button
[color]="layer.visible ? 'primary' : 'default'"
collapsibleButton
tooltip-position="below"
matTooltipShowDelay="500"
[matTooltip]="eyeTooltip | translate"
(click)="toggleVisibility($event)"
>
<mat-icon
aria-hidden="false"
matBadge="?"
matBadgeColor="accent"
matBadgeSize="small"
matBadgePosition="after"
[matBadgeHidden]="queryBadgeHidden$ | async"
[ngClass]="{ disabled: (inResolutionRange$ | async) === false }"
>{{ (layer.visible$ | async) ? 'visibility' : 'visibility_off' }}
</mat-icon>
</button>

<button
<ng-container *ngIf="!unavailableLayer; else showUnavailableLayer">
<mat-list-item class="igo-layer-list-item">
<mat-checkbox
*ngIf="selectionMode"
class="selection-eye"
mat-icon-button
[color]="layer.visible ? 'primary' : 'default'"
collapsibleButton
tooltip-position="below"
class="layerCheck"
matListItemIcon
(change)="check()"
[checked]="layerCheck"
>
</mat-checkbox>
<span
matListItemTitle
class="igo-layer-title"
[matTooltip]="tooltipText"
matTooltipShowDelay="500"
[matTooltip]="
layer.visible
? ('igo.geo.layer.hideLayer' | translate)
: ('igo.geo.layer.showLayer' | translate)
"
(click)="toggleVisibility($event)"
(click)="toggleLegendOnClick()"
>
<mat-icon
aria-hidden="false"
matBadge="?"
matBadgeColor="accent"
matBadgeSize="small"
matBadgePosition="after"
[matBadgeHidden]="queryBadgeHidden$ | async"
[ngClass]="{ disabled: (inResolutionRange$ | async) === false }"
>{{ layer.visible ? 'visibility' : 'visibility_off' }}
</mat-icon>
</button>
{{ layer.title }}
</span>

<button
*ngIf="!selectionMode"
class="actions-button"
tooltip-position="below"
matTooltipShowDelay="500"
[matTooltip]="'igo.geo.layer.moreOptions' | translate"
mat-icon-button
color="primary"
(click)="toggleLayerTool()"
<div matListItemMeta>
<button
*ngIf="!selectionMode"
mat-icon-button
[color]="layer.visible ? 'primary' : 'default'"
collapsibleButton
tooltip-position="below"
matTooltipShowDelay="500"
[matTooltip]="eyeTooltip | translate"
(click)="toggleVisibility($event)"
>
<mat-icon
aria-hidden="false"
matBadge="?"
matBadgeColor="accent"
matBadgeSize="small"
matBadgePosition="after"
[matBadgeHidden]="queryBadgeHidden$ | async"
[ngClass]="{ disabled: (inResolutionRange$ | async) === false }"
>{{ (layer.visible$ | async) ? 'visibility' : 'visibility_off' }}
</mat-icon>
</button>

<button
*ngIf="selectionMode"
class="selection-eye"
mat-icon-button
[color]="layer.visible ? 'primary' : 'default'"
collapsibleButton
tooltip-position="below"
matTooltipShowDelay="500"
[matTooltip]="
layer.visible
? ('igo.geo.layer.hideLayer' | translate)
: ('igo.geo.layer.showLayer' | translate)
"
(click)="toggleVisibility($event)"
>
<mat-icon
aria-hidden="false"
matBadge="?"
matBadgeColor="accent"
matBadgeSize="small"
matBadgePosition="after"
[matBadgeHidden]="queryBadgeHidden$ | async"
[ngClass]="{ disabled: (inResolutionRange$ | async) === false }"
>{{ layer.visible ? 'visibility' : 'visibility_off' }}
</mat-icon>
</button>

<button
*ngIf="!selectionMode"
class="actions-button"
tooltip-position="below"
matTooltipShowDelay="500"
[matTooltip]="'igo.geo.layer.moreOptions' | translate"
mat-icon-button
color="primary"
(click)="toggleLayerTool()"
>
<mat-icon>more_horiz</mat-icon>
</button>
</div>
</mat-list-item>

<div #legend class="igo-layer-legend-container">
<igo-layer-legend
*ngIf="showLegend$ | async"
[layer]="layer"
[updateLegendOnResolutionChange]="updateLegendOnResolutionChange"
>
<mat-icon>more_horiz</mat-icon>
</button>
</igo-layer-legend>
</div>
</mat-list-item>
</ng-container>

<div #legend class="igo-layer-legend-container">
<igo-layer-legend
*ngIf="showLegend$ | async"
[layer]="layer"
[updateLegendOnResolutionChange]="updateLegendOnResolutionChange"
<ng-template #showUnavailableLayer>
<mat-list-item
class="igo-layer-list-item unavailable-layer"
*ngIf="unavailableLayerTitle"
>
</igo-layer-legend>
</div>
<span
matListItemTitle
class="igo-layer-title"
[matTooltip]="unavailableLayerTitle"
tooltip-position="below"
matTooltipShowDelay="500"
>
{{ unavailableLayerTitle }}
</span>
<div matListItemMeta>
<div
class="align-disabled-button-with-tooltip"
[matTooltip]="'igo.geo.layer.unavailableLayer' | translate"
tooltip-position="below"
matTooltipShowDelay="500"
>
<button mat-icon-button disabled="true">
<mat-icon aria-hidden="false">warning</mat-icon>
</button>
</div>
<button
mat-icon-button
color="warn"
[matTooltip]="'igo.geo.layer.deleteLayer' | translate"
tooltip-position="below"
matTooltipShowDelay="500"
(click)="deleteUnavailableLayer(unavailableLayer)"
>
<mat-icon aria-hidden="false">delete</mat-icon>
</button>
</div>
</mat-list-item>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@
width: 16px;
padding-right: 0px;
}

.align-disabled-button-with-tooltip {
display: inline-block;
}
}
89 changes: 57 additions & 32 deletions packages/geo/src/lib/layer/layer-item/layer-item.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import { MetadataLayerOptions } from '../../metadata/shared/metadata.interface';
import { layerIsQueryable } from '../../query/shared/query.utils';
import { LayerLegendComponent } from '../layer-legend/layer-legend.component';
import { AnyLayerOptions } from '../shared';
import { Layer } from '../shared/layers/layer';
import { TooltipType } from '../shared/layers/layer.interface';

Expand Down Expand Up @@ -131,6 +132,22 @@

@Input() changeDetection;

@Input() unavailableLayer: AnyLayerOptions;

get unavailableLayerTitle(): string | undefined {
if (
this.unavailableLayer.sourceOptions &&
'params' in this.unavailableLayer.sourceOptions
) {
return this.unavailableLayer.sourceOptions.params.LAYERS;
} else if (
this.unavailableLayer.sourceOptions &&
'layer' in this.unavailableLayer?.sourceOptions

Check failure on line 145 in packages/geo/src/lib/layer/layer-item/layer-item.component.ts

View workflow job for this annotation

GitHub Actions / Analyze Pull Rrequest

Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError
) {
return this.unavailableLayer.sourceOptions.layer;
}
}

get opacity() {
return this.layer.opacity * 100;
}
Expand All @@ -148,7 +165,9 @@
}
}

@Output() action: EventEmitter<Layer> = new EventEmitter<Layer>(undefined);
@Output() action: EventEmitter<Layer | AnyLayerOptions> = new EventEmitter<
Layer | AnyLayerOptions
>(undefined);
@Output() checkbox = new EventEmitter<{
layer: Layer;
check: boolean;
Expand All @@ -162,46 +181,48 @@
) {}

ngOnInit() {
if (
this.layer.visible &&
this.expandLegendIfVisible &&
this.layer.firstLoadComponent === true
) {
this.layer.firstLoadComponent = false;
this.layer.legendCollapsed = false;
}
this.toggleLegend(this.layer.legendCollapsed);
this.updateQueryBadge();

const resolution$ = this.layer.map.viewController.resolution$;
this.resolution$$ = resolution$.subscribe(() => {
this.onResolutionChange();
});
this.tooltipText = this.computeTooltip();
if (!this.unavailableLayer) {
if (
this.layer.visible &&
this.expandLegendIfVisible &&
this.layer.firstLoadComponent === true
) {
this.layer.firstLoadComponent = false;
this.layer.legendCollapsed = false;
}
this.toggleLegend(this.layer.legendCollapsed);
this.updateQueryBadge();

this.network$$ = this.networkService
.currentState()
.subscribe((state: ConnectionState) => {
this.state = state;
const resolution$ = this.layer.map.viewController.resolution$;
this.resolution$$ = resolution$.subscribe(() => {
this.onResolutionChange();
});
this.tooltipText = this.computeTooltip();

this.network$$ = this.networkService
.currentState()
.subscribe((state: ConnectionState) => {
this.state = state;
this.onResolutionChange();
});

this.layers$$ = this.layers$.subscribe(() => {
if (this.layer && this.layer.options.active) {
this.layerTool$.next(true);
this.renderer.addClass(this.elRef.nativeElement, this.focusedCls);
}
});

this.layers$$ = this.layers$.subscribe(() => {
if (this.layer && this.layer.options.active) {
this.layerTool$.next(true);
this.renderer.addClass(this.elRef.nativeElement, this.focusedCls);
if (this.changeDetection) {
this.changeDetection.subscribe(() => this.cdRef.detectChanges());
}
});

if (this.changeDetection) {
this.changeDetection.subscribe(() => this.cdRef.detectChanges());
}
}

ngOnDestroy() {
this.resolution$$.unsubscribe();
this.network$$.unsubscribe();
this.layers$$.unsubscribe();
this.resolution$$?.unsubscribe();
this.network$$?.unsubscribe();
this.layers$$?.unsubscribe();
}

toggleLegend(collapsed: boolean) {
Expand Down Expand Up @@ -282,4 +303,8 @@
this.layerCheck = !this.layerCheck;
this.checkbox.emit({ layer: this.layer, check: this.layerCheck });
}

deleteUnavailableLayer(anyLayerOptions: AnyLayerOptions) {
this.action.emit(anyLayerOptions);
}
}
Loading
Loading