MOBILE-2317 user: Add profile field delegate

main
Pau Ferrer Ocaña 2018-01-16 15:52:07 +01:00
parent e836171c02
commit ba1267410e
38 changed files with 1297 additions and 6 deletions

View File

@ -0,0 +1,46 @@
// (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 { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { AddonUserProfileFieldCheckboxHandler } from './providers/handler';
import { CoreUserProfileFieldDelegate } from '../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldCheckboxComponent } from './component/checkbox';
import { CoreComponentsModule } from '../../../components/components.module';
@NgModule({
declarations: [
AddonUserProfileFieldCheckboxComponent
],
imports: [
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule
],
providers: [
AddonUserProfileFieldCheckboxHandler
],
exports: [
AddonUserProfileFieldCheckboxComponent
],
entryComponents: [
AddonUserProfileFieldCheckboxComponent
]
})
export class AddonUserProfileFieldCheckboxModule {
constructor(userProfileFieldDelegate: CoreUserProfileFieldDelegate, handler: AddonUserProfileFieldCheckboxHandler) {
userProfileFieldDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,16 @@
<!-- Render (no edit). -->
<ion-item *ngIf="!edit && field && field.name">
<h2>{{ field.name }}</h2>
<p *ngIf="field.value != '0'">
{{ 'core.yes' | translate }}
</p>
<p *ngIf="field.value == '0'">
{{ 'core.no' | translate }}
</p>
</ion-item>
<!-- Edit. -->
<ion-item *ngIf="edit && field && field.shortname">
<ion-label [core-mark-required]="field.required">{{ field.name }}</ion-label>
<ion-checkbox text-wrap [name]="field.modelName" [(ngModel)]="model[field.modelName]" [disabled]="!signup && field.locked" [required]="field.required" core-input-errors>
</ion-checkbox>
</ion-item>

View File

@ -0,0 +1,47 @@
// (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, OnInit } from '@angular/core';
/**
* Directive to render a checkbox user profile field.
*/
@Component({
selector: 'core-user-profile-field-checkbox',
templateUrl: 'checkbox.html'
})
export class AddonUserProfileFieldCheckboxComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
let field = this.field;
if (field && this.edit && this.model) {
field.modelName = 'profile_field_' + field.shortname;
// Initialize the value.
if (typeof field.defaultdata != 'undefined' && typeof this.model[field.modelName] == 'undefined') {
this.model[field.modelName] = field.defaultdata && field.defaultdata !== '0' && field.defaultdata !== 'false';
}
}
}
}

View File

@ -0,0 +1,70 @@
// (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 { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldCheckboxComponent } from '../component/checkbox';
/**
* Checkbox user profile field handlers.
*/
@Injectable()
export class AddonUserProfileFieldCheckboxHandler implements CoreUserProfileFieldHandler {
name = 'checkbox';
constructor() {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the data to send for the field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {CoreUserProfileFieldHandlerData} Data to send for the field.
*/
getData(field: any, signup: boolean, registerAuth: string, model: any): CoreUserProfileFieldHandlerData {
let name = 'profile_field_' + field.shortname;
if (typeof model[name] != 'undefined') {
return {
type: 'checkbox',
name: name,
value: model[name] ? 1 : 0
};
}
}
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) {
return AddonUserProfileFieldCheckboxComponent;
}
}

View File

@ -0,0 +1,10 @@
<!-- Render (no edit). -->
<ion-item *ngIf="!edit && field && field.name">
<h2>{{ field.name }}</h2>
<p>{{ field.value * 1000 | coreFormatDate:"dfmediumdate"}}</p>
</ion-item>
<!-- Edit. -->
<ion-item *ngIf="edit && field && field.shortname" text-wrap>
<ion-label [core-mark-required]="field.required">{{ field.name }}</ion-label>
<ion-datetime [name]="field.modelName" [displayFormat]="field.format | translate" [disabled]="!signup && field.locked" [(ngModel)]="model[field.modelName]" [required]="field.required" core-input-errors [max]="field.max" [min]="field.min"></ion-datetime>
</ion-item>

View File

