diff --git a/src/addon/mod/workshop/assessment/accumulative/accumulative.module.ts b/src/addon/mod/workshop/assessment/accumulative/accumulative.module.ts
new file mode 100644
index 000000000..f20ce1fec
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/accumulative/accumulative.module.ts
@@ -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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/accumulative/component/accumulative.html b/src/addon/mod/workshop/assessment/accumulative/component/accumulative.html
new file mode 100644
index 000000000..a65046ab6
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/accumulative/component/accumulative.html
@@ -0,0 +1,27 @@
+
+
+ {{ field.dimtitle }}
+
+
+
+ {{ 'addon.mod_workshop_assessment_accumulative.dimensiongradefor' | translate : {'$a': field.dimtitle } }}
+
+ {{grade.label}}
+
+
+
+
+ {{ 'addon.mod_workshop_assessment_accumulative.dimensiongradefor' | translate : {'$a': field.dimtitle } }}
+
+ {{grade.label}}
+
+
+
+ {{ 'addon.mod_workshop_assessment_accumulative.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
+ {{ 'addon.mod_workshop_assessment_accumulative.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
diff --git a/src/addon/mod/workshop/assessment/accumulative/component/accumulative.ts b/src/addon/mod/workshop/assessment/accumulative/component/accumulative.ts
new file mode 100644
index 000000000..962c20068
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/accumulative/component/accumulative.ts
@@ -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;
+}
diff --git a/src/addon/mod/workshop/assessment/accumulative/lang/en.json b/src/addon/mod/workshop/assessment/accumulative/lang/en.json
new file mode 100644
index 000000000..72c26cfa8
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/accumulative/lang/en.json
@@ -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"
+}
diff --git a/src/addon/mod/workshop/assessment/accumulative/providers/handler.ts b/src/addon/mod/workshop/assessment/accumulative/providers/handler.ts
new file mode 100644
index 000000000..e0d4496f2
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/accumulative/providers/handler.ts
@@ -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} Whether or not the handler is enabled on a site level.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+
+ /**
+ * Returns the component to render the plugin.
+ *
+ * @return {any|Promise} 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} Promise resolved with original values sorted.
+ */
+ getOriginalValues(form: any, workshopId: number): Promise {
+ 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} Promise resolved with the data to be sent. Or rejected with the input errors object.
+ */
+ prepareAssessmentData(currentValues: any[], form: any): Promise {
+ 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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/assessment.module.ts b/src/addon/mod/workshop/assessment/assessment.module.ts
new file mode 100644
index 000000000..3a77823ad
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/assessment.module.ts
@@ -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 {}
diff --git a/src/addon/mod/workshop/assessment/comments/comments.module.ts b/src/addon/mod/workshop/assessment/comments/comments.module.ts
new file mode 100644
index 000000000..c8f91b558
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/comments/comments.module.ts
@@ -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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/comments/component/comments.html b/src/addon/mod/workshop/assessment/comments/component/comments.html
new file mode 100644
index 000000000..e161192d8
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/comments/component/comments.html
@@ -0,0 +1,15 @@
+
+
+ {{ field.dimtitle }}
+
+
+
+ {{ 'addon.mod_workshop_assessment_comments.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
+
+ {{ 'addon.mod_workshop_assessment_comments.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
diff --git a/src/addon/mod/workshop/assessment/comments/component/comments.ts b/src/addon/mod/workshop/assessment/comments/component/comments.ts
new file mode 100644
index 000000000..ef464cd8e
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/comments/component/comments.ts
@@ -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;
+}
diff --git a/src/addon/mod/workshop/assessment/comments/lang/en.json b/src/addon/mod/workshop/assessment/comments/lang/en.json
new file mode 100644
index 000000000..6db857323
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/comments/lang/en.json
@@ -0,0 +1,4 @@
+{
+ "dimensioncommentfor": "Comment for {{$a}}",
+ "dimensionnumber": "Aspect {{$a}}"
+}
diff --git a/src/addon/mod/workshop/assessment/comments/providers/handler.ts b/src/addon/mod/workshop/assessment/comments/providers/handler.ts
new file mode 100644
index 000000000..ad0c525d4
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/comments/providers/handler.ts
@@ -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} Whether or not the handler is enabled on a site level.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+
+ /**
+ * Returns the component to render the plugin.
+ *
+ * @return {any|Promise} 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} Promise resolved with original values sorted.
+ */
+ getOriginalValues(form: any, workshopId: number): Promise {
+ 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} Promise resolved with the data to be sent. Or rejected with the input errors object.
+ */
+ prepareAssessmentData(currentValues: any[], form: any): Promise {
+ 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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/numerrors/component/numerrors.html b/src/addon/mod/workshop/assessment/numerrors/component/numerrors.html
new file mode 100644
index 000000000..f98777c83
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/numerrors/component/numerrors.html
@@ -0,0 +1,28 @@
+
+
+ {{ field.dimtitle }}
+
+
+
+
+ {{ 'addon.mod_workshop.yourassessmentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
+ {{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
+
+
+
diff --git a/src/addon/mod/workshop/assessment/numerrors/component/numerrors.ts b/src/addon/mod/workshop/assessment/numerrors/component/numerrors.ts
new file mode 100644
index 000000000..37cc36e72
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/numerrors/component/numerrors.ts
@@ -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;
+}
diff --git a/src/addon/mod/workshop/assessment/numerrors/lang/en.json b/src/addon/mod/workshop/assessment/numerrors/lang/en.json
new file mode 100644
index 000000000..d12b03206
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/numerrors/lang/en.json
@@ -0,0 +1,5 @@
+{
+ "dimensioncommentfor": "Comment for {{$a}}",
+ "dimensiongradefor": "Grade for {{$a}}",
+ "dimensionnumber": "Assertion {{$a}}"
+}
diff --git a/src/addon/mod/workshop/assessment/numerrors/numerrors.module.ts b/src/addon/mod/workshop/assessment/numerrors/numerrors.module.ts
new file mode 100644
index 000000000..d066236cb
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/numerrors/numerrors.module.ts
@@ -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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/numerrors/providers/handler.ts b/src/addon/mod/workshop/assessment/numerrors/providers/handler.ts
new file mode 100644
index 000000000..3f3630c65
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/numerrors/providers/handler.ts
@@ -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} Whether or not the handler is enabled on a site level.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+
+ /**
+ * Returns the component to render the plugin.
+ *
+ * @return {any|Promise} 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} Promise resolved with original values sorted.
+ */
+ getOriginalValues(form: any, workshopId: number): Promise {
+ 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} Promise resolved with the data to be sent. Or rejected with the input errors object.
+ */
+ prepareAssessmentData(currentValues: any[], form: any): Promise {
+ 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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/rubric/component/rubric.html b/src/addon/mod/workshop/assessment/rubric/component/rubric.html
new file mode 100644
index 000000000..ad4a76917
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/rubric/component/rubric.html
@@ -0,0 +1,13 @@
+
+
+ {{ field.dimtitle }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/addon/mod/workshop/assessment/rubric/component/rubric.ts b/src/addon/mod/workshop/assessment/rubric/component/rubric.ts
new file mode 100644
index 000000000..4c946500e
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/rubric/component/rubric.ts
@@ -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;
+}
diff --git a/src/addon/mod/workshop/assessment/rubric/lang/en.json b/src/addon/mod/workshop/assessment/rubric/lang/en.json
new file mode 100644
index 000000000..8b0b20c4a
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/rubric/lang/en.json
@@ -0,0 +1,4 @@
+{
+ "dimensionnumber": "Criterion {{$a}}",
+ "mustchooseone": "You have to select one of these items"
+}
\ No newline at end of file
diff --git a/src/addon/mod/workshop/assessment/rubric/providers/handler.ts b/src/addon/mod/workshop/assessment/rubric/providers/handler.ts
new file mode 100644
index 000000000..a0cfc563a
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/rubric/providers/handler.ts
@@ -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} Whether or not the handler is enabled on a site level.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+
+ /**
+ * Returns the component to render the plugin.
+ *
+ * @return {any|Promise} 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} Promise resolved with original values sorted.
+ */
+ getOriginalValues(form: any, workshopId: number): Promise {
+ 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} Promise resolved with the data to be sent. Or rejected with the input errors object.
+ */
+ prepareAssessmentData(currentValues: any[], form: any): Promise {
+ 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);
+ }
+}
diff --git a/src/addon/mod/workshop/assessment/rubric/rubric.module.ts b/src/addon/mod/workshop/assessment/rubric/rubric.module.ts
new file mode 100644
index 000000000..2b5392f31
--- /dev/null
+++ b/src/addon/mod/workshop/assessment/rubric/rubric.module.ts
@@ -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);
+ }
+}
diff --git a/src/addon/mod/workshop/workshop.module.ts b/src/addon/mod/workshop/workshop.module.ts
index 2c1c864e9..b2ab8c4d8 100644
--- a/src/addon/mod/workshop/workshop.module.ts
+++ b/src/addon/mod/workshop/workshop.module.ts
@@ -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,