MOBILE-3638 chat: Migrate sessions pages
parent
e180445b96
commit
1ae24282ed
|
@ -17,18 +17,54 @@ import { RouterModule, Routes } from '@angular/router';
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { AddonModChatComponentsModule } from './components/components.module';
|
import { AddonModChatComponentsModule } from './components/components.module';
|
||||||
import { AddonModChatIndexPage } from './pages/index/index';
|
import { AddonModChatIndexPage } from './pages/index/index';
|
||||||
|
import { AddonModChatChatPage } from './pages/chat/chat';
|
||||||
|
import { AddonModChatSessionMessagesPage } from './pages/session-messages/session-messages';
|
||||||
|
import { CoreScreen } from '@services/screen';
|
||||||
|
import { conditionalRoutes } from '@/app/app-routing.module';
|
||||||
|
import { AddonModChatSessionsPage } from './pages/sessions/sessions';
|
||||||
|
|
||||||
const routes: Routes = [
|
const commonRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: ':courseId/:cmId',
|
path: ':courseId/:cmId',
|
||||||
component: AddonModChatIndexPage,
|
component: AddonModChatIndexPage,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':courseId/:cmId/chat',
|
path: ':courseId/:cmId/chat',
|
||||||
loadChildren: () => import('./pages/chat/chat.module').then(m => m.AddonModChatChatPageModule),
|
component: AddonModChatChatPage,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const mobileRoutes: Routes = [
|
||||||
|
...commonRoutes,
|
||||||
|
{
|
||||||
|
path: ':courseId/:cmId/sessions',
|
||||||
|
component: AddonModChatSessionsPage,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':courseId/:cmId/sessions/:sessionStart/:sessionEnd',
|
||||||
|
component: AddonModChatSessionMessagesPage,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const tabletRoutes: Routes = [
|
||||||
|
...commonRoutes,
|
||||||
|
{
|
||||||
|
path: ':courseId/:cmId/sessions',
|
||||||
|
component: AddonModChatSessionsPage,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: ':sessionStart/:sessionEnd',
|
||||||
|
component: AddonModChatSessionMessagesPage,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
...conditionalRoutes(mobileRoutes, () => CoreScreen.isMobile),
|
||||||
|
...conditionalRoutes(tabletRoutes, () => CoreScreen.isTablet),
|
||||||
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forChild(routes),
|
RouterModule.forChild(routes),
|
||||||
|
@ -37,6 +73,9 @@ const routes: Routes = [
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AddonModChatIndexPage,
|
AddonModChatIndexPage,
|
||||||
|
AddonModChatChatPage,
|
||||||
|
AddonModChatSessionsPage,
|
||||||
|
AddonModChatSessionMessagesPage,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AddonModChatLazyModule {}
|
export class AddonModChatLazyModule {}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>{{ 'addon.mod_chat.messages' | translate }}</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshMessages($event.target)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
<core-loading [hideUntil]="loaded" class="safe-area-page">
|
||||||
|
<ion-list class="addon-messages-discussion-container" aria-live="polite">
|
||||||
|
<ng-container *ngFor="let message of messages; index as index;">
|
||||||
|
|
||||||
|
<h6 class="ion-text-center addon-messages-date" *ngIf="message.showDate">
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimedayshort" }}
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special">
|
||||||
|
<ion-badge class="ion-text-wrap" color="success" *ngIf="message.issystem && message.message == 'enter'">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-sign-in-alt"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
{{ 'addon.mod_chat.messageenter' | translate:{$a: message.userfullname} }}
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
|
||||||
|
<ion-badge class="ion-text-wrap" color="danger" *ngIf="message.issystem && message.message == 'exit'">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-sign-out-alt"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
{{ 'addon.mod_chat.messageexit' | translate:{$a: message.userfullname} }}
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
|
||||||
|
<ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep == 'all'">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-bell"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
{{ 'addon.mod_chat.messagebeepseveryone' | translate:{$a: message.userfullname} }}
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
|
||||||
|
<ion-badge class="ion-text-wrap" color="primary"
|
||||||
|
*ngIf="message.userid != currentUserId && message.beep == currentUserId">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-bell"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
{{ 'addon.mod_chat.messagebeepsyou' | translate:{$a: message.userfullname} }}
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
|
||||||
|
<ion-badge class="ion-text-wrap" color="light"
|
||||||
|
*ngIf="message.userid == currentUserId && message.beep && message.beep != 'all'">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-bell"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
{{ 'addon.mod_chat.messageyoubeep' | translate:{$a: message.beepWho} }}
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
|
||||||
|
<ion-badge class="ion-text-wrap" color="info" *ngIf="!message.issystem && !message.beep">
|
||||||
|
<span>
|
||||||
|
<ion-icon name="fas-asterisk"></ion-icon>
|
||||||
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
<strong>
|
||||||
|
{{ message.userfullname }} <core-format-text [text]="message.message" contextLevel="module"
|
||||||
|
[contextInstanceId]="cmId" [courseId]="courseId"></core-format-text>
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
|
</ion-badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ion-item *ngIf="!message.special" class="ion-text-wrap addon-message"
|
||||||
|
[class.addon-message-mine]="message.userid == currentUserId"
|
||||||
|
[class.addon-message-not-mine]="message.userid != currentUserId"
|
||||||
|
[class.addon-message-no-user]="!message.showUserData">
|
||||||
|
<ion-label>
|
||||||
|
<!-- User data. -->
|
||||||
|
<h2 class="addon-message-user">
|
||||||
|
<core-user-avatar slot="start" [user]="message" [linkProfile]="false" *ngIf="message.showUserData">
|
||||||
|
</core-user-avatar>
|
||||||
|
<div *ngIf="message.showUserData">{{ message.userfullname }}</div>
|
||||||
|
<ion-note>{{ message.timestamp * 1000 | coreFormatDate: "strftimetime" }}</ion-note>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="addon-message-text">
|
||||||
|
<core-format-text [text]="message.message" contextLevel="module" [contextInstanceId]="cmId"
|
||||||
|
[courseId]="courseId">
|
||||||
|
</core-format-text>
|
||||||
|
</p>
|
||||||
|
</ion-label>
|
||||||
|
<div class="tail" *ngIf="message.showTail"></div>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
|
</ion-list>
|
||||||
|
</core-loading>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,6 @@
|
||||||
|
:host {
|
||||||
|
.addon-mod_chat-notice {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { CoreUser } from '@features/user/services/user';
|
||||||
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { AddonModChat } from '../../services/chat';
|
||||||
|
import { AddonModChatFormattedSessionMessage, AddonModChatHelper } from '../../services/chat-helper';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays list of chat session messages.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-addon-mod-chat-session-messages',
|
||||||
|
templateUrl: 'session-messages.html',
|
||||||
|
styleUrls: ['session-messages.scss', '../../../../messages/pages/discussion/discussion.scss'],
|
||||||
|
})
|
||||||
|
export class AddonModChatSessionMessagesPage implements OnInit {
|
||||||
|
|
||||||
|
currentUserId!: number;
|
||||||
|
cmId!: number;
|
||||||
|
messages: AddonModChatFormattedSessionMessage[] = [];
|
||||||
|
loaded = false;
|
||||||
|
courseId!: number;
|
||||||
|
|
||||||
|
protected chatId!: number;
|
||||||
|
protected sessionStart!: number;
|
||||||
|
protected sessionEnd!: number;
|
||||||
|
protected groupId!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.courseId = CoreNavigator.getRouteNumberParam('courseId')!;
|
||||||
|
this.cmId = CoreNavigator.getRouteNumberParam('cmId')!;
|
||||||
|
this.sessionStart = CoreNavigator.getRouteNumberParam('sessionStart')!;
|
||||||
|
this.sessionEnd = CoreNavigator.getRouteNumberParam('sessionEnd')!;
|
||||||
|
this.chatId = CoreNavigator.getRouteNumberParam('chatId')!;
|
||||||
|
this.groupId = CoreNavigator.getRouteNumberParam('groupId') || 0;
|
||||||
|
|
||||||
|
this.currentUserId = CoreSites.getCurrentSiteUserId();
|
||||||
|
|
||||||
|
this.fetchMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch session messages.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async fetchMessages(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const messages = await AddonModChat.getSessionMessages(
|
||||||
|
this.chatId,
|
||||||
|
this.sessionStart,
|
||||||
|
this.sessionEnd,
|
||||||
|
this.groupId,
|
||||||
|
{ cmId: this.cmId },
|
||||||
|
);
|
||||||
|
|
||||||
|
this.messages = await AddonModChat.getMessagesUserData(messages, this.courseId);
|
||||||
|
|
||||||
|
// Calculate which messages need to display the date or user data.
|
||||||
|
for (let index = 0 ; index < this.messages.length; index++) {
|
||||||
|
const prevMessage = index > 0 ? this.messages[index - 1] : undefined;
|
||||||
|
|
||||||
|
this.messages[index] = AddonModChatHelper.formatMessage(this.currentUserId, this.messages[index], prevMessage);
|
||||||
|
|
||||||
|
const message = this.messages[index];
|
||||||
|
|
||||||
|
if (message.beep && message.beep != String(this.currentUserId)) {
|
||||||
|
this.loadMessageBeepWho(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messages[this.messages.length - 1].showTail = true;
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
|
||||||
|
} finally {
|
||||||
|
this.loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async loadMessageBeepWho(message: AddonModChatFormattedSessionMessage): Promise<void> {
|
||||||
|
message.beepWho = await this.getUserFullname(message.beep!);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user fullname for a beep.
|
||||||
|
*
|
||||||
|
* @param id User Id before parsing.
|
||||||
|
* @return User fullname.
|
||||||
|
*/
|
||||||
|
protected async getUserFullname(id: string): Promise<string> {
|
||||||
|
const idNumber = parseInt(id, 10);
|
||||||
|
|
||||||
|
if (isNaN(idNumber)) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await CoreUser.getProfile(idNumber, this.courseId, true);
|
||||||
|
|
||||||
|
return user.fullname;
|
||||||
|
} catch {
|
||||||
|
// Error getting profile.
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh session messages.
|
||||||
|
*
|
||||||
|
* @param refresher Refresher.
|
||||||
|
*/
|
||||||
|
async refreshMessages(refresher: IonRefresher): Promise<void> {
|
||||||
|
try {
|
||||||
|
await CoreUtils.ignoreErrors(AddonModChat.invalidateSessionMessages(this.chatId, this.sessionStart, this.groupId));
|
||||||
|
|
||||||
|
await this.fetchMessages();
|
||||||
|
} finally {
|
||||||
|
refresher.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>{{ 'addon.mod_chat.chatreport' | translate }}</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<core-split-view>
|
||||||
|
<ion-refresher slot="fixed" [disabled]="!sessions.loaded" (ionRefresh)="refreshSessions($event.target)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
<core-loading [hideUntil]="sessions.loaded">
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)">
|
||||||
|
<ion-label id="addon-chat-groupslabel">
|
||||||
|
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
|
||||||
|
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
|
||||||
|
</ion-label>
|
||||||
|
<ion-select [(ngModel)]="groupId" (ionChange)="fetchSessions(true)" aria-labelledby="addon-chat-groupslabel"
|
||||||
|
interface="action-sheet">
|
||||||
|
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
|
||||||
|
{{groupOpt.name}}
|
||||||
|
</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'addon.mod_chat.showincompletesessions' | translate }}</ion-label>
|
||||||
|
<ion-toggle [(ngModel)]="showAll" (ionChange)="fetchSessions(true)"></ion-toggle>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-card *ngFor="let session of sessions.items" (click)="sessions.select(session)"
|
||||||
|
[class.core-selected-item]="sessions.isSelected(session)"
|
||||||
|
[class.addon-mod-chat-session-show-more]="session.sessionusers.length < session.allsessionusers.length">
|
||||||
|
|
||||||
|
<ion-item class="ion-text-wrap">
|
||||||
|
<ion-label>
|
||||||
|
<h2>{{ session.sessionstart * 1000 | coreFormatDate }}</h2>
|
||||||
|
<p *ngIf="session.duration">{{ session.duration | coreDuration }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-card-content>
|
||||||
|
<ion-item *ngFor="let user of session.sessionusers">
|
||||||
|
<ion-label>
|
||||||
|
{{ user.userfullname }} <span *ngIf="user.messagecount">({{ user.messagecount }})</span>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card-content>
|
||||||
|
<div *ngIf="session.sessionusers.length < session.allsessionusers.length">
|
||||||
|
<ion-button fill="clear" (click)="showMoreUsers(session, $event)">
|
||||||
|
{{ 'core.showmore' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</div>
|
||||||
|
</ion-card>
|
||||||
|
|
||||||
|
<core-empty-box *ngIf="sessions.empty" icon="far-comments" [message]="'addon.mod_chat.nosessionsfound' | translate">
|
||||||
|
</core-empty-box>
|
||||||
|
</core-loading>
|
||||||
|
</core-split-view>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,8 @@
|
||||||
|
ion-app.app-root page-addon-mod-chat-sessions {
|
||||||
|
.addon-mod-chat-session-show-more .card-content{
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
.addon-mod-chat-session-selected {
|
||||||
|
border-top: 5px solid $core-splitview-selected;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||||
|
import { Params } from '@angular/router';
|
||||||
|
import { CorePageItemsListManager } from '@classes/page-items-list-manager';
|
||||||
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
|
import { CoreUser } from '@features/user/services/user';
|
||||||
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
import { CoreGroupInfo, CoreGroups } from '@services/groups';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { Translate } from '@singletons';
|
||||||
|
import { AddonModChat, AddonModChatSession, AddonModChatSessionUser } from '../../services/chat';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays list of chat sessions.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-addon-mod-chat-sessions',
|
||||||
|
templateUrl: 'sessions.html',
|
||||||
|
})
|
||||||
|
export class AddonModChatSessionsPage implements AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||||
|
|
||||||
|
sessions!: AddonChatSessionsManager;
|
||||||
|
showAll = false;
|
||||||
|
groupId = 0;
|
||||||
|
groupInfo?: CoreGroupInfo;
|
||||||
|
|
||||||
|
protected courseId!: number;
|
||||||
|
protected cmId!: number;
|
||||||
|
protected chatId!: number;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.sessions = new AddonChatSessionsManager(AddonModChatSessionsPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async ngAfterViewInit(): Promise<void> {
|
||||||
|
this.courseId = CoreNavigator.getRouteNumberParam('courseId')!;
|
||||||
|
this.cmId = CoreNavigator.getRouteNumberParam('cmId')!;
|
||||||
|
this.chatId = CoreNavigator.getRouteNumberParam('chatId')!;
|
||||||
|
this.sessions.setChatId(this.chatId);
|
||||||
|
|
||||||
|
await this.fetchSessions();
|
||||||
|
|
||||||
|
this.sessions.start(this.splitView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch chat sessions.
|
||||||
|
*
|
||||||
|
* @param showLoading Display a loading modal.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async fetchSessions(showLoading?: boolean): Promise<void> {
|
||||||
|
const modal = showLoading ? await CoreDomUtils.showModalLoading() : null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.groupInfo = await CoreGroups.getActivityGroupInfo(this.cmId, false);
|
||||||
|
|
||||||
|
this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo);
|
||||||
|
this.sessions.setGroupId(this.groupId);
|
||||||
|
|
||||||
|
const sessions = await AddonModChat.getSessions(this.chatId, this.groupId, this.showAll, { cmId: this.cmId });
|
||||||
|
|
||||||
|
// Fetch user profiles.
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
const formattedSessions = sessions.map((session: AddonModChatSessionFormatted) => {
|
||||||
|
session.duration = session.sessionend - session.sessionstart;
|
||||||
|
session.sessionusers.forEach((sessionUser) => {
|
||||||
|
// The WS does not return the user name, fetch user profile.
|
||||||
|
promises.push(this.loadUserFullname(sessionUser));
|
||||||
|
});
|
||||||
|
|
||||||
|
// If session has more than 4 users we display a "Show more" link.
|
||||||
|
session.allsessionusers = session.sessionusers;
|
||||||
|
if (session.sessionusers.length > 4) {
|
||||||
|
session.sessionusers = session.allsessionusers.slice(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
this.sessions.setItems(formattedSessions);
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
|
||||||
|
} finally {
|
||||||
|
modal?.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the fullname of a user.
|
||||||
|
*
|
||||||
|
* @param id User ID.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadUserFullname(sessionUser: AddonModChatUserSessionFormatted): Promise<void> {
|
||||||
|
if (sessionUser.userfullname) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await CoreUser.getProfile(sessionUser.userid, this.courseId, true);
|
||||||
|
|
||||||
|
sessionUser.userfullname = user.fullname;
|
||||||
|
} catch {
|
||||||
|
// Error getting profile, most probably the user is deleted.
|
||||||
|
sessionUser.userfullname = Translate.instant('core.deleteduser') + ' ' + sessionUser.userid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh chat sessions.
|
||||||
|
*
|
||||||
|
* @param refresher Refresher.
|
||||||
|
*/
|
||||||
|
async refreshSessions(refresher: IonRefresher): Promise<void> {
|
||||||
|
try {
|
||||||
|
await CoreUtils.ignoreErrors(CoreUtils.allPromises([
|
||||||
|
CoreGroups.invalidateActivityGroupInfo(this.cmId),
|
||||||
|
AddonModChat.invalidateSessions(this.chatId, this.groupId, this.showAll),
|
||||||
|
]));
|
||||||
|
|
||||||
|
await this.fetchSessions();
|
||||||
|
} finally {
|
||||||
|
refresher.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show more session users.
|
||||||
|
*
|
||||||
|
* @param session Chat session.
|
||||||
|
* @param event The event.
|
||||||
|
*/
|
||||||
|
showMoreUsers(session: AddonModChatSessionFormatted, event: Event): void {
|
||||||
|
session.sessionusers = session.allsessionusers!;
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.sessions.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to manage sessions.
|
||||||
|
*/
|
||||||
|
class AddonChatSessionsManager extends CorePageItemsListManager<AddonModChatSessionFormatted> {
|
||||||
|
|
||||||
|
chatId = -1;
|
||||||
|
groupId = 0;
|
||||||
|
|
||||||
|
constructor(pageComponent: unknown) {
|
||||||
|
super(pageComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set chat ID.
|
||||||
|
*
|
||||||
|
* @param chatId Chat ID.
|
||||||
|
*/
|
||||||
|
setChatId(chatId: number): void {
|
||||||
|
this.chatId = chatId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group ID.
|
||||||
|
*
|
||||||
|
* @param groupId Group ID.
|
||||||
|
*/
|
||||||
|
setGroupId(groupId: number): void {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
protected getItemPath(session: AddonModChatSessionFormatted): string {
|
||||||
|
return `${session.sessionstart}/${session.sessionend}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
protected getItemQueryParams(): Params {
|
||||||
|
return {
|
||||||
|
chatId: this.chatId,
|
||||||
|
groupId: this.groupId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields added to chat session in this view.
|
||||||
|
*/
|
||||||
|
type AddonModChatSessionFormatted = Omit<AddonModChatSession, 'sessionusers'> & {
|
||||||
|
duration?: number; // Session duration.
|
||||||
|
sessionusers: AddonModChatUserSessionFormatted[];
|
||||||
|
allsessionusers?: AddonModChatUserSessionFormatted[]; // All session users.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields added to user session in this view.
|
||||||
|
*/
|
||||||
|
type AddonModChatUserSessionFormatted = AddonModChatSessionUser & {
|
||||||
|
userfullname?: string; // User full name.
|
||||||
|
};
|
Loading…
Reference in New Issue