Skip to content

Commit

Permalink
#292 Controlled Time Layers only make initial query, refactored to re…
Browse files Browse the repository at this point in the history
…move a conflicting setTimeout (#293)
  • Loading branch information
tariqksoliman authored Dec 12, 2022
1 parent d52f58a commit 3e9604e
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 190 deletions.
14 changes: 7 additions & 7 deletions config/js/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -1121,20 +1121,20 @@ function makeLayerBarAndModal(d, level, options) {
timeFalseSel = "selected";
}

var timeGlobalSel = "",
var timeRequerySel = "",
timeLocalSel = "";
if (typeof d.time != "undefined") {
switch (d.time.type) {
case "global":
timeGlobalSel = "selected";
case "requery":
timeRequerySel = "selected";
break;
case "local":
timeLocalSel = "selected";
break;
default:
}
} else {
timeGlobalSel = "selected";
timeRequerySel = "selected";
}

var timeCompositeTileTrueSel = "",
Expand Down Expand Up @@ -1458,10 +1458,10 @@ function makeLayerBarAndModal(d, level, options) {
"</div>" +
"<div id='timeTypeEl' class='input-field col s2 push-s1' style='display: " + timeTypeEl + "'>" +
"<select>" +
"<option value='global' " + timeGlobalSel + ">Global</option>" +
"<option value='requery' " + timeRequerySel + ">Requery</option>" +
"<option value='local' " + timeLocalSel + ">Local</option>" +
"</select>" +
"<label style='cursor: default;' title='Global: Will rerequest the entire layer with updated {time-like} parameters.\nLocal: Just filter the existing features based on the specified time properties.'>Tile Type <i class='mdi mdi-information mdi-14px'></i></label>" +
"<label style='cursor: default;' title='Requery: Will rerequest the entire layer with updated {time-like} parameters.\nLocal: Just filter the existing features based on the specified time properties.'>Time Type <i class='mdi mdi-information mdi-14px'></i></label>" +
"</div>" +
"<div id='timeStartPropEl' class='input-field col s2 push-s1' style='display: " + timeStartPropEl + "'>" +
"<input id='TimeStartProp" + n + "' type='text' class='validate' value='" + ((typeof d.time != "undefined") ? d.time.startProp || "" : "") + "'>" +
Expand Down Expand Up @@ -2379,7 +2379,7 @@ function save() {
// time properties
layerObject.time = {};
layerObject.time.enabled = modalTime; // static or timed
layerObject.time.type = modalTimeType; // 'global or local'
layerObject.time.type = modalTimeType; // 'requery or local'
layerObject.time.isRelative = true; // absolute or relative
layerObject.time.current =
new Date().toISOString().split(".")[0] + "Z"; // initial time
Expand Down
8 changes: 6 additions & 2 deletions docs/pages/Configure/Layers/Vector/Vector.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ A file path that points to a geojson. If the path is relative, it will be relati
_type:_ bool
Whether the layer can be dynamically updated or not. If true, the layer can be dynamically updated and the URL is not required.

If true and a URL is set and Time Enabled is true, the initial url query will be performed.

#### Legend

_type:_ string
Expand All @@ -55,10 +57,12 @@ A value from 0 to 1 of the layer's initial opacity. 1 is fully opaque.
_type:_ bool
True if the layer is time enabled. URLs that contain `{starttime}` or `{endtime}` will be dynamically replaced by their set values when the layer is fetched.

If true and a URL is set and Controlled is true, only the initial url query will be performed.

#### Time Type

_type:_ enum [Global, Individual]
Whether the layer should use global time values or function independently with its own time values.
_type:_ enum [Requery, Local]
When the time changes, whether the layer should Requery the source or filter the layer Locally (based on feature properties.

#### Time Format

Expand Down
172 changes: 45 additions & 127 deletions src/essence/Ancillary/TimeControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ const relativeTimeFormat = new RegExp(
var TimeControl = {
enabled: false,
isRelative: true,
currentTime: new Date().toISOString().split('.')[0] + 'Z',
currentTime: null,
timeOffset: '01:00:00',
startTime: new Date().toISOString().split('.')[0] + 'Z',
endTime: new Date().toISOString().split('.')[0] + 'Z',
startTime: null,
endTime: null,
relativeStartTime: '01:00:00',
relativeEndTime: '00:00:00',
globalTimeFormat: null,
Expand All @@ -37,40 +37,18 @@ var TimeControl = {
return
}

// prettier-ignore
const markup = [
"<label id='currentTimeLabel'></label>",

"<label id='startTimeLabel'>Start:</label>",
`<input id='startTimeInput' value='${this.startTime}'></input>`,

"<label id='endTimeLabel'>End:</label>",
`<input id='endTimeInput' value='${this.endTime}'></input>`,

"<label id='offsetTime'>Offset:</label>",
`<input id='offsetTimeInput' value='${this.timeOffset}'></input>`,

`<input id='isRelativeTime' type='checkbox' ${this.isRelative ? 'checked' : ''}></input>`,
"<label id='isRelativeTimeLabel'>Relative Time</label>",

"<label id='startRelativeTime'>Start: -</label>",
`<input id='startRelativeTimeInput' value='${this.relativeStartTime}'></input>`,

"<label id='endRelativeTime'>End: +</label>",
`<input id='endRelativeTimeInput' value='${this.relativeEndTime}'></input>`,
].join('\n');

TimeControl.timeUI = TimeUI.init(timeInputChange)

//updateTime()
if (L_.configData.time.visible == false) {
TimeControl.toggleTimeUI(false)
}

//initLayerDataTimes()
initLayerTimes()
initLayerDataTimes()
},
fina: function () {
initLayerTimes()
TimeControl.timeUI.fina()
},
toggleTimeUI: function (isOn) {
d3.select('#timeUI').style('visibility', function () {
Expand Down Expand Up @@ -177,18 +155,19 @@ var TimeControl = {
if (layer.time) return layer.time.end
return false
},
reloadLayer: async function (layer, evenIfOff) {
reloadLayer: async function (layer, evenIfOff, evenIfControlled) {
// reload layer
if (typeof layer == 'string') {
layer = L_.layersNamed[layer]
}

if (L_.layersGroup[layer.name] === null) return

var layerTimeFormat = d3.utcFormat(layer.time.format)
layer.time.current = TimeControl.currentTime // keeps track of when layer was refreshed

if (layer.type == 'tile') {
if (layer.time && layer.time.enabled == true) {
if (layer.type === 'tile') {
if (layer.time && layer.time.enabled === true) {
TimeControl.setLayerWmsParams(layer)
}

Expand All @@ -197,10 +176,14 @@ var TimeControl = {
L_.toggleLayer(layer)
}
} else {
var originalUrl = layer.url

// replace start/endtime keywords
if (layer.time && layer.time.enabled == true) {
if (layer.time.type === 'global') {
var originalUrl = layer.url
if (layer.time && layer.time.enabled === true) {
if (
layer.time.type === 'global' ||
layer.time.type === 'requery'
) {
layer.url = layer.url
.replace(
/{starttime}/g,
Expand All @@ -217,18 +200,20 @@ var TimeControl = {
layer.time.type === 'local' &&
layer.time.endProp != null
) {
L_.timeFilterVectorLayer(
layer.name,
new Date(layer.time.start).getTime(),
new Date(layer.time.end).getTime()
)
if (evenIfControlled === true || layer.controlled !== true)
L_.timeFilterVectorLayer(
layer.name,
new Date(layer.time.start).getTime(),
new Date(layer.time.end).getTime()
)
} else {
// refresh map
if (L_.toggledArray[layer.name] || evenIfOff) {
await Map_.refreshLayer(layer)
}
if (evenIfControlled === true || layer.controlled !== true)
if (L_.toggledArray[layer.name] || evenIfOff) {
await Map_.refreshLayer(layer)
}
// put start/endtime keywords back
if (layer.time && layer.time.enabled == true)
if (layer.time && layer.time.enabled === true)
layer.url = originalUrl
}
}
Expand All @@ -240,7 +225,7 @@ var TimeControl = {
var reloadedLayers = []
for (let layerName in L_.layersNamed) {
const layer = L_.layersNamed[layerName]
if (layer.time && layer.time.enabled == true) {
if (layer.time && layer.time.enabled === true) {
TimeControl.reloadLayer(layer)
reloadedLayers.push(layer.name)
}
Expand All @@ -251,7 +236,7 @@ var TimeControl = {
var updatedLayers = []
for (let layerName in L_.layersNamed) {
const layer = L_.layersNamed[layerName]
if (layer.time && layer.time.enabled == true) {
if (layer.time && layer.time.enabled === true) {
layer.time.start = TimeControl.startTime
layer.time.end = TimeControl.currentTime
d3.select('.starttime.' + layer.name.replace(/\s/g, '')).text(
Expand Down Expand Up @@ -287,8 +272,8 @@ var TimeControl = {
const layer = L_.layersNamed[layerName]
if (
layer.time &&
layer.time.enabled == true &&
layer.time.type == 'global'
layer.time.enabled === true &&
(layer.time.type === 'global' || layer.time.type === 'requery')
) {
TimeControl.setLayerTimeStatus(layer, color)
updatedLayers.push(layer.name)
Expand All @@ -298,45 +283,34 @@ var TimeControl = {
},
setLayerWmsParams: function (layer) {
var layerTimeFormat = d3.utcFormat(layer.time.format)
const l = L_.layersGroup[layer.name]

if (layer.type == 'tile') {
L_.layersGroup[layer.name].options.time = layerTimeFormat(
Date.parse(layer.time.end)
)
L_.layersGroup[layer.name].options.starttime = layerTimeFormat(
Date.parse(layer.time.start)
)
L_.layersGroup[layer.name].options.endtime = layerTimeFormat(
Date.parse(layer.time.end)
)
if (l != null && layer.type === 'tile') {
l.options.time = layerTimeFormat(Date.parse(layer.time.end))
l.options.starttime = layerTimeFormat(Date.parse(layer.time.start))
l.options.endtime = layerTimeFormat(Date.parse(layer.time.end))
}
},
}

function initLayerDataTimes() {
for (let i in L_.layersData) {
const layer = L_.layersData[i]
if (layer.time && layer.time.enabled == true) {
if (layer.time && layer.time.enabled === true) {
layer.time.start = L_.FUTURES.startTime
? L_.FUTURES.startTime.toISOString().split('.')[0] + 'Z'
: TimeControl.startTime
layer.time.end = L_.FUTURES.endTime
? L_.FUTURES.endTime.toISOString().split('.')[0] + 'Z'
: TimeControl.endTime
d3.select('.starttime.' + layer.name.replace(/\s/g, '')).text(
layer.time.start
)
d3.select('.endtime.' + layer.name.replace(/\s/g, '')).text(
layer.time.end
)
}
}
}

function initLayerTimes() {
for (let layerName in L_.layersNamed) {
const layer = L_.layersNamed[layerName]
if (layer.time && layer.time.enabled == true) {
if (layer.time && layer.time.enabled === true) {
layer.time.start = L_.FUTURES.startTime
? L_.FUTURES.startTime.toISOString().split('.')[0] + 'Z'
: TimeControl.startTime
Expand All @@ -357,58 +331,16 @@ function initLayerTimes() {
}
}

function updateTime() {
if (!TimeControl._updateLockedForAcceptingInput && TimeControl.enabled) {
// Continuously update global time clock and UI elements
var now = new Date()
var offset = 0
var offsetTime = d3.select('#offsetTimeInput').property('value')
if (relativeTimeFormat.test(offsetTime)) {
offset = parseTime(offsetTime)
}
var currentTime = new moment(now).add(offset, 'seconds')
d3.select('#currentTimeLabel').text(
TimeControl.globalTimeFormat(currentTime)
)
TimeControl.currentTime =
currentTime.toDate().toISOString().split('.')[0] + 'Z'

if (d3.select('#isRelativeTime').property('checked') == true) {
var start = parseTime(
d3.select('#startRelativeTimeInput').property('value')
)
var end = parseTime(
d3.select('#endRelativeTimeInput').property('value')
)
var startTime = new moment(currentTime).subtract(start, 'seconds')
var endTime = new moment(currentTime).add(end, 'seconds')

TimeControl.startTime =
startTime.toDate().toISOString().split('.')[0] + 'Z'
TimeControl.endTime =
endTime.toDate().toISOString().split('.')[0] + 'Z'

d3.select('#startTimeInput').property(
'value',
startTime.toISOString().split('.')[0] + 'Z'
)
d3.select('#endTimeInput').property(
'value',
endTime.toISOString().split('.')[0] + 'Z'
)
}
}
setTimeout(updateTime, 100)
}

function timeInputChange(startTime, endTime, currentTime) {
function timeInputChange(startTime, endTime, currentTime, skipUpdate) {
TimeControl.startTime = startTime
TimeControl.currentTime = currentTime == null ? endTime : currentTime
TimeControl.endTime = endTime

// Update layer times and reload
TimeControl.updateLayersTime()
TimeControl.reloadTimeLayers()
if (skipUpdate !== true) {
// Update layer times and reload
TimeControl.updateLayersTime()
TimeControl.reloadTimeLayers()
}
}

function parseTime(t) {
Expand All @@ -423,18 +355,4 @@ function parseTime(t) {
return seconds
}

function formatTimeString(seconds) {
// converts seconds to hh:mm:ss
if (typeof seconds === 'undefined') {
return '00:00:00'
}
var t = Math.abs(seconds)
var days = Math.floor(t / 86400)
var dt = new Date(t * 1000)
var dtString = dt.toISOString().substr(11, 8)
var s = dtString.split(':')
var hours = +s[0] + days * 24
return (seconds < 0 ? '-' : '') + hours + ':' + s[1] + ':' + s[2]
}

export default TimeControl
Loading

0 comments on commit 3e9604e

Please sign in to comment.