Merge pull request #3654 from dpalou/MOBILE-4322
MOBILE-4322 bbb: Display all playbacks in recordingsmain
commit
d8f6aaed84
|
@ -462,8 +462,6 @@
|
|||
"addon.mod_bigbluebuttonbn.view_message_viewer": "bigbluebuttonbn",
|
||||
"addon.mod_bigbluebuttonbn.view_message_viewers": "bigbluebuttonbn",
|
||||
"addon.mod_bigbluebuttonbn.view_nojoin": "bigbluebuttonbn",
|
||||
"addon.mod_bigbluebuttonbn.view_recording_format_presentation": "bigbluebuttonbn",
|
||||
"addon.mod_bigbluebuttonbn.view_recording_list_action_play": "bigbluebuttonbn",
|
||||
"addon.mod_bigbluebuttonbn.view_section_title_recordings": "bigbluebuttonbn",
|
||||
"addon.mod_book.errorchapter": "book",
|
||||
"addon.mod_book.modulenameplural": "book",
|
||||
|
|
|
@ -90,9 +90,8 @@
|
|||
</ion-label>
|
||||
</ion-item>
|
||||
<ng-container *ngFor="let recording of recordings">
|
||||
<ion-item *ngIf="recording.url" button class="addon-mod_bbb-recording-title" [attr.aria-expanded]="recording.expanded"
|
||||
(click)="toggle(recording)" [attr.aria-label]="(recording.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||
detail="false">
|
||||
<ion-item button class="addon-mod_bbb-recording-title" [attr.aria-expanded]="recording.expanded" (click)="toggle(recording)"
|
||||
[attr.aria-label]="(recording.expanded ? 'core.collapse' : 'core.expand') | translate" detail="false">
|
||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||
[class.expandable-status-icon-expanded]="recording.expanded">
|
||||
</ion-icon>
|
||||
|
@ -100,12 +99,22 @@
|
|||
<p>{{ recording.type }}</p>
|
||||
<p>{{ recording.name }}</p>
|
||||
</ion-label>
|
||||
<ion-button slot="end" fill="clear" (click)="playRecording($event, recording)"
|
||||
[attr.aria-label]="'addon.mod_bigbluebuttonbn.view_recording_list_action_play' | translate">
|
||||
<ion-icon name="fas-circle-play" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<div [hidden]="!recording.expanded" class="addon-mod_bbb-recording-details">
|
||||
<div *ngIf="recording.playbacks.length" class="addon-mod_bbb-recording-playbacks">
|
||||
<ion-item class="ion-text-wrap addon-mod_bbb-recording-playback-title">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ recording.playbackLabel }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let playback of recording.playbacks" button (click)="openPlayback($event, playback)"
|
||||
class="ion-text-wrap addon-mod_bbb-recording-playback-item">
|
||||
<ion-label>
|
||||
<p>{{ playback.name }}</p>
|
||||
</ion-label>
|
||||
<ion-icon slot="end" [name]="playback.icon" aria-hidden="true"></ion-icon>
|
||||
</ion-item>
|
||||
</div>
|
||||
<ion-item *ngFor="let data of recording.details" class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ data.label }}</p>
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
font-size: 100%;
|
||||
}
|
||||
|
||||
.addon-mod_bbb-recording-playback-title ion-label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.addon-mod_bbb-recording-details {
|
||||
border-top: 2px solid var(--recording-details-border);
|
||||
border-bottom: 2px solid var(--recording-details-border);
|
||||
|
|
|
@ -25,7 +25,13 @@ import { CoreTextUtils } from '@services/utils/text';
|
|||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { Translate } from '@singletons';
|
||||
import { AddonModBBB, AddonModBBBData, AddonModBBBMeetingInfo, AddonModBBBService } from '../../services/bigbluebuttonbn';
|
||||
import {
|
||||
AddonModBBB,
|
||||
AddonModBBBData,
|
||||
AddonModBBBMeetingInfo,
|
||||
AddonModBBBRecordingPlaybackTypes,
|
||||
AddonModBBBService,
|
||||
} from '../../services/bigbluebuttonbn';
|
||||
|
||||
/**
|
||||
* Component that displays a Big Blue Button activity.
|
||||
|
@ -43,7 +49,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
groupInfo?: CoreGroupInfo;
|
||||
groupId = 0;
|
||||
meetingInfo?: AddonModBBBMeetingInfo;
|
||||
recordings?: RecordingData[];
|
||||
recordings?: Recording[];
|
||||
|
||||
constructor(
|
||||
protected content?: IonContent,
|
||||
|
@ -139,13 +145,17 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
const columns = CoreUtils.arrayToObject(recordingsTable.columns, 'key');
|
||||
|
||||
this.recordings = recordingsTable.parsedData.map(recordingData => {
|
||||
const playbackEl = CoreDomUtils.convertToElement(String(recordingData.playback));
|
||||
const playbackAnchor = playbackEl.querySelector('a');
|
||||
const details: RecordingDetailData[] = [];
|
||||
const details: RecordingDetail[] = [];
|
||||
const playbacksEl = CoreDomUtils.convertToElement(String(recordingData.playback));
|
||||
const playbacks: RecordingPlayback[] = Array.from(playbacksEl.querySelectorAll('a')).map(playbackAnchor => ({
|
||||
name: playbackAnchor.textContent ?? '',
|
||||
url: playbackAnchor.href,
|
||||
icon: this.getPlaybackIcon(playbackAnchor),
|
||||
}));
|
||||
|
||||
Object.entries(recordingData).forEach(([key, value]) => {
|
||||
const columnData = columns[key];
|
||||
if (!columnData || value === '' || key === 'actionbar') {
|
||||
if (!columnData || value === '' || key === 'actionbar' || key === 'playback') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -158,16 +168,11 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
return;
|
||||
}
|
||||
|
||||
if (key === 'playback') {
|
||||
// Remove HTML, we're only interested in the text.
|
||||
value = (valueElement.textContent ?? '').trim();
|
||||
} else {
|
||||
// Treat "quick edit" buttons, they aren't supported in the app.
|
||||
const quickEditLink = valueElement.querySelector('.quickeditlink');
|
||||
if (quickEditLink) {
|
||||
// The first span in quick edit link contains the actual HTML, use it.
|
||||
value = (quickEditLink.querySelector('span')?.innerHTML ?? '').trim();
|
||||
}
|
||||
// Treat "quick edit" buttons, they aren't supported in the app.
|
||||
const quickEditLink = valueElement.querySelector('.quickeditlink');
|
||||
if (quickEditLink) {
|
||||
// The first span in quick edit link contains the actual HTML, use it.
|
||||
value = (quickEditLink.querySelector('span')?.innerHTML ?? '').trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,16 +184,40 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
});
|
||||
|
||||
return {
|
||||
type: playbackAnchor?.innerText ??
|
||||
Translate.instant('addon.mod_bigbluebuttonbn.view_recording_format_presentation'),
|
||||
name: CoreTextUtils.cleanTags(String(recordingData.recording), { singleLine: true }),
|
||||
url: playbackAnchor?.href ?? '',
|
||||
playbackLabel: columns.playback.label,
|
||||
playbacks,
|
||||
details,
|
||||
expanded: false,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the playback icon.
|
||||
*
|
||||
* @param playbackAnchor Anchor element.
|
||||
* @returns Icon name.
|
||||
*/
|
||||
protected getPlaybackIcon(playbackAnchor: HTMLAnchorElement): string {
|
||||
const type = playbackAnchor.dataset.target;
|
||||
switch (type) {
|
||||
case AddonModBBBRecordingPlaybackTypes.NOTES:
|
||||
return 'far-file-lines';
|
||||
case AddonModBBBRecordingPlaybackTypes.PODCAST:
|
||||
return 'fas-microphone-lines';
|
||||
case AddonModBBBRecordingPlaybackTypes.SCREENSHARE:
|
||||
return 'fas-display';
|
||||
case AddonModBBBRecordingPlaybackTypes.STATISTICS:
|
||||
return 'fas-chart-line';
|
||||
case AddonModBBBRecordingPlaybackTypes.VIDEO:
|
||||
return 'fas-video';
|
||||
case AddonModBBBRecordingPlaybackTypes.PRESENTATION:
|
||||
default:
|
||||
return 'fas-circle-play';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
@ -323,21 +352,21 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
*
|
||||
* @param recording Recording.
|
||||
*/
|
||||
toggle(recording: RecordingData): void {
|
||||
toggle(recording: Recording): void {
|
||||
recording.expanded = !recording.expanded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play a recording.
|
||||
* Open a recording playback.
|
||||
*
|
||||
* @param event Click event.
|
||||
* @param recording Recording.
|
||||
* @param playback Playback.
|
||||
*/
|
||||
playRecording(event: MouseEvent, recording: RecordingData): void {
|
||||
openPlayback(event: MouseEvent, playback: RecordingPlayback): void {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(recording.url);
|
||||
CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(playback.url);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -345,19 +374,28 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
/**
|
||||
* Recording data.
|
||||
*/
|
||||
type RecordingData = {
|
||||
type: string;
|
||||
type Recording = {
|
||||
name: string;
|
||||
url: string;
|
||||
expanded: boolean;
|
||||
details: RecordingDetailData[];
|
||||
playbackLabel: string;
|
||||
playbacks: RecordingPlayback[];
|
||||
details: RecordingDetail[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Recording detail data.
|
||||
*/
|
||||
type RecordingDetailData = {
|
||||
type RecordingDetail = {
|
||||
label: string;
|
||||
value: string;
|
||||
allowHTML: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recording playback data.
|
||||
*/
|
||||
type RecordingPlayback = {
|
||||
name: string;
|
||||
url: string;
|
||||
icon: string;
|
||||
};
|
||||
|
|
|
@ -17,7 +17,5 @@
|
|||
"view_message_viewer": "viewer",
|
||||
"view_message_viewers": "viewers",
|
||||
"view_nojoin": "You do not have a role that is allowed to join this session.",
|
||||
"view_recording_format_presentation": "Presentation",
|
||||
"view_recording_list_action_play": "Play",
|
||||
"view_section_title_recordings": "Recordings"
|
||||
}
|
||||
|
|
|
@ -548,3 +548,15 @@ export type AddonModBBBRecordingsWSTableData = {
|
|||
export type AddonModBBBRecordingsTableData = AddonModBBBRecordingsWSTableData & {
|
||||
parsedData: Record<string, string|number|boolean>[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Recording playback types.
|
||||
*/
|
||||
export enum AddonModBBBRecordingPlaybackTypes {
|
||||
NOTES = 'notes',
|
||||
PODCAST = 'podcast',
|
||||
PRESENTATION = 'presentation',
|
||||
SCREENSHARE = 'screenshare',
|
||||
STATISTICS = 'statistics',
|
||||
VIDEO = 'video',
|
||||
}
|
||||
|
|
|
@ -143,15 +143,15 @@ Feature: Test basic usage of BBB activity in app
|
|||
| BBB | Recording 1 | Description 1 | 3 |
|
||||
| BBB | Recording 2 | Description 2 | 3 |
|
||||
And I entered the bigbluebuttonbn activity "BBB" on course "Course 1" as "student1" in the app
|
||||
Then I should find "Presentation" in the app
|
||||
And I should find "Recording 1" in the app
|
||||
Then I should find "Recording 1" in the app
|
||||
And I should find "Recording 2" in the app
|
||||
But I should not find "Description 1" in the app
|
||||
And I should not find "Description 2" in the app
|
||||
And I should not find "Presentation" in the app
|
||||
|
||||
When I press "Recording 1" in the app
|
||||
Then I should find "Description 1" in the app
|
||||
And I should find "Presentation" within "Playback" "ion-item" in the app
|
||||
And I should find "Presentation" in the app
|
||||
And I should find "Recording 1" within "Name" "ion-item" in the app
|
||||
And I should find "Date" in the app
|
||||
And I should find "3600" within "Duration" "ion-item" in the app
|
||||
|
@ -162,12 +162,12 @@ Feature: Test basic usage of BBB activity in app
|
|||
|
||||
When I press "Recording 2" in the app
|
||||
Then I should find "Description 2" in the app
|
||||
And I should find "Presentation" within "Playback" "ion-item" in the app
|
||||
And I should find "Presentation" in the app
|
||||
And I should find "Recording 2" within "Name" "ion-item" in the app
|
||||
But I should not find "Description 1" in the app
|
||||
|
||||
# Test play button, but the mock server doesn't support viewing recordings.
|
||||
When I press "Play" near "Recording 1" in the app
|
||||
When I press "Presentation" in the app
|
||||
And I press "OK" in the app
|
||||
And I switch to the browser tab opened by the app
|
||||
And I log in as "student1"
|
||||
|
|
Loading…
Reference in New Issue