@ -0,0 +1,63 @@
// (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, OnInit } from '@angular/core';
/**
* Directive to render a datetime user profile field.
*/
@Component({
selector: 'core-user-profile-field-datetime',
templateUrl: 'datetime.html'
})
export class AddonUserProfileFieldDatetimeComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
let field = this.field,
year;
if (field && this.edit && this.model) {
field.modelName = 'profile_field_' + field.shortname;
// Check if it's only date or it has time too.
field.hasTime = field.param3 && field.param3 !== '0' && field.param3 !== 'false';
field.format = field.hasTime ? 'core.dffulldate' : 'core.dfdaymonthyear';
// Check min value.
if (field.param1) {
year = parseInt(field.param1, 10);
if (year) {
field.min = year;
}
}
// Check max value.
if (field.param2) {
year = parseInt(field.param2, 10);
if (year) {
field.max = year;
}
}
}
}
}

View File

@ -0,0 +1,48 @@
// (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 { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { AddonUserProfileFieldDatetimeHandler } from './providers/handler';
import { CoreUserProfileFieldDelegate } from '../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldDatetimeComponent } from './component/datetime';
import { CoreComponentsModule } from '../../../components/components.module';
import { CorePipesModule } from '../../../pipes/pipes.module';
@NgModule({
declarations: [
AddonUserProfileFieldDatetimeComponent
],
imports: [
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CorePipesModule
],
providers: [
AddonUserProfileFieldDatetimeHandler
],
exports: [
AddonUserProfileFieldDatetimeComponent
],
entryComponents: [
AddonUserProfileFieldDatetimeComponent
]
})
export class AddonUserProfileFieldDatetimeModule {
constructor(userProfileFieldDelegate: CoreUserProfileFieldDelegate, handler: AddonUserProfileFieldDatetimeHandler) {
userProfileFieldDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,85 @@
// (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 { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldDatetimeComponent } from '../component/datetime';
import { Platform } from 'ionic-angular';
/**
* Datetime user profile field handlers.
*/
@Injectable()
export class AddonUserProfileFieldDatetimeHandler implements CoreUserProfileFieldHandler {
name = 'datetime';
constructor(private platform: Platform) {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the data to send for the field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {CoreUserProfileFieldHandlerData} Data to send for the field.
*/
getData(field: any, signup: boolean, registerAuth: string, model: any): CoreUserProfileFieldHandlerData {
let hasTime = field.param3 && field.param3 !== '0' && field.param3 !== 'false',
modelName = 'profile_field_' + field.shortname,
date = JSON.parse(JSON.stringify(model[modelName + '_date'])),
time;
if (date) {
if (hasTime && this.platform.is('ios')) {
// In iOS the time is in a different input. Add it to the date.
time = model[modelName + '_time'];
if (!time) {
return;
}
date.setHours(time.getHours());
date.setMinutes(time.getMinutes());
}
return {
type: 'datetime',
name: 'profile_field_' + field.shortname,
value: Math.round(date.getTime() / 1000)
};
}
}
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) {
return AddonUserProfileFieldDatetimeComponent;
}
}

View File

@ -0,0 +1,13 @@
<!-- Render (no edit). -->
<ion-item *ngIf="!edit && field && field.name">
<h2>{{ field.name }}</h2>
<p><core-format-text [text]="field.value"></core-format-text></p>
</ion-item>
<!-- Edit. -->
<ion-item *ngIf="edit && field && field.shortname" text-wrap>
<ion-label [core-mark-required]="field.required">{{ field.name }}</ion-label>
<ion-select [name]="field.modelName" [(ngModel)]="model[field.modelName]" [disabled]="!signup && field.locked" [required]="field.required" core-input-errors>
<ion-option value="">{{ 'core.choosedots' | translate }}</ion-option>
<ion-option *ngFor="let option of field.options" [value]="option">{{option}}</ion-option>
</ion-select>
</ion-item>

View File

@ -0,0 +1,55 @@
// (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, OnInit } from '@angular/core';
/**
* Directive to render a menu user profile field.
*/
@Component({
selector: 'core-user-profile-field-menu',
templateUrl: 'menu.html'
})
export class AddonUserProfileFieldMenuComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
let field = this.field;
if (field && this.edit && this.model) {
field.modelName = 'profile_field_' + field.shortname;
// Parse options.
if (field.param1) {
field.options = field.param1.split(/\r\n|\r|\n/g);
} else {
field.options = [];
}
// Initialize the value using default data.
if (typeof field.defaultdata != 'undefined' && typeof this.model[field.modelName] == 'undefined') {
this.model[field.modelName] = field.defaultdata;
}
}
}
}

