MOBILE-3643 forum: Migrate new discussion form
parent
fbad712136
commit
d4bc77b386
|
@ -40,6 +40,14 @@ import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { AddonModForumDiscussionOptionsMenuComponent } from '../discussion-options-menu/discussion-options-menu';
|
import { AddonModForumDiscussionOptionsMenuComponent } from '../discussion-options-menu/discussion-options-menu';
|
||||||
import { AddonModForumSortOrderSelectorComponent } from '../sort-order-selector/sort-order-selector';
|
import { AddonModForumSortOrderSelectorComponent } from '../sort-order-selector/sort-order-selector';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type to use for selecting new discussion form in the discussions manager.
|
||||||
|
*/
|
||||||
|
type NewDiscussionForm = {
|
||||||
|
newDiscussion: true;
|
||||||
|
timeCreated: number;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a forum entry page.
|
* Component that displays a forum entry page.
|
||||||
*/
|
*/
|
||||||
|
@ -193,17 +201,16 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
||||||
.getForum(this.courseId, this.module.id)
|
.getForum(this.courseId, this.module.id)
|
||||||
.then(async (forum) => {
|
.then(async (forum) => {
|
||||||
this.forum = forum;
|
this.forum = forum;
|
||||||
|
|
||||||
this.description = forum.intro || this.description;
|
this.description = forum.intro || this.description;
|
||||||
|
this.availabilityMessage = AddonModForumHelper.instance.getAvailabilityMessage(forum);
|
||||||
this.descriptionNote = Translate.instant('addon.mod_forum.numdiscussions', {
|
this.descriptionNote = Translate.instant('addon.mod_forum.numdiscussions', {
|
||||||
numdiscussions: forum.numdiscussions,
|
numdiscussions: forum.numdiscussions,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof forum.istracked != 'undefined') {
|
if (typeof forum.istracked != 'undefined') {
|
||||||
this.trackPosts = forum.istracked;
|
this.trackPosts = forum.istracked;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.availabilityMessage = AddonModForumHelper.instance.getAvailabilityMessage(forum);
|
|
||||||
|
|
||||||
this.dataRetrieved.emit(forum);
|
this.dataRetrieved.emit(forum);
|
||||||
|
|
||||||
switch (forum.type) {
|
switch (forum.type) {
|
||||||
|
@ -218,23 +225,19 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
||||||
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewdiscussion');
|
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewdiscussion');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sync) {
|
if (sync) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to synchronize the forum.
|
// Try to synchronize the forum.
|
||||||
const updated = await this.syncActivity(showErrors);
|
const updated = await this.syncActivity(showErrors);
|
||||||
|
|
||||||
if (!updated) {
|
if (updated) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync successful, send event.
|
// Sync successful, send event.
|
||||||
CoreEvents.trigger(AddonModForumSyncProvider.MANUAL_SYNCED, {
|
CoreEvents.trigger(AddonModForumSyncProvider.MANUAL_SYNCED, {
|
||||||
forumId: forum.id,
|
forumId: forum.id,
|
||||||
userId: CoreSites.instance.getCurrentSiteUserId(),
|
userId: CoreSites.instance.getCurrentSiteUserId(),
|
||||||
source: 'index',
|
source: 'index',
|
||||||
}, CoreSites.instance.getCurrentSiteId());
|
}, CoreSites.instance.getCurrentSiteId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
@ -507,18 +510,10 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
||||||
* @param timeCreated Creation time of the offline discussion.
|
* @param timeCreated Creation time of the offline discussion.
|
||||||
*/
|
*/
|
||||||
openNewDiscussion(timeCreated: number = 0): void {
|
openNewDiscussion(timeCreated: number = 0): void {
|
||||||
alert(`Open new discussion at ${timeCreated} not implemented!`);
|
this.discussions.select({
|
||||||
|
newDiscussion: true,
|
||||||
// @todo
|
timeCreated,
|
||||||
// const params = {
|
});
|
||||||
// courseId: this.courseId,
|
|
||||||
// cmId: this.module.id,
|
|
||||||
// forumId: this.forum.id,
|
|
||||||
// timeCreated: timeCreated,
|
|
||||||
// };
|
|
||||||
// this.splitviewCtrl.push('AddonModForumNewDiscussionPage', params);
|
|
||||||
|
|
||||||
this.selectedDiscussion = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -598,7 +593,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddonModForumDiscussionsManager extends CorePageItemsListManager<AddonModForumDiscussion> {
|
class AddonModForumDiscussionsManager extends CorePageItemsListManager<AddonModForumDiscussion | NewDiscussionForm> {
|
||||||
|
|
||||||
private discussionsPathPrefix: string;
|
private discussionsPathPrefix: string;
|
||||||
private component: AddonModForumIndexComponent;
|
private component: AddonModForumIndexComponent;
|
||||||
|
@ -610,18 +605,21 @@ class AddonModForumDiscussionsManager extends CorePageItemsListManager<AddonModF
|
||||||
this.discussionsPathPrefix = discussionsPathPrefix;
|
this.discussionsPathPrefix = discussionsPathPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemQueryParams(discussion: AddonModForumDiscussion): Params {
|
getItemQueryParams(discussion: AddonModForumDiscussion | NewDiscussionForm): Params {
|
||||||
return {
|
return {
|
||||||
discussion,
|
|
||||||
courseId: this.component.courseId,
|
courseId: this.component.courseId,
|
||||||
cmId: this.component.module!.id,
|
cmId: this.component.module!.id,
|
||||||
forumId: this.component.forum!.id,
|
forumId: this.component.forum!.id,
|
||||||
trackPosts: this.component.trackPosts,
|
...(
|
||||||
|
this.isNewDiscussionForm(discussion)
|
||||||
|
? { timeCreated: discussion.timeCreated }
|
||||||
|
: { discussion, trackPosts: this.component.trackPosts }
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getItemPath(discussion: AddonModForumDiscussion): string {
|
protected getItemPath(discussion: AddonModForumDiscussion | NewDiscussionForm): string {
|
||||||
const discussionId = discussion.id;
|
const discussionId = this.isNewDiscussionForm(discussion) ? 'new' : discussion.id;
|
||||||
|
|
||||||
return this.discussionsPathPrefix + discussionId;
|
return this.discussionsPathPrefix + discussionId;
|
||||||
}
|
}
|
||||||
|
@ -632,4 +630,8 @@ class AddonModForumDiscussionsManager extends CorePageItemsListManager<AddonModF
|
||||||
return discussionId ? this.discussionsPathPrefix + discussionId : null;
|
return discussionId ? this.discussionsPathPrefix + discussionId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isNewDiscussionForm(discussion: AddonModForumDiscussion | NewDiscussionForm): discussion is NewDiscussionForm {
|
||||||
|
return 'newDiscussion' in discussion;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,26 @@ import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
|
import { CoreEditorComponentsModule } from '@features/editor/components/components.module';
|
||||||
|
|
||||||
import { AddonModForumComponentsModule } from './components/components.module';
|
import { AddonModForumComponentsModule } from './components/components.module';
|
||||||
import { AddonModForumIndexPage } from './pages/index';
|
import { AddonModForumIndexPage } from './pages/index';
|
||||||
import { conditionalRoutes } from '@/app/app-routing.module';
|
import { conditionalRoutes } from '@/app/app-routing.module';
|
||||||
import { CoreScreen } from '@services/screen';
|
import { CoreScreen } from '@services/screen';
|
||||||
|
import { AddonModForumNewDiscussionPage } from './pages/new-discussion/new-discussion';
|
||||||
|
|
||||||
const mobileRoutes: Routes = [
|
const mobileRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: ':courseId/:cmId',
|
path: ':courseId/:cmId',
|
||||||
component: AddonModForumIndexPage,
|
component: AddonModForumIndexPage,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: ':courseId/:cmId/new',
|
||||||
|
component: AddonModForumNewDiscussionPage,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: ':courseId/:cmId/:discussionId',
|
path: ':courseId/:cmId/:discussionId',
|
||||||
loadChildren: () => import('./pages/discussion/discussion.module').then(m => m.AddonForumDiscussionPageModule),
|
loadChildren: () => import('./pages/discussion/discussion.module').then(m => m.AddonForumDiscussionPageModule),
|
||||||
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -39,6 +44,10 @@ const tabletRoutes: Routes = [
|
||||||
path: ':courseId/:cmId',
|
path: ':courseId/:cmId',
|
||||||
component: AddonModForumIndexPage,
|
component: AddonModForumIndexPage,
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: 'new',
|
||||||
|
component: AddonModForumNewDiscussionPage,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: ':discussionId',
|
path: ':discussionId',
|
||||||
loadChildren: () => import('./pages/discussion/discussion.module').then(m => m.AddonForumDiscussionPageModule),
|
loadChildren: () => import('./pages/discussion/discussion.module').then(m => m.AddonForumDiscussionPageModule),
|
||||||
|
@ -58,9 +67,11 @@ const routes: Routes = [
|
||||||
RouterModule.forChild(routes),
|
RouterModule.forChild(routes),
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
AddonModForumComponentsModule,
|
AddonModForumComponentsModule,
|
||||||
|
CoreEditorComponentsModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AddonModForumIndexPage,
|
AddonModForumIndexPage,
|
||||||
|
AddonModForumNewDiscussionPage,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AddonModForumLazyModule {}
|
export class AddonModForumLazyModule {}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
<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_forum.addanewdiscussion' | translate }}</ion-title>
|
||||||
|
<ion-buttons slot="end">
|
||||||
|
<!-- The context menu will be added in here. -->
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-refresher slot="fixed" [disabled]="!groupsLoaded" (ionRefresh)="refreshGroups($event.target)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
|
||||||
|
<core-loading [hideUntil]="groupsLoaded">
|
||||||
|
<form ion-list *ngIf="showForm" #newDiscFormEl>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label position="stacked">{{ 'addon.mod_forum.subject' | translate }}</ion-label>
|
||||||
|
<ion-input type="text" [placeholder]="'addon.mod_forum.subject' | translate" [(ngModel)]="newDiscussion.subject" name="subject"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label position="stacked">{{ 'addon.mod_forum.message' | translate }}</ion-label>
|
||||||
|
<core-rich-text-editor item-content name="addon_mod_forum_new_discussion" contextLevel="module" elementId="message"
|
||||||
|
[control]="messageControl" [placeholder]="'addon.mod_forum.message' | translate" [component]="component"
|
||||||
|
[componentId]="forum.cmid" [autoSave]="true" [contextInstanceId]="forum.cmid"
|
||||||
|
(contentChanged)="onMessageChange($event)">
|
||||||
|
</core-rich-text-editor>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()">
|
||||||
|
<ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-icon *ngIf="advanced" name="fa-caret-down" slot="start">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-label>{{ 'addon.mod_forum.advanced' | translate }}</ion-label>
|
||||||
|
</ion-item-divider>
|
||||||
|
<ng-container *ngIf="advanced">
|
||||||
|
<ion-item *ngIf="showGroups && groupIds.length > 1 && accessInfo.cancanposttomygroups">
|
||||||
|
<ion-label>{{ 'addon.mod_forum.posttomygroups' | translate }}</ion-label>
|
||||||
|
<ion-toggle [(ngModel)]="newDiscussion.postToAllGroups" name="postallgroups"></ion-toggle>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item *ngIf="showGroups">
|
||||||
|
<ion-label id="addon-mod-forum-groupslabel">{{ 'addon.mod_forum.group' | translate }}</ion-label>
|
||||||
|
<ion-select [(ngModel)]="newDiscussion.groupId" [disabled]="newDiscussion.postToAllGroups"
|
||||||
|
aria-labelledby="addon-mod-forum-groupslabel" interface="action-sheet" name="groupid">
|
||||||
|
<ion-select-option *ngFor="let group of groups" [value]="group.id">{{ group.name }}</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'addon.mod_forum.discussionsubscription' | translate }}</ion-label>
|
||||||
|
<ion-toggle [(ngModel)]="newDiscussion.subscribe" name="subscribe"></ion-toggle>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item *ngIf="canPin">
|
||||||
|
<ion-label>{{ 'addon.mod_forum.discussionpinned' | translate }}</ion-label>
|
||||||
|
<ion-toggle [(ngModel)]="newDiscussion.pin" name="pin"></ion-toggle>
|
||||||
|
</ion-item>
|
||||||
|
<core-attachments *ngIf="canCreateAttachments && forum && forum.maxattachments > 0"
|
||||||
|
[files]="newDiscussion.files" [maxSize]="forum.maxbytes" [maxSubmissions]="forum.maxattachments"
|
||||||
|
[component]="component" [componentId]="forum.cmid" [allowOffline]="true">
|
||||||
|
</core-attachments>
|
||||||
|
</ng-container>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>
|
||||||
|
<ion-row>
|
||||||
|
<ion-col>
|
||||||
|
<ion-button expand="block" (click)="add()" [disabled]="newDiscussion.subject == '' || newDiscussion.message == null">
|
||||||
|
{{ 'addon.mod_forum.posttoforum' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col *ngIf="hasOffline">
|
||||||
|
<ion-button expand="block" color="light" (click)="discard()">{{ 'core.discard' | translate }}</ion-button>
|
||||||
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</form>
|
||||||
|
</core-loading>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,594 @@
|
||||||
|
// (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, OnDestroy, ViewChild, ElementRef, OnInit } from '@angular/core';
|
||||||
|
import { FileEntry } from '@ionic-native/file/ngx';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { CoreEvents, CoreEventObserver } from '@singletons/events';
|
||||||
|
import { CoreGroup, CoreGroups, CoreGroupsProvider } from '@services/groups';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import {
|
||||||
|
AddonModForum,
|
||||||
|
AddonModForumAccessInformation,
|
||||||
|
AddonModForumCanAddDiscussion,
|
||||||
|
AddonModForumData,
|
||||||
|
AddonModForumProvider,
|
||||||
|
} from '@addons/mod/forum/services/forum.service';
|
||||||
|
import { CoreEditorRichTextEditorComponent } from '@features/editor/components/rich-text-editor/rich-text-editor';
|
||||||
|
import { AddonModForumSync, AddonModForumSyncProvider } from '@addons/mod/forum/services/sync.service';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { Translate } from '@singletons';
|
||||||
|
import { CoreSync } from '@services/sync';
|
||||||
|
import { AddonModForumDiscussionOptions, AddonModForumOffline } from '@addons/mod/forum/services/offline.service';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { AddonModForumHelper } from '@addons/mod/forum/services/helper.service';
|
||||||
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
import { CoreFileUploader } from '@features/fileuploader/services/fileuploader';
|
||||||
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
|
|
||||||
|
type NewDiscussionData = {
|
||||||
|
subject: string;
|
||||||
|
message: string | null; // Null means empty or just white space.
|
||||||
|
postToAllGroups: boolean;
|
||||||
|
groupId: number;
|
||||||
|
subscribe: boolean;
|
||||||
|
pin: boolean;
|
||||||
|
files: FileEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays the new discussion form.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-addon-mod-forum-new-discussion',
|
||||||
|
templateUrl: 'new-discussion.html',
|
||||||
|
})
|
||||||
|
export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild('newDiscFormEl') formElement!: ElementRef;
|
||||||
|
@ViewChild(CoreEditorRichTextEditorComponent) messageEditor!: CoreEditorRichTextEditorComponent;
|
||||||
|
|
||||||
|
component = AddonModForumProvider.COMPONENT;
|
||||||
|
messageControl = new FormControl();
|
||||||
|
groupsLoaded = false;
|
||||||
|
showGroups = false;
|
||||||
|
hasOffline = false;
|
||||||
|
canCreateAttachments = true; // Assume we can by default.
|
||||||
|
canPin = false;
|
||||||
|
forum!: AddonModForumData;
|
||||||
|
showForm = false;
|
||||||
|
groups: CoreGroup[] = [];
|
||||||
|
groupIds: number[] = [];
|
||||||
|
newDiscussion: NewDiscussionData = {
|
||||||
|
subject: '',
|
||||||
|
message: null,
|
||||||
|
postToAllGroups: false,
|
||||||
|
groupId: 0,
|
||||||
|
subscribe: true,
|
||||||
|
pin: false,
|
||||||
|
files: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
advanced = false; // Display all form fields.
|
||||||
|
accessInfo: AddonModForumAccessInformation = {};
|
||||||
|
|
||||||
|
protected courseId!: number;
|
||||||
|
protected cmId!: number;
|
||||||
|
protected forumId!: number;
|
||||||
|
protected timeCreated!: number;
|
||||||
|
protected syncId!: string;
|
||||||
|
protected syncObserver?: CoreEventObserver;
|
||||||
|
protected isDestroyed = false;
|
||||||
|
protected originalData?: Partial<NewDiscussionData>;
|
||||||
|
protected forceLeave = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component being initialized.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
|
||||||
|
this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
|
||||||
|
this.forumId = CoreNavigator.instance.getRouteNumberParam('forumId')!;
|
||||||
|
this.timeCreated = CoreNavigator.instance.getRouteNumberParam('timeCreated')!;
|
||||||
|
|
||||||
|
this.fetchDiscussionData().finally(() => {
|
||||||
|
this.groupsLoaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User entered the page that contains the component.
|
||||||
|
*/
|
||||||
|
ionViewDidEnter(): void {
|
||||||
|
if (this.syncObserver) {
|
||||||
|
// Already setup.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh data if this discussion is synchronized automatically.
|
||||||
|
this.syncObserver = CoreEvents.on(AddonModForumSyncProvider.AUTO_SYNCED, (data: any) => {
|
||||||
|
if (data.forumId == this.forumId && data.userId == CoreSites.instance.getCurrentSiteUserId()) {
|
||||||
|
CoreDomUtils.instance.showAlertTranslated('core.notice', 'core.contenteditingsynced');
|
||||||
|
this.returnToDiscussions();
|
||||||
|
}
|
||||||
|
}, CoreSites.instance.getCurrentSiteId());
|
||||||
|
|
||||||
|
// Trigger view event, to highlight the current opened discussion in the split view.
|
||||||
|
CoreEvents.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, {
|
||||||
|
forumId: this.forumId,
|
||||||
|
discussion: -this.timeCreated,
|
||||||
|
}, CoreSites.instance.getCurrentSiteId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch if forum uses groups and the groups it uses.
|
||||||
|
*
|
||||||
|
* @param refresh Whether we're refreshing data.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async fetchDiscussionData(refresh?: boolean): Promise<void> {
|
||||||
|
try {
|
||||||
|
const mode = await CoreGroups.instance.getActivityGroupMode(this.cmId);
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
if (mode === CoreGroupsProvider.SEPARATEGROUPS || mode === CoreGroupsProvider.VISIBLEGROUPS) {
|
||||||
|
promises.push(
|
||||||
|
CoreGroups.instance
|
||||||
|
.getActivityAllowedGroups(this.cmId)
|
||||||
|
.then((result) => {
|
||||||
|
let promise;
|
||||||
|
if (mode === CoreGroupsProvider.VISIBLEGROUPS) {
|
||||||
|
// We need to check which of the returned groups the user can post to.
|
||||||
|
promise = this.validateVisibleGroups(result.groups);
|
||||||
|
} else {
|
||||||
|
// WS already filters groups, no need to do it ourselves. Add "All participants" if needed.
|
||||||
|
promise = this.addAllParticipantsOption(result.groups, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line promise/no-nesting
|
||||||
|
return promise.then((forumGroups) => {
|
||||||
|
if (forumGroups.length > 0) {
|
||||||
|
this.groups = forumGroups;
|
||||||
|
this.groupIds = forumGroups.map((group) => group.id).filter((id) => id > 0);
|
||||||
|
// Do not override group id.
|
||||||
|
this.newDiscussion.groupId = this.newDiscussion.groupId || forumGroups[0].id;
|
||||||
|
this.showGroups = true;
|
||||||
|
if (this.groupIds.length <= 1) {
|
||||||
|
this.newDiscussion.postToAllGroups = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const message = mode === CoreGroupsProvider.SEPARATEGROUPS ?
|
||||||
|
'addon.mod_forum.cannotadddiscussionall' : 'addon.mod_forum.cannotadddiscussion';
|
||||||
|
|
||||||
|
throw new Error(Translate.instant(message));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.showGroups = false;
|
||||||
|
this.newDiscussion.postToAllGroups = false;
|
||||||
|
|
||||||
|
// Use the canAddDiscussion WS to check if the user can add attachments and pin discussions.
|
||||||
|
promises.push(
|
||||||
|
CoreUtils.instance.ignoreErrors(
|
||||||
|
AddonModForum.instance
|
||||||
|
.canAddDiscussionToAll(this.forumId, { cmId: this.cmId })
|
||||||
|
.then((response) => {
|
||||||
|
this.canPin = !!response.canpindiscussions;
|
||||||
|
this.canCreateAttachments = !!response.cancreateattachment;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get forum.
|
||||||
|
promises.push(AddonModForum.instance.getForum(this.courseId, this.cmId).then((forum) => this.forum = forum));
|
||||||
|
|
||||||
|
// Get access information.
|
||||||
|
promises.push(
|
||||||
|
AddonModForum.instance
|
||||||
|
.getAccessInformation(this.forumId, { cmId: this.cmId })
|
||||||
|
.then((accessInfo) => this.accessInfo = accessInfo),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
// If editing a discussion, get offline data.
|
||||||
|
if (this.timeCreated && !refresh) {
|
||||||
|
this.syncId = AddonModForumSync.instance.getForumSyncId(this.forumId);
|
||||||
|
|
||||||
|
await AddonModForumSync.instance.waitForSync(this.syncId).then(() => {
|
||||||
|
// Do not block if the scope is already destroyed.
|
||||||
|
if (!this.isDestroyed) {
|
||||||
|
CoreSync.instance.blockOperation(AddonModForumProvider.COMPONENT, this.syncId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line promise/no-nesting
|
||||||
|
return AddonModForumOffline.instance
|
||||||
|
.getNewDiscussion(this.forumId, this.timeCreated)
|
||||||
|
.then(async (discussion) => {
|
||||||
|
this.hasOffline = true;
|
||||||
|
discussion.options = discussion.options || {};
|
||||||
|
if (discussion.groupid == AddonModForumProvider.ALL_GROUPS) {
|
||||||
|
this.newDiscussion.groupId = this.groups[0].id;
|
||||||
|
this.newDiscussion.postToAllGroups = true;
|
||||||
|
} else {
|
||||||
|
this.newDiscussion.groupId = discussion.groupid;
|
||||||
|
this.newDiscussion.postToAllGroups = false;
|
||||||
|
}
|
||||||
|
this.newDiscussion.subject = discussion.subject;
|
||||||
|
this.newDiscussion.message = discussion.message;
|
||||||
|
this.newDiscussion.subscribe = !!discussion.options.discussionsubscribe;
|
||||||
|
this.newDiscussion.pin = !!discussion.options.discussionpinned;
|
||||||
|
this.messageControl.setValue(discussion.message);
|
||||||
|
|
||||||
|
// Treat offline attachments if any.
|
||||||
|
if (typeof discussion.options.attachmentsid === 'object' && discussion.options.attachmentsid.offline) {
|
||||||
|
const files = await AddonModForumHelper.instance.getNewDiscussionStoredFiles(
|
||||||
|
this.forumId,
|
||||||
|
this.timeCreated,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.newDiscussion.files = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show advanced fields by default if any of them has not the default value.
|
||||||
|
if (
|
||||||
|
!this.newDiscussion.subscribe ||
|
||||||
|
this.newDiscussion.pin ||
|
||||||
|
this.newDiscussion.files.length ||
|
||||||
|
this.groups.length > 0 && this.newDiscussion.groupId != this.groups[0].id ||
|
||||||
|
this.newDiscussion.postToAllGroups
|
||||||
|
) {
|
||||||
|
this.advanced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.originalData) {
|
||||||
|
// Initialize original data.
|
||||||
|
this.originalData = {
|
||||||
|
subject: this.newDiscussion.subject,
|
||||||
|
message: this.newDiscussion.message,
|
||||||
|
files: this.newDiscussion.files.slice(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showForm = true;
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModalDefault(error, 'addon.mod_forum.errorgetgroups', true);
|
||||||
|
|
||||||
|
this.showForm = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate which of the groups returned by getActivityAllowedGroups in visible groups should be shown to post to.
|
||||||
|
*
|
||||||
|
* @param forumGroups Forum groups.
|
||||||
|
* @return Promise resolved with the list of groups.
|
||||||
|
*/
|
||||||
|
protected async validateVisibleGroups(forumGroups: CoreGroup[]): Promise<CoreGroup[]> {
|
||||||
|
let response: AddonModForumCanAddDiscussion;
|
||||||
|
|
||||||
|
// We first check if the user can post to all the groups.
|
||||||
|
try {
|
||||||
|
response = await AddonModForum.instance.canAddDiscussionToAll(this.forumId, { cmId: this.cmId });
|
||||||
|
} catch (error) {
|
||||||
|
// The call failed, let's assume he can't.
|
||||||
|
response = {
|
||||||
|
status: false,
|
||||||
|
canpindiscussions: false,
|
||||||
|
cancreateattachment: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canPin = !!response.canpindiscussions;
|
||||||
|
this.canCreateAttachments = !!response.cancreateattachment;
|
||||||
|
|
||||||
|
// The user can post to all groups, add the "All participants" option and return them all.
|
||||||
|
if (response.status) {
|
||||||
|
return this.addAllParticipantsOption(forumGroups, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The user can't post to all groups, let's check which groups he can post to.
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
const filtered: CoreGroup[] = [];
|
||||||
|
|
||||||
|
forumGroups.forEach((group) => {
|
||||||
|
promises.push(
|
||||||
|
AddonModForum.instance
|
||||||
|
.canAddDiscussion(this.forumId, group.id, { cmId: this.cmId })
|
||||||
|
|
||||||
|
// The call failed, let's return true so the group is shown.
|
||||||
|
// If the user can't post to it an error will be shown when he tries to add the discussion.
|
||||||
|
.catch(() =>({ status: true }))
|
||||||
|
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status) {
|
||||||
|
filtered.push(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter forum groups, returning only those that are inside user groups.
|
||||||
|
*
|
||||||
|
* @param forumGroups Forum groups.
|
||||||
|
* @param userGroups User groups.
|
||||||
|
* @return Filtered groups.
|
||||||
|
*/
|
||||||
|
protected filterGroups(forumGroups: CoreGroup[], userGroups: CoreGroup[]): CoreGroup[] {
|
||||||
|
const userGroupsIds = userGroups.map(group => group.id);
|
||||||
|
|
||||||
|
return forumGroups.filter(forumGroup => userGroupsIds.indexOf(forumGroup.id) > -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the "All participants" option to a list of groups if the user can add a discussion to all participants.
|
||||||
|
*
|
||||||
|
* @param groups Groups.
|
||||||
|
* @param check True to check if the user can add a discussion to all participants.
|
||||||
|
* @return Promise resolved with the list of groups.
|
||||||
|
*/
|
||||||
|
protected addAllParticipantsOption(groups: CoreGroup[], check: boolean): Promise<CoreGroup[]> {
|
||||||
|
if (!AddonModForum.instance.isAllParticipantsFixed()) {
|
||||||
|
// All participants has a bug, don't add it.
|
||||||
|
return Promise.resolve(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise;
|
||||||
|
|
||||||
|
if (check) {
|
||||||
|
// We need to check if the user can add a discussion to all participants.
|
||||||
|
promise = AddonModForum.instance.canAddDiscussionToAll(this.forumId, { cmId: this.cmId }).then((response) => {
|
||||||
|
this.canPin = !!response.canpindiscussions;
|
||||||
|
this.canCreateAttachments = !!response.cancreateattachment;
|
||||||
|
|
||||||
|
return response.status;
|
||||||
|
}).catch(() =>
|
||||||
|
// The call failed, let's assume he can't.
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
// No need to check, assume the user can.
|
||||||
|
promise = Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then((canAdd) => {
|
||||||
|
if (canAdd) {
|
||||||
|
groups.unshift({
|
||||||
|
courseid: this.courseId,
|
||||||
|
id: AddonModForumProvider.ALL_PARTICIPANTS,
|
||||||
|
name: Translate.instant('core.allparticipants'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull to refresh.
|
||||||
|
*
|
||||||
|
* @param refresher Refresher.
|
||||||
|
*/
|
||||||
|
refreshGroups(refresher?: IonRefresher): void {
|
||||||
|
const promises = [
|
||||||
|
CoreGroups.instance.invalidateActivityGroupMode(this.cmId),
|
||||||
|
CoreGroups.instance.invalidateActivityAllowedGroups(this.cmId),
|
||||||
|
AddonModForum.instance.invalidateCanAddDiscussion(this.forumId),
|
||||||
|
];
|
||||||
|
|
||||||
|
Promise.all(promises).finally(() => {
|
||||||
|
this.fetchDiscussionData(true).finally(() => {
|
||||||
|
refresher?.complete();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to update or return to discussions depending on device.
|
||||||
|
*
|
||||||
|
* @param discussionIds Ids of the new discussions.
|
||||||
|
* @param discTimecreated The time created of the discussion (if offline).
|
||||||
|
*/
|
||||||
|
protected returnToDiscussions(discussionIds?: number[] | null, discTimecreated?: number): void {
|
||||||
|
const data: any = {
|
||||||
|
forumId: this.forumId,
|
||||||
|
cmId: this.cmId,
|
||||||
|
discussionIds: discussionIds,
|
||||||
|
discTimecreated: discTimecreated,
|
||||||
|
};
|
||||||
|
CoreEvents.trigger(AddonModForumProvider.NEW_DISCUSSION_EVENT, data, CoreSites.instance.getCurrentSiteId());
|
||||||
|
|
||||||
|
// Delete the local files from the tmp folder.
|
||||||
|
CoreFileUploader.instance.clearTmpFiles(this.newDiscussion.files);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message changed.
|
||||||
|
*
|
||||||
|
* @param text The new text.
|
||||||
|
*/
|
||||||
|
onMessageChange(text: string): void {
|
||||||
|
this.newDiscussion.message = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new discussion.
|
||||||
|
*/
|
||||||
|
async add(): Promise<void> {
|
||||||
|
const forumName = this.forum.name;
|
||||||
|
const subject = this.newDiscussion.subject;
|
||||||
|
let message = this.newDiscussion.message || '';
|
||||||
|
const pin = this.newDiscussion.pin;
|
||||||
|
const attachments = this.newDiscussion.files;
|
||||||
|
const discTimecreated = this.timeCreated || Date.now();
|
||||||
|
const options: AddonModForumDiscussionOptions = {
|
||||||
|
discussionsubscribe: !!this.newDiscussion.subscribe,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!subject) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('addon.mod_forum.erroremptysubject', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!message) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('addon.mod_forum.erroremptymessage', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = await CoreDomUtils.instance.showModalLoading('core.sending', true);
|
||||||
|
|
||||||
|
// Add some HTML to the message if needed.
|
||||||
|
message = CoreTextUtils.instance.formatHtmlLines(message);
|
||||||
|
|
||||||
|
if (pin) {
|
||||||
|
options.discussionpinned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupIds = this.newDiscussion.postToAllGroups ? this.groupIds : [this.newDiscussion.groupId];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const discussionIds = await AddonModForumHelper.instance.addNewDiscussion(
|
||||||
|
this.forumId,
|
||||||
|
forumName,
|
||||||
|
this.courseId,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
attachments,
|
||||||
|
options,
|
||||||
|
groupIds,
|
||||||
|
discTimecreated,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (discussionIds) {
|
||||||
|
// Data sent to server, delete stored files (if any).
|
||||||
|
AddonModForumHelper.instance.deleteNewDiscussionStoredFiles(this.forumId, discTimecreated);
|
||||||
|
|
||||||
|
CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'forum' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discussionIds && discussionIds.length < groupIds.length) {
|
||||||
|
// Some discussions could not be created.
|
||||||
|
CoreDomUtils.instance.showErrorModalDefault(null, 'addon.mod_forum.errorposttoallgroups', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreDomUtils.instance.triggerFormSubmittedEvent(
|
||||||
|
this.formElement,
|
||||||
|
!!discussionIds,
|
||||||
|
CoreSites.instance.getCurrentSiteId(),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.returnToDiscussions(discussionIds, discTimecreated);
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModalDefault(error, 'addon.mod_forum.cannotcreatediscussion', true);
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discard an offline saved discussion.
|
||||||
|
*/
|
||||||
|
async discard(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await CoreDomUtils.instance.showConfirm(Translate.instant('core.areyousure'));
|
||||||
|
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
promises.push(AddonModForumOffline.instance.deleteNewDiscussion(this.forumId, this.timeCreated));
|
||||||
|
promises.push(
|
||||||
|
CoreUtils.instance.ignoreErrors(
|
||||||
|
AddonModForumHelper.instance.deleteNewDiscussionStoredFiles(this.forumId, this.timeCreated),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
CoreDomUtils.instance.triggerFormCancelledEvent(this.formElement, CoreSites.instance.getCurrentSiteId());
|
||||||
|
|
||||||
|
this.returnToDiscussions();
|
||||||
|
} catch (error) {
|
||||||
|
// Cancelled.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show or hide advanced form fields.
|
||||||
|
*/
|
||||||
|
toggleAdvanced(): void {
|
||||||
|
this.advanced = !this.advanced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we can leave the page or not.
|
||||||
|
*
|
||||||
|
* @return Resolved if we can leave it, rejected if not.
|
||||||
|
*/
|
||||||
|
async ionViewCanLeave(): Promise<void> {
|
||||||
|
if (this.forceLeave) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AddonModForumHelper.instance.hasPostDataChanged(this.newDiscussion, this.originalData)) {
|
||||||
|
// Show confirmation if some data has been modified.
|
||||||
|
await CoreDomUtils.instance.showConfirm(Translate.instant('core.confirmcanceledit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the local files from the tmp folder.
|
||||||
|
CoreFileUploader.instance.clearTmpFiles(this.newDiscussion.files);
|
||||||
|
|
||||||
|
if (this.formElement) {
|
||||||
|
CoreDomUtils.instance.triggerFormCancelledEvent(this.formElement, CoreSites.instance.getCurrentSiteId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs when the page is about to leave and no longer be the active page.
|
||||||
|
*/
|
||||||
|
ionViewWillLeave(): void {
|
||||||
|
this.syncObserver && this.syncObserver.off();
|
||||||
|
delete this.syncObserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page destroyed.
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.syncId) {
|
||||||
|
CoreSync.instance.unblockOperation(AddonModForumProvider.COMPONENT, this.syncId);
|
||||||
|
}
|
||||||
|
this.isDestroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { FileEntry } from '@ionic-native/file/ngx';
|
||||||
import { CoreFileEntry, CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader';
|
import { CoreFileEntry, CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader';
|
||||||
import { CoreUser } from '@features/user/services/user';
|
import { CoreUser } from '@features/user/services/user';
|
||||||
import { CoreApp } from '@services/app';
|
import { CoreApp } from '@services/app';
|
||||||
|
|
|
@ -403,7 +403,9 @@ export class AddonModForumOfflineProvider {
|
||||||
export class AddonModForumOffline extends makeSingleton(AddonModForumOfflineProvider) {}
|
export class AddonModForumOffline extends makeSingleton(AddonModForumOfflineProvider) {}
|
||||||
|
|
||||||
export type AddonModForumDiscussionOptions = {
|
export type AddonModForumDiscussionOptions = {
|
||||||
attachmentsid: number | CoreFileUploaderStoreFilesResult;
|
attachmentsid?: number | CoreFileUploaderStoreFilesResult;
|
||||||
|
discussionsubscribe?: boolean;
|
||||||
|
discussionpinned?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AddonModForumReplyOptions = {
|
export type AddonModForumReplyOptions = {
|
||||||
|
|
|
@ -743,7 +743,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @param error Error to check.
|
* @param error Error to check.
|
||||||
* @return Whether it's a canceled error.
|
* @return Whether it's a canceled error.
|
||||||
*/
|
*/
|
||||||
isCanceledError(error: CoreError | CoreTextErrorObject | string): boolean {
|
isCanceledError(error: CoreError | CoreTextErrorObject | string | null): boolean {
|
||||||
return error instanceof CoreCanceledError;
|
return error instanceof CoreCanceledError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1393,7 +1393,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @return Promise resolved with the alert modal.
|
* @return Promise resolved with the alert modal.
|
||||||
*/
|
*/
|
||||||
async showErrorModalDefault(
|
async showErrorModalDefault(
|
||||||
error: CoreError | CoreTextErrorObject | string,
|
error: CoreError | CoreTextErrorObject | string | null,
|
||||||
defaultError: string,
|
defaultError: string,
|
||||||
needsTranslate?: boolean,
|
needsTranslate?: boolean,
|
||||||
autocloseTime?: number,
|
autocloseTime?: number,
|
||||||
|
@ -1409,7 +1409,7 @@ export class CoreDomUtilsProvider {
|
||||||
errorMessage = CoreTextUtils.instance.getErrorMessageFromError(error);
|
errorMessage = CoreTextUtils.instance.getErrorMessageFromError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.showErrorModal(typeof errorMessage == 'string' ? error : defaultError, needsTranslate, autocloseTime);
|
return this.showErrorModal(typeof errorMessage == 'string' ? error! : defaultError, needsTranslate, autocloseTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue