Add label to timeline marker with current time.

This commit is contained in:
Dermot Duffy
2023-04-15 09:31:05 -07:00
parent 6ea7c7d260
commit 91f6f48696
4 changed files with 69 additions and 15 deletions
+26 -9
View File
@@ -19,7 +19,7 @@ import isEqual from 'lodash-es/isEqual';
import throttle from 'lodash-es/throttle'; import throttle from 'lodash-es/throttle';
import { ViewContext } from 'view'; import { ViewContext } from 'view';
import { DataSet } from 'vis-data/esnext'; import { DataSet } from 'vis-data/esnext';
import type { DataGroupCollectionType, IdType } from 'vis-timeline/esnext'; import type { DataGroupCollectionType, DateType, IdType } from 'vis-timeline/esnext';
import { import {
Timeline, Timeline,
TimelineEventPropertiesResult, TimelineEventPropertiesResult,
@@ -46,6 +46,7 @@ import { stopEventFromActivatingCardWideActions } from '../utils/action';
import { import {
contentsChanged, contentsChanged,
dispatchFrigateCardEvent, dispatchFrigateCardEvent,
formatDateAndTime,
isHoverableDevice, isHoverableDevice,
setOrRemoveAttribute, setOrRemoveAttribute,
} from '../utils/basic'; } from '../utils/basic';
@@ -89,6 +90,11 @@ declare module 'view' {
} }
} }
interface ExtendedTimeline extends Timeline {
// setCustomTimeMarker currently missing from Timeline types.
setCustomTimeMarker?(time: DateType, id?: IdType): void;
}
// An event used to fetch data required for thumbnail rendering. See special // An event used to fetch data required for thumbnail rendering. See special
// note below on why this is necessary. // note below on why this is necessary.
interface ThumbnailDataRequest { interface ThumbnailDataRequest {
@@ -206,8 +212,7 @@ export class FrigateCardTimelineCore extends LitElement {
protected _refDatePicker: Ref<FrigateCardDatePicker> = createRef(); protected _refDatePicker: Ref<FrigateCardDatePicker> = createRef();
protected _refTimeline: Ref<HTMLElement> = createRef(); protected _refTimeline: Ref<HTMLElement> = createRef();
protected _timeline?: ExtendedTimeline;
protected _timeline?: Timeline;
protected _timelineSource: TimelineDataSource | null = null; protected _timelineSource: TimelineDataSource | null = null;
@@ -417,6 +422,22 @@ export class FrigateCardTimelineCore extends LitElement {
} else { } else {
this._timeline?.setCustomTime(targetTime, TIMELINE_TARGET_BAR_ID); this._timeline?.setCustomTime(targetTime, TIMELINE_TARGET_BAR_ID);
} }
const window = this._timeline.getWindow();
const markerProportion =
(targetTime.getTime() - window.start.getTime()) /
(window.end.getTime() - window.start.getTime());
// Position the marker proportionally to how 'far' the pointer is being
// held relative to the timeline window.
this.setAttribute(
'target-bar-marker-direction',
markerProportion < 0.25 ? 'right' : markerProportion > 0.75 ? 'left' : 'center',
);
this._timeline?.setCustomTimeMarker?.(
formatDateAndTime(targetTime, true),
TIMELINE_TARGET_BAR_ID,
);
} else { } else {
this._removeTargetBar(); this._removeTargetBar();
} }
@@ -426,6 +447,7 @@ export class FrigateCardTimelineCore extends LitElement {
* Remove the target bar. * Remove the target bar.
*/ */
protected _removeTargetBar(): void { protected _removeTargetBar(): void {
this.removeAttribute('target-bar-direction');
if (this._targetBarVisible) { if (this._targetBarVisible) {
this._timeline?.removeCustomTime(TIMELINE_TARGET_BAR_ID); this._timeline?.removeCustomTime(TIMELINE_TARGET_BAR_ID);
this._targetBarVisible = false; this._targetBarVisible = false;
@@ -463,12 +485,7 @@ export class FrigateCardTimelineCore extends LitElement {
: results : results
.clone() .clone()
.resetSelectedResult() .resetSelectedResult()
.selectBestResult((media) => .selectBestResult((media) => findBestMediaIndex(media, targetTime));
findBestMediaIndex(
media,
targetTime,
),
);
const desiredView: FrigateCardView = this.mini const desiredView: FrigateCardView = this.mini
? targetTime >= new Date() ? targetTime >= new Date()
+21 -4
View File
@@ -144,13 +144,30 @@ div.vis-tooltip {
} }
.target_bar { .target_bar {
border-left: 2px solid var(--primary-color); background-color: var(--primary-color);
opacity: 0.7; width: 2px;
box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 3px 1px var(--primary-color));
z-index: 20;
// Prevent the mouse interacting with the custom time. // Prevent the mouse interacting with the custom time.
pointer-events: none; pointer-events: none;
} }
.target_bar .vis-custom-time-marker {
background-color: var(--primary-background-color);
color: var(--primary-text-color);
bottom: 0px;
top: unset;
}
:host([target-bar-marker-direction='right']) .target_bar .vis-custom-time-marker {
left: 2px;
}
:host([target-bar-marker-direction='left']) .target_bar .vis-custom-time-marker {
right: 2px;
}
:host([target-bar-marker-direction='center']) .target_bar .vis-custom-time-marker {
left: 0px;
transform: translateX(-50%);
}
.timeline-tools { .timeline-tools {
position: absolute; position: absolute;
@@ -162,4 +179,4 @@ div.vis-tooltip {
.timeline-tools ha-icon { .timeline-tools ha-icon {
cursor: pointer; cursor: pointer;
} }
+2 -2
View File
@@ -114,8 +114,8 @@ export const isHoverableDevice = (): boolean =>
* @param date A Date object. * @param date A Date object.
* @returns A date and time. * @returns A date and time.
*/ */
export const formatDateAndTime = (date: Date): string => { export const formatDateAndTime = (date: Date, includeSeconds?: boolean): string => {
return format(date, 'yyyy-MM-dd HH:mm'); return format(date, `yyyy-MM-dd HH:mm${includeSeconds ? ':ss' : ''}`);
}; };
/** /**
+20
View File
@@ -17,6 +17,7 @@ import {
prettifyTitle, prettifyTitle,
runWhenIdleIfSupported, runWhenIdleIfSupported,
setify, setify,
setOrRemoveAttribute,
sleep, sleep,
} from '../src/utils/basic'; } from '../src/utils/basic';
@@ -131,6 +132,10 @@ describe('formatDateAndTime', () => {
const date = new Date(2023, 3, 14, 13, 35, 0); const date = new Date(2023, 3, 14, 13, 35, 0);
expect(formatDateAndTime(date)).toBe('2023-04-14 13:35'); expect(formatDateAndTime(date)).toBe('2023-04-14 13:35');
}); });
it('should format date and time with seconds', () => {
const date = new Date(2023, 3, 14, 13, 35, 1);
expect(formatDateAndTime(date, true)).toBe('2023-04-14 13:35:01');
});
}); });
describe('formatDate', () => { describe('formatDate', () => {
@@ -220,3 +225,18 @@ describe('isValidDate', () => {
expect(isValidDate(new Date('moo'))).toBeFalsy(); expect(isValidDate(new Date('moo'))).toBeFalsy();
}); });
}); });
describe('setOrRemoveAttribute', () => {
it('should set attribute', () => {
const element = document.createElement('div');
setOrRemoveAttribute(element, true, 'key', 'value');
expect(element.getAttribute('key')).toBe('value');
});
it('should remove attribute date', () => {
const element = document.createElement('div');
element.setAttribute('key', 'value');
setOrRemoveAttribute(element, false, 'key');
expect(element.getAttribute('key')).toBeFalsy();
});
});