View File

@ -0,0 +1,48 @@
// (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 { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { AddonUserProfileFieldMenuHandler } from './providers/handler';
import { CoreUserProfileFieldDelegate } from '../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldMenuComponent } from './component/menu';
import { CoreComponentsModule } from '../../../components/components.module';
import { CoreDirectivesModule } from '../../../directives/directives.module';
@NgModule({
declarations: [
AddonUserProfileFieldMenuComponent
],
imports: [
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonUserProfileFieldMenuHandler
],
exports: [
AddonUserProfileFieldMenuComponent
],
entryComponents: [
AddonUserProfileFieldMenuComponent
]
})
export class AddonUserProfileFieldMenuModule {
constructor(userProfileFieldDelegate: CoreUserProfileFieldDelegate, handler: AddonUserProfileFieldMenuHandler) {
userProfileFieldDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,70 @@
// (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 { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldMenuComponent } from '../component/menu';
/**
* Menu user profile field handlers.
*/
@Injectable()
export class AddonUserProfileFieldMenuHandler implements CoreUserProfileFieldHandler {
name = 'menu';
constructor() {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the data to send for the field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {CoreUserProfileFieldHandlerData} Data to send for the field.
*/
getData(field: any, signup: boolean, registerAuth: string, model: any): CoreUserProfileFieldHandlerData {
let name = 'profile_field_' + field.shortname;
if (model[name]) {
return {
type: 'menu',
name: name,
value: model[name]
};
}
}
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) {
return AddonUserProfileFieldMenuComponent;
}
}

View File

@ -0,0 +1,10 @@
<!-- Render (no edit). -->
<ion-item *ngIf="!edit && field && field.name">
<h2>{{ field.name }}</h2>
<p><core-format-text [text]="field.value"></core-format-text></p>
</ion-item>
<!-- Edit. -->
<ion-item *ngIf="edit && field && field.shortname" text-wrap>
<ion-label [core-mark-required]="field.required">{{ field.name }}</ion-label>
<ion-input [type]="field.inputType" [name]="field.modelName" [placeholder]="field.name" [(ngModel)]="model[field.modelName]" [disabled]="!signup && field.locked" maxlength="{{field.maxlength}}" [required]="field.required" core-input-errors></ion-input>
</ion-item>

View File

@ -0,0 +1,55 @@
// (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, OnInit } from '@angular/core';
/**
* Directive to render a text user profile field.
*/
@Component({
selector: 'core-user-profile-field-text',
templateUrl: 'text.html'
})
export class AddonUserProfileFieldTextComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
let field = this.field;
if (field && this.edit && this.model) {
field.modelName = 'profile_field_' + field.shortname;
// Check max length.
if (field.param2) {
field.maxlength = parseInt(field.param2, 10) || '';
}
// Check if it's a password or text.
field.inputType = field.param3 && field.param3 !== '0' && field.param3 !== 'false' ? 'password' : 'text';
// Initialize the value using default data.
if (typeof field.defaultdata != 'undefined' && typeof this.model[field.modelName] == 'undefined') {
this.model[field.modelName] = field.defaultdata;
}
}
}
}

View File

@ -0,0 +1,69 @@
// (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 { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldTextComponent } from '../component/text';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
/**
* Text user profile field handlers.
*/
@Injectable()
export class AddonUserProfileFieldTextHandler implements CoreUserProfileFieldHandler {
name = 'text';
constructor(private textUtils: CoreTextUtilsProvider) {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the data to send for the field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {CoreUserProfileFieldHandlerData} Data to send for the field.
*/
getData(field: any, signup: boolean, registerAuth: string, model: any): CoreUserProfileFieldHandlerData {
let name = 'profile_field_' + field.shortname;
return {
type: 'text',
name: name,
value: this.textUtils.cleanTags(model[name])
};
}
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) {
return AddonUserProfileFieldTextComponent;
}
}

