commit
11e3cca5c1
|
@ -68,6 +68,7 @@ import { CoreSettingsModule } from '@core/settings/settings.module';
|
|||
import { CoreSitePluginsModule } from '@core/siteplugins/siteplugins.module';
|
||||
import { CoreCompileModule } from '@core/compile/compile.module';
|
||||
import { CoreQuestionModule } from '@core/question/question.module';
|
||||
import { CoreCommentsModule } from '@core/comments/comments.module';
|
||||
|
||||
// Addon modules.
|
||||
import { AddonBadgesModule } from '@addon/badges/badges.module';
|
||||
|
@ -162,6 +163,7 @@ export const CORE_PROVIDERS: any[] = [
|
|||
CoreSitePluginsModule,
|
||||
CoreCompileModule,
|
||||
CoreQuestionModule,
|
||||
CoreCommentsModule,
|
||||
AddonBadgesModule,
|
||||
AddonCalendarModule,
|
||||
AddonCompetencyModule,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { NgModule } from '@angular/core';
|
||||
import { CoreCommentsProvider } from './providers/comments';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreCommentsProvider
|
||||
]
|
||||
})
|
||||
export class CoreCommentsModule {}
|
|
@ -0,0 +1,8 @@
|
|||
<core-loading [hideUntil]="commentsLoaded">
|
||||
<div (click)="openComments()" *ngIf="commentsCount >= 0">
|
||||
{{ 'core.commentscount' | translate : {'$a': commentsCount} }}
|
||||
</div>
|
||||
<div *ngIf="commentsCount < 0">
|
||||
{{ 'core.commentsnotworking' | translate }}
|
||||
</div>
|
||||
</core-loading>
|
|
@ -0,0 +1,71 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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, Input } from '@angular/core';
|
||||
import { NavParams, NavController } from 'ionic-angular';
|
||||
import { CoreCommentsProvider } from '../../providers/comments';
|
||||
|
||||
/**
|
||||
* Component that displays the count of comments.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-comments',
|
||||
templateUrl: 'comments.html',
|
||||
})
|
||||
export class CoreCommentsCommentsComponent {
|
||||
@Input() contextLevel: string;
|
||||
@Input() instanceId: number;
|
||||
@Input() component: string;
|
||||
@Input() itemId: number;
|
||||
@Input() area = '';
|
||||
@Input() page = 0;
|
||||
@Input() title?: string;
|
||||
|
||||
commentsLoaded = false;
|
||||
commentsCount: number;
|
||||
|
||||
constructor(navParams: NavParams, private navCtrl: NavController, private commentsProvider: CoreCommentsProvider) {}
|
||||
|
||||
/**
|
||||
* View loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.commentsProvider.getComments(this.contextLevel, this.instanceId, this.component, this.itemId, this.area, this.page)
|
||||
.then((comments) => {
|
||||
this.commentsCount = comments && comments.length ? comments.length : 0;
|
||||
}).catch(() => {
|
||||
this.commentsCount = -1;
|
||||
}).finally(() => {
|
||||
this.commentsLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the comments page.
|
||||
*/
|
||||
openComments(): void {
|
||||
if (this.commentsCount > 0) {
|
||||
// Open a new state with the interpolated contents.
|
||||
this.navCtrl.push('CoreCommentsViewerPage', {
|
||||
contextLevel: this.contextLevel,
|
||||
instanceId: this.instanceId,
|
||||
component: this.component,
|
||||
itemId: this.itemId,
|
||||
area: this.area,
|
||||
page: this.page,
|
||||
title: this.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreCommentsCommentsComponent } from './comments/comments';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCommentsCommentsComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
TranslateModule.forChild(),
|
||||
CoreComponentsModule
|
||||
],
|
||||
providers: [
|
||||
],
|
||||
exports: [
|
||||
CoreCommentsCommentsComponent
|
||||
],
|
||||
entryComponents: [
|
||||
CoreCommentsCommentsComponent
|
||||
]
|
||||
})
|
||||
export class CoreCommentsComponentsModule {}
|
|
@ -0,0 +1,26 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title><core-format-text [text]="title"></core-format-text></ion-title>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-refresher [enabled]="commentsLoaded" (ionRefresh)="refreshComments($event)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="commentsLoaded">
|
||||
<core-empty-box *ngIf="!comments || !comments.length" icon="chatbubbles" [message]="'core.nocomments' | translate"></core-empty-box>
|
||||
|
||||
<ion-card *ngFor="let comment of comments">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start>
|
||||
<img [src]="comment.profileimageurl" onError="this.src='assets/img/user-avatar.png'" core-external-content core-user-link [userId]="comment.userid" [alt]="'core.pictureof' | translate:{$a: comment.fullname}" role="presentation">
|
||||
</ion-avatar>
|
||||
<h2>{{ comment.fullname }}</h2>
|
||||
<p>{{ comment.time }}</p>
|
||||
</ion-item>
|
||||
<ion-item text-wrap>
|
||||
<core-format-text clean="true" [text]="comment.content"></core-format-text>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</core-loading>
|
||||
</ion-content>
|
|
@ -0,0 +1,35 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreCommentsViewerPage } from './viewer';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCommentsComponentsModule } from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCommentsViewerPage
|
||||
],
|
||||
imports: [
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule,
|
||||
CoreCommentsComponentsModule,
|
||||
IonicPageModule.forChild(CoreCommentsViewerPage),
|
||||
TranslateModule.forChild()
|
||||
],
|
||||
})
|
||||
export class CoreCommentsViewerPageModule {}
|
|
@ -0,0 +1,111 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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, ViewChild } from '@angular/core';
|
||||
import { IonicPage, Content, NavParams } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreCommentsProvider } from '../../providers/comments';
|
||||
|
||||
/**
|
||||
* Page that displays comments.
|
||||
*/
|
||||
@IonicPage({ segment: 'core-comments-viewer' })
|
||||
@Component({
|
||||
selector: 'page-core-comments-viewer',
|
||||
templateUrl: 'viewer.html',
|
||||
})
|
||||
export class CoreCommentsViewerPage {
|
||||
@ViewChild(Content) content: Content;
|
||||
|
||||
comments = [];
|
||||
commentsLoaded = false;
|
||||
contextLevel: string;
|
||||
instanceId: number;
|
||||
component: string;
|
||||
itemId: number;
|
||||
area: string;
|
||||
page: number;
|
||||
title: string;
|
||||
|
||||
constructor(navParams: NavParams, sitesProvider: CoreSitesProvider, private userProvider: CoreUserProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private translate: TranslateService,
|
||||
private commentsProvider: CoreCommentsProvider) {
|
||||
|
||||
this.contextLevel = navParams.get('contextLevel');
|
||||
this.instanceId = navParams.get('instanceId');
|
||||
this.component = navParams.get('component');
|
||||
this.itemId = navParams.get('itemId');
|
||||
this.area = navParams.get('area') || '';
|
||||
this.page = navParams.get('page') || 0;
|
||||
this.title = navParams.get('title') || this.translate.instant('core.comments');
|
||||
}
|
||||
|
||||
/**
|
||||
* View loaded.
|
||||
*/
|
||||
ionViewDidLoad(): void {
|
||||
this.fetchComments().finally(() => {
|
||||
this.commentsLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the comments.
|
||||
*
|
||||
* @return {Promise<any>} Resolved when done.
|
||||
*/
|
||||
protected fetchComments(): Promise<any> {
|
||||
// Get comments data.
|
||||
return this.commentsProvider.getComments(this.contextLevel, this.instanceId, this.component, this.itemId,
|
||||
this.area, this.page).then((comments) => {
|
||||
this.comments = comments;
|
||||
this.comments.sort((a, b) => b.timecreated - a.timecreated);
|
||||
this.comments.forEach((comment) => {
|
||||
// Get the user profile image.
|
||||
this.userProvider.getProfile(comment.userid, undefined, true).then((user) => {
|
||||
comment.profileimageurl = user.profileimageurl;
|
||||
});
|
||||
});
|
||||
}).catch((error) => {
|
||||
if (error) {
|
||||
if (this.component == 'assignsubmission_comments') {
|
||||
this.domUtils.showAlertTranslated('core.notice', 'core.commentsnotworking');
|
||||
} else {
|
||||
this.domUtils.showErrorModal(error);
|
||||
}
|
||||
} else {
|
||||
this.domUtils.showErrorModal(this.translate.instant('core.error') + ': get_comments');
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the comments.
|
||||
*
|
||||
* @param {any} refresher Refresher.
|
||||
*/
|
||||
refreshComments(refresher: any): void {
|
||||
this.commentsProvider.invalidateCommentsData(this.contextLevel, this.instanceId, this.component,
|
||||
this.itemId, this.area, this.page).finally(() => {
|
||||
return this.fetchComments().finally(() => {
|
||||
refresher.complete();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
||||
/**
|
||||
* Service that provides some features regarding comments.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreCommentsProvider {
|
||||
|
||||
protected ROOT_CACHE_KEY = 'mmComments:';
|
||||
|
||||
constructor(private sitesProvider: CoreSitesProvider) {}
|
||||
|
||||
/**
|
||||
* Get cache key for get comments data WS calls.
|
||||
*
|
||||
* @param {string} contextLevel Contextlevel system, course, user...
|
||||
* @param {number} instanceId The Instance id of item associated with the context level.
|
||||
* @param {string} component Component name.
|
||||
* @param {number} itemId Associated id.
|
||||
* @param {string} [area=''] String comment area. Default empty.
|
||||
* @param {number} [page=0] Page number (0 based). Default 0.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getCommentsCacheKey(contextLevel: string, instanceId: number, component: string,
|
||||
itemId: number, area: string = '', page: number = 0): string {
|
||||
return this.getCommentsPrefixCacheKey(contextLevel, instanceId) + ':' + component + ':' + itemId + ':' + area + ':' + page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for get comments instance data WS calls.
|
||||
*
|
||||
* @param {string} contextLevel Contextlevel system, course, user...
|
||||
* @param {number} instanceId The Instance id of item associated with the context level.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getCommentsPrefixCacheKey(contextLevel: string, instanceId: number): string {
|
||||
return this.ROOT_CACHE_KEY + 'comments:' + contextLevel + ':' + instanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of comments.
|
||||
*
|
||||
* @param {string} contextLevel Contextlevel system, course, user...
|
||||
* @param {number} instanceId The Instance id of item associated with the context level.
|
||||
* @param {string} component Component name.
|
||||
* @param {number} itemId Associated id.
|
||||
* @param {string} [area=''] String comment area. Default empty.
|
||||
* @param {number} [page=0] Page number (0 based). Default 0.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved with the comments.
|
||||
*/
|
||||
getComments(contextLevel: string, instanceId: number, component: string, itemId: number,
|
||||
area: string = '', page: number = 0, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params: any = {
|
||||
contextlevel: contextLevel,
|
||||
instanceid: instanceId,
|
||||
component: component,
|
||||
itemid: itemId,
|
||||
area: area,
|
||||
page: page,
|
||||
};
|
||||
|
||||
const preSets = {
|
||||
cacheKey: this.getCommentsCacheKey(contextLevel, instanceId, component, itemId, area, page)
|
||||
};
|
||||
|
||||
return site.read('core_comment_get_comments', params, preSets).then((response) => {
|
||||
if (response.comments) {
|
||||
return response.comments;
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates comments data.
|
||||
*
|
||||
* @param {string} contextLevel Contextlevel system, course, user...
|
||||
* @param {number} instanceId The Instance id of item associated with the context level.
|
||||
* @param {string} component Component name.
|
||||
* @param {number} itemId Associated id.
|
||||
* @param {string} [area=''] String comment area. Default empty.
|
||||
* @param {number} [page=0] Page number (0 based). Default 0.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||
*/
|
||||
invalidateCommentsData(contextLevel: string, instanceId: number, component: string, itemId: number,
|
||||
area: string = '', page: number = 0, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.invalidateWsCacheForKey(this.getCommentsCacheKey(contextLevel, instanceId, component, itemId, area, page));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates all comments data for an instance.
|
||||
*
|
||||
* @param {string} contextLevel Contextlevel system, course, user...
|
||||
* @param {number} instanceId The Instance id of item associated with the context level.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||
*/
|
||||
invalidateCommentsByInstance(contextLevel: string, instanceId: number, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.invalidateWsCacheForKeyStartingWith(this.getCommentsPrefixCacheKey(contextLevel, instanceId));
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue