Skip to content

Commit

Permalink
Feat: Introduce Layercontrol datetime tool (#1162)
Browse files Browse the repository at this point in the history
* feat: introduce `datetime` tool

* chore: clock icon

* fix: add datetime to default tools

* feat: introduce `disablePlay` and `slider` to `layerDatetime`

* chore: format

* fix: tools order

* fix: return layer def on `datetime:updated`

* fix: adapt story

* chore: format

* chore(docs): add basic docs for layerDateTime

* fix: mirror timecontrol API naming

---------

Co-authored-by: silvester-pari <silvester.pari@eox.at>
  • Loading branch information
A-Behairi and silvester-pari authored Aug 12, 2024
1 parent a1a2fcb commit 6df8daa
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 15 deletions.
1 change: 1 addition & 0 deletions elements/layercontrol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@eox/eslint-config": "^1.0.0",
"@eox/jsonform": "latest",
"@eox/map": "latest",
"@eox/timecontrol": "latest",
"@types/sortablejs": "^1.15.1",
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
Expand Down
128 changes: 128 additions & 0 deletions elements/layercontrol/src/components/layer-datetime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { LitElement, html } from "lit";
import { when } from "lit/directives/when.js";

/**
* `EOxLayerControlLayerDatetime` is a component that handles date time options for layers using eox-timecontrol.
* It triggers an event of the currently selected datetime value; allowing users to show and update a specific layer for a specific time.
*
*
* @element eox-layercontrol-layer-datetime
* @extends LitElement
*/
export class EOxLayerControlLayerDatetime extends LitElement {
// Define static properties for the component
static properties = {
unstyled: { type: Boolean },
noShadow: { type: Boolean },
layerDatetime: { attribute: false },
layer: { attribute: false },
};

constructor() {
super();

/**
* Render the element without additional styles
*
* @type {Boolean}
*/
this.unstyled = false;

/**
* Renders the element without a shadow root
*
* @type {Boolean}
*/
this.noShadow = false;

/**
* Layer config for eox-jsonform
*
* @type {{
* disablePlay?: boolean;
* slider?: boolean;
* currentStep: string|number;
* controlValues: (string|number)[]
* }}
*/
this.layerDatetime = null;

/**
* The native OL layer
*
* @type {import("ol/layer").Layer}
* @see {@link https://openlayers.org/en/latest/apidoc/module-ol_layer_Layer-Layer.html}
*/
this.layer = null;
}

/**
* Overrides createRenderRoot to handle shadow DOM creation based on the noShadow property.
*/
createRenderRoot() {
return this.noShadow ? this : super.createRenderRoot();
}

/**
* Handles timecontrol Stepchange &
* triggers `datetime:updated` event on step change
*
* @param {CustomEvent<{currentStep:string|number}>} evt
**/
#handleStepChange(evt) {
this.dispatchEvent(
new CustomEvent("datetime:updated", {
bubbles: true,
detail: {
datetime: evt.detail.currentStep,
layer: this.layer,
},
})
);

this.layerDatetime.currentStep = evt.detail.currentStep;
this.requestUpdate();
}

/**
* Renders a Time Control for datetime options of a layer.
*/
render() {
if (!customElements.get("eox-timecontrol")) {
console.error(
"Please import @eox/timecontrol in order to use layerDatetime"
);
}
return html`
<style>
${this.#styleBasic}
${!this.unstyled && this.#styleEOX}
</style>
${when(
this.layerDatetime,
() => html`
<!-- Render a Timecontrol for layer date time -->
<eox-timecontrol
?unstyled=${this.unstyled}
.for=${undefined}
.layer=${undefined}
.slider=${this.layerDatetime.slider ?? false}
.disablePlay=${this.layerDatetime.disablePlay ?? false}
.controlValues=${this.layerDatetime.controlValues}
.controlProperty=${undefined}
current-step=${this.layerDatetime.currentStep}
@stepchange=${this.#handleStepChange}
></eox-timecontrol>
`
)}
`;
}

#styleBasic = ``;
#styleEOX = ``;
}

customElements.define(
"eox-layercontrol-layer-datetime",
EOxLayerControlLayerDatetime
);
21 changes: 21 additions & 0 deletions elements/layercontrol/src/components/layer-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { map } from "lit/directives/map.js";
import { when } from "lit/directives/when.js";
import { live } from "lit/directives/live.js";
import "./layer-config";
import "./layer-datetime";
import "./tabs";
import { button } from "../../../../utils/styles/button";
import { radio } from "../../../../utils/styles/radio";
Expand Down Expand Up @@ -171,6 +172,22 @@ export class EOxLayerControlLayerTools extends LitElement {
`
)}
</div>
<div slot="datetime-content">
<!-- Layer datetime -->
${when(
this.layer.get("layerDatetime"),
() => html`
<eox-layercontrol-layer-datetime
slot="datetime-content"
.noShadow=${true}
.layerDatetime=${this.layer.get("layerDatetime")}
.layer=${this.layer}
.unstyled=${this.unstyled}
@changed=${() => this.requestUpdate()}
></eox-layercontrol-layer-datetime>
`
)}
</div>
<div slot="remove-icon">${this._removeButton()}</div>
<div slot="sort-icon">${this._sortButton()}</div>
</eox-layercontrol-tabs>
Expand Down Expand Up @@ -268,6 +285,10 @@ export class EOxLayerControlLayerTools extends LitElement {
button.icon[slot=config-icon]::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23004170' viewBox='0 0 24 24'%3E%3Ctitle%3Etune%3C/title%3E%3Cpath d='M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z' /%3E%3C/svg%3E");
}
details.tools summary .datetime-icon,
button.icon[slot=datetime-icon]::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ctitle%3Eclock-outline%3C/title%3E%3Cpath d='M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22C6.47,22 2,17.5 2,12A10,10 0 0,1 12,2M12.5,7V12.25L17,14.92L16.25,16.15L11,13V7H12.5Z' /%3E%3C/svg%3E");
}
.single-action .remove-icon::before,
[slot=remove-icon] button.icon::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23ff0000' viewBox='0 0 24 24'%3E%3Ctitle%3Edelete-outline%3C/title%3E%3Cpath d='M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19M8,9H16V19H8V9M15.5,4L14.5,3H9.5L8.5,4H5V6H19V4H15.5Z' /%3E%3C/svg%3E");
Expand Down
1 change: 1 addition & 0 deletions elements/layercontrol/src/enums/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export {
STORIES_LAYER_EOX_CLOUDLESS_2019,
STORIES_LAYER_DEFORESTED_BIOMASS,
STORIES_LAYER_TERRAIN_LIGHT,
STORIES_LAYER_VESSEL_DENSITY_CARGO,
STORIES_LAYER_CROPOMHUSC2,
STORIES_LAYER_SEE,
} from "./stories";
98 changes: 98 additions & 0 deletions elements/layercontrol/src/enums/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,101 @@ export const STORIES_LAYER_SEE = {
],
},
};

export const STORIES_LAYER_VESSEL_DENSITY_CARGO = {
type: "Tile",
properties: {
id: "lz83t24tf72212zcxq6",
title: "vessel_density_cargo",
layerControlExpand: true,
layerControlToolsExpand: true,
layerDatetime: {
disablePlay: true,
slider: true,
currentStep: "2021-03-01",
controlValues: [
"2022-12-01",
"2022-11-01",
"2022-10-01",
"2022-09-01",
"2022-08-01",
"2022-07-01",
"2022-06-01",
"2022-05-01",
"2022-04-01",
"2022-03-01",
"2022-02-01",
"2022-01-01",
"2021-12-01",
"2021-11-01",
"2021-10-01",
"2021-09-01",
"2021-08-01",
"2021-07-01",
"2021-06-01",
"2021-05-01",
"2021-04-01",
"2021-03-01",
"2021-02-01",
"2021-01-01",
"2020-12-01",
"2020-11-01",
"2020-10-01",
"2020-09-01",
"2020-08-01",
"2020-07-01",
"2020-06-01",
"2020-05-01",
"2020-04-01",
"2020-03-01",
"2020-02-01",
"2020-01-01",
"2019-12-01",
"2019-11-01",
"2019-10-01",
"2019-09-01",
"2019-08-01",
"2019-07-01",
"2019-06-01",
"2019-05-01",
"2019-04-01",
"2019-03-01",
"2019-02-01",
"2019-01-01",
"2018-12-01",
"2018-11-01",
"2018-10-01",
"2018-09-01",
"2018-08-01",
"2018-07-01",
"2018-06-01",
"2018-05-01",
"2018-04-01",
"2018-03-01",
"2018-02-01",
"2018-01-01",
"2017-12-01",
"2017-11-01",
"2017-10-01",
"2017-09-01",
"2017-08-01",
"2017-07-01",
"2017-06-01",
"2017-05-01",
"2017-04-01",
"2017-03-01",
"2017-02-01",
"2017-01-01",
],
},
},
source: {
type: "TileWMS",
url: "https://services.sentinel-hub.com/ogc/wms/0635c213-17a1-48ee-aef7-9d1731695a54",
params: {
LAYERS: ["AWS_VIS_VESSELDENSITY_CARGO"],
TILED: true,
TIME: "2021-03-01T00:00:00Z",
},
},
};
2 changes: 1 addition & 1 deletion elements/layercontrol/src/helpers/layer-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const _parseTools = (tools, layer) =>
if (["remove", "sort"].includes(t)) pass = false;
if (t === "info") pass = layer.get("description");
if (t === "config") pass = layer.get("layerConfig");

if (t === "datetime") pass = layer.get("layerDatetime");
return pass;
});

Expand Down
16 changes: 15 additions & 1 deletion elements/layercontrol/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ import {
* #### `layerConfig?: Object`
* Configuration options for the layer (displayed in the layer tools' "config" tab)
*
* #### `layerDateTime?: Object`
* Partial eox-timecontrol config passed to the "datetime" tool
*
* @element eox-layercontrol
*/
export class EOxLayerControl extends LitElement {
Expand Down Expand Up @@ -108,7 +111,7 @@ export class EOxLayerControl extends LitElement {
*
* @type {Array<String>}
*/
this.tools = ["info", "opacity", "config", "remove", "sort"];
this.tools = ["info", "opacity", "datetime", "config", "remove", "sort"];

/**
* Enable-disable external layer
Expand Down Expand Up @@ -170,6 +173,16 @@ export class EOxLayerControl extends LitElement {
this.dispatchEvent(new CustomEvent("layerchange", { detail: evt.detail }));
}

/**
* Dispatches datetime updates from layer datetime to the layercontrol
* @param {CustomEvent} evt
*/
#handleDatetimeUpdate(evt) {
this.dispatchEvent(
new CustomEvent("datetime:updated", { detail: evt.detail })
);
}

render() {
// Checks if there are any layers with the 'layerControlOptional' property set to true
const layers = this.map?.getLayers().getArray();
Expand Down Expand Up @@ -209,6 +222,7 @@ export class EOxLayerControl extends LitElement {
.tools=${this.tools}
.unstyled=${this.unstyled}
@changed=${this.#handleLayerControlLayerListChange}
@datetime:updated=${this.#handleDatetimeUpdate}
></eox-layercontrol-layer-list>
`
)}
Expand Down
1 change: 1 addition & 0 deletions elements/layercontrol/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as ExpandedLayersStory } from "./expanded-layers";
export { default as ToolsStory } from "./tools";
export { default as LayerConfigStory } from "./layer-config";
export { default as LayerStylesConfigStory } from "./layer-config-styles";
export { default as layerDatetimeStory } from "./layer-datetime";
export { default as HiddenLayersStory } from "./hidden-layer";
export { default as SingleLayerStory } from "./single-layer";
export { default as LayerListStory } from "./layer-list";
Expand Down
36 changes: 36 additions & 0 deletions elements/layercontrol/stories/layer-datetime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { html } from "lit";
import {
STORIES_LAYER_VESSEL_DENSITY_CARGO,
STORIES_MAP_STYLE,
STORIES_LAYER_TERRAIN_LIGHT,
} from "../src/enums";

export const LayerDateTime = {
args: {
/** @param {CustomEvent<{datetime:string|number,layer:import("ol/layer").Layer}>} evt */
onDatetimeUpdated: (evt) => {
evt.detail.layer.getSource().updateParams({ TIME: evt.detail.datetime });
},
},
render: (args) => html`
<eox-layercontrol
.tools=${["datetime"]}
for="eox-map#datetime"
@datetime:updated=${args.onDatetimeUpdated}
></eox-layercontrol>
<hr />
<eox-map
.center=${[2000000, 8000000]}
.zoom=${4}
id="datetime"
.style=${STORIES_MAP_STYLE}
.layers=${[
STORIES_LAYER_VESSEL_DENSITY_CARGO,
STORIES_LAYER_TERRAIN_LIGHT,
]}
>
</eox-map>
`,
};

export default LayerDateTime;
Loading

0 comments on commit 6df8daa

Please sign in to comment.