Add helpdesk icon and feature
Adds a "helpdesk" Jitsi room feature. Can be enabled using the OpenSlides config page Shows a 'Call support' button in the conference control bar clicking the support button will connect the user to a "support" jitsi room The name of the support room will be `JITSI_ROOM_NAME`-SUPPORT
This commit is contained in:
parent
cc65b756c7
commit
024b9c74e6
@ -61,7 +61,7 @@
|
|||||||
matTooltip="{{ 'Exit live conference and continue livestream' | translate }}"
|
matTooltip="{{ 'Exit live conference and continue livestream' | translate }}"
|
||||||
*ngIf="videoStreamUrl && canSeeLiveStream && !isJitsiDialogOpen"
|
*ngIf="videoStreamUrl && canSeeLiveStream && !isJitsiDialogOpen"
|
||||||
>
|
>
|
||||||
<mat-icon color="warn"> meeting_room </mat-icon>
|
<mat-icon color="warn">meeting_room</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- mute/unmute button -->
|
<!-- mute/unmute button -->
|
||||||
@ -85,7 +85,7 @@
|
|||||||
*ngIf="enableJitsi && isAccessPermitted"
|
*ngIf="enableJitsi && isAccessPermitted"
|
||||||
class="quick-icon indicator"
|
class="quick-icon indicator"
|
||||||
mat-mini-fab
|
mat-mini-fab
|
||||||
(click)="enterConversation()"
|
(click)="enterConferenceRoom()"
|
||||||
matTooltip="{{ 'Enter live conference' | translate }}"
|
matTooltip="{{ 'Enter live conference' | translate }}"
|
||||||
>
|
>
|
||||||
<mat-icon
|
<mat-icon
|
||||||
@ -109,6 +109,18 @@
|
|||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Call support button -->
|
||||||
|
<button
|
||||||
|
class="indicator quick-icon"
|
||||||
|
mat-mini-fab
|
||||||
|
(click)="enterSupportRoom()"
|
||||||
|
[disabled]="isJitsiActive"
|
||||||
|
matTooltip="{{ 'Access help desk' | translate }}"
|
||||||
|
*ngIf="canAccessSupport"
|
||||||
|
>
|
||||||
|
<mat-icon color="primary">live_help</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- applause button -->
|
<!-- applause button -->
|
||||||
<button
|
<button
|
||||||
class="quick-icon indicator"
|
class="quick-icon indicator"
|
||||||
@ -137,7 +149,8 @@
|
|||||||
<!-- open-window button -->
|
<!-- open-window button -->
|
||||||
<button class="toggle-list-button" mat-button (click)="toggleShowJitsi()">
|
<button class="toggle-list-button" mat-button (click)="toggleShowJitsi()">
|
||||||
<ng-container *ngIf="currentState == state.jitsi">
|
<ng-container *ngIf="currentState == state.jitsi">
|
||||||
<div class="ellipsis-overflow">{{ 'Live conference' | translate }}</div>
|
<div *ngIf="!connectToHelpDesk" class="ellipsis-overflow">{{ 'Live conference' | translate }}</div>
|
||||||
|
<div *ngIf="connectToHelpDesk" class="ellipsis-overflow">{{ 'Help desk' | translate }}</div>
|
||||||
<div class="one-line">
|
<div class="one-line">
|
||||||
|
|
||||||
<span *ngIf="currentDominantSpeaker">
|
<span *ngIf="currentDominantSpeaker">
|
||||||
@ -248,7 +261,7 @@
|
|||||||
<button
|
<button
|
||||||
mat-mini-fab
|
mat-mini-fab
|
||||||
color="accent"
|
color="accent"
|
||||||
(click)="enterConversation()"
|
(click)="enterConferenceRoom()"
|
||||||
[disabled]="
|
[disabled]="
|
||||||
!enableJitsi || isJitsiActive || isJitsiActiveInAnotherTab || !isAccessPermitted
|
!enableJitsi || isJitsiActive || isJitsiActiveInAnotherTab || !isAccessPermitted
|
||||||
"
|
"
|
||||||
|
@ -82,9 +82,13 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
public enableJitsi: boolean;
|
public enableJitsi: boolean;
|
||||||
|
|
||||||
private autoconnect: boolean;
|
private autoconnect: boolean;
|
||||||
private roomName: string;
|
private defaultRoomName: string;
|
||||||
|
private actualRoomName: string;
|
||||||
private roomPassword: string;
|
private roomPassword: string;
|
||||||
private jitsiDomain: string;
|
private jitsiDomain: string;
|
||||||
|
private isSupportEnabled: boolean;
|
||||||
|
|
||||||
|
public connectToHelpDesk = false;
|
||||||
|
|
||||||
public restricted = false;
|
public restricted = false;
|
||||||
public videoStreamUrl: string;
|
public videoStreamUrl: string;
|
||||||
@ -139,6 +143,10 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
return this.roomPassword?.length > 0;
|
return this.roomPassword?.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get canAccessSupport(): boolean {
|
||||||
|
return this.isSupportEnabled && this.enableJitsi && !!this.defaultRoomName;
|
||||||
|
}
|
||||||
|
|
||||||
private isOnCurrentLos: boolean;
|
private isOnCurrentLos: boolean;
|
||||||
|
|
||||||
public canSeeLiveStream: boolean;
|
public canSeeLiveStream: boolean;
|
||||||
@ -174,7 +182,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get jitsiMeetUrl(): string {
|
public get jitsiMeetUrl(): string {
|
||||||
return `https://${this.jitsiDomain}/${this.roomName}`;
|
return `https://${this.jitsiDomain}/${this.actualRoomName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -339,7 +347,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
this.constantsService.get<JitsiSettings>('Settings').subscribe(settings => {
|
this.constantsService.get<JitsiSettings>('Settings').subscribe(settings => {
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.jitsiDomain = settings.JITSI_DOMAIN;
|
this.jitsiDomain = settings.JITSI_DOMAIN;
|
||||||
this.roomName = settings.JITSI_ROOM_NAME;
|
this.defaultRoomName = settings.JITSI_ROOM_NAME;
|
||||||
this.roomPassword = settings.JITSI_ROOM_PASSWORD;
|
this.roomPassword = settings.JITSI_ROOM_PASSWORD;
|
||||||
this.constantsLoaded.resolve();
|
this.constantsLoaded.resolve();
|
||||||
}
|
}
|
||||||
@ -352,7 +360,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
.get<boolean>('general_system_conference_auto_connect')
|
.get<boolean>('general_system_conference_auto_connect')
|
||||||
.subscribe(autoconnect => (this.autoconnect = autoconnect)),
|
.subscribe(autoconnect => (this.autoconnect = autoconnect)),
|
||||||
this.configService.get<boolean>('general_system_conference_show').subscribe(show => {
|
this.configService.get<boolean>('general_system_conference_show').subscribe(show => {
|
||||||
this.enableJitsi = show && !!this.jitsiDomain && !!this.roomName;
|
this.enableJitsi = show && !!this.jitsiDomain && !!this.defaultRoomName;
|
||||||
if (this.enableJitsi && this.autoconnect) {
|
if (this.enableJitsi && this.autoconnect) {
|
||||||
this.startJitsi();
|
this.startJitsi();
|
||||||
} else {
|
} else {
|
||||||
@ -392,6 +400,9 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
} else {
|
} else {
|
||||||
this.isApplausBarUsed = false;
|
this.isApplausBarUsed = false;
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
this.configService.get<boolean>('general_system_conference_enable_helpdesk').subscribe(enabled => {
|
||||||
|
this.isSupportEnabled = enabled;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -425,19 +436,22 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
|
|
||||||
private startJitsi(): void {
|
private startJitsi(): void {
|
||||||
if (!this.isJitsiActiveInAnotherTab && this.enableJitsi && !this.isJitsiActive && this.jitsiNode) {
|
if (!this.isJitsiActiveInAnotherTab && this.enableJitsi && !this.isJitsiActive && this.jitsiNode) {
|
||||||
this.enterConversation();
|
this.enterConferenceRoom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async enterConversation(): Promise<void> {
|
private async enterConversation(): Promise<void> {
|
||||||
await this.operator.loaded;
|
await this.operator.loaded;
|
||||||
try {
|
try {
|
||||||
await this.userMediaPermService.requestMediaAccess();
|
await this.userMediaPermService.requestMediaAccess();
|
||||||
this.storageMap.set(this.RTC_LOGGED_STORAGE_KEY, true).subscribe(() => {});
|
this.storageMap.set(this.RTC_LOGGED_STORAGE_KEY, true).subscribe(() => {});
|
||||||
this.setConferenceState(ConferenceState.jitsi);
|
this.setConferenceState(ConferenceState.jitsi);
|
||||||
this.setOptions();
|
this.setOptions();
|
||||||
|
if (this.api) {
|
||||||
|
this.api.dispose();
|
||||||
|
this.api = undefined;
|
||||||
|
}
|
||||||
this.api = new JitsiMeetExternalAPI(this.jitsiDomain, this.options);
|
this.api = new JitsiMeetExternalAPI(this.jitsiDomain, this.options);
|
||||||
|
|
||||||
const jitsiname = this.userRepo.getShortName(this.operator.user);
|
const jitsiname = this.userRepo.getShortName(this.operator.user);
|
||||||
this.api.executeCommand('displayName', jitsiname);
|
this.api.executeCommand('displayName', jitsiname);
|
||||||
this.loadApiCallbacks();
|
this.loadApiCallbacks();
|
||||||
@ -503,7 +517,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
operatorClosIndex <= this.nextSpeakerAmount &&
|
operatorClosIndex <= this.nextSpeakerAmount &&
|
||||||
!this.isJitsiActive
|
!this.isJitsiActive
|
||||||
) {
|
) {
|
||||||
this.enterConversation();
|
this.enterConferenceRoom();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.isOnCurrentLos = false;
|
this.isOnCurrentLos = false;
|
||||||
@ -563,6 +577,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async stopJitsi(): Promise<void> {
|
public async stopJitsi(): Promise<void> {
|
||||||
|
this.connectToHelpDesk = false;
|
||||||
if (this.isJitsiActive) {
|
if (this.isJitsiActive) {
|
||||||
this.api.executeCommand('hangup');
|
this.api.executeCommand('hangup');
|
||||||
this.clearMembers();
|
this.clearMembers();
|
||||||
@ -578,7 +593,7 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
|
|
||||||
private setOptions(): void {
|
private setOptions(): void {
|
||||||
this.options = {
|
this.options = {
|
||||||
roomName: this.roomName,
|
roomName: this.actualRoomName,
|
||||||
parentNode: this.jitsiNode.nativeElement,
|
parentNode: this.jitsiNode.nativeElement,
|
||||||
configOverwrite: this.configOverwrite,
|
configOverwrite: this.configOverwrite,
|
||||||
interfaceConfigOverwrite: this.interfaceConfigOverwrite
|
interfaceConfigOverwrite: this.interfaceConfigOverwrite
|
||||||
@ -617,6 +632,18 @@ export class JitsiComponent extends BaseViewComponentDirective implements OnInit
|
|||||||
this.storageMap.set(this.STREAM_RUNNING_STORAGE_KEY, true).subscribe(() => {});
|
this.storageMap.set(this.STREAM_RUNNING_STORAGE_KEY, true).subscribe(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enterConferenceRoom(): void {
|
||||||
|
this.actualRoomName = this.defaultRoomName;
|
||||||
|
this.connectToHelpDesk = false;
|
||||||
|
this.enterConversation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enterSupportRoom(): void {
|
||||||
|
this.actualRoomName = `${this.defaultRoomName}-SUPPORT`;
|
||||||
|
this.connectToHelpDesk = true;
|
||||||
|
this.enterConversation();
|
||||||
|
}
|
||||||
|
|
||||||
private onLiveStreamAvailable(liveStreamUrl: string): void {
|
private onLiveStreamAvailable(liveStreamUrl: string): void {
|
||||||
this.videoStreamUrl = liveStreamUrl;
|
this.videoStreamUrl = liveStreamUrl;
|
||||||
// this is the "dead" state; you would see the jitsi state; but are not connected
|
// this is the "dead" state; you would see the jitsi state; but are not connected
|
||||||
|
@ -169,6 +169,20 @@ def get_config_variables():
|
|||||||
subgroup="Live conference",
|
subgroup="Live conference",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
yield ConfigVariable(
|
||||||
|
name="general_system_conference_enable_helpdesk",
|
||||||
|
default_value=False,
|
||||||
|
input_type="boolean",
|
||||||
|
label="Enable help desk",
|
||||||
|
help_text="""
|
||||||
|
Shows a help icon in the conference bar.
|
||||||
|
Users can connect to a dedicated conference.
|
||||||
|
The conference host has to manually ensure the coverage of the help desk.
|
||||||
|
""",
|
||||||
|
weight=148,
|
||||||
|
subgroup="Live conference",
|
||||||
|
)
|
||||||
|
|
||||||
# Applause
|
# Applause
|
||||||
|
|
||||||
yield ConfigVariable(
|
yield ConfigVariable(
|
||||||
|
Loading…
Reference in New Issue
Block a user