- Components
-
EventImageViewComponent
widgets/implementations/events/event-image-view/event-image-view.component.ts
@if (showEmptyState()) {
<div class="p-relative p-24">
<c8y-ui-empty-state
[icon]="'image'"
[title]="'No image events to display.' | translate"
>
<p c8y-guide-docs>
<small
translate
[translateParams]="{ docsUrl: DOCS_URL }"
ngNonBindable
>
Find out more in the
<a c8y-guide-href="{{ docsUrl }}">user documentation</a>.
</small>
</p>
</c8y-ui-empty-state>
@if (hasOlderImages()) {
<div class="text-center">
<ng-container [ngTemplateOutlet]="loadOlderButton"></ng-container>
</div>
}
</div>
} @else {
@if (isLoading()) {
<div class="p-absolute fit-w overflow-hidden p-b-4">
<c8y-loading [layout]="'page'"></c8y-loading>
</div>
}
<div class="d-col flex-grow min-height-0">
<!-- Image area -->
<div class="d-flex a-i-center j-c-center flex-grow overflow-hidden min-height-0 p-relative">
@if (imageUrl()) {
<img
class="img-fit-contain"
[src]="imageUrl()"
[alt]="currentEvent()?.text || ''"
(error)="onImageError()"
/>
} @else if (imageError(); as error) {
<c8y-ui-empty-state
[icon]="'no-image'"
[title]="IMAGE_ERRORS[error].title"
[subtitle]="IMAGE_ERRORS[error].subtitle"
[horizontal]="true"
data-cy="c8y-event-image-view--image-error"
></c8y-ui-empty-state>
}
@if (isLoadingImage()) {
<div class="p-absolute fit p-absolute--center">
<c8y-loading></c8y-loading>
</div>
}
</div>
<!-- Event info & navigation -->
@if (imageEvents().length > 0) {
<div class="d-col p-16 bg-component">
@if (currentEvent(); as event) {
<div
class="d-flex flex-wrap a-i-center gap-8"
[class.m-b-8]="showNavigation()"
>
@if (event.source?.name) {
<p
class="small text-truncate m-0"
data-cy="c8y-event-image-view--event-source"
>
<span
class="text-label-small m-r-4"
translate
>Source</span
>
{{ event.source.name }}
</p>
}
<p
class="small text-truncate m-0"
data-cy="c8y-event-image-view--event-type"
>
<span
class="text-label-small m-r-4"
translate
>Type</span
>
{{ event.type }}
</p>
<p
class="small text-truncate m-0"
data-cy="c8y-event-image-view--event-time"
>
<span
class="text-label-small m-r-4"
translate
>Time</span
>
{{ event.time | c8yDate: 'mediumDate' }}
{{ event.time | c8yDate: 'mediumTime' }}
<button
class="btn-help btn-help--sm"
[attr.aria-label]="'Help' | translate"
[popover]="TIME_HELP_TEXT | translate"
placement="right"
triggers="focus"
container="body"
type="button"
></button>
</p>
</div>
}
@if (showNavigation()) {
<div class="d-flex a-i-center gap-8 p-r-16">
@if (hasOlderImages() && currentIndex() === 0) {
<ng-container [ngTemplateOutlet]="loadOlderButton"></ng-container>
}
@if (historyMode()) {
@let slideshowLabel =
(isPlaying() ? PAUSE_SLIDESHOW_LABEL : PLAY_SLIDESHOW_LABEL) | translate;
<button
class="btn btn-icon"
[attr.aria-label]="slideshowLabel"
[tooltip]="slideshowLabel"
placement="top"
container="body"
type="button"
[delay]="500"
[disabled]="isLoading()"
(click)="toggleSlideshow()"
>
<i
[c8yIcon]="isPlaying() ? 'pause' : 'play'"
aria-hidden="true"
></i>
</button>
}
@let sliderValueText =
hasOlderImages()
? ('Image {{ current }} of more than {{ total }}' | translate: sliderPosition())
: ('Image {{ current }} of {{ total }}' | translate: sliderPosition());
<c8y-range
class="flex-grow"
[class.m-l-8]="historyMode()"
[ngModel]="currentIndex()"
>
<ng-template #c8yRangeValue>
<span aria-hidden="true">{{ currentIndex() + 1 }} / {{ totalLabel() }}</span>
</ng-template>
<input
[attr.aria-label]="'Select image' | translate"
[attr.aria-valuetext]="sliderValueText"
type="range"
min="0"
#slider
[max]="totalEvents() - 1"
(input)="onSliderChange(slider.valueAsNumber)"
/>
</c8y-range>
</div>
}
</div>
}
</div>
}
<ng-template #loadOlderButton>
<button
class="btn btn-default btn-sm"
[class.btn-pending]="isLoadingOlder()"
[attr.aria-busy]="isLoadingOlder()"
type="button"
[disabled]="isLoading()"
(click)="loadOlderImages()"
>
{{ 'Load older images' | translate }}
</button>
</ng-template>