MOBILE-3592 user: Implement user tag area handler

main
Dani Palou 2020-12-10 18:05:42 +01:00
parent 90bd583147
commit 36d03d27c5
10 changed files with 154 additions and 10 deletions

View File

@ -86,7 +86,7 @@ export class CoreDelegate<HandlerType extends CoreDelegateHandler> {
* @param delegateName Delegate name used for logging purposes.
* @param listenSiteEvents Whether to update the handler when a site event occurs (login, site updated, ...).
*/
constructor(delegateName: string, listenSiteEvents?: boolean) {
constructor(delegateName: string, listenSiteEvents: boolean = true) {
this.logger = CoreLogger.getInstance(delegateName);
this.handlersInitPromise = new Promise((resolve): void => {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Type } from '@angular/core';
import { IonInfiniteScroll, IonRefresher } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTag } from '@features/tag/services/tag';
@ -20,6 +20,7 @@ import { CoreTagFeedElement } from '../../services/tag-helper';
import { ActivatedRoute } from '@angular/router';
import { CoreTagAreaDelegate } from '../../services/tag-area-delegate';
import { Translate } from '@singletons';
import { CoreUtils } from '@services/utils/utils';
/**
* Page that displays the tag index area.
@ -47,7 +48,7 @@ export class CoreTagIndexAreaPage implements OnInit {
items: CoreTagFeedElement[] = [];
nextPage = 0;
canLoadMore = false;
areaComponent: any; // @todo
areaComponent?: Type<unknown>;
loadMoreError = false;
constructor(
@ -59,7 +60,7 @@ export class CoreTagIndexAreaPage implements OnInit {
*/
async ngOnInit(): Promise<void> {
const navParams = this.route.snapshot.queryParamMap;
const navParams = this.route.snapshot.queryParams;
this.tagId = navParams['tagId'] ? parseInt(navParams['tagId'], 10) : this.tagId;
this.tagName = navParams['tagName'] || this.tagName;
@ -74,8 +75,8 @@ export class CoreTagIndexAreaPage implements OnInit {
this.componentName = navParams['componentName'];
this.itemType = navParams['itemType'];
this.items = []; // @todo navParams['items'] || [];
this.nextPage = navParams.has('nextPage') ? parseInt(navParams['nextPage']!, 10) : 0;
this.canLoadMore = !!navParams['canLoadMore'];
this.nextPage = typeof navParams['nextPage'] != 'undefined' ? parseInt(navParams['nextPage'], 10) : 0;
this.canLoadMore = CoreUtils.instance.isTrueOrOne(navParams['canLoadMore']);
try {
if (!this.componentName || !this.itemType || !this.items.length || this.nextPage == 0) {

View File

@ -168,8 +168,11 @@ export class CoreTagIndexPage implements OnInit {
canLoadMore: area.canLoadMore,
nextPage: 1,
};
// this.splitviewCtrl.push('core-tag-index-area', params);
this.router.navigate(['core-tag-index-area'], { queryParams: params });
// this.splitviewCtrl.push('index-area', params);
this.router.navigate(['../index-area'], {
queryParams: params,
relativeTo: this.route,
});
}

View File

@ -52,7 +52,7 @@ export class CoreTagAreaDelegateService extends CoreDelegate<CoreTagAreaHandler>
protected handlerNameProperty = 'type';
constructor() {
super('CoreTagAreaDelegate');
super('CoreTagAreaDelegate', true);
}
/**

View File

@ -24,7 +24,7 @@ import { CoreUserProfileField } from '@features/user/services/user';
@Component({
template: '',
})
export class CoreUserProfileFieldBaseComponent implements OnInit {
export abstract class CoreUserProfileFieldBaseComponent implements OnInit {
@Input() field?: AuthEmailSignupProfileField | CoreUserProfileField; // The profile field to be rendered.
@Input() edit = false; // True if editing the field. Defaults to false.

View File

@ -21,10 +21,12 @@ import { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { CorePipesModule } from '@pipes/pipes.module';
import { CoreUserProfileFieldComponent } from './user-profile-field/user-profile-field';
import { CoreUserTagAreaComponent } from './tag-area/tag-area';
@NgModule({
declarations: [
CoreUserProfileFieldComponent,
CoreUserTagAreaComponent,
],
imports: [
CommonModule,
@ -38,6 +40,7 @@ import { CoreUserProfileFieldComponent } from './user-profile-field/user-profile
],
exports: [
CoreUserProfileFieldComponent,
CoreUserTagAreaComponent,
],
})
export class CoreUserComponentsModule {}

View File

@ -0,0 +1,6 @@
<ion-item class="ion-text-wrap" *ngFor="let item of items" core-user-link [userId]="item.user.id">
<core-user-avatar [user]="item.user" slot="start"></core-user-avatar>
<ion-label>
<h2>{{ item.heading }}</h2>
</ion-label>
</ion-item>

View File

@ -0,0 +1,30 @@
// (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, Input } from '@angular/core';
import { CoreUserTagFeedElement } from '@features/user/services/handlers/tag-area-handler';
/**
* Component to render the user tag area.
*/
@Component({
selector: 'core-user-tag-area',
templateUrl: 'core-user-tag-area.html',
})
export class CoreUserTagAreaComponent {
@Input() items?: CoreUserTagFeedElement[]; // Area items to render.
}

View File

@ -0,0 +1,98 @@
// (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 { Injectable, Type } from '@angular/core';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
import { CoreUserTagAreaComponent } from '@features/user/components/tag-area/tag-area';
import { CoreTagFeedElement } from '@features/tag/services/tag-helper';
import { CoreUserBasicData } from '../user';
import { makeSingleton } from '@singletons';
/**
* Handler to support tags.
*/
@Injectable({ providedIn: 'root' })
export class CoreUserTagAreaHandlerService implements CoreTagAreaHandler {
name = 'CoreUserTagAreaHandler';
type = 'core/user';
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
async isEnabled(): Promise<boolean> {
return true;
}
/**
* Parses the rendered content of a tag index and returns the items.
*
* @param content Rendered content.
* @return Area items (or promise resolved with the items).
*/
parseContent(content: string): CoreUserTagFeedElement[] {
const items: CoreUserTagFeedElement[] = [];
const element = CoreDomUtils.instance.convertToElement(content);
Array.from(element.querySelectorAll('div.user-box')).forEach((userbox: HTMLElement) => {
const avatarLink = userbox.querySelector('a:first-child');
if (!avatarLink) {
return;
}
const profileUrl = avatarLink.getAttribute('href') || '';
const match = profileUrl.match(/.*\/user\/(?:profile|view)\.php\?id=(\d+)/);
if (!match) {
return;
}
const avatarImg = avatarLink.querySelector('img.userpicture');
const avatarUrl = avatarImg ? avatarImg.getAttribute('src') : '';
items.push({
avatarUrl,
heading: userbox.innerText,
details: [],
user: {
id: Number(match[1]),
profileimageurl: avatarUrl || '',
fullname: userbox.innerText,
},
});
});
return items;
}
/**
* Get the component to use to display items.
*
* @param injector Injector.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(): Type<unknown> | Promise<Type<unknown>> {
return CoreUserTagAreaComponent;
}
}
export class CoreUserTagAreaHandler extends makeSingleton(CoreUserTagAreaHandlerService) {}
export type CoreUserTagFeedElement = CoreTagFeedElement & {
user: CoreUserBasicData;
};

View File

@ -25,6 +25,8 @@ import { CoreContentLinksDelegate } from '@features/contentlinks/services/conten
import { CoreUserProfileLinkHandler } from './services/handlers/profile-link';
import { CoreCronDelegate } from '@services/cron';
import { CoreUserSyncCronHandler } from './services/handlers/sync-cron';
import { CoreUserTagAreaHandler } from './services/handlers/tag-area-handler';
import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate';
const routes: Routes = [
{
@ -55,6 +57,7 @@ const routes: Routes = [
CoreUserDelegate.instance.registerHandler(CoreUserProfileMailHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(CoreUserProfileLinkHandler.instance);
CoreCronDelegate.instance.register(CoreUserSyncCronHandler.instance);
CoreTagAreaDelegate.instance.registerHandler(CoreUserTagAreaHandler.instance);
},
},
],