View File

@ -0,0 +1,48 @@
// (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 { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { AddonUserProfileFieldTextHandler } from './providers/handler';
import { CoreUserProfileFieldDelegate } from '../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldTextComponent } from './component/text';
import { CoreComponentsModule } from '../../../components/components.module';
import { CoreDirectivesModule } from '../../../directives/directives.module';
@NgModule({
declarations: [
AddonUserProfileFieldTextComponent
],
imports: [
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonUserProfileFieldTextHandler
],
exports: [
AddonUserProfileFieldTextComponent
],
entryComponents: [
AddonUserProfileFieldTextComponent
]
})
export class AddonUserProfileFieldTextModule {
constructor(userProfileFieldDelegate: CoreUserProfileFieldDelegate, handler: AddonUserProfileFieldTextHandler) {
userProfileFieldDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,10 @@
<!-- Render (no edit). -->
<ion-item *ngIf="!edit && field && field.name">
<h2>{{ field.name }}</h2>
<p><core-format-text [text]="field.value"></core-format-text></p>
</ion-item>
<!-- Edit. -->
<ion-item *ngIf="edit && field && field.shortname" text-wrap>
<ion-label [core-mark-required]="field.required">{{ field.name }}</ion-label>
<ion-textarea [name]="field.modelName" [(ngModel)]="model[field.modelName]" [placeholder]="field.name" [disabled]="!signup && field.locked" [required]="field.required"></ion-textarea>
</ion-item>

View File

@ -0,0 +1,50 @@
// (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, OnInit } from '@angular/core';
/**
* Directive to render a textarea user profile field.
*/
@Component({
selector: 'core-user-profile-field-textarea',
templateUrl: 'textarea.html'
})
export class AddonUserProfileFieldTextareaComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
let field = this.field;
if (field && this.edit && this.model) {
field.modelName = 'profile_field_' + field.shortname;
this.model[field.modelName] = {
format: 1
};
// Initialize the value using default data.
if (typeof field.defaultdata != 'undefined' && typeof this.model[field.modelName].text == 'undefined') {
this.model[field.modelName].text = field.defaultdata;
}
}
}
}

View File

@ -0,0 +1,83 @@
// (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 { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldTextareaComponent } from '../component/textarea';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
/**
* Textarea user profile field handlers.
*/
@Injectable()
export class AddonUserProfileFieldTextareaHandler implements CoreUserProfileFieldHandler {
name = 'textarea';
constructor(private textUtils: CoreTextUtilsProvider, private domUtils: CoreDomUtilsProvider) {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the data to send for the field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {Promise<CoreUserProfileFieldHandlerData>} Data to send for the field.
*/
getData(field: any, signup: boolean, registerAuth: string, model: any): Promise<CoreUserProfileFieldHandlerData> {
let name = 'profile_field_' + field.shortname;
if (model[name]) {
return this.domUtils.isRichTextEditorEnabled().then((enabled) => {
let text = model[name].text || '';
if (!enabled) {
// Rich text editor not enabled, add some HTML to the message if needed.
text = this.textUtils.formatHtmlLines(text);
}
return {
type: 'textarea',
name: name,
value: JSON.stringify({
text: text,
format: model[name].format || 1
})
};
});
}
}
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) {
return AddonUserProfileFieldTextareaComponent;
}
}

View File

