diff --git a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.html b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.html
index c7b7f2c62..71255d9b0 100644
--- a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.html
+++ b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.html
@@ -11,6 +11,19 @@
+
+
-
+
|
{{'app.playlist.summary' | translate}}
diff --git a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.scss b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.scss
index d2bbb1913..61fcb1649 100644
--- a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.scss
+++ b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.scss
@@ -53,7 +53,44 @@
color: $kGrayscale3;
}
}
-
+.kTableHeader {
+ display: flex;
+ align-items: center;
+ padding: 16px 24px;
+ position: relative;
+ .kTableTitle {
+ font-size: 20px;
+ font-weight: 700;
+ color: $kGrayscale1;
+ }
+ .closeIcon {
+ position: absolute;
+ right: 28px;
+ top: 20px;
+ cursor: pointer;
+ &.disable {
+ opacity: 0.3;
+ cursor: default;
+ pointer-events: none;
+ }
+ &:hover {
+ .close {
+ fill: $kGrayscale1;
+ }
+ }
+ }
+ .kSearchInput {
+ margin-left: auto;
+ background: $kMagnifyingGlassBkg;
+ width: 200px;
+ padding: 6px 32px 6px 32px;
+ border-radius: 4px;
+ border: 1px solid $kGrayscale3;
+ color: $kGrayscale1;
+ font-size: 15px;
+ font-weight: 400;
+ }
+}
:host ::ng-deep .kRowExpansion {
padding: 0 !important;
text-align: center;
diff --git a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.ts b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.ts
index 61cfde8f8..5fd518239 100644
--- a/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.ts
+++ b/src/app/modules/entry-ep/views/session/viewer-engagement/viewer-engagement.component.ts
@@ -1,6 +1,6 @@
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import { Tab } from 'shared/components/report-tabs/report-tabs.component';
-import { KalturaEndUserReportInputFilter, KalturaFilterPager, KalturaReportInterval, KalturaReportTable, KalturaReportTotal, KalturaReportType } from 'kaltura-ngx-client';
+import {KalturaClient, KalturaEndUserReportInputFilter, KalturaFilterPager, KalturaReportInterval, KalturaReportTable, KalturaReportTotal, KalturaReportType, KalturaUserFilter, UserListAction} from 'kaltura-ngx-client';
import { AreaBlockerMessage } from '@kaltura-ng/kaltura-ui';
import {AppAnalytics, AuthService, ButtonType, ErrorsManagerService, NavigationDrillDownService, ReportConfig, ReportService} from 'shared/services';
import { switchMap } from 'rxjs/operators';
@@ -19,6 +19,7 @@ import { DateFilterUtils } from "shared/components/date-filter/date-filter-utils
import { ExportItem } from "shared/components/export-csv/export-config-base.service";
import { ExportConfig } from "./export.config";
import { analyticsConfig } from "configuration/analytics-config";
+import {cancelOnDestroy} from "@kaltura-ng/kaltura-common";
@Component({
selector: 'app-ep-viewer-engagement',
@@ -31,7 +32,7 @@ import { analyticsConfig } from "configuration/analytics-config";
ExportConfig
]
})
-export class EpViewerEngagementComponent implements OnInit {
+export class EpViewerEngagementComponent implements OnInit, OnDestroy {
@Input() entryIdIn = '';
@Input() startDate: Date;
@Input() actualStartDate: Date; // session actual start date
@@ -61,9 +62,12 @@ export class EpViewerEngagementComponent implements OnInit {
searchInAdminTags: false
});
+ public _peopleSearch = '';
+
constructor(private _frameEventManager: FrameEventManagerService,
private _reportService: ReportService,
private _analytics: AppAnalytics,
+ private _kalturaClient: KalturaClient,
private _errorsManager: ErrorsManagerService,
_dataConfigService: ViewerEngagementConfig,
private _authService: AuthService,
@@ -83,11 +87,11 @@ export class EpViewerEngagementComponent implements OnInit {
endDay: null,
startDay: null,
compare: null
- }
+ };
this._loadReport();
}
- private _loadReport(sections = this._dataConfig): void {
+ private _loadReport(sections = this._dataConfig, userIds = ''): void {
this._isBusy = true;
this._blockerMessage = null;
@@ -96,11 +100,17 @@ export class EpViewerEngagementComponent implements OnInit {
this._filter.fromDate = Math.floor(this.startDate.getTime() / 1000);
this._filter.toDate = Math.floor(this.endDate.getTime() / 1000);
this._filter.interval = KalturaReportInterval.days;
+ if (userIds.length > 0) {
+ this._filter.userIds = userIds;
+ } else {
+ delete this._filter.userIds;
+ }
+
const reportConfig: ReportConfig = { reportType: this._reportType, filter: this._filter, pager: this._pager, order: this._order };
this._reportService.getReport(reportConfig, sections)
.pipe(switchMap(report => {
- return ObservableOf({ report, compare: null })
+ return ObservableOf({ report, compare: null });
}))
.subscribe(({ report, compare }) => {
this._tableData = [];
@@ -204,4 +214,41 @@ export class EpViewerEngagementComponent implements OnInit {
this._analytics.trackButtonClickEvent(ButtonType.Expand, 'Events_session_expand_user');
}
}
+
+ public _onSearch(): void {
+ if (this._peopleSearch.length) {
+ this._isBusy = true;
+ this._kalturaClient.request(new UserListAction({
+ pager: new KalturaFilterPager({pageSize: 500, pageIndex: 0}),
+ filter: new KalturaUserFilter({
+ firstNameOrLastNameStartsWith: this._peopleSearch
+ })
+ }))
+ .pipe(cancelOnDestroy(this))
+ .subscribe(response => {
+ if (response?.objects?.length) {
+ const userIds = response.objects.map(user => user.id).join(analyticsConfig.valueSeparator);
+ this._loadReport({ table: this._dataConfig[ReportDataSection.table] }, userIds);
+ } else {
+ this._loadReport({ table: this._dataConfig[ReportDataSection.table] }, this._peopleSearch + Math.random()); // make sure no users will be found
+ }
+ },
+ error => {
+ this._isBusy = false;
+ const actions = {
+ 'close': () => {
+ this._blockerMessage = null;
+ },
+ 'retry': () => {
+ this._onSearch();
+ },
+ };
+ this._blockerMessage = this._errorsManager.getErrorMessage(error, actions);
+ });
+ } else {
+ this._loadReport();
+ }
+ }
+
+ ngOnDestroy(): void {}
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 4c93613d4..af3afe581 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -586,6 +586,8 @@
"count_reaction_clicked": "Reactions",
"count_raise_hand_clicked": "Raised hands",
"combined_live_engaged_users_play_time_ratio": "Live engagement rate",
+ "people": "Attendees",
+ "search": "Search attendees",
"heatMap": {
"engaged": "Engaged",
"notEngaged": "Not Engaged",
|