Improve error rendering.
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
scrollbar-width: none; // Hide scrollbar: Firefox
|
scrollbar-width: none; // Hide scrollbar: Firefox
|
||||||
}
|
}
|
||||||
|
|
||||||
.frigate-card-exception {
|
.frigate-card-attention {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
+42
-28
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
// TODO Action handlers.
|
// TODO Action handlers.
|
||||||
|
|
||||||
// TODO _getEvents may throw errors, catch them when called.
|
|
||||||
|
|
||||||
// TODO Can I use Zod for FrigateCardConfig validation?
|
// TODO Can I use Zod for FrigateCardConfig validation?
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
@@ -34,7 +32,7 @@ import './editor';
|
|||||||
|
|
||||||
import style from './frigate-card.scss'
|
import style from './frigate-card.scss'
|
||||||
|
|
||||||
import { frigateEventSchema, frigateGetEventsResponseSchema } from './types';
|
import { frigateGetEventsResponseSchema } from './types';
|
||||||
import type { FrigateCardConfig, FrigateEvent, FrigateGetEventsResponse, GetEventsParameters, ControlVideosParameters } from './types';
|
import type { FrigateCardConfig, FrigateEvent, FrigateGetEventsResponse, GetEventsParameters, ControlVideosParameters } from './types';
|
||||||
import { actionHandler } from './action-handler-directive';
|
import { actionHandler } from './action-handler-directive';
|
||||||
import { CARD_VERSION } from './const';
|
import { CARD_VERSION } from './const';
|
||||||
@@ -228,35 +226,51 @@ export class FrigateCard extends LitElement {
|
|||||||
try {
|
try {
|
||||||
raw_json = await response.json();
|
raw_json = await response.json();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.warn(e);
|
||||||
throw new Error(`Could not JSON decode Frigate API response: ${e}`);
|
throw new Error(`Could not JSON decode Frigate API response: ${e}`);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return frigateGetEventsResponseSchema.parse(raw_json);
|
return frigateGetEventsResponseSchema.parse(raw_json);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.warn(e);
|
||||||
throw new Error(`Frigate events were malformed: ${e}`);
|
throw new Error(`Frigate events were malformed: ${e}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: Catch when json decoding fails.
|
const error_message = `Frigate API request failed with status: ${response.status}`;
|
||||||
throw new Error(`Frigate API request failed with status: ${response.status}`);
|
console.warn(error_message);
|
||||||
|
throw new Error(error_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _renderAttentionIcon(icon: string): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="frigate-card-attention">
|
||||||
|
<ha-icon icon="${icon}">
|
||||||
|
</ha-icon>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render an embedded error situation.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
protected _renderError(_error: string) : TemplateResult {
|
||||||
|
return this._renderAttentionIcon("mdi:alert-circle");
|
||||||
|
}
|
||||||
|
|
||||||
// Render Frigate events into a card gallery.
|
// Render Frigate events into a card gallery.
|
||||||
protected async _renderEvents() : Promise<TemplateResult> {
|
protected async _renderEvents() : Promise<TemplateResult> {
|
||||||
const want_clips = this._viewMode == FrigateCardView.CLIPS;
|
const want_clips = this._viewMode == FrigateCardView.CLIPS;
|
||||||
|
let events;
|
||||||
const events = await this._getEvents({
|
try {
|
||||||
|
events = await this._getEvents({
|
||||||
has_clip: want_clips,
|
has_clip: want_clips,
|
||||||
has_snapshot: !want_clips,
|
has_snapshot: !want_clips,
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return this._renderError(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
return html`
|
return this._renderAttentionIcon(want_clips ? "mdi:filmstrip-off" : "mdi:camera-off");
|
||||||
<div class="frigate-card-exception">
|
|
||||||
<ha-icon
|
|
||||||
icon="${want_clips ? "mdi:filmstrip-off" : "mdi:camera-off"}"
|
|
||||||
></ha-icon>
|
|
||||||
</div>`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
@@ -281,7 +295,7 @@ export class FrigateCard extends LitElement {
|
|||||||
// Render a progress spinner while content loads.
|
// Render a progress spinner while content loads.
|
||||||
protected _renderProgressIndicator(): TemplateResult {
|
protected _renderProgressIndicator(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<div class="frigate-card-exception">
|
<div class="frigate-card-attention">
|
||||||
<ha-circular-progress
|
<ha-circular-progress
|
||||||
active="true"
|
active="true"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -369,20 +383,20 @@ export class FrigateCard extends LitElement {
|
|||||||
|
|
||||||
// Render the player for a saved clip.
|
// Render the player for a saved clip.
|
||||||
protected async _renderClipPlayer(): Promise<TemplateResult> {
|
protected async _renderClipPlayer(): Promise<TemplateResult> {
|
||||||
let event: FrigateEvent;
|
let event: FrigateEvent, events: FrigateGetEventsResponse;
|
||||||
if (this._viewEvent) {
|
if (this._viewEvent) {
|
||||||
event = this._viewEvent;
|
event = this._viewEvent;
|
||||||
} else {
|
} else {
|
||||||
const events = await this._getEvents({
|
try {
|
||||||
|
events = await this._getEvents({
|
||||||
has_clip: true,
|
has_clip: true,
|
||||||
limit: 1
|
limit: 1
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return this._renderError(e);
|
||||||
|
}
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
return html`
|
return this._renderAttentionIcon("mdi:camera-off");
|
||||||
<div class="frigate-card-exception">
|
|
||||||
<ha-icon icon="mdi:camera-off">
|
|
||||||
</ha-icon>
|
|
||||||
</div>`
|
|
||||||
}
|
}
|
||||||
event = events[0];
|
event = events[0];
|
||||||
}
|
}
|
||||||
@@ -396,20 +410,20 @@ export class FrigateCard extends LitElement {
|
|||||||
|
|
||||||
// Render a snapshot.
|
// Render a snapshot.
|
||||||
protected async _renderSnapshotViewer(): Promise<TemplateResult> {
|
protected async _renderSnapshotViewer(): Promise<TemplateResult> {
|
||||||
let event: FrigateEvent;
|
let event: FrigateEvent, events: FrigateGetEventsResponse;
|
||||||
if (this._viewEvent) {
|
if (this._viewEvent) {
|
||||||
event = this._viewEvent;
|
event = this._viewEvent;
|
||||||
} else {
|
} else {
|
||||||
const events = await this._getEvents({
|
try {
|
||||||
|
events = await this._getEvents({
|
||||||
has_snapshot: true,
|
has_snapshot: true,
|
||||||
limit: 1
|
limit: 1
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return this._renderError(e);
|
||||||
|
}
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
return html`
|
return this._renderAttentionIcon("mdi:filmstrip-off");
|
||||||
<div class="frigate-card-exception">
|
|
||||||
<ha-icon icon="mdi:filmstrip-off">
|
|
||||||
</ha-icon>
|
|
||||||
</div>`
|
|
||||||
}
|
}
|
||||||
event = events[0];
|
event = events[0];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user