remote-access protocol collection; dashboard site timezone + badge alignment
This commit is contained in:
@@ -237,7 +237,8 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { notificationsApi, businessUnitsApi, dashboardDefaultsApi } from '@/api'
|
||||
import { notificationsApi, businessUnitsApi, dashboardDefaultsApi, settingsApi } from '@/api'
|
||||
import { formatInZone, zonedInputFromUtc, DEFAULT_TZ } from '@/utils/datetime'
|
||||
import { getFacilityName, getSiteLogo, getServicenowUrls } from '@/utils/siteSettings'
|
||||
import { withBase } from '@/utils/basePath'
|
||||
|
||||
@@ -386,17 +387,30 @@ const upcomingNotifications = computed(() =>
|
||||
)
|
||||
|
||||
// Clock
|
||||
// Site timezone drives every time on the board. Defaults until the setting
|
||||
// loads, so a slow settings call shows plausible time rather than blank.
|
||||
const siteTimezone = ref(DEFAULT_TZ)
|
||||
|
||||
const currentTime = ref('')
|
||||
function updateClock() {
|
||||
const now = new Date()
|
||||
currentTime.value = now.toLocaleTimeString('en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
// The wall clock too: a board showing a different time to the cards beneath
|
||||
// it is worse than either being wrong on its own.
|
||||
currentTime.value = formatInZone(new Date(), siteTimezone.value, {
|
||||
year: undefined, month: undefined, day: undefined,
|
||||
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Before the first clock tick, so the board never renders viewer-zone time.
|
||||
try {
|
||||
const response = await settingsApi.get('site_timezone')
|
||||
const value = response?.data?.data?.value
|
||||
if (value) siteTimezone.value = value
|
||||
} catch (e) {
|
||||
// Keep the default zone; the board must still come up.
|
||||
}
|
||||
|
||||
updateClock()
|
||||
setInterval(updateClock, 1000)
|
||||
|
||||
@@ -528,15 +542,24 @@ function stateKind(item) {
|
||||
// timestamp alone makes a reader do the arithmetic.
|
||||
function startsWhen(dateStr) {
|
||||
if (!dateStr) return 'SOON'
|
||||
const start = new Date(dateStr)
|
||||
const time = start.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })
|
||||
const startday = new Date(start.getFullYear(), start.getMonth(), start.getDate())
|
||||
const now = new Date()
|
||||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
||||
const days = Math.round((startday - today) / 86400000)
|
||||
const time = formatInZone(dateStr, siteTimezone.value, {
|
||||
year: undefined, month: undefined, day: undefined,
|
||||
hour: 'numeric', minute: '2-digit'
|
||||
})
|
||||
// TODAY/TOMORROW has to be decided on the SITE's calendar day. Doing the
|
||||
// arithmetic on browser-local days makes the wording itself wrong for a
|
||||
// viewer in another zone - a card can read TOMORROW to a remote admin and
|
||||
// TODAY on the board, from the same data.
|
||||
const startday = zonedInputFromUtc(dateStr, siteTimezone.value).slice(0, 10)
|
||||
const todayday = zonedInputFromUtc(new Date(), siteTimezone.value).slice(0, 10)
|
||||
const days = Math.round(
|
||||
(new Date(`${startday}T00:00:00`) - new Date(`${todayday}T00:00:00`)) / 86400000)
|
||||
if (days <= 0) return `TODAY ${time}`
|
||||
if (days === 1) return `TOMORROW ${time}`
|
||||
const when = start.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' })
|
||||
const when = formatInZone(dateStr, siteTimezone.value, {
|
||||
weekday: 'short', month: 'short', day: 'numeric',
|
||||
hour: undefined, minute: undefined
|
||||
})
|
||||
return `${when} ${time}`
|
||||
}
|
||||
|
||||
@@ -604,17 +627,20 @@ function textOn(backgroundcolor) {
|
||||
return (0.2126 * r + 0.7152 * g + 0.0722 * b) > 150 ? '#231b00' : '#fff'
|
||||
}
|
||||
|
||||
// SITE zone, not the viewer's. A board hangs on a wall in the plant: it must
|
||||
// read plant time whatever the machine driving it is set to, and a kiosk with a
|
||||
// wrong system timezone would otherwise silently show wrong times to the floor.
|
||||
function formatTime(dateStr) {
|
||||
if (!dateStr) return ''
|
||||
return new Date(dateStr).toLocaleTimeString('en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
return formatInZone(dateStr, siteTimezone.value, {
|
||||
year: undefined, month: undefined, day: undefined,
|
||||
hour: '2-digit', minute: '2-digit'
|
||||
})
|
||||
}
|
||||
|
||||
function formatDateTime(dateStr) {
|
||||
if (!dateStr) return ''
|
||||
return new Date(dateStr).toLocaleString('en-US', {
|
||||
return formatInZone(dateStr, siteTimezone.value, {
|
||||
weekday: 'short',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
@@ -935,7 +961,9 @@ function handlePhotoError(e) {
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 8px;
|
||||
/* No margin-bottom. .chip-row centres each item's MARGIN box, so a bottom
|
||||
margin here lifted this chip ~4px and left the state chip beside it
|
||||
looking low. The row already provides the spacing underneath. */
|
||||
}
|
||||
|
||||
/* Type colour as a bar down the left edge, the way the legacy board marked a
|
||||
|
||||
Reference in New Issue
Block a user