File
Implements
Methods
Async
bulkUnsubscribeSubscribers
|
bulkUnsubscribeSubscribers(subscribersNames: string[])
|
Parameters :
Name |
Type |
Optional |
subscribersNames |
string[]
|
No
|
Returns : Promise<void>
|
ngAfterViewInit
|
ngAfterViewInit()
|
|
actionControls
|
Type : ActionControl[]
|
Default value : [
{
type: 'unsubscribeSubscriber',
icon: 'unsubscribe',
text: gettext('Unsubscribe'),
callback: (subscriber: MessagingSubscriber) => this.unsubscribeSubscriber(subscriber),
showIf: () => this.permissions.hasRole(Permissions.ROLE_TENANT_MANAGEMENT_ADMIN)
}
]
|
appState
|
Default value : inject(AppStateService)
|
bulkActionControls
|
Type : BulkActionControl[]
|
Default value : [
{
type: 'unsubscribeSubscriber',
icon: 'unsubscribe',
text: gettext('Unsubscribe'),
callback: (subscribersNames: string[]) => this.bulkUnsubscribeSubscribers(subscribersNames),
showIf: () => this.permissions.hasRole(Permissions.ROLE_TENANT_MANAGEMENT_ADMIN)
}
]
|
columns
|
Type : Column[]
|
Default value : this.topicSubscribersDataGridService.getColumns()
|
dataGrid
|
Type : DataGridComponent
|
Decorators :
@ViewChild(DataGridComponent, {static: true})
|
destroyRef
|
Default value : inject(DestroyRef)
|
loading$
|
Default value : new BehaviorSubject<boolean>(false)
|
loadingItemsLabel
|
Default value : gettext('Loading subscribers...')
|
loadMoreItemsLabel
|
Default value : gettext('Load more subscribers')
|
namespaceId$
|
Default value : this.route.params.pipe(map(params => params['namespace'] as string))
|
namespaceLabel$
|
Default value : this.namespaceId$.pipe(
map(namespaceId => this.translateService.instant(NAMESPACE_PROPS[namespaceId].label))
)
|
namespacesService
|
Default value : inject(MessagingNamespacesService)
|
noDataMessage
|
Default value : gettext('No subscribers to display.')
|
noDataSubtitle
|
Default value : gettext('Create new subscribers to monitor them here.')
|
noResultsMessage
|
Default value : gettext('No matching subscribers found.')
|
noResultsSubtitle
|
Default value : gettext('Refine your search terms or check your spelling.')
|
overview$
|
Default value : combineLatest([this.tenantId$, this.namespaceId$, this.topicId$, this.refresh]).pipe(
tap(() => this.loading$.next(true)),
switchMap(async ([tenantId, namespaceId, topicId]) => ({
topic: (
await this.topicsService.detail({
tenant: tenantId,
namespace: namespaceId,
topic: topicId,
type: MessagingTopicType.Persistent
})
).data,
policies: await this.namespacesService.getNamespacePolicies(tenantId, namespaceId)
})),
tap(() => this.loading$.next(false)),
shareReplay(1)
)
|
pagination
|
Type : Pagination
|
Default value : {
pageSize: 20,
currentPage: 1
}
|
permissions
|
Default value : inject(Permissions)
|
refresh
|
Default value : new EventEmitter<void>()
|
route
|
Default value : inject(ActivatedRoute)
|
selectable
|
Default value : true
|
tableTitle
|
Default value : gettext('Subscribers')
|
tenantId$
|
Default value : this.appState.currentTenant.pipe(map(tenant => tenant.name))
|
topicId$
|
Default value : this.route.params.pipe(map(params => params['topic'] as string))
|
topicName$
|
Default value : this.overview$.pipe(map(overview => overview.topic.name))
|
topicsService
|
Default value : inject(MessagingTopicsService)
|
topicSubscribersDataGridService
|
Default value : inject(TopicSubscribersDataGridService)
|
translateService
|
Default value : inject(TranslateService)
|
<c8y-title>{{ topicName$ | async }}</c8y-title>
<c8y-breadcrumb>
<c8y-breadcrumb-item
[icon]="'monitoring'"
[label]="'Monitoring' | translate"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item
[label]="'Messaging service' | translate"
[path]="'/monitoring/messaging-service'"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item
[label]="namespaceLabel$ | async"
[path]="'/monitoring/messaging-service/namespace/' + (namespaceId$ | async)"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item [label]="topicName$ | async"></c8y-breadcrumb-item>
</c8y-breadcrumb>
<c8y-action-bar-item [placement]="'right'">
<a
class="btn btn-link"
title="{{ 'Reload' | translate }}"
(click)="refresh.emit()"
>
<i
c8yIcon="refresh"
[ngClass]="{ 'icon-spin': loading$ | async }"
></i>
{{ 'Reload' | translate }}
</a>
</c8y-action-bar-item>
<div class="card content-fullpage d-flex d-col">
<div class="bg-level-1 separator-bottom flex-no-shrink">
<div class="card-block">
<div
class="col-md-4 m-b-24 col-xs-12 d-flex p-t-24 gap-16 text-default a-i-center a-s-stretch"
>
<div class="text-center d-col">
<i
class="m-b-8 icon-40 c8y-icon-duocolor"
[c8yIcon]="'day-view'"
></i>
<span class="tag tag--default">{{ 'Topic' | translate }}</span>
</div>
<span class="h4">{{ topicName$ | async }}</span>
</div>
<div class="col-md-4">
<fieldset class="c8y-fieldset c8y-fieldset--lg">
<legend translate>Topic usage</legend>
<ng-container *ngIf="loading$ | async; else topicSummary">
<c8y-loading></c8y-loading>
</ng-container>
<ng-template #topicSummary>
<ng-container *ngIf="overview$ | async as overview">
<ul class="list-unstyled small animated fadeIn">
<li class="p-t-4 p-b-4 d-flex separator-bottom text-nowrap">
<label class="small m-b-0 m-r-auto">{{ 'Active subscribers' | translate }}</label>
<span class="m-l-16">{{ overview.topic.activeSubscribers | number }}</span>
</li>
<li class="p-t-4 p-b-4 d-flex separator-bottom text-nowrap">
<label class="small m-b-0 m-r-auto">{{ 'Total subscribers' | translate }}</label>
<span class="m-l-16">{{ overview.topic.subscribers | number }}</span>
</li>
<li class="p-t-4 p-b-4 d-flex separator-bottom text-nowrap">
<label class="small m-b-0 m-r-auto">
{{ 'Total unacknowledged messages' | translate }}
</label>
<span class="m-l-16">{{ overview.topic.unackMsgBacklog | number }}</span>
</li>
<li class="p-t-4 p-b-4 d-flex separator-bottom text-nowrap">
<label class="small m-b-0 m-r-auto">
{{ 'Message rate in' | translate }}
</label>
<span
class="m-l-16"
ngNonBindable
translate
[translateParams]="{
messagesPerSecond: overview.topic.msgRateIn | number
}"
>
{{ messagesPerSecond }} msg/s
</span>
</li>
<li class="p-t-4 p-b-4 d-flex text-nowrap">
<label class="small m-b-0 m-r-auto">
{{ 'Message rate out' | translate }}
</label>
<span
class="m-l-16"
ngNonBindable
translate
[translateParams]="{
messagesPerSecond: overview.topic.msgRateOut | number
}"
>
{{ messagesPerSecond }} msg/s
</span>
</li>
</ul>
</ng-container>
</ng-template>
</fieldset>
</div>
<div class="col-md-4">
<fieldset class="c8y-fieldset c8y-fieldset--lg">
<legend translate>Topic message backlog</legend>
<ng-container *ngIf="loading$ | async; else topicBacklog">
<c8y-loading></c8y-loading>
</ng-container>
<ng-template #topicBacklog>
<ng-container *ngIf="overview$ | async as overview">
<ul class="list-unstyled small animated fadeIn">
<li class="p-t-4 p-b-4 d-flex separator-bottom text-nowrap">
<label
class="small m-b-0 m-r-auto"
translate
>
Backlog usage
</label>
<app-usage [percentage]="overview.topic.backlogUsagePercentage"></app-usage>
<span class="m-l-16">{{ overview.topic.backlogSize | bytes }}</span>
</li>
<li class="p-t-4 p-b-4 d-flex text-nowrap">
<label
class="small m-b-0 m-r-auto"
translate
>
Backlog quota
</label>
<span class="m-l-16">
{{
overview.policies.backlogQuota?.limit > 0
? (overview.policies.backlogQuota?.limit | bytes)
: '-'
}}
</span>
</li>
</ul>
</ng-container>
</ng-template>
</fieldset>
</div>
</div>
</div>
<c8y-data-grid
class="content-fullpage d-flex d-col border-top border-bottom"
[title]="tableTitle | translate"
[loadingItemsLabel]="loadingItemsLabel | translate"
[loadMoreItemsLabel]="loadMoreItemsLabel | translate"
[columns]="columns"
[pagination]="pagination"
[serverSideDataCallback]="serverSideDataCallback"
[refresh]="refresh"
[hideReload]="true"
[selectable]="selectable"
[actionControls]="actionControls"
[bulkActionControls]="bulkActionControls"
>
<c8y-ui-empty-state
[icon]="stats?.size > 0 ? 'search' : 'input'"
[title]="stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)"
[subtitle]="stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)"
*emptyStateContext="let stats"
[horizontal]="stats?.size > 0"
></c8y-ui-empty-state>
<c8y-column name="name">
<ng-container *c8yCellRendererDef="let context">
<span title="{{ context.value }}">
{{ context.value }}
</span>
</ng-container>
</c8y-column>
<c8y-column name="activeClients">
<ng-container *c8yCellRendererDef="let context">
<span title="{{ context.value | number }}">
{{ context.value | number }}
</span>
</ng-container>
</c8y-column>
<c8y-column name="messageAckRate">
<ng-container *c8yCellRendererDef="let context">
<span title="{{ context.value | number }}">
{{ context.value | number }}
</span>
</ng-container>
</c8y-column>
<c8y-column name="lastAcknowledgeDate">
<ng-container *c8yCellRendererDef="let context">
<span
title="{{ context.value }}"
*ngIf="context.value; else noLastAcknwoldegeDate"
>
{{ context.value | relativeTime }}
</span>
<ng-template #noLastAcknwoldegeDate>–</ng-template>
</ng-container>
</c8y-column>
<c8y-column name="unackMsgBacklog">
<ng-container *c8yCellRendererDef="let context">
<span title="{{ context.value | number }}">
{{ context.value | number }}
</span>
</ng-container>
</c8y-column>
<c8y-column name="backlogUsagePercentage">
<ng-container *c8yCellRendererDef="let context">
<span title="{{ context.value / 100 | percent: '1.0-2' }}">
{{ context.value / 100 | percent: '1.0-2' }}
</span>
</ng-container>
</c8y-column>
</c8y-data-grid>
</div>