Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

641 fix follow current time for schematic status display #642

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 33 additions & 21 deletions src/components/general/DateTimeSlider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<div class="slider-container">
<vue-slider
v-model="dateIndex"
:max="maxIndex"
:marks="marks"
:hide-label="hideLabel"
step="1"
:tooltipFormatter="dateString"
silent
:max="maxIndex"
@change="stopFollowNow"
>
<template v-slot:step="{ active, style, activeStyle }">
Expand Down Expand Up @@ -80,11 +80,14 @@ import { computed, ref, watch } from 'vue'
import { scaleTime } from 'd3-scale'
import { DateTime } from 'luxon'

import { onMounted } from 'vue'
import { findDateIndex } from '@/lib/utils/findDateIndex'

import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/antd.css'

interface Properties {
selectedDate: Date
selectedDate?: Date
dates: Date[]
isLoading?: boolean
doFollowNow?: boolean
Expand All @@ -94,9 +97,9 @@ interface Properties {

const props = withDefaults(defineProps<Properties>(), {
isLoading: false,
doFollowNow: false,
doFollowNow: true,
playInterval: 1000,
followNowInterval: 10000,
followNowInterval: 60000,
})
const emit = defineEmits(['update:selectedDate', 'update:doFollowNow'])

Expand All @@ -113,6 +116,12 @@ let followNowIntervalTimer: ReturnType<typeof setInterval> | null = null

const hideLabel = ref(true)

onMounted(() => {
if (props.doFollowNow) {
startFollowNow()
}
})

const marks = computed(() => {
const dayMarks: Record<string, any> = {}
const dateScale = scaleTime().domain(props.dates)
Expand Down Expand Up @@ -142,14 +151,15 @@ const marks = computed(() => {

// Synchronise selectedDate property and local index variable.
watch(dateIndex, (index) => {
emit('update:selectedDate', props.dates[index] ?? new Date())
emit('update:selectedDate', props.dates[index])
})

watch(
() => props.selectedDate,
(selectedDate) => {
let index = findIndexForDate(selectedDate)
if (index == dateIndex.value) return
if (selectedDate === undefined) return
let index = findDateIndex(props.dates, selectedDate)
if (index === dateIndex.value) return
dateIndex.value = index
},
)
Expand All @@ -158,6 +168,7 @@ watch(
watch(doFollowNow, (doFollowNow) => {
emit('update:doFollowNow', doFollowNow)
})

watch(
() => props.doFollowNow,
(doFollowNowProp) => {
Expand All @@ -169,9 +180,20 @@ watch(
// member of the new dates array.
watch(
() => props.dates,
(_, oldDates) => {
const oldDate = oldDates[dateIndex.value]
dateIndex.value = findIndexForDate(oldDate)
() => {
if (doFollowNow.value) {
setDateToNow()
if (
props.selectedDate?.getTime() !== props.dates[dateIndex.value].getTime()
) {
emit('update:selectedDate', props.dates[dateIndex.value])
}
} else {
if (props.selectedDate) {
const oldDate = props.selectedDate
dateIndex.value = findDateIndex(props.dates, oldDate)
}
}
},
)

Expand Down Expand Up @@ -224,17 +246,7 @@ function stopFollowNow(): void {

function setDateToNow(): void {
const now = new Date()
dateIndex.value = findIndexForDate(now)
}

function findIndexForDate(date: Date): number {
const index = props.dates.findIndex((current) => current >= date)
if (index === -1) {
// No time was found that was larger than the current time, so use the first date.
return 0
} else {
return index
}
dateIndex.value = findDateIndex(props.dates, now)
}

function togglePlay(): void {
Expand Down
89 changes: 89 additions & 0 deletions src/lib/utils/findDateIndex.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { expect, test } from 'vitest'
import { findDateIndex } from './findDateIndex'

test('should return the index of the target date in the array', () => {
const dates = [
new Date('2022-01-01'),
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-03-01')
const expectedIndex = 2

const result = findDateIndex(dates, targetDate)

expect(result).toBe(expectedIndex)
})

test('should return the index of the target date ISO8601', () => {
const dates = [
new Date('2022-01-01'),
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-03-01T00:00:00.000Z')
const expectedIndex = 2

const result = findDateIndex(dates, targetDate)

expect(result).toBe(expectedIndex)
})

test('should return the index before the target date ISO8601', () => {
const dates = [
new Date('2022-01-01'),
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-03-01T00:00:00.100Z')
const expectedIndex = 3

const result = findDateIndex(dates, targetDate)

expect(result).toBe(expectedIndex)
})

test('should return the index of the target date in the array', () => {
const dates = [
new Date('2022-01-01'),
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-03-01T00:00:00.000Z')
const expectedIndex = 2

const result = findDateIndex(dates, targetDate)

expect(result).toBe(expectedIndex)
})

test('should return 0 if the target date is before the first date in the array', () => {
const dates = [
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-01-01')
const expectedIndex = 0
const result = findDateIndex(dates, targetDate)
expect(result).toBe(expectedIndex)
})

test('should return the last index of the array if the target date is after the latest date in the array', () => {
const dates = [
new Date('2022-01-01'),
new Date('2022-02-01'),
new Date('2022-03-01'),
new Date('2022-04-01'),
]
const targetDate = new Date('2022-05-01')
const expectedIndex = dates.length - 1

const result = findDateIndex(dates, targetDate)

expect(result).toBe(expectedIndex)
})
31 changes: 31 additions & 0 deletions src/lib/utils/findDateIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Finds the index of a target date in an array of dates using bisection.
* @param dates - The array of dates to search in.
* @param targetDate - The target date to find the index of.
* @returns The index of the target date in the array, or the length of the array if the target date is not found.
*/
export function findDateIndex(dates: Date[], targetDate: Date): number {
let left = 0
let right = dates.length - 1
console.log('target', targetDate, right)

while (left < right) {
const mid = Math.floor((left + right) / 2)
if (dates[mid].getTime() === targetDate.getTime()) {
return mid
} else if (dates[mid] < targetDate) {
left = mid + 1
} else {
right = mid - 1
}
}
return left
}

// export function findDateIndex(dates: Date[], targetDate: Date): number {
// let index = 0;
// while (index < dates.length && dates[index] <= targetDate) {
// index++
// }
// return index;
// }
3 changes: 3 additions & 0 deletions src/services/useSsd/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export interface UseSsdReturn {
dates: Ref<Date[]>
}

const REFRESH_INTERVAL = 1000 * 60 * 5 // 5 minutes

function findGroup(
capabilities: SsdGetCapabilitiesResponse,
name: string,
Expand Down Expand Up @@ -72,6 +74,7 @@ export function useSsd(
}

loadCapabilities()
setInterval(loadCapabilities, REFRESH_INTERVAL)

watchEffect(() => {
const groupIdValue = toValue(groupId)
Expand Down
1 change: 1 addition & 0 deletions src/views/SchematicStatusDisplayView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ onMounted(() => {
})

const selectedDateString = computed(() => {
if (selectedDate.value === undefined) return ''
const dateString = selectedDate.value.toISOString()
return dateString.substring(0, 19) + 'Z'
})
Expand Down
Loading