Show the fiscal week beside the site name
The classic ASP site prints a week number under the site title, and people quote it in conversation and on paperwork. Anyone with both sites open needs the two to agree, so this is a port of the old arithmetic rather than a fresh interpretation of what a fiscal week is: ISO 8601, week 1 contains 4 January, and the week's Thursday decides which year it belongs to. That rule is what makes late December and early January land in the right year, which is exactly where a naive day-of-year count goes wrong, so it is what the tests cover. Worth recording: a true GE fiscal calendar need not follow ISO weeks. Nobody has asked for a different rule, and inventing one here would silently disagree with the site people compare against. Computed in local time on purpose. The number people quote is the one on the wall where they stand, and a UTC week rolls over hours early in the evening at a US site. The sidebar re-checks every half hour; the shop-floor board picks it up with the clock it already ticks.
This commit is contained in:
@@ -4,6 +4,11 @@
|
||||
<div class="sidebar-header">
|
||||
<img :src="siteLogo" alt="Site logo" class="sidebar-logo" />
|
||||
<h1>{{ facilityName }}</h1>
|
||||
<!-- Under the site name, where the classic site put it. -->
|
||||
<div class="fiscal-week">
|
||||
<span class="fiscal-week-label">Fiscal Week</span>
|
||||
<span class="fiscal-week-number">{{ currentFiscalWeek }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-search">
|
||||
@@ -98,7 +103,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import ToastHost from '../components/ToastHost.vue'
|
||||
import {
|
||||
@@ -109,6 +114,7 @@ import {
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { currentTheme, toggleTheme } from '../stores/theme'
|
||||
import { dashboardApi, notificationsApi } from '../api'
|
||||
import { fiscalWeek } from '@/utils/fiscalWeek'
|
||||
import { getFacilityName, getSiteLogo, getServicenowUrls } from '../utils/siteSettings'
|
||||
import { withBase } from '../utils/basePath'
|
||||
|
||||
@@ -137,6 +143,11 @@ const searchQuery = ref('')
|
||||
const navItems = ref([])
|
||||
const activeNotifications = ref([])
|
||||
const facilityName = ref('ShopDB')
|
||||
|
||||
// A tab left open overnight would otherwise show last week's number until
|
||||
// somebody reloaded. Recomputed on a timer rather than only at mount.
|
||||
const currentFiscalWeek = ref(fiscalWeek())
|
||||
let fiscalWeekTimer = null
|
||||
const siteLogo = ref(withBase('/ge-aerospace-logo.svg'))
|
||||
const servicenowConfig = ref({ enabled: true, searchUrl: '' })
|
||||
|
||||
@@ -222,6 +233,10 @@ function buildNavItems(items) {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Half-hourly: cheap, and it crosses midnight into the new week without a
|
||||
// reload on a screen nobody touches.
|
||||
fiscalWeekTimer = setInterval(() => { currentFiscalWeek.value = fiscalWeek() }, 30 * 60 * 1000)
|
||||
|
||||
getFacilityName().then(name => { facilityName.value = name })
|
||||
getSiteLogo().then(logo => { siteLogo.value = logo })
|
||||
getServicenowUrls().then(config => { servicenowConfig.value = config })
|
||||
@@ -274,9 +289,32 @@ function onAvatarError(event) {
|
||||
event.target.src = fallbackAvatar
|
||||
event.target.classList.add('ge-avatar-fallback')
|
||||
}
|
||||
onUnmounted(() => {
|
||||
if (fiscalWeekTimer) clearInterval(fiscalWeekTimer)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Fiscal week, under the site name, where the classic site put it. The number
|
||||
carries the weight; the label is small because it never changes. */
|
||||
.fiscal-week {
|
||||
margin-top: 0.35rem;
|
||||
text-align: center;
|
||||
line-height: 1.15;
|
||||
}
|
||||
.fiscal-week-label {
|
||||
display: block;
|
||||
font-size: 0.62rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.65;
|
||||
}
|
||||
.fiscal-week-number {
|
||||
display: block;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Footer user block: identity row on top, compact icon actions below, all
|
||||
kept inside the fixed-width sidebar (no full-width buttons overflowing). */
|
||||
.user-menu { display: flex; flex-direction: column; gap: 0.6rem; }
|
||||
@@ -305,4 +343,4 @@ function onAvatarError(event) {
|
||||
text-decoration: none;
|
||||
}
|
||||
.icon-btn:hover { background: rgba(255,255,255,0.16); color: #fff; }
|
||||
</style>
|
||||
</style>
|
||||
@@ -9,6 +9,9 @@
|
||||
<div class="header-center">
|
||||
<div class="location-title">{{ facilityName }}</div>
|
||||
<h1>Shopfloor Dashboard</h1>
|
||||
<!-- Same number the sidebar and the classic site show, since the board
|
||||
is what people read it off from across the floor. -->
|
||||
<div class="fiscal-week">Fiscal Week {{ currentFiscalWeek }}</div>
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
@@ -241,9 +244,12 @@ import { notificationsApi, businessUnitsApi, dashboardDefaultsApi, settingsApi }
|
||||
import { formatInZone, zonedInputFromUtc, DEFAULT_TZ } from '@/utils/datetime'
|
||||
import { getFacilityName, getSiteLogo, getServicenowUrls } from '@/utils/siteSettings'
|
||||
import { withBase } from '@/utils/basePath'
|
||||
import { fiscalWeek } from '@/utils/fiscalWeek'
|
||||
|
||||
const loading = ref(true)
|
||||
const facilityName = ref('ShopDB')
|
||||
// A wall display runs for weeks; the clock tick refreshes this too.
|
||||
const currentFiscalWeek = ref(fiscalWeek())
|
||||
const siteLogo = ref(withBase('/ge-aerospace-logo.svg'))
|
||||
// Employee photo placeholder: the shipped GE monogram (square avatar). Kept
|
||||
// separate from siteLogo so a blank/broken site_logo setting never leaves an
|
||||
@@ -716,6 +722,15 @@ function handlePhotoError(e) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fiscal-week {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2px;
|
||||
color: #b8c4d8;
|
||||
margin-top: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.location-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user