ov-components: Add participant badges directive for enhanced participant panel functionality

master
Carlos Santos 2025-08-05 17:39:29 +02:00
parent 00fcb0b115
commit b1d0269211
5 changed files with 90 additions and 41 deletions

View File

@ -18,6 +18,11 @@
<span *ngIf="isLocalParticipant" class="local-indicator">
{{ 'PANEL.PARTICIPANTS.YOU' | translate }}
</span>
<!-- Participant badges -->
<div class="participant-badges">
<ng-container *ngTemplateOutlet="participantBadgeTemplate"></ng-container>
</div>
</div>
<div class="participant-subtitle">
@ -62,15 +67,5 @@
</div>
</div>
</div>
<!-- Content after local participant (only for local participant) -->
<!-- <div
class="after-local-content"
*ngIf="hasAfterLocalContent"
role="region"
[attr.aria-label]="'Additional content for local participant'"
>
<ng-container *ngTemplateOutlet="afterLocalParticipantTemplate"></ng-container>
</div> -->
</mat-list-item>
</mat-list>

View File

@ -209,6 +209,30 @@
}
}
// Participant badges container
.participant-badges {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
// Badge styling
::ng-deep .badge {
// Badge variants
&.moderator {
color: var(--ov-warning-color, #f57c00);
}
&.speaker {
color: var(--ov-primary-color, #1976d2);
}
&.host {
color: var(--ov-success-color, #4caf50);
}
}
}
// After local participant content area
.after-local-content {
margin-top: 12px;

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core';
import { Subscription } from 'rxjs';
import { ParticipantPanelItemElementsDirective } from '../../../../directives/template/openvidu-components-angular.directive';
// import { ParticipantPanelAfterLocalParticipantDirective } from '../../../../directives/template/internals.directive';
import { ParticipantPanelParticipantBadgeDirective } from '../../../../directives/template/internals.directive';
import { ParticipantModel } from '../../../../models/participant.model';
import { OpenViduComponentsConfigService } from '../../../../services/config/directive-config.service';
import { ParticipantService } from '../../../../services/participant/participant.service';
@ -42,16 +42,16 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
}
}
// /**
// * @ignore
// */
// @ContentChild(ParticipantPanelAfterLocalParticipantDirective)
// set externalAfterLocalParticipant(afterLocalParticipant: ParticipantPanelAfterLocalParticipantDirective) {
// this._externalAfterLocalParticipant = afterLocalParticipant;
// if (afterLocalParticipant) {
// this.updateTemplatesAndMarkForCheck();
// }
// }
/**
* @ignore
*/
@ContentChild(ParticipantPanelParticipantBadgeDirective)
set externalParticipantBadge(participantBadge: ParticipantPanelParticipantBadgeDirective) {
this._externalParticipantBadge = participantBadge;
if (participantBadge) {
this.updateTemplatesAndMarkForCheck();
}
}
/**
* @internal
@ -61,7 +61,7 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
// Store directive references for template setup
private _externalItemElements?: ParticipantPanelItemElementsDirective;
// private _externalAfterLocalParticipant?: ParticipantPanelAfterLocalParticipantDirective;
private _externalParticipantBadge?: ParticipantPanelParticipantBadgeDirective;
/**
* The participant to be displayed
@ -119,11 +119,11 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
}
/**
* Gets the template for content after local participant
* Gets the template for local participant badge
*/
// get afterLocalParticipantTemplate(): TemplateRef<any> | undefined {
// return this._externalAfterLocalParticipant?.template;
// }
get participantBadgeTemplate(): TemplateRef<any> | undefined {
return this._externalParticipantBadge?.template;
}
/**
* Checks if the current participant is the local participant
@ -146,21 +146,12 @@ export class ParticipantPanelItemComponent implements OnInit, OnDestroy {
return !!this.participantPanelItemElementsTemplate;
}
/**
* Checks if after local participant content is available
*/
// get hasAfterLocalContent(): boolean {
// return this.isLocalParticipant && !!this.afterLocalParticipantTemplate;
// }
/**
* @internal
* Sets up all templates using the template manager service
*/
private setupTemplates(): void {
this.templateConfig = this.templateManagerService.setupParticipantPanelItemTemplates(
this._externalItemElements
);
this.templateConfig = this.templateManagerService.setupParticipantPanelItemTemplates(this._externalItemElements);
// Apply templates to component properties for backward compatibility
this.applyTemplateConfiguration();

View File

@ -194,7 +194,6 @@ export class PreJoinDirective {
) {}
}
/**
* The ***ovParticipantPanelAfterLocalParticipant** directive allows you to inject custom HTML or Angular templates
* immediately after the local participant item in the participant panel.
@ -249,4 +248,37 @@ export class LayoutAdditionalElementsDirective {
public template: TemplateRef<any>,
public container: ViewContainerRef
) {}
}
}
/**
* The ***ovParticipantPanelParticipantBadge** directive allows you to inject custom badges or indicators
* in the participant panel.
* This enables you to add role indicators, status badges, or other visual elements.
*
* Usage example:
* ```html
* <ov-participants-panel>
* <div *ovParticipantPanelItem="let participant">
* <ov-participant-panel-item [participant]="participant">
* <!-- Custom badge for local participant only -->
* <ng-container *ovParticipantPanelParticipantBadge>
* <span class="moderator-badge">
* <mat-icon>admin_panel_settings</mat-icon>
* Moderator
* </span>
* </ng-container>
* </ov-participant-panel-item>
* </div>
* </ov-participants-panel>
* ```
*/
@Directive({
selector: '[ovParticipantPanelParticipantBadge]',
standalone: false
})
export class ParticipantPanelParticipantBadgeDirective {
constructor(
public template: TemplateRef<any>,
public container: ViewContainerRef
) {}
}

View File

@ -14,7 +14,12 @@ import {
ActivitiesPanelDirective,
BackgroundEffectsPanelDirective
} from './openvidu-components-angular.directive';
import { LayoutAdditionalElementsDirective, ParticipantPanelAfterLocalParticipantDirective, PreJoinDirective } from './internals.directive';
import {
LayoutAdditionalElementsDirective,
ParticipantPanelAfterLocalParticipantDirective,
ParticipantPanelParticipantBadgeDirective,
PreJoinDirective
} from './internals.directive';
@NgModule({
declarations: [
@ -32,7 +37,8 @@ import { LayoutAdditionalElementsDirective, ParticipantPanelAfterLocalParticipan
ActivitiesPanelDirective,
PreJoinDirective,
ParticipantPanelAfterLocalParticipantDirective,
LayoutAdditionalElementsDirective
LayoutAdditionalElementsDirective,
ParticipantPanelParticipantBadgeDirective
// BackgroundEffectsPanelDirective
],
exports: [
@ -50,7 +56,8 @@ import { LayoutAdditionalElementsDirective, ParticipantPanelAfterLocalParticipan
ActivitiesPanelDirective,
PreJoinDirective,
ParticipantPanelAfterLocalParticipantDirective,
LayoutAdditionalElementsDirective
LayoutAdditionalElementsDirective,
ParticipantPanelParticipantBadgeDirective
// BackgroundEffectsPanelDirective
]
})