@ -0,0 +1,48 @@
// (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 { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { AddonUserProfileFieldTextareaHandler } from './providers/handler';
import { CoreUserProfileFieldDelegate } from '../../../core/user/providers/user-profile-field-delegate';
import { AddonUserProfileFieldTextareaComponent } from './component/textarea';
import { CoreComponentsModule } from '../../../components/components.module';
import { CoreDirectivesModule } from '../../../directives/directives.module';
@NgModule({
declarations: [
AddonUserProfileFieldTextareaComponent
],
imports: [
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonUserProfileFieldTextareaHandler
],
exports: [
AddonUserProfileFieldTextareaComponent
],
entryComponents: [
AddonUserProfileFieldTextareaComponent
]
})
export class AddonUserProfileFieldTextareaModule {
constructor(userProfileFieldDelegate: CoreUserProfileFieldDelegate, handler: AddonUserProfileFieldTextareaHandler) {
userProfileFieldDelegate.registerHandler(handler);
}
}

View File

@ -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 { AddonUserProfileFieldCheckboxModule } from './checkbox/checkbox.module';
import { AddonUserProfileFieldDatetimeModule } from './datetime/datetime.module';
import { AddonUserProfileFieldMenuModule } from './menu/menu.module';
import { AddonUserProfileFieldTextModule } from './text/text.module';
import { AddonUserProfileFieldTextareaModule } from './textarea/textarea.module';
@NgModule({
declarations: [],
imports: [
AddonUserProfileFieldCheckboxModule,
AddonUserProfileFieldDatetimeModule,
AddonUserProfileFieldMenuModule,
AddonUserProfileFieldTextModule,
AddonUserProfileFieldTextareaModule
],
providers: [
],
exports: []
})
export class AddonUserProfileFieldModule {}

View File

