238 lines
8.1 KiB
HTML
238 lines
8.1 KiB
HTML
<div class="page-content">
|
|
<div class="page-header">
|
|
<h2>Subscriptions</h2>
|
|
<div class="header-actions">
|
|
<button nz-button (click)="loadSubscriptions()">
|
|
<span nz-icon nzType="reload"></span>
|
|
Refresh
|
|
</button>
|
|
<button nz-button nzType="primary" (click)="openCreateModal()">
|
|
<span nz-icon nzType="plus"></span>
|
|
Subscribe
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<nz-tabset (nzSelectedIndexChange)="onTabChange($event)">
|
|
<nz-tab nzTitle="All"></nz-tab>
|
|
<nz-tab nzTitle="Own"></nz-tab>
|
|
<nz-tab nzTitle="Deactivated"></nz-tab>
|
|
<nz-tab nzTitle="External"></nz-tab>
|
|
<nz-tab nzTitle="Incoming"></nz-tab>
|
|
</nz-tabset>
|
|
|
|
@if (getTabDescription()) {
|
|
<nz-alert
|
|
nzType="info"
|
|
[nzMessage]="getTabDescription()!"
|
|
nzShowIcon
|
|
style="margin-bottom: 16px;"
|
|
></nz-alert>
|
|
}
|
|
|
|
<nz-table
|
|
#subscriptionTable
|
|
nzBordered
|
|
[nzData]="subscriptions()"
|
|
[nzLoading]="loading()"
|
|
[nzShowPagination]="false"
|
|
[nzNoResult]="noResultTpl"
|
|
nzSize="middle"
|
|
>
|
|
<ng-template #noResultTpl></ng-template>
|
|
<thead>
|
|
<tr>
|
|
<th nzWidth="0">ID</th>
|
|
<th nzWidth="0">Type</th>
|
|
<th>Channel</th>
|
|
<th>Subscriber</th>
|
|
<th>Owner</th>
|
|
<th nzWidth="0">Confirmation</th>
|
|
<th nzWidth="0">Active</th>
|
|
<th nzWidth="0">Created</th>
|
|
<th nzWidth="0">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (sub of subscriptions(); track sub.subscription_id) {
|
|
<tr class="clickable-row">
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<span class="mono subscription-id">{{ sub.subscription_id }}</span>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<nz-tag [nzColor]="getTypeLabel(sub).color">
|
|
{{ getTypeLabel(sub).label }}
|
|
</nz-tag>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<div class="cell-name">{{ sub.channel_internal_name }}</div>
|
|
<div class="cell-id mono">{{ sub.channel_id }}</div>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<div class="cell-name">{{ getUserDisplayName(sub.subscriber_user_id) }}</div>
|
|
<div class="cell-id mono">{{ sub.subscriber_user_id }}</div>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<div class="cell-name">{{ getUserDisplayName(sub.channel_owner_user_id) }}</div>
|
|
<div class="cell-id mono">{{ sub.channel_owner_user_id }}</div>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<nz-tag [nzColor]="getConfirmationInfo(sub).color">
|
|
{{ getConfirmationInfo(sub).label }}
|
|
</nz-tag>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<nz-tag [nzColor]="getActiveInfo(sub).color">
|
|
{{ getActiveInfo(sub).label }}
|
|
</nz-tag>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a class="cell-link" [routerLink]="['/subscriptions', sub.subscription_id]">
|
|
<div class="timestamp-absolute">{{ sub.timestamp_created | date:'yyyy-MM-dd HH:mm:ss' }}</div>
|
|
<div class="timestamp-relative">{{ sub.timestamp_created | relativeTime }}</div>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<div class="action-buttons">
|
|
@if (!sub.confirmed && isOwner(sub)) {
|
|
<!-- Incoming unconfirmed: can accept or deny -->
|
|
<button
|
|
nz-button
|
|
nzSize="small"
|
|
nzType="primary"
|
|
nz-tooltip
|
|
nzTooltipTitle="Accept"
|
|
(click)="acceptSubscription(sub)"
|
|
>
|
|
<span nz-icon nzType="check"></span>
|
|
</button>
|
|
<button
|
|
nz-button
|
|
nzSize="small"
|
|
nzDanger
|
|
nz-tooltip
|
|
nzTooltipTitle="Deny"
|
|
nz-popconfirm
|
|
nzPopconfirmTitle="Deny this subscription request?"
|
|
(nzOnConfirm)="denySubscription(sub)"
|
|
>
|
|
<span nz-icon nzType="close"></span>
|
|
</button>
|
|
} @else {
|
|
<!-- Own subscriptions: can activate/deactivate -->
|
|
@if (isOwnSubscription(sub)) {
|
|
@if (sub.active) {
|
|
<button
|
|
nz-button
|
|
nzSize="small"
|
|
nz-tooltip
|
|
nzTooltipTitle="Deactivate"
|
|
nz-popconfirm
|
|
nzPopconfirmTitle="Deactivate this subscription?"
|
|
(nzOnConfirm)="deactivateSubscription(sub)"
|
|
>
|
|
<span nz-icon nzType="pause-circle"></span>
|
|
</button>
|
|
} @else {
|
|
<button
|
|
nz-button
|
|
nzSize="small"
|
|
nzType="primary"
|
|
nz-tooltip
|
|
nzTooltipTitle="Activate"
|
|
(click)="activateSubscription(sub)"
|
|
>
|
|
<span nz-icon nzType="play-circle"></span>
|
|
</button>
|
|
}
|
|
}
|
|
<!-- Confirmed or outgoing: can revoke -->
|
|
@if (expertMode()) {
|
|
<button
|
|
nz-button
|
|
nzSize="small"
|
|
nzDanger
|
|
nz-tooltip
|
|
nzTooltipTitle="Revoke"
|
|
nz-popconfirm
|
|
nzPopconfirmTitle="Revoke this subscription?"
|
|
(nzOnConfirm)="revokeSubscription(sub)"
|
|
>
|
|
<span nz-icon nzType="delete"></span>
|
|
</button>
|
|
}
|
|
}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="9">
|
|
<nz-empty nzNotFoundContent="No subscriptions found"></nz-empty>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</nz-table>
|
|
|
|
<div class="pagination-controls">
|
|
<nz-pagination
|
|
[nzPageIndex]="currentPage()"
|
|
[nzPageSize]="pageSize"
|
|
[nzTotal]="totalCount()"
|
|
[nzDisabled]="loading()"
|
|
(nzPageIndexChange)="goToPage($event)"
|
|
></nz-pagination>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Subscription Modal -->
|
|
<nz-modal
|
|
[(nzVisible)]="showCreateModal"
|
|
nzTitle="Subscribe to Channel"
|
|
(nzOnCancel)="closeCreateModal()"
|
|
(nzOnOk)="createSubscription()"
|
|
[nzOkLoading]="creating()"
|
|
[nzOkDisabled]="!newChannelOwner.trim() || !newChannelName.trim()"
|
|
>
|
|
<ng-container *nzModalContent>
|
|
<p class="modal-hint">Enter the channel owner's User ID and the channel name to subscribe.</p>
|
|
<nz-form-item>
|
|
<nz-form-label>Channel Owner User ID</nz-form-label>
|
|
<nz-form-control>
|
|
<input
|
|
type="text"
|
|
nz-input
|
|
placeholder="e.g., USR12345"
|
|
[(ngModel)]="newChannelOwner"
|
|
/>
|
|
</nz-form-control>
|
|
</nz-form-item>
|
|
<nz-form-item class="mb-0">
|
|
<nz-form-label>Channel Name</nz-form-label>
|
|
<nz-form-control>
|
|
<input
|
|
type="text"
|
|
nz-input
|
|
placeholder="e.g., main"
|
|
[(ngModel)]="newChannelName"
|
|
/>
|
|
</nz-form-control>
|
|
</nz-form-item>
|
|
</ng-container>
|
|
</nz-modal>
|