169 lines
8.1 KiB
HTML
169 lines
8.1 KiB
HTML
<ng-container *transloco="let t; read: 'events-widget'">
|
|
|
|
@if (accountService.isAdmin$ | async) {
|
|
@if (downloadService.activeDownloads$ | async; as activeDownloads) {
|
|
@if (errors$ | async; as errors) {
|
|
@if (infos$ | async; as infos) {
|
|
@if (messageHub.onlineUsers$ | async; as onlineUsers) {
|
|
<button type="button" class="btn btn-icon"
|
|
[ngbPopover]="popContent" [title]="t('title-alt')"
|
|
placement="bottom" [popoverClass]="'nav-events'"
|
|
[autoClose]="'outside'">
|
|
|
|
@if (onlineUsers.length > 1) {
|
|
<span class="me-2" [ngClass]="{'colored': ((activeEvents$ | async) || 0) > 0 || activeDownloads.length > 0 || updateAvailable}">{{onlineUsers.length}}</span>
|
|
}
|
|
|
|
<i aria-hidden="true" class="fa fa-wave-square nav" [ngClass]="{'colored': ((activeEvents$ | async) || 0) > 0 || activeDownloads.length > 0 || updateAvailable}"></i>
|
|
|
|
|
|
@if (errors.length > 0) {
|
|
<i aria-hidden="true" class="fa fa-circle-exclamation nav widget-button--indicator error"></i>
|
|
} @else if (infos.length > 0) {
|
|
<i aria-hidden="true" class="fa fa-circle-info nav widget-button--indicator info"></i>
|
|
} @else if (((activeEvents$ | async) || 0) > 0 || activeDownloads.length > 0) {
|
|
<div class="nav widget-button--indicator spinner-border spinner-border-sm"></div>
|
|
} @else if (updateAvailable) {
|
|
<i aria-hidden="true" class="fa fa-circle-arrow-up nav widget-button--indicator update"></i>
|
|
}
|
|
</button>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
<ng-template #popContent>
|
|
<ul class="list-group list-group-flush dark-menu">
|
|
@if(errors$ | async; as errors) {
|
|
@if(infos$ | async; as infos) {
|
|
@if (errors.length > 0 || infos.length > 0) {
|
|
<li class="list-group-item dark-menu-item clickable" (click)="clearAllErrorOrInfos()">
|
|
{{t('dismiss-all')}}
|
|
</li>
|
|
}
|
|
}
|
|
}
|
|
|
|
<!-- Progress Events-->
|
|
@if (progressEvents$ | async; as progressUpdates) {
|
|
@for (message of progressUpdates; track message) {
|
|
@if (message.progress === 'indeterminate' || message.progress === 'none') {
|
|
<li class="list-group-item dark-menu-item">
|
|
<div class="h6 mb-1">{{message.title}}</div>
|
|
@if (message.subTitle !== '') {
|
|
<div class="accent-text mb-1" [title]="message.subTitle">{{message.subTitle}}</div>
|
|
}
|
|
@if (message.name === EVENTS.ScanProgress && message.body.leftToProcess > 0) {
|
|
<div class="accent-text mb-1" [title]="t('left-to-process', {leftToProcess: message.body.leftToProcess})">
|
|
{{t('left-to-process', {leftToProcess: message.body.leftToProcess})}}
|
|
</div>
|
|
}
|
|
<div class="progress-container row g-0 align-items-center">
|
|
@if(message.progress === 'indeterminate') {
|
|
<div class="progress" role="progressbar" style="height: 0.3125rem;">
|
|
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 100%" [attr.aria-valuenow]="100" aria-valuemin="0" aria-valuemax="100"></div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</li>
|
|
} @else {
|
|
<li class="list-group-item dark-menu-item">
|
|
<div class="h6 mb-1">{{message.title}}</div>
|
|
@if (message.subTitle !== '') {
|
|
<div class="accent-text mb-1" [title]="message.subTitle">{{message.subTitle}}</div>
|
|
}
|
|
<div class="progress-container row g-0 align-items-center">
|
|
<div class="col-2">{{prettyPrintProgress(message.body.progress) + '%'}}</div>
|
|
<div class="col-10 progress" role="progressbar" style="height: 0.3125rem;">
|
|
<div class="progress-bar"
|
|
[ngStyle]="{'width': message.body.progress * 100 + '%'}"
|
|
[attr.aria-valuenow]="message.body.progress * 100"
|
|
aria-valuemin="0" aria-valuemax="100"></div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
}
|
|
}
|
|
}
|
|
|
|
<!-- Single updates (Informational/Update available)-->
|
|
@if (singleUpdates$ | async; as singleUpdates) {
|
|
@for(singleUpdate of singleUpdates; track singleUpdate) {
|
|
@if (singleUpdate.name === EVENTS.UpdateAvailable) {
|
|
<li class="list-group-item dark-menu-item update-available" (click)="handleUpdateAvailableClick(singleUpdate)">
|
|
<i class="fa fa-chevron-circle-up me-1" aria-hidden="true"></i>{{t('update-available')}}
|
|
</li>
|
|
} @else {
|
|
<li class="list-group-item dark-menu-item update-available">
|
|
<div>{{singleUpdate.title}}</div>
|
|
@if (singleUpdate.subTitle !== '') {
|
|
<div class="accent-text">{{singleUpdate.subTitle}}</div>
|
|
}
|
|
</li>
|
|
}
|
|
}
|
|
}
|
|
|
|
<!-- Active Downloads by the user-->
|
|
@if (downloadService.activeDownloads$ | async; as activeDownloads) {
|
|
@for(download of activeDownloads; track download) {
|
|
<li class="list-group-item dark-menu-item">
|
|
<div class="h6 mb-1">{{t('downloading-item', {item: download.entityType | sentenceCase})}}</div>
|
|
|
|
@if (download.subTitle !== '') {
|
|
<div class="accent-text mb-1" [title]="download.subTitle">{{download.subTitle}}</div>
|
|
}
|
|
|
|
<div class="progress-container row g-0 align-items-center">
|
|
<div class="col-2">{{download.progress}}%</div>
|
|
<div class="col-10 progress" role="progressbar" style="height: 0.3125rem;">
|
|
<div class="progress-bar" [ngStyle]="{'width': download.progress + '%'}" [attr.aria-valuenow]="download.progress" aria-valuemin="0" aria-valuemax="100"></div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
}
|
|
@if(activeDownloads.length > 1) {
|
|
<li class="list-group-item dark-menu-item">{{t('download-in-queue', {num: activeDownloads.length})}}</li>
|
|
}
|
|
}
|
|
|
|
<!-- Errors -->
|
|
@if (errors$ | async; as errors) {
|
|
@for (error of errors; track error) {
|
|
<li class="list-group-item dark-menu-item error" role="alert" (click)="seeMore(error)">
|
|
<div>
|
|
<div class="h6 mb-1"><i class="fa-solid fa-triangle-exclamation me-2" aria-hidden="true"></i>{{error.title}}</div>
|
|
<div class="accent-text mb-1">{{t('more-info')}}</div>
|
|
</div>
|
|
<button type="button" class="btn-close float-end" [attr.aria-label]="t('close')" (click)="removeErrorOrInfo(error, $event)"></button>
|
|
</li>
|
|
}
|
|
}
|
|
|
|
<!-- Infos -->
|
|
@if (infos$ | async; as infos) {
|
|
@for (info of infos; track info) {
|
|
<li class="list-group-item dark-menu-item info" role="alert" (click)="seeMore(info)">
|
|
<div>
|
|
<div class="h6 mb-1"><i class="fa-solid fa-circle-info me-2" aria-hidden="true"></i>{{info.title}}</div>
|
|
<div class="accent-text mb-1">{{t('more-info')}}</div>
|
|
</div>
|
|
<button type="button" class="btn-close float-end" [attr.aria-label]="t('close')" (click)="removeErrorOrInfo(info, $event)"></button>
|
|
</li>
|
|
}
|
|
}
|
|
|
|
@if (downloadService.activeDownloads$ | async; as activeDownloads) {
|
|
@if (errors$ | async; as errors) {
|
|
@if (infos$ | async; as infos) {
|
|
@if (infos.length === 0 && errors.length === 0 && activeDownloads.length === 0 && activeEvents === 0) {
|
|
<li class="list-group-item dark-menu-item">{{t('no-data')}}</li>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</ul>
|
|
</ng-template>
|
|
}
|
|
|
|
</ng-container>
|