@ -64,6 +64,8 @@ import { CoreUserModule } from '../core/user/user.module';
// Addon modules.
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
import { AddonUserProfileFieldModule } from '../addon/userprofilefield/userprofilefield.module';
// For translate loader. AoT requires an exported function for factories.
export function createTranslateLoader(http: HttpClient) {
@ -99,7 +101,8 @@ export function createTranslateLoader(http: HttpClient) {
CoreSiteHomeModule,
CoreContentLinksModule,
CoreUserModule,
AddonCalendarModule
AddonCalendarModule,
AddonUserProfileFieldModule
],
bootstrap: [IonicApp],
entryComponents: [

View File

@ -0,0 +1,36 @@
// (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 { CoreUserProfileFieldComponent } from './user-profile-field/user-profile-field';
@NgModule({
declarations: [
CoreUserProfileFieldComponent
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
],
providers: [
],
exports: [
CoreUserProfileFieldComponent
]
})
export class CoreUserComponentsModule {}

View File

@ -0,0 +1,2 @@
<!-- User profile field that overrides the default one. -->
<ng-template #userProfileField></ng-template>

View File

@ -0,0 +1,5 @@
core-user-profile-field {
}

View File

@ -0,0 +1,98 @@
// (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, ViewChild, ViewContainerRef, ComponentFactoryResolver, ComponentRef, OnInit } from '@angular/core';
import { CoreLoggerProvider } from '../../../../providers/logger';
import { CoreUserProfileFieldDelegate } from '../../providers/user-profile-field-delegate';
/**
* Directive to render user profile field.
*/
@Component({
selector: 'core-user-profile-field',
templateUrl: 'user-profile-field.html'
})
export class CoreUserProfileFieldComponent implements OnInit {
@Input() field: any; // The profile field to be rendered.
@Input() signup?: boolean = false; // True if editing the field in signup. Defaults to false.
@Input() edit?: boolean = false; // True if editing the field. Defaults to false.
@Input() model?: any; // Model where to store the data. Required if edit=true or signup=true.
@Input() registerAuth?: string; // Register auth method. E.g. 'email'.
// Get the containers where to inject dynamic components. We use a setter because they might be inside a *ngIf.
@ViewChild('userProfileField', { read: ViewContainerRef }) set userProfileField (el: ViewContainerRef) {
if (this.field) {
this.createComponent(this.ufDelegate.getComponent(this.field, this.signup, this.registerAuth), el);
} else {
// The component hasn't been initialized yet. Store the container.
this.fieldContainer = el;
}
};
protected logger;
// Instances and containers of all the components that the handler could define.
protected fieldContainer: ViewContainerRef;
protected fieldInstance: any;
constructor(logger: CoreLoggerProvider, private factoryResolver: ComponentFactoryResolver,
private ufDelegate: CoreUserProfileFieldDelegate) {
this.logger = logger.getInstance('CoreUserProfileFieldComponent');
}
/**
* Component being initialized.
*/
ngOnInit() {
this.createComponent(this.ufDelegate.getComponent(this.field, this.signup, this.registerAuth), this.fieldContainer);
}
/**
* Create a component, add it to a container and set the input data.
*
* @param {any} componentClass The class of the component to create.
* @param {ViewContainerRef} container The container to add the component to.
* @return {boolean} Whether the component was successfully created.
*/
protected createComponent(componentClass: any, container: ViewContainerRef) : boolean {
if (!componentClass || !container) {
// No component to instantiate or container doesn't exist right now.
return false;
}
if (this.fieldInstance && container === this.fieldContainer) {
// Component already instantiated and the component hasn't been destroyed, nothing to do.
return true;
}
try {
// Create the component and add it to the container.
const factory = this.factoryResolver.resolveComponentFactory(componentClass),
componentRef = container.createComponent(factory);
this.fieldContainer = container;
this.fieldInstance = componentRef.instance;
// Set the Input data.
this.fieldInstance.field = this.field;
this.fieldInstance.edit = this.edit;
this.fieldInstance.model = this.model;
return true;
} catch(ex) {
this.logger.error('Error creating user field component', ex, componentClass);
return false;
}
}
}

View File

@ -59,6 +59,7 @@
<h2>{{ 'core.user.interests' | translate}}</h2>
<p><core-format-text [text]="user.interests"></core-format-text></p>
</ion-item>
<core-user-profile-field *ngFor="let field of user.customfields" [field]="field"></core-user-profile-field>
</ion-item-group>
<ion-item-group *ngIf="user.description">
<ion-item-divider color="light">{{ 'core.user.description' | translate}}</ion-item-divider>

View File

@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { CoreUserAboutPage } from './about';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreUserComponentsModule } from '../../components/components.module';
@NgModule({
declarations: [
@ -26,6 +27,7 @@ import { CoreComponentsModule } from '../../../../components/components.module';
imports: [
CoreComponentsModule,
CoreDirectivesModule,
CoreUserComponentsModule,
IonicPageModule.forChild(CoreUserAboutPage),
TranslateModule.forChild()
],

View File

@ -23,7 +23,7 @@ import { CoreEventsProvider } from '../../../../providers/events';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreMimetypeUtilsProvider } from '../../../../providers/utils/mimetype';
import { CoreFileUploaderHelperProvider } from '../../../fileuploader/providers/helper';
import { CoreUserDelegate } from '../../providers/delegate';
import { CoreUserDelegate } from '../../providers/user-delegate';
/**
* Page that displays an user profile page.
@ -103,7 +103,6 @@ export class CoreUserProfilePage {
this.isLoadingHandlers = true;
this.userDelegate.getProfileHandlersFor(user, this.courseId).then((handlers) => {
console.error(handlers);
this.actionHandlers = [];
this.newPageHandlers = [];
this.communicationHandlers = [];

View File

@ -124,7 +124,7 @@ export class CoreUserDelegate extends CoreDelegate {
protected featurePrefix = '$mmUserDelegate_';
constructor(protected loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
private coursesProvider: CoreCoursesProvider, protected eventsProvider: CoreEventsProvider) {
private coursesProvider: CoreCoursesProvider, protected eventsProvider: CoreEventsProvider) {
super('CoreUserDelegate', loggerProvider, sitesProvider, eventsProvider);
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from './delegate';
import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from './user-delegate';
import { CoreSitesProvider } from '../../../providers/sites';
/**

View File

@ -0,0 +1,164 @@
// (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 { CoreDelegate, CoreDelegateHandler } from '../../../classes/delegate';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreEventsProvider } from '../../../providers/events';
export interface CoreUserProfileFieldHandler extends CoreDelegateHandler {
/**
* Return the Component to use to display the user profile field.
*
* @param {any} field User field to get the data for.
* @param {boolean} [signup] True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string): any;
/**
* Get the data to send for the field based on the input data.
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {Promise<CoreUserProfileFieldHandlerData>|CoreUserProfileFieldHandlerData} Data to send for the field.
*/
getData?(field: any, signup: boolean, registerAuth: string, model: any):
Promise<CoreUserProfileFieldHandlerData> | CoreUserProfileFieldHandlerData;
};
export interface CoreUserProfileFieldHandlerData {
/**
* Name to display.
* @type {string}
*/
name: string;
/**
* Field type.
* @type {string}
*/
type?: string;
/**
* Value of the field.
* @type {any}
*/
value: any;
};
/**
* Service to interact with user profile fields. Provides functions to register a plugin.
*/
@Injectable()
export class CoreUserProfileFieldDelegate extends CoreDelegate {
protected handlers: {[s: string]: CoreUserProfileFieldHandler} = {};
protected enabledHandlers: {[s: string]: CoreUserProfileFieldHandler} = {};
constructor(protected loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
protected eventsProvider: CoreEventsProvider) {
super('CoreUserProfileFieldDelegate', loggerProvider, sitesProvider, eventsProvider);
}
/**
* Get the component to use to display an user field.
*
* @param {any} field User field to get the directive for.
* @param {boolean} signup True if user is in signup page.
* @param {string} registerAuth Register auth method. E.g. 'email'
* @return {any} The component to use, undefined if not found.
*/
getComponent(field: any, signup: boolean, registerAuth: string) : any {
let type = field.type || field.datatype;
return this.executeFunction(type, 'getComponent', [field, signup, registerAuth]);
}
/**
* Get the data to send for a certain field based on the input data.
*
* @param {any} field User field to get the data for.
* @param {boolean} signup True if user is in signup page.
* @param {string} registerAuth Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {Promise<any>} Data to send for the field.
*/
getDataForField(field: any, signup: boolean, registerAuth: string, model: any): Promise<any> {
let handler = this.getHandler(field, signup);
if (handler) {
let name = 'profile_field_' + field.shortname;
if (handler.getData) {
return Promise.resolve(handler.getData(field, signup, registerAuth, model));
} else if (field.shortname && typeof model[name] != 'undefined') {
// Handler doesn't implement the function, but the model has data for the field.
return Promise.resolve({
type: field.type || field.datatype,
name: name,
value: model[name]
});
}
}
return Promise.reject(null);
}
/**
* Get the data to send for a list of fields based on the input data.
*
* @param {any[]} fields User fields to get the data for.
* @param {boolean} [signup] True if user is in signup page.
* @param {string} [registerAuth] Register auth method. E.g. 'email'.
* @param {any} model Model with the input data.
* @return {Promise<any>} Data to send.
*/
getDataForFields(fields: any[], signup = false, registerAuth = "", model: any): Promise<any> {
let result = [],
promises = [];
fields.forEach((field) => {
this.getDataForField(field, signup, registerAuth, model).then((data) => {
result.push(data);
}).catch(() => {
// Ignore errors.
});
});
return Promise.all(promises).then(() => {
return result;
});
}
/**
* Get a handler.
*
* @param {any} field User field to get the directive for.
* @param {boolean} signup True if user is in signup page.
* @return {any} Handler.
*/
protected getHandler(field: any, signup: boolean): any {
let type = field.type || field.datatype;
if (signup) {
if (this.handlers[type]) {
return this.handlers[type];
}
return false;
}
return this.enabledHandlers[type];
}
}

View File

@ -13,7 +13,8 @@
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreUserDelegate } from './providers/delegate';
import { CoreUserDelegate } from './providers/user-delegate';
import { CoreUserProfileFieldDelegate } from './providers/user-profile-field-delegate';
import { CoreUserProvider } from './providers/user';
import { CoreUserHelperProvider } from './providers/helper';
import { CoreUserProfileMailHandler } from './providers/user-handler';
@ -25,6 +26,7 @@ import { CoreUserProfileMailHandler } from './providers/user-handler';
],
providers: [
CoreUserDelegate,
CoreUserProfileFieldDelegate,
CoreUserProfileMailHandler,
CoreUserProvider,
CoreUserHelperProvider