Skip to content

Commit b8a5259

Browse files
Merge pull request #17 from SunshineLuke90/indicator-refresh
Indicator refresh interval fixes
2 parents 893155b + ebf7c93 commit b8a5259

6 files changed

Lines changed: 85 additions & 6 deletions

File tree

indicator/config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@
1919
"valueMaxDecimalPlaces": 1,
2020
"valuePrefix": "",
2121
"valueSuffix": "",
22-
"valueUnitPrefix": true
22+
"valueUnitPrefix": true,
23+
"refreshIntervalValue": 5,
24+
"refreshIntervalUnit": "minutes"
2325
}

indicator/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
{
22
"name": "exb-indicator",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "A simple indicator widget for Experience Builder, based on the indicator widget from ArcGIS Dashboards.",
55
"author": "Lucius Creamer",
66
"license": "MIT",
77
"keywords": [
88
"exb-widget",
99
"experience-builder",
1010
"exb"
11-
]
11+
],
12+
"repository": {
13+
"type": "git",
14+
"url": "git+https://github.com/SunshineLuke90/widgets.git",
15+
"directory": "indicator"
16+
}
1217
}

indicator/src/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ export interface Config {
7373

7474
showLastUpdateTime: boolean
7575
lastUpdateTimeTextColor: string
76+
77+
refreshIntervalValue: number
78+
refreshIntervalUnit: "seconds" | "minutes" | "hours"
7679
}
7780

7881
export type IMConfig = ImmutableObject<Config>

indicator/src/runtime/utils.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,7 @@ export function getActiveStyles (
297297

298298
export function relativeTime (date: Date): string {
299299
const diff = Math.floor((Date.now() - date.getTime()) / 1000)
300-
if (diff < 60) return "Updated just now"
300+
if (diff < 60) return `Updated ${diff}s ago`
301301
if (diff < 3600) return `Updated ${Math.floor(diff / 60)}m ago`
302-
if (diff < 86400) return `Updated ${Math.floor(diff / 3600)}h ago`
303-
return `Updated ${date.toLocaleDateString()}`
302+
return `Updated ${Math.floor(diff / 3600)}h ago`
304303
}

indicator/src/runtime/widget.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,33 @@ export default function Widget (props: AllWidgetProps<IMConfig>) {
405405
setFeatureIndex((prev) => (prev >= featureCount - 1 ? 0 : prev + 1))
406406
}, [featureCount])
407407

408+
// ── Display tick (re-renders "Last Updated" text every 5 s) ─────────
409+
410+
const [, setTick] = React.useState(0)
411+
React.useEffect(() => {
412+
if (!isConfigured) return
413+
const id = setInterval(() => { setTick((v) => v + 1) }, 5000)
414+
return () => { clearInterval(id) }
415+
}, [isConfigured])
416+
417+
// ── Data refresh on configurable interval ────────────────────────────
418+
419+
const refreshMs = React.useMemo(() => {
420+
const val = config.refreshIntervalValue ?? 5
421+
const unit = config.refreshIntervalUnit ?? "minutes"
422+
const multiplier = unit === "hours" ? 3600000 : unit === "minutes" ? 60000 : 1000
423+
return Math.max(val * multiplier, 1000)
424+
}, [config.refreshIntervalValue, config.refreshIntervalUnit])
425+
426+
React.useEffect(() => {
427+
if (!isConfigured) return
428+
const id = setInterval(() => {
429+
setMainTrigger((v) => v + 1)
430+
setRefTrigger((v) => v + 1)
431+
}, refreshMs)
432+
return () => { clearInterval(id) }
433+
}, [isConfigured, refreshMs])
434+
408435
// ── Main query effect ──────────────────────────────────────────────────
409436

410437
React.useEffect(() => {

indicator/src/setting/setting.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,49 @@ export default function Setting (props: AllWidgetSettingProps<IMConfig>) {
830830
}}
831831
/>
832832
</SettingRow>
833+
<SettingRow
834+
label={props.intl.formatMessage({
835+
id: "refreshInterval",
836+
defaultMessage: "Refresh Interval"
837+
})}
838+
flow={"wrap"}
839+
>
840+
<div style={{ display: "flex", gap: 6, alignItems: "center" }}>
841+
<NumericInput
842+
min={1}
843+
max={9999}
844+
value={config.refreshIntervalValue ?? 5}
845+
style={{ width: 70 }}
846+
onChange={(value) => {
847+
onSettingChange({
848+
id,
849+
config: {
850+
...config,
851+
refreshIntervalValue: value
852+
}
853+
})
854+
}}
855+
/>
856+
<Select
857+
size="sm"
858+
style={{ width: 110 }}
859+
value={config.refreshIntervalUnit ?? "minutes"}
860+
onChange={(e) => {
861+
onSettingChange({
862+
id,
863+
config: {
864+
...config,
865+
refreshIntervalUnit: e.target.value
866+
}
867+
})
868+
}}
869+
>
870+
<option value="seconds">Seconds</option>
871+
<option value="minutes">Minutes</option>
872+
<option value="hours">Hours</option>
873+
</Select>
874+
</div>
875+
</SettingRow>
833876
<SettingRow
834877
label={props.intl.formatMessage({
835878
id: "conditionalFormatting",

0 commit comments

Comments
 (0)