MOBILE-2354 workshop: Assessment strategy handlers

main
Albert Gasset 2018-06-12 10:18:42 +02:00
parent f0c80085d8
commit e7582678f9
22 changed files with 973 additions and 1 deletions

View File

@ -0,0 +1,51 @@
// (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 { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from './component/accumulative';
import { AddonModWorkshopAssessmentStrategyAccumulativeHandler } from './providers/handler';
import { AddonWorkshopAssessmentStrategyDelegate } from '../../providers/assessment-strategy-delegate';
@NgModule({
declarations: [
AddonModWorkshopAssessmentStrategyAccumulativeComponent,
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonModWorkshopAssessmentStrategyAccumulativeHandler
],
exports: [
AddonModWorkshopAssessmentStrategyAccumulativeComponent
],
entryComponents: [
AddonModWorkshopAssessmentStrategyAccumulativeComponent
]
})
export class AddonModWorkshopAssessmentStrategyAccumulativeModule {
constructor(strategyDelegate: AddonWorkshopAssessmentStrategyDelegate,
strategyHandler: AddonModWorkshopAssessmentStrategyAccumulativeHandler) {
strategyDelegate.registerHandler(strategyHandler);
}
}

View File

@ -0,0 +1,27 @@
<ion-card *ngFor="let field of assessment.form.fields; let n = index">
<ion-item text-wrap>
<h2>{{ field.dimtitle }}</h2>
<core-format-text [text]="field.description"></core-format-text>
</ion-item>
<ion-item *ngIf="edit && field.grades">
<ion-label [core-mark-required]="true" stacked>{{ 'addon.mod_workshop_assessment_accumulative.dimensiongradefor' | translate : {'$a': field.dimtitle } }}</ion-label>
<ion-select [(ngModel)]="selectedValues[n].grade">
<ion-option *ngFor="let grade of field.grades" [value]="grade.value">{{grade.label}}</ion-option>
</ion-select>
<core-input-errors item-content *ngIf="fieldErrors['grade_' + n]" [errorText]="fieldErrors['grade_' + n]"></core-input-errors>
</ion-item>
<ion-item *ngIf="!edit && field.grades" text-wrap>
<h2>{{ 'addon.mod_workshop_assessment_accumulative.dimensiongradefor' | translate : {'$a': field.dimtitle } }}</h2>
<ng-container *ngFor="let grade of field.grades">
<p *ngIf="grade.value === selectedValues[n].grade">{{grade.label}}</p>
</ng-container>
</ion-item>
<ion-item *ngIf="edit">
<ion-label stacked>{{ 'addon.mod_workshop_assessment_accumulative.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</ion-label>
<ion-textarea aria-multiline="true" [(ngModel)]="selectedValues[n].peercomment" core-auto-rows></ion-textarea>
</ion-item>
<ion-item *ngIf="!edit" text-wrap>
<h2>{{ 'addon.mod_workshop_assessment_accumulative.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</h2>
<p><core-format-text [text]="selectedValues[n].peercomment"></core-format-text></p>
</ion-item>
</ion-card>

View File

@ -0,0 +1,30 @@
// (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';
/**
* Component for accumulative assessment strategy.
*/
@Component({
selector: 'addon-mod-workshop-assessment-strategy-accumulative',
templateUrl: 'accumulative.html',
})
export class AddonModWorkshopAssessmentStrategyAccumulativeComponent {
@Input() workshopId: number;
@Input() assessment: any;
@Input() edit: boolean;
@Input() selectedValues: any[];
@Input() fieldErrors: any;
}

View File

@ -0,0 +1,6 @@
{
"dimensioncommentfor": "Comment for {{$a}}",
"dimensiongradefor": "Grade for {{$a}}",
"dimensionnumber": "Aspect {{$a}}",
"mustchoosegrade": "You have to select a grade for this aspect"
}

View File

@ -0,0 +1,144 @@
// (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 { TranslateService } from '@ngx-translate/core';
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
import { AddonWorkshopAssessmentStrategyHandler } from '../../../providers/assessment-strategy-delegate';
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from '../component/accumulative';
/**
* Handler for accumulative assessment strategy plugin.
*/
@Injectable()
export class AddonModWorkshopAssessmentStrategyAccumulativeHandler implements AddonWorkshopAssessmentStrategyHandler {
name = 'AddonModWorkshopAssessmentStrategyAccumulative';
strategyName = 'accumulative';
constructor(private translate: TranslateService, private gradesHelper: CoreGradesHelperProvider) {}
/**
* Whether or not the handler is enabled on a site level.
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
/**
* Returns the component to render the plugin.
*
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(): any {
return AddonModWorkshopAssessmentStrategyAccumulativeComponent;
}
/**
* Prepare original values to be shown and compared.
*
* @param {any} form Original data of the form.
* @param {number} workshopId WorkShop Id
* @return {Promise<any[]>} Promise resolved with original values sorted.
*/
getOriginalValues(form: any, workshopId: number): Promise<any[]> {
const defaultGrade = this.translate.instant('core.choosedots'),
originalValues = [],
promises = [];
form.fields.forEach((field, n) => {
field.dimtitle = this.translate.instant(
'addon.mod_workshop_assessment_accumulative.dimensionnumber', {$a: field.number});
const scale = parseInt(field.grade, 10) < 0 ? form.dimensionsinfo[n].scale : null;
if (!form.current[n]) {
form.current[n] = {};
}
originalValues[n] = {
peercomment: form.current[n].peercomment || '',
number: field.number
};
form.current[n].grade = form.current[n].grade ? parseInt(form.current[n].grade, 10) : -1;
promises.push(this.gradesHelper.makeGradesMenu(field.grade, workshopId, defaultGrade, -1, scale).then((grades) => {
field.grades = grades;
originalValues[n].grade = form.current[n].grade;
}));
});
return Promise.all(promises).then(() => {
return originalValues;
});
}
/**
* Check if the assessment data has changed for a certain submission and workshop for a this strategy plugin.
*
* @param {any[]} originalValues Original values of the form.
* @param {any[]} currentValues Current values of the form.
* @return {boolean} True if data has changed, false otherwise.
*/
hasDataChanged(originalValues: any[], currentValues: any[]): boolean {
for (const x in originalValues) {
if (originalValues[x].grade != currentValues[x].grade) {
return true;
}
if (originalValues[x].peercomment != currentValues[x].peercomment) {
return true;
}
}
return false;
}
/**
* Prepare assessment data to be sent to the server depending on the strategy selected.
*
* @param {any{}} currentValues Current values of the form.
* @param {any} form Assessment form data.
* @return {Promise<any>} Promise resolved with the data to be sent. Or rejected with the input errors object.
*/
prepareAssessmentData(currentValues: any[], form: any): Promise<any> {
const data = {};
const errors = {};
let hasErrors = false;
form.fields.forEach((field, idx) => {
const grade = parseInt(currentValues[idx].grade, 10);
if (!isNaN(grade) && grade >= 0) {
data['grade__idx_' + idx] = grade;
} else {
errors['grade_' + idx] = this.translate.instant('addon.mod_workshop_assessment_accumulative.mustchoosegrade');
hasErrors = true;
}
if (currentValues[idx].peercomment) {
data['peercomment__idx_' + idx] = currentValues[idx].peercomment;
}
data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
data['weight__idx_' + idx] = parseInt(field.weight, 10) || 0;
});
if (hasErrors) {
return Promise.reject(errors);
}
return Promise.resolve(data);
}
}

View File

@ -0,0 +1,29 @@
// (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 { AddonModWorkshopAssessmentStrategyAccumulativeModule } from './accumulative/accumulative.module';
import { AddonModWorkshopAssessmentStrategyCommentsModule } from './comments/comments.module';
import { AddonModWorkshopAssessmentStrategyNumErrorsModule } from './numerrors/numerrors.module';
import { AddonModWorkshopAssessmentStrategyRubricModule } from './rubric/rubric.module';
@NgModule({
imports: [
AddonModWorkshopAssessmentStrategyAccumulativeModule,
AddonModWorkshopAssessmentStrategyCommentsModule,
AddonModWorkshopAssessmentStrategyNumErrorsModule,
AddonModWorkshopAssessmentStrategyRubricModule,
]
})
export class AddonModWorkshopAssessmentStrategyModule {}

View File

@ -0,0 +1,51 @@
// (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 { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from './component/comments';
import { AddonModWorkshopAssessmentStrategyCommentsHandler } from './providers/handler';
import { AddonWorkshopAssessmentStrategyDelegate } from '../../providers/assessment-strategy-delegate';
@NgModule({
declarations: [
AddonModWorkshopAssessmentStrategyCommentsComponent,
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonModWorkshopAssessmentStrategyCommentsHandler
],
exports: [
AddonModWorkshopAssessmentStrategyCommentsComponent
],
entryComponents: [
AddonModWorkshopAssessmentStrategyCommentsComponent
]
})
export class AddonModWorkshopAssessmentStrategyCommentsModule {
constructor(strategyDelegate: AddonWorkshopAssessmentStrategyDelegate,
strategyHandler: AddonModWorkshopAssessmentStrategyCommentsHandler) {
strategyDelegate.registerHandler(strategyHandler);
}
}

View File

@ -0,0 +1,15 @@
<ion-card *ngFor="let field of assessment.form.fields; let n = index">
<ion-item text-wrap>
<h2>{{ field.dimtitle }}</h2>
<core-format-text [text]="field.description"></core-format-text>
</ion-item>
<ion-item *ngIf="edit">
<ion-label stacked [core-mark-required]="true">{{ 'addon.mod_workshop_assessment_comments.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</ion-label>
<ion-textarea aria-multiline="true" [(ngModel)]="selectedValues[n].peercomment" core-auto-rows></ion-textarea>
<core-input-errors item-content *ngIf="fieldErrors['peercomment_' + n]" [errorText]="fieldErrors['peercomment_' + n]"></core-input-errors>
</ion-item>
<ion-item *ngIf="!edit" text-wrap>
<h2>{{ 'addon.mod_workshop_assessment_comments.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</h2>
<p><core-format-text [text]="selectedValues[n].peercomment"></core-format-text></p>
</ion-item>
</ion-card>

View File

@ -0,0 +1,30 @@
// (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';
/**
* Component for comments assessment strategy.
*/
@Component({
selector: 'addon-mod-workshop-assessment-strategy-comments',
templateUrl: 'comments.html',
})
export class AddonModWorkshopAssessmentStrategyCommentsComponent {
@Input() workshopId: number;
@Input() assessment: any;
@Input() edit: boolean;
@Input() selectedValues: any[];
@Input() fieldErrors: any;
}

View File

@ -0,0 +1,4 @@
{
"dimensioncommentfor": "Comment for {{$a}}",
"dimensionnumber": "Aspect {{$a}}"
}

View File

@ -0,0 +1,120 @@
// (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 { TranslateService } from '@ngx-translate/core';
import { AddonWorkshopAssessmentStrategyHandler } from '../../../providers/assessment-strategy-delegate';
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from '../component/comments';
/**
* Handler for comments assessment strategy plugin.
*/
@Injectable()
export class AddonModWorkshopAssessmentStrategyCommentsHandler implements AddonWorkshopAssessmentStrategyHandler {
name = 'AddonModWorkshopAssessmentStrategyComments';
strategyName = 'comments';
constructor(private translate: TranslateService) {}
/**
* Whether or not the handler is enabled on a site level.
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
/**
* Returns the component to render the plugin.
*
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(): any {
return AddonModWorkshopAssessmentStrategyCommentsComponent;
}
/**
* Prepare original values to be shown and compared.
*
* @param {any} form Original data of the form.
* @param {number} workshopId Workshop Id
* @return {Promise<any[]>} Promise resolved with original values sorted.
*/
getOriginalValues(form: any, workshopId: number): Promise<any[]> {
const originalValues = [];
form.fields.forEach((field, n) => {
field.dimtitle = this.translate.instant('addon.mod_workshop_assessment_comments.dimensionnumber', {$a: field.number});
if (!form.current[n]) {
form.current[n] = {};
}
originalValues[n] = {
peercomment: form.current[n].peercomment || '',
number: field.number
};
});
return Promise.resolve(originalValues);
}
/**
* Check if the assessment data has changed for a certain submission and workshop for a this strategy plugin.
*
* @param {any[]} originalValues Original values of the form.
* @param {any[]} currentValues Current values of the form.
* @return {boolean} True if data has changed, false otherwise.
*/
hasDataChanged(originalValues: any[], currentValues: any[]): boolean {
for (const x in originalValues) {
if (originalValues[x].peercomment != currentValues[x].peercomment) {
return true;
}
}
return false;
}
/**
* Prepare assessment data to be sent to the server depending on the strategy selected.
*
* @param {any{}} currentValues Current values of the form.
* @param {any} form Assessment form data.
* @return {Promise<any>} Promise resolved with the data to be sent. Or rejected with the input errors object.
*/
prepareAssessmentData(currentValues: any[], form: any): Promise<any> {
const data = {};
const errors = {};
let hasErrors = false;
form.fields.forEach((field, idx) => {
if (currentValues[idx].peercomment) {
data['peercomment__idx_' + idx] = currentValues[idx].peercomment;
} else {
errors['peercomment_' + idx] = this.translate.instant('core.err_required');
hasErrors = true;
}
data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
});
if (hasErrors) {
return Promise.reject(errors);
}
return Promise.resolve(data);
}
}

View File

@ -0,0 +1,28 @@
<ion-card *ngFor="let field of assessment.form.fields; let n = index">
<ion-item text-wrap>
<h2>{{ field.dimtitle }}</h2>
<core-format-text [text]="field.description"></core-format-text>
</ion-item>
<ion-list radio-group [(ngModel)]="selectedValues[n].grade" [name]="'grade_' + n">
<ion-item>
<ion-label stacked [core-mark-required]="edit">{{ 'addon.mod_workshop.yourassessmentfor' | translate : {'$a': field.dimtitle } }}</ion-label>
<core-input-errors item-content *ngIf="edit && fieldErrors['grade_' + n]" [errorText]="fieldErrors['grade_' + n]"></core-input-errors>
</ion-item>
<ion-item>
<ion-label><core-format-text [text]="field.grade0"></core-format-text></ion-label>
<ion-radio [value]="-1" [disabled]="!edit"></ion-radio>
</ion-item>
<ion-item>
<ion-label><core-format-text [text]="field.grade1"></core-format-text></ion-label>
<ion-radio [value]="1" [disabled]="!edit"></ion-radio>
</ion-item>
</ion-list>
<ion-item *ngIf="edit">
<ion-label stacked>{{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</ion-label>
<ion-textarea aria-multiline="true" [(ngModel)]="selectedValues[n].peercomment" [name]="'peercomment_' + n" core-auto-rows></ion-textarea>
</ion-item>
<ion-item *ngIf="!edit" text-wrap>
<h2>{{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}</h2>
<p><core-format-text [text]="selectedValues[n].peercomment"></core-format-text></p>
</ion-item>
</ion-card>

View File

@ -0,0 +1,30 @@
// (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';
/**
* Component for numerrors assessment strategy.
*/
@Component({
selector: 'addon-mod-workshop-assessment-strategy-numerrors',
templateUrl: 'numerrors.html',
})
export class AddonModWorkshopAssessmentStrategyNumErrorsComponent {
@Input() workshopId: number;
@Input() assessment: any;
@Input() edit: boolean;
@Input() selectedValues: any[];
@Input() fieldErrors: any;
}

View File

@ -0,0 +1,5 @@
{
"dimensioncommentfor": "Comment for {{$a}}",
"dimensiongradefor": "Grade for {{$a}}",
"dimensionnumber": "Assertion {{$a}}"
}

View File

@ -0,0 +1,51 @@
// (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 { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from './component/numerrors';
import { AddonModWorkshopAssessmentStrategyNumErrorsHandler } from './providers/handler';
import { AddonWorkshopAssessmentStrategyDelegate } from '../../providers/assessment-strategy-delegate';
@NgModule({
declarations: [
AddonModWorkshopAssessmentStrategyNumErrorsComponent,
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonModWorkshopAssessmentStrategyNumErrorsHandler
],
exports: [
AddonModWorkshopAssessmentStrategyNumErrorsComponent
],
entryComponents: [
AddonModWorkshopAssessmentStrategyNumErrorsComponent
]
})
export class AddonModWorkshopAssessmentStrategyNumErrorsModule {
constructor(strategyDelegate: AddonWorkshopAssessmentStrategyDelegate,
strategyHandler: AddonModWorkshopAssessmentStrategyNumErrorsHandler) {
strategyDelegate.registerHandler(strategyHandler);
}
}

View File

@ -0,0 +1,130 @@
// (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 { TranslateService } from '@ngx-translate/core';
import { AddonWorkshopAssessmentStrategyHandler } from '../../../providers/assessment-strategy-delegate';
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from '../component/numerrors';
/**
* Handler for numerrors assessment strategy plugin.
*/
@Injectable()
export class AddonModWorkshopAssessmentStrategyNumErrorsHandler implements AddonWorkshopAssessmentStrategyHandler {
name = 'AddonModWorkshopAssessmentStrategyNumErrors';
strategyName = 'numerrors';
constructor(private translate: TranslateService) {}
/**
* Whether or not the handler is enabled on a site level.
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
/**
* Returns the component to render the plugin.
*
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(): any {
return AddonModWorkshopAssessmentStrategyNumErrorsComponent;
}
/**
* Prepare original values to be shown and compared.
*
* @param {any} form Original data of the form.
* @param {number} workshopId Workshop Id
* @return {Promise<any[]>} Promise resolved with original values sorted.
*/
getOriginalValues(form: any, workshopId: number): Promise<any[]> {
const originalValues = [];
form.fields.forEach((field, n) => {
field.dimtitle = this.translate.instant('addon.mod_workshop_assessment_numerrors.dimensionnumber', {$a: field.number});
if (!form.current[n]) {
form.current[n] = {};
}
originalValues[n] = {
peercomment: form.current[n].peercomment || '',
number: field.number,
grade: form.current[n].grade || ''
};
});
return Promise.resolve(originalValues);
}
/**
* Check if the assessment data has changed for a certain submission and workshop for a this strategy plugin.
*
* @param {any[]} originalValues Original values of the form.
* @param {any[]} currentValues Current values of the form.
* @return {boolean} True if data has changed, false otherwise.
*/
hasDataChanged(originalValues: any[], currentValues: any[]): boolean {
for (const x in originalValues) {
if (originalValues[x].grade != currentValues[x].grade) {
return true;
}
if (originalValues[x].peercomment != currentValues[x].peercomment) {
return true;
}
}
return false;
}
/**
* Prepare assessment data to be sent to the server depending on the strategy selected.
*
* @param {any{}} currentValues Current values of the form.
* @param {any} form Assessment form data.
* @return {Promise<any>} Promise resolved with the data to be sent. Or rejected with the input errors object.
*/
prepareAssessmentData(currentValues: any[], form: any): Promise<any> {
const data = {};
const errors = {};
let hasErrors = false;
form.fields.forEach((field, idx) => {
const grade = parseInt(currentValues[idx].grade);
if (!isNaN(grade) && grade >= 0) {
data['grade__idx_' + idx] = grade;
} else {
errors['grade_' + idx] = this.translate.instant('core.required');
hasErrors = true;
}
if (currentValues[idx].peercomment) {
data['peercomment__idx_' + idx] = currentValues[idx].peercomment;
}
data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
data['weight__idx_' + idx] = parseInt(field.weight, 10) || 0;
});
if (hasErrors) {
return Promise.reject(errors);
}
return Promise.resolve(data);
}
}

View File

@ -0,0 +1,13 @@
<ion-card *ngFor="let field of assessment.form.fields; let n = index">
<ion-item text-wrap>
<h2 [core-mark-required]="edit">{{ field.dimtitle }}</h2>
<core-format-text [text]="field.description"></core-format-text>
<core-input-errors *ngIf="edit && fieldErrors['chosenlevelid_' + n]" [errorText]="fieldErrors['chosenlevelid_' + n]"></core-input-errors>
</ion-item>
<ion-list radio-group [(ngModel)]="selectedValues[n].chosenlevelid" [name]="'chosenlevelid_' + n">
<ion-item *ngFor="let subfield of field.fields">
<ion-label><p><core-format-text [text]="subfield.definition"></core-format-text></p></ion-label>
<ion-radio [value]="subfield.levelid" [disabled]="!edit"></ion-radio>
</ion-item>
</ion-list>
</ion-card>

View File

@ -0,0 +1,30 @@
// (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';
/**
* Component for rubric assessment strategy.
*/
@Component({
selector: 'addon-mod-workshop-assessment-strategy-rubric',
templateUrl: 'rubric.html',
})
export class AddonModWorkshopAssessmentStrategyRubricComponent {
@Input() workshopId: number;
@Input() assessment: any;
@Input() edit: boolean;
@Input() selectedValues: any[];
@Input() fieldErrors: any;
}

View File

@ -0,0 +1,4 @@
{
"dimensionnumber": "Criterion {{$a}}",
"mustchooseone": "You have to select one of these items"
}

View File

@ -0,0 +1,121 @@
// (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 { TranslateService } from '@ngx-translate/core';
import { AddonWorkshopAssessmentStrategyHandler } from '../../../providers/assessment-strategy-delegate';
import { AddonModWorkshopAssessmentStrategyRubricComponent } from '../component/rubric';
/**
* Handler for rubric assessment strategy plugin.
*/
@Injectable()
export class AddonModWorkshopAssessmentStrategyRubricHandler implements AddonWorkshopAssessmentStrategyHandler {
name = 'AddonModWorkshopAssessmentStrategyRubric';
strategyName = 'rubric';
constructor(private translate: TranslateService) {}
/**
* Whether or not the handler is enabled on a site level.
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
/**
* Returns the component to render the plugin.
*
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(): any {
return AddonModWorkshopAssessmentStrategyRubricComponent;
}
/**
* Prepare original values to be shown and compared.
*
* @param {any} form Original data of the form.
* @param {number} workshopId Workshop Id
* @return {Promise<any[]>} Promise resolved with original values sorted.
*/
getOriginalValues(form: any, workshopId: number): Promise<any[]> {
const originalValues = [];
form.fields.forEach((field, n) => {
field.dimtitle = this.translate.instant('addon.mod_workshop_assessment_rubric.dimensionnumber', {$a: field.number});
if (!form.current[n]) {
form.current[n] = {};
}
originalValues[n] = {
chosenlevelid: form.current[n].chosenlevelid || '',
number: field.number
};
});
return Promise.resolve(originalValues);
}
/**
* Check if the assessment data has changed for a certain submission and workshop for a this strategy plugin.
*
* @param {any[]} originalValues Original values of the form.
* @param {any[]} currentValues Current values of the form.
* @return {boolean} True if data has changed, false otherwise.
*/
hasDataChanged(originalValues: any[], currentValues: any[]): boolean {
for (const x in originalValues) {
if (originalValues[x].chosenlevelid != (currentValues[x].chosenlevelid || '')) {
return true;
}
}
return false;
}
/**
* Prepare assessment data to be sent to the server depending on the strategy selected.
*
* @param {any{}} currentValues Current values of the form.
* @param {any} form Assessment form data.
* @return {Promise<any>} Promise resolved with the data to be sent. Or rejected with the input errors object.
*/
prepareAssessmentData(currentValues: any[], form: any): Promise<any> {
const data = {};
const errors = {};
let hasErrors = false;
form.fields.forEach((field, idx) => {
const id = parseInt(currentValues[idx].chosenlevelid, 10);
if (!isNaN(id) && id >= 0) {
data['chosenlevelid__idx_' + idx] = id;
} else {
errors['chosenlevelid_' + idx] = this.translate.instant('addon.mod_workshop_assessment_rubric.mustchooseone');
hasErrors = true;
}
data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
});
if (hasErrors) {
return Promise.reject(errors);
}
return Promise.resolve(data);
}
}

View File

@ -0,0 +1,51 @@
// (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 { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { AddonModWorkshopAssessmentStrategyRubricComponent } from './component/rubric';
import { AddonModWorkshopAssessmentStrategyRubricHandler } from './providers/handler';
import { AddonWorkshopAssessmentStrategyDelegate } from '../../providers/assessment-strategy-delegate';
@NgModule({
declarations: [
AddonModWorkshopAssessmentStrategyRubricComponent,
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
AddonModWorkshopAssessmentStrategyRubricHandler
],
exports: [
AddonModWorkshopAssessmentStrategyRubricComponent
],
entryComponents: [
AddonModWorkshopAssessmentStrategyRubricComponent
]
})
export class AddonModWorkshopAssessmentStrategyRubricModule {
constructor(strategyDelegate: AddonWorkshopAssessmentStrategyDelegate,
strategyHandler: AddonModWorkshopAssessmentStrategyRubricHandler) {
strategyDelegate.registerHandler(strategyHandler);
}
}

View File

@ -17,6 +17,7 @@ import { CoreCronDelegate } from '@providers/cron';
import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate';
import { CoreCourseModuleDelegate } from '@core/course/providers/module-delegate';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { AddonModWorkshopAssessmentStrategyModule } from './assessment/assessment.module';
import { AddonModWorkshopComponentsModule } from './components/components.module';
import { AddonModWorkshopModuleHandler } from './providers/module-handler';
import { AddonModWorkshopProvider } from './providers/workshop';
@ -32,7 +33,8 @@ import { AddonModWorkshopSyncCronHandler } from './providers/sync-cron-handler';
declarations: [
],
imports: [
AddonModWorkshopComponentsModule
AddonModWorkshopComponentsModule,
AddonModWorkshopAssessmentStrategyModule
],
providers: [
AddonModWorkshopProvider,