Improve quantity/display of thumbnail details.

This commit is contained in:
Dermot Duffy
2023-02-27 20:51:56 -08:00
parent bd52db3e31
commit d87c4244f6
5 changed files with 109 additions and 69 deletions
+75 -33
View File
@@ -15,7 +15,12 @@ import thumbnailFeatureEventStyle from '../scss/thumbnail-feature-event.scss';
import thumbnailFeatureRecordingStyle from '../scss/thumbnail-feature-recording.scss'; import thumbnailFeatureRecordingStyle from '../scss/thumbnail-feature-recording.scss';
import thumbnailStyle from '../scss/thumbnail.scss'; import thumbnailStyle from '../scss/thumbnail.scss';
import { stopEventFromActivatingCardWideActions } from '../utils/action.js'; import { stopEventFromActivatingCardWideActions } from '../utils/action.js';
import { errorToConsole, getDurationString, prettifyTitle } from '../utils/basic.js'; import {
errorToConsole,
formatDateAndTime,
getDurationString,
prettifyTitle,
} from '../utils/basic.js';
import { renderTask } from '../utils/task.js'; import { renderTask } from '../utils/task.js';
import { createFetchThumbnailTask, FetchThumbnailTaskArgs } from '../utils/thumbnail.js'; import { createFetchThumbnailTask, FetchThumbnailTaskArgs } from '../utils/thumbnail.js';
import { View } from '../view/view.js'; import { View } from '../view/view.js';
@@ -150,6 +155,9 @@ export class FrigateCardThumbnailDetailsEvent extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public seek?: Date; public seek?: Date;
@property({ attribute: false })
public cameraTitle?: string;
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.media) { if (!this.media) {
return; return;
@@ -158,35 +166,48 @@ export class FrigateCardThumbnailDetailsEvent extends LitElement {
const startTime = this.media.getStartTime(); const startTime = this.media.getStartTime();
const endTime = this.media.getEndTime(); const endTime = this.media.getEndTime();
const what = this.media.getWhat(); const what = this.media.getWhat();
const where = this.media.getWhere();
return html` <div class="left"> return html`
${what ? html`<div class="larger">${prettifyTitle(what.join(', '))}</div>` : ``} ${what
${startTime ? html` <div class="title" title=${localize('event.what')}>
? html` <div> ${prettifyTitle(what.join(', '))}
<span class="heading">${localize('event.start')}:</span> ${score ? html`(${(score * 100).toFixed(2) + '%'})` : ''}
<span>${format(startTime, 'HH:mm:ss')}</span>
</div>
<div>
<span class="heading">${localize('event.duration')}:</span>
<span
>${endTime
? getDurationString(startTime, endTime)
: localize('event.in_progress')}</span
>
</div>` </div>`
: ``} : ``}
<div class="details">
${startTime
? html` <div title=${localize('event.start')}>
<ha-icon .icon=${'mdi:calendar-clock-outline'}></ha-icon>
${formatDateAndTime(startTime)}
</div>
<div title=${localize('event.duration')}>
<ha-icon .icon=${'mdi:clock-outline'}></ha-icon>
${endTime
? getDurationString(startTime, endTime)
: localize('event.in_progress')}
</div>`
: ''}
${this.cameraTitle
? html` <div title=${localize('event.camera')}>
<ha-icon .icon=${'mdi:cctv'}></ha-icon>
${this.cameraTitle}
</div>`
: ''}
${where
? html` <div title=${localize('event.where')}>
<ha-icon .icon=${'mdi:map-marker-outline'}></ha-icon>
${prettifyTitle(where.join(', '))}
</div>`
: html``}
${this.seek ${this.seek
? html` <div> ? html` <div title=${localize('event.seek')}>
<span class="heading">${localize('event.seek')}</span> <ha-icon .icon=${'mdi:clock-fast'}></ha-icon>
<span>${format(this.seek, 'HH:mm:ss')}</span> ${format(this.seek, 'HH:mm:ss')}
</div>` </div>`
: html``} : html``}
</div> </div>
${score `;
? html`<div class="right">
<span class="larger">${(score * 100).toFixed(2) + '%'}</span>
</div>`
: ``}`;
} }
static get styles(): CSSResult { static get styles(): CSSResult {
@@ -209,22 +230,42 @@ export class FrigateCardThumbnailDetailsRecording extends LitElement {
if (!this.media) { if (!this.media) {
return; return;
} }
const startTime = this.media.getStartTime();
const endTime = this.media.getEndTime();
const eventCount = this.media.getEventCount(); const eventCount = this.media.getEventCount();
return html`<div class="left"> return html`
<div class="larger">${this.cameraTitle ?? ''}</div> ${this.cameraTitle
? html` <div class="title" title=${localize('recording.camera')}>
${this.cameraTitle}
</div>`
: ``}
<div class="details">
${startTime
? html` <div title=${localize('recording.start')}>
<ha-icon .icon=${'mdi:calendar-clock-outline'}></ha-icon>
${formatDateAndTime(startTime)}
</div>
<div title=${localize('recording.duration')}>
<ha-icon .icon=${'mdi:clock-outline'}></ha-icon>
${endTime
? getDurationString(startTime, endTime)
: localize('event.in_progress')}
</div>`
: ''}
${this.seek ${this.seek
? html` <div> ? html` <div title=${localize('event.seek')}>
<span class="heading">${localize('recording.seek')}</span> <ha-icon .icon=${'mdi:clock-fast'}></ha-icon>
<span>${format(this.seek, 'HH:mm:ss')}</span> ${format(this.seek, 'HH:mm:ss')}
</div>` </div>`
: html``} : html``}
</div>
${eventCount !== null ${eventCount !== null
? html`<div class="right"> ? html`<div title=${localize('recording.events')}>
<span class="larger">${eventCount}</span> <ha-icon .icon=${'mdi:shield-alert'}></ha-icon>
<span>${localize('recording.events')}</span> ${eventCount}
</div>` </div>`
: ``}`; : ``}
</div>
`;
} }
static get styles(): CSSResult { static get styles(): CSSResult {
@@ -336,6 +377,7 @@ export class FrigateCardThumbnail extends LitElement {
${this.details && ViewMediaClassifier.isEvent(this.media) ${this.details && ViewMediaClassifier.isEvent(this.media)
? html`<frigate-card-thumbnail-details-event ? html`<frigate-card-thumbnail-details-event
.media=${this.media ?? undefined} .media=${this.media ?? undefined}
.cameraTitle=${cameraTitle}
.seek=${this.seek} .seek=${this.seek}
></frigate-card-thumbnail-details-event>` ></frigate-card-thumbnail-details-event>`
: this.details && ViewMediaClassifier.isRecording(this.media) : this.details && ViewMediaClassifier.isRecording(this.media)
+8 -2
View File
@@ -392,11 +392,14 @@
"webrtc_card_waiting": "Waiting for WebRTC Card to load ..." "webrtc_card_waiting": "Waiting for WebRTC Card to load ..."
}, },
"event": { "event": {
"camera": "Camera",
"duration": "Duration", "duration": "Duration",
"in_progress": "In Progress", "in_progress": "In Progress",
"score": "Score", "score": "Score",
"seek": "Seek",
"start": "Start", "start": "Start",
"seek": "Seek" "what": "What",
"where": "Where"
}, },
"media_filter": { "media_filter": {
"all": "All", "all": "All",
@@ -426,8 +429,11 @@
"where": "Where" "where": "Where"
}, },
"recording": { "recording": {
"camera": "Camera",
"duration": "Duration",
"events": "Events", "events": "Events",
"seek": "Seek" "seek": "Seek",
"start": "Start"
}, },
"thumbnail": { "thumbnail": {
"no_thumbnail": "No thumbnail available", "no_thumbnail": "No thumbnail available",
+8 -2
View File
@@ -385,11 +385,14 @@
"webrtc_card_waiting": "Aspettando che la scheda WebRTC si carichi ..." "webrtc_card_waiting": "Aspettando che la scheda WebRTC si carichi ..."
}, },
"event": { "event": {
"camera": "",
"duration": "Durata", "duration": "Durata",
"in_progress": "In corso", "in_progress": "In corso",
"score": "Punteggio", "score": "Punteggio",
"seek": "Cercare",
"start": "Avvia", "start": "Avvia",
"seek": "Cercare" "what": "",
"where": ""
}, },
"media_filter": { "media_filter": {
"all": "", "all": "",
@@ -419,8 +422,11 @@
"where": "" "where": ""
}, },
"recording": { "recording": {
"camera": "",
"duration": "",
"events": "Eventi", "events": "Eventi",
"seek": "Cercare" "seek": "Cercare",
"start": ""
}, },
"thumbnail": { "thumbnail": {
"no_thumbnail": "Nessuna miniatura disponibile", "no_thumbnail": "Nessuna miniatura disponibile",
+8 -2
View File
@@ -385,11 +385,14 @@
"webrtc_card_waiting": "Aguardando o cartão WebRTC carregar ..." "webrtc_card_waiting": "Aguardando o cartão WebRTC carregar ..."
}, },
"event": { "event": {
"camera": "",
"duration": "Duração", "duration": "Duração",
"in_progress": "Em andamento", "in_progress": "Em andamento",
"score": "Pontuação", "score": "Pontuação",
"seek": "Procurar",
"start": "Início", "start": "Início",
"seek": "Procurar" "what": "",
"where": ""
}, },
"media_filter": { "media_filter": {
"all": "", "all": "",
@@ -419,8 +422,11 @@
"where": "" "where": ""
}, },
"recording": { "recording": {
"camera": "",
"duration": "",
"events": "Eventos", "events": "Eventos",
"seek": "Procurar" "seek": "Procurar",
"start": ""
}, },
"thumbnail": { "thumbnail": {
"no_thumbnail": "Nenhuma miniatura disponível", "no_thumbnail": "Nenhuma miniatura disponível",
+10 -30
View File
@@ -1,48 +1,28 @@
:host { :host {
display: flex; display: flex;
flex-direction: column;
width: 100%; width: 100%;
margin-left: 5px; margin-left: 5px;
padding: 8px; padding: 5px;
color: var(--primary-text-color); color: var(--primary-text-color);
overflow: hidden; overflow: hidden;
column-gap: 5%; column-gap: 5%;
} }
div.right, div.title {
div.left { font-size: 1.2rem;
display: flex; font-weight: bold;
flex-direction: column;
justify-content: center;
font-size: 0.8rem;
line-height: normal;
}
div.right {
align-items: center;
} }
div.left { div.details {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-wrap: wrap; flex-wrap: wrap;
align-content: flex-start; --mdc-icon-size: 16px;
justify-content: center;
overflow: hidden; // Details panel can shrink as well as grow.
min-height: 0px;
column-gap: 5%;
}
div.left div {
width: 100%;
}
span.heading {
font-weight: bold;
}
div.larger,
span.larger {
font-size: 1.4rem;
} }