Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VIH-11147 refactor participant panel component to read from the redux store #2307

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VideoWeb/VideoWeb.EventHub/VideoWeb.EventHub.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VideoWeb.Common\VideoWeb.Common.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ public async Task should_return_the_statuses_for_the_conference()
}

[Test]
public async Task should_return_NoContent_status_code_if_video_control_statuses_is_null()
public async Task should_return_empty_dictionary_if_video_control_statuses_is_null()
{

var conferenceVideoControlStatuses = new ConferenceVideoControlStatuses();

_mocker.Mock<IConferenceVideoControlStatusService>()
.Setup(x => x.GetVideoControlStateForConference(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(() => default);

var response = await _sut.GetVideoControlStatusesForConference(_conferenceId) as NoContentResult;
var response = await _sut.GetVideoControlStatusesForConference(_conferenceId);

ClassicAssert.AreEqual(response.StatusCode, (int)HttpStatusCode.NoContent);

response.Should().BeAssignableTo<OkObjectResult>().Which.Value.Should().BeEquivalentTo(conferenceVideoControlStatuses);
}

[Test]
Expand Down
9 changes: 3 additions & 6 deletions VideoWeb/VideoWeb.UnitTests/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -2240,11 +2240,8 @@
},
"System.Text.Json": {
"type": "Transitive",
"resolved": "8.0.4",
"contentHash": "bAkhgDJ88XTsqczoxEMliSrpijKZHhbJQldhAmObj/RbrN3sU5dcokuXmWJWsdQAhiMJ9bTayWsL1C9fbbCRhw==",
"dependencies": {
"System.Text.Encodings.Web": "8.0.0"
}
"resolved": "8.0.5",
"contentHash": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg=="
},
"System.Text.RegularExpressions": {
"type": "Transitive",
Expand Down Expand Up @@ -2407,7 +2404,7 @@
"Microsoft.ApplicationInsights.AspNetCore": "[2.22.0, )",
"Microsoft.AspNetCore.SignalR": "[1.1.0, )",
"Microsoft.Extensions.Caching.Abstractions": "[8.0.0, )",
"System.Text.Json": "[8.0.4, )",
"System.Text.Json": "[8.0.5, )",
"VideoWeb.Common": "[1.0.0, )",
"VideoWeb.Contract": "[1.0.0, )"
}
Expand Down
32 changes: 16 additions & 16 deletions VideoWeb/VideoWeb/ClientApp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion VideoWeb/VideoWeb/ClientApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"ng-mocks": "^14.12.2",
"nswag": "^14.1.0",
"prettier": "^3.3.3",
"puppeteer": "^23.7.1",
"puppeteer": "^23.8.0",
"run-script-os": "^1.1.6",
"sass": "^1.77.8",
"typescript": ">=5.2.0 <5.4.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('AudioRecordingService', () => {
isRemoteMuted: false,
isSpotlighted: false,
handRaised: false,
isVideoMuted: false,
pexipDisplayName: 'vh-wowza',
uuid: 'unique-identifier',
callTag: 'call-tag',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2019,15 +2019,6 @@ export class ApiClient extends ApiClientBase {
return _observableOf(result200);
})
);
} else if (status === 204) {
return blobToText(responseBlob).pipe(
_observableMergeMap(_responseText => {
let result204: any = null;
let resultData204 = _responseText === '' ? null : JSON.parse(_responseText, this.jsonParseReviver);
result204 = ConferenceVideoControlStatuses.fromJS(resultData204);
return _observableOf(result204);
})
);
} else if (status === 401) {
return blobToText(responseBlob).pipe(
_observableMergeMap(_responseText => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ describe('ParticipantService', () => {
callTag: undefined,
isRemoteMuted: false,
isSpotlighted: false,
isVideoMuted: false,
handRaised: false,
isAudioOnlyCall: false,
isVideoCall: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ export class ParticipantService {
this.logger.debug(`${this.loggerPrefix} loading participants and VMRs`);

const conferenceId = this.conferenceService.currentConferenceId;
if (!conferenceId) {
return;
}
return zip(
this.conferenceService.getParticipantsForConference(conferenceId),
this.conferenceService.getEndpointsForConference(conferenceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export class HearingLayoutService {

getCurrentRecommendedLayout(): Observable<HearingLayout> {
return this.conferenceService.currentConference$.pipe(
filter(conference => conference !== null),
take(1),
map(conference => conference.id),
mergeMap(conferenceId => this.apiClient.getRecommendedLayoutForHearing(conferenceId))
Expand All @@ -135,6 +136,7 @@ export class HearingLayoutService {
updateCurrentLayout(layout: HearingLayout) {
this.conferenceService.currentConference$
.pipe(
filter(conference => conference !== null),
take(1),
map(conference => conference.id)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,37 @@ import { PanelModel } from 'src/app/waiting-space/models/panel-model-base';
import { ParticipantPanelModel } from 'src/app/waiting-space/models/participant-panel-model';
import { ParticipantModel } from '../models/participant';
import { HearingRole } from 'src/app/waiting-space/models/hearing-role-model';
import { VHParticipant } from 'src/app/waiting-space/store/models/vh-conference';

export class ParticipantPanelModelMapper {
mapFromVHParticipants(participants: VHParticipant[]): PanelModel[] {
const panelModels: PanelModel[] = [];
participants.forEach(p => {
const panelModel = new ParticipantPanelModel(
p.id,
p.displayName,
p.role,
p.tiledDisplayName,
p.hearingRole,
p.representee,
p.status
);
if (p.pexipInfo) {
panelModel.assignPexipId(p.pexipInfo.uuid);
panelModel.updateParticipant(
p.pexipInfo.isRemoteMuted,
p.pexipInfo.handRaised,
p.pexipInfo.isSpotlighted,
p.id,
p.localMediaStatus?.isMicrophoneMuted,
p.localMediaStatus?.isCameraOff
);
}
panelModels.push(panelModel);
});
return panelModels;
}

mapFromParticipantUserResponseArray(pats: ParticipantForUserResponse[]): PanelModel[] {
const participants: PanelModel[] = [];
pats.forEach(x => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const mockWowzaAgent: VHPexipParticipant = {
handRaised: false,
isAudioOnlyCall: true,
isRemoteMuted: false,
isVideoMuted: false,
isSpotlighted: false,
isVideoCall: false,
pexipDisplayName: 'vh-wowza',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ describe('HearingControlsBaseComponent', () => {
pexipDisplayName: undefined,
isRemoteMuted: false,
isSpotlighted: true,
isVideoMuted: false,
handRaised: false,
uuid: undefined,
callTag: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ <h1 #roomTitleLabel class="room-title-label">{{ getCaseNameAndNumber() }}</h1>
[roomLabel]="this.participant.current_room?.label"
>
</app-private-consultation-participants>
<app-participants-panel *ngIf="!isPrivateConsultation"
[isCountdownCompleted]='countdownComplete'></app-participants-panel>
<app-participants-panel></app-participants-panel>
</div>
<div *ngIf="hearing && !isPrivateConsultation" class="panel-wrapper"
[ngClass]="{ 'hide-panel': !panelStates['Chat'] }">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class ParticipantPanelModel extends IndividualPanelModel {
}

isAvailable(): boolean {
return (this.isQuickLinkUser && this.status === ParticipantStatus.InConsultation) || this.status === ParticipantStatus.Available;
return this.status === ParticipantStatus.InConsultation || this.status === ParticipantStatus.Available;
}

isInConsultation(): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ describe('ParticipantPanelModel', () => {
expect(model.isAvailable()).toBe(true);
});

it('returns isAvailable: false when participant is not quick link user and status is in consultation', () => {
it('returns isAvailable: true when participant is not quick link user and status is in consultation', () => {
participant.status = ParticipantStatus.InConsultation;
model = mapper.mapFromParticipantUserResponse(participant);
spyOnProperty(model, 'isQuickLinkUser').and.returnValue(false);
expect(model.isAvailable()).toBe(false);
expect(model.isAvailable()).toBe(true);
});

it('returns isAvailable: true when participant is quick link user and status is available', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,30 @@ export class ParticipantDeleted {
}

export class ParticipantUpdated {
/** Has been administratively audio muted. */
public isRemoteMuted: boolean;
/** Is spotlighted. */
public isSpotlighted: boolean;
/** Is hand raised. */
public handRaised: boolean;
/** Pexip display name (string delimited values). */
public pexipDisplayName: string;
/** Pexip UUID of participant. */
public uuid: string;
/** Participant call tag. */
public callTag: string;
/** Is the participant an audio only call. */
public isAudioOnlyCall: boolean;
/** IDoes the participant have video capability. */
public isVideoCall: boolean;
public protocol: string;
/** The audio mix this participant is receiving e.g. "main". */
public receivingAudioMix: string;
/** The audio mixes this participant is sending to. */
public sentAudioMixes: PexipAudioMix[];
public role: PexipParticipantRole;
/** Has the participant muted their video */
public isVideoMuted: boolean;

private constructor(
isRemoteMuted: string,
Expand Down Expand Up @@ -61,7 +73,7 @@ export class ParticipantUpdated {
}

static fromPexipParticipant(pexipParticipant: PexipParticipant) {
return new ParticipantUpdated(
const p = new ParticipantUpdated(
pexipParticipant.is_muted,
pexipParticipant.buzz_time,
pexipParticipant.display_name,
Expand All @@ -75,6 +87,10 @@ export class ParticipantUpdated {
pexipParticipant.receive_from_audio_mix,
pexipParticipant.send_to_audio_mixes
);

p.isVideoMuted = pexipParticipant.is_video_muted;

return p;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { EndpointStatus, Role, VideoEndpointResponse } from '../../services/clients/api-client';
import { VHEndpoint } from '../store/models/vh-conference';
import { IndividualPanelModel } from './individual-panel-model';

export class VideoEndpointPanelModel extends IndividualPanelModel {
public status: EndpointStatus;

constructor(endpoint: VideoEndpointResponse) {
super(endpoint.id, endpoint.display_name, Role.Individual, endpoint.pexip_display_name, 'Video access point', '');
constructor(endpoint: VideoEndpointResponse | VHEndpoint) {
if (endpoint instanceof VideoEndpointResponse) {
super(endpoint.id, endpoint.display_name, Role.Individual, endpoint.pexip_display_name, 'Video access point', '');
} else {
super(endpoint.id, endpoint.displayName, Role.Individual, endpoint?.pexipInfo?.pexipDisplayName, 'Video access point', '');
}
this.status = endpoint.status;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,19 @@
<img
*ngIf="participant.isMicRemoteMuted()"
appTooltip
[text]="participant.isMicRemoteMuted() ? 'participants-panel.unmute-lock' : ('participants-panel.mute-participant' | translate)"
[text]="
participant.isMicRemoteMuted()
? ('participants-panel.unmute-lock' | translate)
: ('participants-panel.mute-participant' | translate)
"
colour="grey"
[src]="participant.isMicRemoteMuted() ? '/assets/images/mic_remote_mute.png' : '/assets/images/mic.png'"
class="panel-icon"
[attr.alt]="
(participant.isMicRemoteMuted() ? 'participants-panel.microphone-muted-icon' : 'participants-panel.microphone-on-icon')
| translate
(participant.isMicRemoteMuted()
? ('participants-panel.microphone-muted-icon' | translate)
: 'participants-panel.microphone-on-icon'
) | translate
"
(click)="toggleParticipantMute(); $event.stopPropagation()"
tabindex="0"
Expand Down
Loading
Loading