Merge pull request #3756 from NoelDeMartin/MOBILE-4272
MOBILE-4272: Decouple workshop from initial bundlemain
commit
475975fc33
|
@ -13,15 +13,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from './component/accumulative';
|
|
||||||
import { AddonModWorkshopAssessmentStrategyAccumulativeHandler } from './services/handler';
|
|
||||||
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
|
import { getAssessmentStrategyHandlerInstance } from '@addons/mod/workshop/assessment/accumulative/services/handler';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
|
||||||
AddonModWorkshopAssessmentStrategyAccumulativeComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
],
|
],
|
||||||
|
@ -30,14 +26,9 @@ import { CoreSharedModule } from '@/core/shared.module';
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
multi: true,
|
multi: true,
|
||||||
useValue: () => {
|
useValue: () => {
|
||||||
AddonWorkshopAssessmentStrategyDelegate.registerHandler(
|
AddonWorkshopAssessmentStrategyDelegate.registerHandler(getAssessmentStrategyHandlerInstance());
|
||||||
AddonModWorkshopAssessmentStrategyAccumulativeHandler.instance,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exports: [
|
|
||||||
AddonModWorkshopAssessmentStrategyAccumulativeComponent,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class AddonModWorkshopAssessmentStrategyAccumulativeModule {}
|
export class AddonModWorkshopAssessmentStrategyAccumulativeModule {}
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddonModWorkshopAssessmentStrategyFieldErrors,
|
||||||
|
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
||||||
|
import {
|
||||||
|
AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
||||||
|
} from '@addons/mod/workshop/services/workshop';
|
||||||
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
import { CoreGradesHelper } from '@features/grades/services/grades-helper';
|
||||||
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
|
import { CoreFormFields } from '@singletons/form';
|
||||||
|
import { AddonWorkshopAssessmentStrategyHandler } from '../../../services/assessment-strategy-delegate';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from '../component/accumulative';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyAccumulativeHandlerService } from './handler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for accumulative assessment strategy plugin.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopAssessmentStrategyAccumulativeHandlerLazyService
|
||||||
|
extends AddonModWorkshopAssessmentStrategyAccumulativeHandlerService
|
||||||
|
implements AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async isEnabled(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
getComponent(): Type<unknown> {
|
||||||
|
return AddonModWorkshopAssessmentStrategyAccumulativeComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getOriginalValues(
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
||||||
|
const defaultGrade = Translate.instant('core.choosedots');
|
||||||
|
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
||||||
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
form.fields.forEach((field, n) => {
|
||||||
|
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_accumulative.dimensionnumber', { $a: field.number });
|
||||||
|
|
||||||
|
if (!form.current[n]) {
|
||||||
|
form.current[n] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
originalValues[n] = {};
|
||||||
|
originalValues[n].peercomment = form.current[n].peercomment || '';
|
||||||
|
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
||||||
|
|
||||||
|
form.current[n].grade = form.current[n].grade ? parseInt(String(form.current[n].grade), 10) : -1;
|
||||||
|
|
||||||
|
const gradingType = parseInt(String(field.grade), 10);
|
||||||
|
const dimension = form.dimensionsinfo.find((dimension) => dimension.id == parseInt(field.dimensionid, 10));
|
||||||
|
const scale = dimension && gradingType < 0 ? dimension.scale : undefined;
|
||||||
|
|
||||||
|
promises.push(CoreGradesHelper.makeGradesMenu(gradingType, undefined, defaultGrade, -1, scale).then((grades) => {
|
||||||
|
field.grades = grades;
|
||||||
|
originalValues[n].grade = form.current[n].grade;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
return originalValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
hasDataChanged(
|
||||||
|
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
): 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async prepareAssessmentData(
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<CoreFormFields> {
|
||||||
|
const data: CoreFormFields = {};
|
||||||
|
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
form.fields.forEach((field, idx) => {
|
||||||
|
if (idx < form.dimenssionscount) {
|
||||||
|
const grade = parseInt(String(currentValues[idx].grade), 10);
|
||||||
|
if (!isNaN(grade) && grade >= 0) {
|
||||||
|
data['grade__idx_' + idx] = grade;
|
||||||
|
} else {
|
||||||
|
errors['grade_' + idx] = Translate.instant('addon.mod_workshop_assessment_accumulative.mustchoosegrade');
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopAssessmentStrategyAccumulativeHandler =
|
||||||
|
makeSingleton(AddonModWorkshopAssessmentStrategyAccumulativeHandlerLazyService);
|
|
@ -12,138 +12,33 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopAssessmentStrategyFieldErrors,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_NAME,
|
||||||
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_STRATEGY_NAME,
|
||||||
import {
|
} from '@addons/mod/workshop/assessment/constants';
|
||||||
AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
|
||||||
} from '@addons/mod/workshop/services/workshop';
|
|
||||||
import { Injectable, Type } from '@angular/core';
|
|
||||||
import { CoreGradesHelper } from '@features/grades/services/grades-helper';
|
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
|
||||||
import { CoreFormFields } from '@singletons/form';
|
|
||||||
import { AddonWorkshopAssessmentStrategyHandler } from '../../../services/assessment-strategy-delegate';
|
|
||||||
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from '../component/accumulative';
|
|
||||||
|
|
||||||
/**
|
export class AddonModWorkshopAssessmentStrategyAccumulativeHandlerService {
|
||||||
* Handler for accumulative assessment strategy plugin.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopAssessmentStrategyAccumulativeHandlerService implements AddonWorkshopAssessmentStrategyHandler {
|
|
||||||
|
|
||||||
name = 'AddonModWorkshopAssessmentStrategyAccumulative';
|
name = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_NAME;
|
||||||
strategyName = 'accumulative';
|
strategyName = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_STRATEGY_NAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async isEnabled(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
getComponent(): Type<unknown> {
|
|
||||||
return AddonModWorkshopAssessmentStrategyAccumulativeComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async getOriginalValues(
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
|
||||||
const defaultGrade = Translate.instant('core.choosedots');
|
|
||||||
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
|
||||||
const promises: Promise<void>[] = [];
|
|
||||||
|
|
||||||
form.fields.forEach((field, n) => {
|
|
||||||
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_accumulative.dimensionnumber', { $a: field.number });
|
|
||||||
|
|
||||||
if (!form.current[n]) {
|
|
||||||
form.current[n] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValues[n] = {};
|
|
||||||
originalValues[n].peercomment = form.current[n].peercomment || '';
|
|
||||||
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
|
||||||
|
|
||||||
form.current[n].grade = form.current[n].grade ? parseInt(String(form.current[n].grade), 10) : -1;
|
|
||||||
|
|
||||||
const gradingType = parseInt(String(field.grade), 10);
|
|
||||||
const dimension = form.dimensionsinfo.find((dimension) => dimension.id == parseInt(field.dimensionid, 10));
|
|
||||||
const scale = dimension && gradingType < 0 ? dimension.scale : undefined;
|
|
||||||
|
|
||||||
promises.push(CoreGradesHelper.makeGradesMenu(gradingType, undefined, defaultGrade, -1, scale).then((grades) => {
|
|
||||||
field.grades = grades;
|
|
||||||
originalValues[n].grade = form.current[n].grade;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
return originalValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
hasDataChanged(
|
|
||||||
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
): 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async prepareAssessmentData(
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<CoreFormFields> {
|
|
||||||
const data: CoreFormFields = {};
|
|
||||||
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
|
||||||
let hasErrors = false;
|
|
||||||
|
|
||||||
form.fields.forEach((field, idx) => {
|
|
||||||
if (idx < form.dimenssionscount) {
|
|
||||||
const grade = parseInt(String(currentValues[idx].grade), 10);
|
|
||||||
if (!isNaN(grade) && grade >= 0) {
|
|
||||||
data['grade__idx_' + idx] = grade;
|
|
||||||
} else {
|
|
||||||
errors['grade_' + idx] = Translate.instant('addon.mod_workshop_assessment_accumulative.mustchoosegrade');
|
|
||||||
hasErrors = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
throw errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopAssessmentStrategyAccumulativeHandler =
|
|
||||||
makeSingleton(AddonModWorkshopAssessmentStrategyAccumulativeHandlerService);
|
/**
|
||||||
|
* Get assessment strategy handler instance.
|
||||||
|
*
|
||||||
|
* @returns Assessment strategy handler.
|
||||||
|
*/
|
||||||
|
export function getAssessmentStrategyHandlerInstance(): AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
const lazyHandler = asyncInstance(async () => {
|
||||||
|
const { AddonModWorkshopAssessmentStrategyAccumulativeHandler } = await import('./handler-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopAssessmentStrategyAccumulativeHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopAssessmentStrategyAccumulativeHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from './comments/component/comments';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyAccumulativeComponent } from './accumulative/component/accumulative';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from './numerrors/component/numerrors';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyRubricComponent } from './rubric/component/rubric';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CoreSharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AddonModWorkshopAssessmentStrategyAccumulativeComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyCommentsComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyNumErrorsComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyRubricComponent,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
AddonModWorkshopAssessmentStrategyAccumulativeComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyCommentsComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyNumErrorsComponent,
|
||||||
|
AddonModWorkshopAssessmentStrategyRubricComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AddonModWorkshopAssessmentComponentsModule {}
|
|
@ -15,13 +15,9 @@
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
||||||
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from './component/comments';
|
import { getAssessmentStrategyHandlerInstance } from './services/handler';
|
||||||
import { AddonModWorkshopAssessmentStrategyCommentsHandler } from './services/handler';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
|
||||||
AddonModWorkshopAssessmentStrategyCommentsComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
],
|
],
|
||||||
|
@ -30,14 +26,9 @@ import { AddonModWorkshopAssessmentStrategyCommentsHandler } from './services/ha
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
multi: true,
|
multi: true,
|
||||||
useValue: () => {
|
useValue: () => {
|
||||||
AddonWorkshopAssessmentStrategyDelegate.registerHandler(
|
AddonWorkshopAssessmentStrategyDelegate.registerHandler(getAssessmentStrategyHandlerInstance());
|
||||||
AddonModWorkshopAssessmentStrategyCommentsHandler.instance,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exports: [
|
|
||||||
AddonModWorkshopAssessmentStrategyCommentsComponent,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class AddonModWorkshopAssessmentStrategyCommentsModule {}
|
export class AddonModWorkshopAssessmentStrategyCommentsModule {}
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddonModWorkshopAssessmentStrategyFieldErrors,
|
||||||
|
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
||||||
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
|
import {
|
||||||
|
AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
||||||
|
} from '@addons/mod/workshop/services/workshop';
|
||||||
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
|
import { CoreFormFields } from '@singletons/form';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from '../component/comments';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyCommentsHandlerService } from './handler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for comments assessment strategy plugin.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopAssessmentStrategyCommentsHandlerLazyService
|
||||||
|
extends AddonModWorkshopAssessmentStrategyCommentsHandlerService
|
||||||
|
implements AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async isEnabled(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
getComponent(): Type<unknown> {
|
||||||
|
return AddonModWorkshopAssessmentStrategyCommentsComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getOriginalValues(
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
||||||
|
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
||||||
|
|
||||||
|
form.fields.forEach((field, n) => {
|
||||||
|
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_comments.dimensionnumber', { $a: field.number });
|
||||||
|
|
||||||
|
if (!form.current[n]) {
|
||||||
|
form.current[n] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
originalValues[n] = {};
|
||||||
|
originalValues[n].peercomment = form.current[n].peercomment || '';
|
||||||
|
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
||||||
|
});
|
||||||
|
|
||||||
|
return originalValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
hasDataChanged(
|
||||||
|
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
): boolean {
|
||||||
|
for (const x in originalValues) {
|
||||||
|
if (originalValues[x].peercomment != currentValues[x].peercomment) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async prepareAssessmentData(
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<CoreFormFields> {
|
||||||
|
const data: CoreFormFields = {};
|
||||||
|
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
form.fields.forEach((field, idx) => {
|
||||||
|
if (idx < form.dimenssionscount) {
|
||||||
|
if (currentValues[idx].peercomment) {
|
||||||
|
data['peercomment__idx_' + idx] = currentValues[idx].peercomment;
|
||||||
|
} else {
|
||||||
|
errors['peercomment_' + idx] = 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) {
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopAssessmentStrategyCommentsHandler =
|
||||||
|
makeSingleton(AddonModWorkshopAssessmentStrategyCommentsHandlerLazyService);
|
|
@ -12,113 +12,33 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
AddonModWorkshopAssessmentStrategyFieldErrors,
|
|
||||||
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
|
||||||
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopGetAssessmentFormDefinitionData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_NAME,
|
||||||
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_STRATEGY_NAME,
|
||||||
} from '@addons/mod/workshop/services/workshop';
|
} from '@addons/mod/workshop/assessment/constants';
|
||||||
import { Injectable, Type } from '@angular/core';
|
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
|
||||||
import { CoreFormFields } from '@singletons/form';
|
|
||||||
import { AddonModWorkshopAssessmentStrategyCommentsComponent } from '../component/comments';
|
|
||||||
|
|
||||||
/**
|
export class AddonModWorkshopAssessmentStrategyCommentsHandlerService {
|
||||||
* Handler for comments assessment strategy plugin.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopAssessmentStrategyCommentsHandlerService implements AddonWorkshopAssessmentStrategyHandler {
|
|
||||||
|
|
||||||
name = 'AddonModWorkshopAssessmentStrategyComments';
|
name = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_NAME;
|
||||||
strategyName = 'comments';
|
strategyName = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_STRATEGY_NAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async isEnabled(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
getComponent(): Type<unknown> {
|
|
||||||
return AddonModWorkshopAssessmentStrategyCommentsComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async getOriginalValues(
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
|
||||||
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
|
||||||
|
|
||||||
form.fields.forEach((field, n) => {
|
|
||||||
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_comments.dimensionnumber', { $a: field.number });
|
|
||||||
|
|
||||||
if (!form.current[n]) {
|
|
||||||
form.current[n] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValues[n] = {};
|
|
||||||
originalValues[n].peercomment = form.current[n].peercomment || '';
|
|
||||||
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
|
||||||
});
|
|
||||||
|
|
||||||
return originalValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
hasDataChanged(
|
|
||||||
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
): boolean {
|
|
||||||
for (const x in originalValues) {
|
|
||||||
if (originalValues[x].peercomment != currentValues[x].peercomment) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async prepareAssessmentData(
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<CoreFormFields> {
|
|
||||||
const data: CoreFormFields = {};
|
|
||||||
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
|
||||||
let hasErrors = false;
|
|
||||||
|
|
||||||
form.fields.forEach((field, idx) => {
|
|
||||||
if (idx < form.dimenssionscount) {
|
|
||||||
if (currentValues[idx].peercomment) {
|
|
||||||
data['peercomment__idx_' + idx] = currentValues[idx].peercomment;
|
|
||||||
} else {
|
|
||||||
errors['peercomment_' + idx] = 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) {
|
|
||||||
throw errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopAssessmentStrategyCommentsHandler =
|
|
||||||
makeSingleton(AddonModWorkshopAssessmentStrategyCommentsHandlerService);
|
/**
|
||||||
|
* Get assessment strategy handler instance.
|
||||||
|
*
|
||||||
|
* @returns Assessment strategy handler.
|
||||||
|
*/
|
||||||
|
export function getAssessmentStrategyHandlerInstance(): AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
const lazyHandler = asyncInstance(async () => {
|
||||||
|
const { AddonModWorkshopAssessmentStrategyCommentsHandler } = await import('./handler-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopAssessmentStrategyCommentsHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopAssessmentStrategyCommentsHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_NAME = 'AddonModWorkshopAssessmentStrategyAccumulative';
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_ACCUMULATIVE_STRATEGY_NAME = 'accumulative';
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_NAME = 'AddonModWorkshopAssessmentStrategyComments';
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_COMMENTS_STRATEGY_NAME = 'comments';
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_NAME = 'AddonModWorkshopAssessmentStrategyNumErrors';
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_STRATEGY_NAME = 'numerrors';
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_NAME = 'AddonModWorkshopAssessmentStrategyRubric';
|
||||||
|
export const ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_STRATEGY_NAME = 'rubric';
|
|
@ -15,13 +15,9 @@
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
||||||
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from './component/numerrors';
|
import { getAssessmentStrategyHandlerInstance } from './services/handler';
|
||||||
import { AddonModWorkshopAssessmentStrategyNumErrorsHandler } from './services/handler';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
|
||||||
AddonModWorkshopAssessmentStrategyNumErrorsComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
],
|
],
|
||||||
|
@ -30,14 +26,9 @@ import { AddonModWorkshopAssessmentStrategyNumErrorsHandler } from './services/h
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
multi: true,
|
multi: true,
|
||||||
useValue: () => {
|
useValue: () => {
|
||||||
AddonWorkshopAssessmentStrategyDelegate.registerHandler(
|
AddonWorkshopAssessmentStrategyDelegate.registerHandler(getAssessmentStrategyHandlerInstance());
|
||||||
AddonModWorkshopAssessmentStrategyNumErrorsHandler.instance,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exports: [
|
|
||||||
AddonModWorkshopAssessmentStrategyNumErrorsComponent,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class AddonModWorkshopAssessmentStrategyNumErrorsModule {}
|
export class AddonModWorkshopAssessmentStrategyNumErrorsModule {}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddonModWorkshopAssessmentStrategyFieldErrors,
|
||||||
|
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
||||||
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
|
import {
|
||||||
|
AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
||||||
|
} from '@addons/mod/workshop/services/workshop';
|
||||||
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
import { Translate, makeSingleton } from '@singletons';
|
||||||
|
import { CoreFormFields } from '@singletons/form';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from '../component/numerrors';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyNumErrorsHandlerService } from './handler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for numerrors assessment strategy plugin.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerLazyService
|
||||||
|
extends AddonModWorkshopAssessmentStrategyNumErrorsHandlerService
|
||||||
|
implements AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async isEnabled(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
getComponent(): Type<unknown> {
|
||||||
|
return AddonModWorkshopAssessmentStrategyNumErrorsComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getOriginalValues(
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
||||||
|
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
||||||
|
|
||||||
|
form.fields.forEach((field, n) => {
|
||||||
|
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_numerrors.dimensionnumber', { $a: field.number });
|
||||||
|
|
||||||
|
if (!form.current[n]) {
|
||||||
|
form.current[n] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
originalValues[n] = {};
|
||||||
|
originalValues[n].peercomment = form.current[n].peercomment || '';
|
||||||
|
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
||||||
|
originalValues[n].grade = form.current[n].grade || '';
|
||||||
|
});
|
||||||
|
|
||||||
|
return originalValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
hasDataChanged(
|
||||||
|
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
): 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async prepareAssessmentData(
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<CoreFormFields> {
|
||||||
|
const data: CoreFormFields = {};
|
||||||
|
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
form.fields.forEach((field, idx) => {
|
||||||
|
if (idx < form.dimenssionscount) {
|
||||||
|
const grade = parseInt(String(currentValues[idx].grade), 10);
|
||||||
|
if (!isNaN(grade) && (grade == 1 || grade == -1)) {
|
||||||
|
data['grade__idx_' + idx] = grade;
|
||||||
|
} else {
|
||||||
|
errors['grade_' + idx] = Translate.instant('core.required');
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopAssessmentStrategyNumErrorsHandler =
|
||||||
|
makeSingleton(AddonModWorkshopAssessmentStrategyNumErrorsHandlerLazyService);
|
|
@ -12,121 +12,33 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
AddonModWorkshopAssessmentStrategyFieldErrors,
|
|
||||||
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
|
||||||
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopGetAssessmentFormDefinitionData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_NAME,
|
||||||
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_STRATEGY_NAME,
|
||||||
} from '@addons/mod/workshop/services/workshop';
|
} from '@addons/mod/workshop/assessment/constants';
|
||||||
import { Injectable, Type } from '@angular/core';
|
|
||||||
import { Translate, makeSingleton } from '@singletons';
|
|
||||||
import { CoreFormFields } from '@singletons/form';
|
|
||||||
import { AddonModWorkshopAssessmentStrategyNumErrorsComponent } from '../component/numerrors';
|
|
||||||
|
|
||||||
/**
|
export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerService {
|
||||||
* Handler for numerrors assessment strategy plugin.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerService implements AddonWorkshopAssessmentStrategyHandler {
|
|
||||||
|
|
||||||
name = 'AddonModWorkshopAssessmentStrategyNumErrors';
|
name = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_NAME;
|
||||||
strategyName = 'numerrors';
|
strategyName = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_NUMERRORS_STRATEGY_NAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async isEnabled(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
getComponent(): Type<unknown> {
|
|
||||||
return AddonModWorkshopAssessmentStrategyNumErrorsComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async getOriginalValues(
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
|
||||||
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
|
||||||
|
|
||||||
form.fields.forEach((field, n) => {
|
|
||||||
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_numerrors.dimensionnumber', { $a: field.number });
|
|
||||||
|
|
||||||
if (!form.current[n]) {
|
|
||||||
form.current[n] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValues[n] = {};
|
|
||||||
originalValues[n].peercomment = form.current[n].peercomment || '';
|
|
||||||
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
|
||||||
originalValues[n].grade = form.current[n].grade || '';
|
|
||||||
});
|
|
||||||
|
|
||||||
return originalValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
hasDataChanged(
|
|
||||||
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
): 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async prepareAssessmentData(
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<CoreFormFields> {
|
|
||||||
const data: CoreFormFields = {};
|
|
||||||
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
|
||||||
let hasErrors = false;
|
|
||||||
|
|
||||||
form.fields.forEach((field, idx) => {
|
|
||||||
if (idx < form.dimenssionscount) {
|
|
||||||
const grade = parseInt(String(currentValues[idx].grade), 10);
|
|
||||||
if (!isNaN(grade) && (grade == 1 || grade == -1)) {
|
|
||||||
data['grade__idx_' + idx] = grade;
|
|
||||||
} else {
|
|
||||||
errors['grade_' + idx] = Translate.instant('core.required');
|
|
||||||
hasErrors = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
throw errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopAssessmentStrategyNumErrorsHandler =
|
|
||||||
makeSingleton(AddonModWorkshopAssessmentStrategyNumErrorsHandlerService);
|
/**
|
||||||
|
* Get assessment strategy handler instance.
|
||||||
|
*
|
||||||
|
* @returns Assessment strategy handler.
|
||||||
|
*/
|
||||||
|
export function getAssessmentStrategyHandlerInstance(): AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
const lazyHandler = asyncInstance(async () => {
|
||||||
|
const { AddonModWorkshopAssessmentStrategyNumErrorsHandler } = await import('./handler-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopAssessmentStrategyNumErrorsHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopAssessmentStrategyNumErrorsHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -15,13 +15,9 @@
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyDelegate } from '../../services/assessment-strategy-delegate';
|
||||||
import { AddonModWorkshopAssessmentStrategyRubricComponent } from './component/rubric';
|
import { getAssessmentStrategyHandlerInstance } from './services/handler';
|
||||||
import { AddonModWorkshopAssessmentStrategyRubricHandler } from './services/handler';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
|
||||||
AddonModWorkshopAssessmentStrategyRubricComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
],
|
],
|
||||||
|
@ -30,14 +26,9 @@ import { AddonModWorkshopAssessmentStrategyRubricHandler } from './services/hand
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
multi: true,
|
multi: true,
|
||||||
useValue: () => {
|
useValue: () => {
|
||||||
AddonWorkshopAssessmentStrategyDelegate.registerHandler(
|
AddonWorkshopAssessmentStrategyDelegate.registerHandler(getAssessmentStrategyHandlerInstance());
|
||||||
AddonModWorkshopAssessmentStrategyRubricHandler.instance,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exports: [
|
|
||||||
AddonModWorkshopAssessmentStrategyRubricComponent,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class AddonModWorkshopAssessmentStrategyRubricModule {}
|
export class AddonModWorkshopAssessmentStrategyRubricModule {}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddonModWorkshopAssessmentStrategyFieldErrors,
|
||||||
|
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
||||||
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
|
import {
|
||||||
|
AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
||||||
|
} from '@addons/mod/workshop/services/workshop';
|
||||||
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
import { Translate, makeSingleton } from '@singletons';
|
||||||
|
import { CoreFormFields } from '@singletons/form';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyRubricComponent } from '../component/rubric';
|
||||||
|
import { AddonModWorkshopAssessmentStrategyRubricHandlerService } from './handler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for rubric assessment strategy plugin.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopAssessmentStrategyRubricHandlerLazyService
|
||||||
|
extends AddonModWorkshopAssessmentStrategyRubricHandlerService
|
||||||
|
implements AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async isEnabled(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
getComponent(): Type<unknown> {
|
||||||
|
return AddonModWorkshopAssessmentStrategyRubricComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getOriginalValues(
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
||||||
|
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
||||||
|
|
||||||
|
form.fields.forEach((field, n) => {
|
||||||
|
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_rubric.dimensionnumber', { $a: field.number });
|
||||||
|
|
||||||
|
if (!form.current[n]) {
|
||||||
|
form.current[n] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
originalValues[n] = {};
|
||||||
|
originalValues[n].chosenlevelid = form.current[n].chosenlevelid || '';
|
||||||
|
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
||||||
|
});
|
||||||
|
|
||||||
|
return originalValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
hasDataChanged(
|
||||||
|
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
): boolean {
|
||||||
|
for (const x in originalValues) {
|
||||||
|
if (originalValues[x].chosenlevelid != (currentValues[x].chosenlevelid || '')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async prepareAssessmentData(
|
||||||
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
|
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
||||||
|
): Promise<CoreFormFields> {
|
||||||
|
const data: CoreFormFields = {};
|
||||||
|
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
form.fields.forEach((field, idx) => {
|
||||||
|
if (idx < form.dimenssionscount) {
|
||||||
|
const id = parseInt(currentValues[idx].chosenlevelid, 10);
|
||||||
|
if (!isNaN(id) && id >= 0) {
|
||||||
|
data['chosenlevelid__idx_' + idx] = id;
|
||||||
|
} else {
|
||||||
|
errors['chosenlevelid_' + idx] = 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) {
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopAssessmentStrategyRubricHandler =
|
||||||
|
makeSingleton(AddonModWorkshopAssessmentStrategyRubricHandlerLazyService);
|
|
@ -12,114 +12,33 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
AddonModWorkshopAssessmentStrategyFieldErrors,
|
|
||||||
} from '@addons/mod/workshop/components/assessment-strategy/assessment-strategy';
|
|
||||||
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
import { AddonWorkshopAssessmentStrategyHandler } from '@addons/mod/workshop/services/assessment-strategy-delegate';
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopGetAssessmentFormDefinitionData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_NAME,
|
||||||
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_STRATEGY_NAME,
|
||||||
} from '@addons/mod/workshop/services/workshop';
|
} from '@addons/mod/workshop/assessment/constants';
|
||||||
import { Injectable, Type } from '@angular/core';
|
|
||||||
import { Translate, makeSingleton } from '@singletons';
|
|
||||||
import { CoreFormFields } from '@singletons/form';
|
|
||||||
import { AddonModWorkshopAssessmentStrategyRubricComponent } from '../component/rubric';
|
|
||||||
|
|
||||||
/**
|
export class AddonModWorkshopAssessmentStrategyRubricHandlerService {
|
||||||
* Handler for rubric assessment strategy plugin.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopAssessmentStrategyRubricHandlerService implements AddonWorkshopAssessmentStrategyHandler {
|
|
||||||
|
|
||||||
name = 'AddonModWorkshopAssessmentStrategyRubric';
|
name = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_NAME;
|
||||||
strategyName = 'rubric';
|
strategyName = ADDON_MOD_WORKSHOP_ASSESSMENT_STRATEGY_RUBRIC_STRATEGY_NAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async isEnabled(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
getComponent(): Type<unknown> {
|
|
||||||
return AddonModWorkshopAssessmentStrategyRubricComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async getOriginalValues(
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<AddonModWorkshopGetAssessmentFormFieldsParsedData[]> {
|
|
||||||
const originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[] = [];
|
|
||||||
|
|
||||||
form.fields.forEach((field, n) => {
|
|
||||||
field.dimtitle = Translate.instant('addon.mod_workshop_assessment_rubric.dimensionnumber', { $a: field.number });
|
|
||||||
|
|
||||||
if (!form.current[n]) {
|
|
||||||
form.current[n] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValues[n] = {};
|
|
||||||
originalValues[n].chosenlevelid = form.current[n].chosenlevelid || '';
|
|
||||||
originalValues[n].number = field.number; // eslint-disable-line id-blacklist
|
|
||||||
});
|
|
||||||
|
|
||||||
return originalValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
hasDataChanged(
|
|
||||||
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
): boolean {
|
|
||||||
for (const x in originalValues) {
|
|
||||||
if (originalValues[x].chosenlevelid != (currentValues[x].chosenlevelid || '')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async prepareAssessmentData(
|
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
|
||||||
form: AddonModWorkshopGetAssessmentFormDefinitionData,
|
|
||||||
): Promise<CoreFormFields> {
|
|
||||||
const data: CoreFormFields = {};
|
|
||||||
const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
|
|
||||||
let hasErrors = false;
|
|
||||||
|
|
||||||
form.fields.forEach((field, idx) => {
|
|
||||||
if (idx < form.dimenssionscount) {
|
|
||||||
const id = parseInt(currentValues[idx].chosenlevelid, 10);
|
|
||||||
if (!isNaN(id) && id >= 0) {
|
|
||||||
data['chosenlevelid__idx_' + idx] = id;
|
|
||||||
} else {
|
|
||||||
errors['chosenlevelid_' + idx] = 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) {
|
|
||||||
throw errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopAssessmentStrategyRubricHandler =
|
|
||||||
makeSingleton(AddonModWorkshopAssessmentStrategyRubricHandlerService);
|
/**
|
||||||
|
* Get assessment strategy handler instance.
|
||||||
|
*
|
||||||
|
* @returns Assessment strategy handler.
|
||||||
|
*/
|
||||||
|
export function getAssessmentStrategyHandlerInstance(): AddonWorkshopAssessmentStrategyHandler {
|
||||||
|
const lazyHandler = asyncInstance(async () => {
|
||||||
|
const { AddonModWorkshopAssessmentStrategyRubricHandler } = await import('./handler-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopAssessmentStrategyRubricHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopAssessmentStrategyRubricHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import {
|
||||||
} from '../../services/workshop';
|
} from '../../services/workshop';
|
||||||
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionAssessmentWithFormData } from '../../services/workshop-helper';
|
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionAssessmentWithFormData } from '../../services/workshop-helper';
|
||||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays workshop assessment strategy form.
|
* Component that displays workshop assessment strategy form.
|
||||||
|
@ -75,7 +76,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
feedbackControl = new FormControl();
|
feedbackControl = new FormControl();
|
||||||
overallFeedkback = false;
|
overallFeedkback = false;
|
||||||
overallFeedkbackRequired = false;
|
overallFeedkbackRequired = false;
|
||||||
component = AddonModWorkshopProvider.COMPONENT;
|
component = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
componentId?: number;
|
componentId?: number;
|
||||||
weights: number[] = [];
|
weights: number[] = [];
|
||||||
weight?: number;
|
weight?: number;
|
||||||
|
@ -110,7 +111,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
this.data.moduleId = this.workshop.coursemodule;
|
this.data.moduleId = this.workshop.coursemodule;
|
||||||
this.data.courseId = this.workshop.course;
|
this.data.courseId = this.workshop.course;
|
||||||
|
|
||||||
this.componentClass = AddonWorkshopAssessmentStrategyDelegate.getComponentForPlugin(this.strategy);
|
this.componentClass = await AddonWorkshopAssessmentStrategyDelegate.getComponentForPlugin(this.strategy);
|
||||||
if (this.componentClass) {
|
if (this.componentClass) {
|
||||||
this.overallFeedkback = this.workshop.overallfeedbackmode != AddonModWorkshopOverallFeedbackMode.DISABLED;
|
this.overallFeedkback = this.workshop.overallfeedbackmode != AddonModWorkshopOverallFeedbackMode.DISABLED;
|
||||||
this.overallFeedkbackRequired =
|
this.overallFeedkbackRequired =
|
||||||
|
@ -128,7 +129,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
// Check if rich text editor is enabled.
|
// Check if rich text editor is enabled.
|
||||||
if (this.edit) {
|
if (this.edit) {
|
||||||
// Block the workshop.
|
// Block the workshop.
|
||||||
CoreSync.blockOperation(AddonModWorkshopProvider.COMPONENT, this.workshop.id);
|
CoreSync.blockOperation(ADDON_MOD_WORKSHOP_COMPONENT, this.workshop.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -232,7 +233,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
this.originalData.selectedValues = CoreUtils.clone(this.data.selectedValues);
|
this.originalData.selectedValues = CoreUtils.clone(this.data.selectedValues);
|
||||||
if (this.edit) {
|
if (this.edit) {
|
||||||
CoreFileSession.setFiles(
|
CoreFileSession.setFiles(
|
||||||
AddonModWorkshopProvider.COMPONENT,
|
ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
this.workshop.id + '_' + this.assessmentId,
|
this.workshop.id + '_' + this.assessmentId,
|
||||||
this.data.assessment.feedbackattachmentfiles,
|
this.data.assessment.feedbackattachmentfiles,
|
||||||
);
|
);
|
||||||
|
@ -265,7 +266,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
|
|
||||||
// Compare feedback files.
|
// Compare feedback files.
|
||||||
const files = CoreFileSession.getFiles(
|
const files = CoreFileSession.getFiles(
|
||||||
AddonModWorkshopProvider.COMPONENT,
|
ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
this.workshop.id + '_' + this.assessmentId,
|
this.workshop.id + '_' + this.assessmentId,
|
||||||
) || [];
|
) || [];
|
||||||
if (CoreFileUploader.areFileListDifferent(files, this.originalData.files)) {
|
if (CoreFileUploader.areFileListDifferent(files, this.originalData.files)) {
|
||||||
|
@ -290,7 +291,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
|
||||||
}
|
}
|
||||||
|
|
||||||
const files = CoreFileSession.getFiles(
|
const files = CoreFileSession.getFiles(
|
||||||
AddonModWorkshopProvider.COMPONENT,
|
ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
this.workshop.id + '_' + this.assessmentId,
|
this.workshop.id + '_' + this.assessmentId,
|
||||||
) || [];
|
) || [];
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { AddonModWorkshopSubmissionComponent } from './submission/submission';
|
||||||
import { CoreCourseComponentsModule } from '@features/course/components/components.module';
|
import { CoreCourseComponentsModule } from '@features/course/components/components.module';
|
||||||
import { CoreEditorComponentsModule } from '@features/editor/components/components.module';
|
import { CoreEditorComponentsModule } from '@features/editor/components/components.module';
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
|
import { AddonModWorkshopAssessmentComponentsModule } from '@addons/mod/workshop/assessment/assesment-components.module';
|
||||||
import { AddonModWorkshopPhaseInfoComponent } from './phase/phase';
|
import { AddonModWorkshopPhaseInfoComponent } from './phase/phase';
|
||||||
import { AddonModWorkshopAssessmentComponent } from './assessment/assessment';
|
import { AddonModWorkshopAssessmentComponent } from './assessment/assessment';
|
||||||
import { AddonModWorkshopAssessmentStrategyComponent } from './assessment-strategy/assessment-strategy';
|
import { AddonModWorkshopAssessmentStrategyComponent } from './assessment-strategy/assessment-strategy';
|
||||||
|
@ -34,6 +35,7 @@ import { AddonModWorkshopAssessmentStrategyComponent } from './assessment-strate
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
CoreCourseComponentsModule,
|
CoreCourseComponentsModule,
|
||||||
CoreEditorComponentsModule,
|
CoreEditorComponentsModule,
|
||||||
|
AddonModWorkshopAssessmentComponentsModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
AddonModWorkshopIndexComponent,
|
AddonModWorkshopIndexComponent,
|
||||||
|
|
|
@ -25,7 +25,6 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { AddonModWorkshopModuleHandlerService } from '../../services/handlers/module';
|
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopProvider,
|
AddonModWorkshopProvider,
|
||||||
AddonModWorkshopPhase,
|
AddonModWorkshopPhase,
|
||||||
|
@ -53,6 +52,7 @@ import {
|
||||||
AddonModWorkshopSyncResult,
|
AddonModWorkshopSyncResult,
|
||||||
} from '../../services/workshop-sync';
|
} from '../../services/workshop-sync';
|
||||||
import { AddonModWorkshopPhaseInfoComponent } from '../phase/phase';
|
import { AddonModWorkshopPhaseInfoComponent } from '../phase/phase';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT, ADDON_MOD_WORKSHOP_PAGE_NAME } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a workshop index page.
|
* Component that displays a workshop index page.
|
||||||
|
@ -65,7 +65,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
|
||||||
|
|
||||||
@Input() group = 0;
|
@Input() group = 0;
|
||||||
|
|
||||||
component = AddonModWorkshopProvider.COMPONENT;
|
component = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
pluginName = 'workshop';
|
pluginName = 'workshop';
|
||||||
|
|
||||||
workshop?: AddonModWorkshopData;
|
workshop?: AddonModWorkshopData;
|
||||||
|
@ -379,7 +379,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
|
||||||
|
|
||||||
const submissionId = this.submission?.id || 0;
|
const submissionId = this.submission?.id || 0;
|
||||||
CoreNavigator.navigateToSitePath(
|
CoreNavigator.navigateToSitePath(
|
||||||
AddonModWorkshopModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.module.id}/${submissionId}/edit`,
|
`${ADDON_MOD_WORKSHOP_PAGE_NAME}/${this.courseId}/${this.module.id}/${submissionId}/edit`,
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,7 @@ import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { AddonModWorkshopSubmissionPage } from '../../pages/submission/submission';
|
import { AddonModWorkshopSubmissionPage } from '../../pages/submission/submission';
|
||||||
import { AddonModWorkshopModuleHandlerService } from '../../services/handlers/module';
|
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopProvider,
|
|
||||||
AddonModWorkshopPhase,
|
AddonModWorkshopPhase,
|
||||||
AddonModWorkshopData,
|
AddonModWorkshopData,
|
||||||
AddonModWorkshopGetWorkshopAccessInformationWSResponse,
|
AddonModWorkshopGetWorkshopAccessInformationWSResponse,
|
||||||
|
@ -32,6 +30,7 @@ import {
|
||||||
AddonModWorkshopSubmissionDataWithOfflineData,
|
AddonModWorkshopSubmissionDataWithOfflineData,
|
||||||
} from '../../services/workshop-helper';
|
} from '../../services/workshop-helper';
|
||||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT, ADDON_MOD_WORKSHOP_PAGE_NAME } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays workshop submission.
|
* Component that displays workshop submission.
|
||||||
|
@ -51,7 +50,7 @@ export class AddonModWorkshopSubmissionComponent implements OnInit {
|
||||||
@Input() assessment?: AddonModWorkshopSubmissionAssessmentWithFormData;
|
@Input() assessment?: AddonModWorkshopSubmissionAssessmentWithFormData;
|
||||||
@Input() summary = false;
|
@Input() summary = false;
|
||||||
|
|
||||||
component = AddonModWorkshopProvider.COMPONENT;
|
component = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
componentId?: number;
|
componentId?: number;
|
||||||
userId: number;
|
userId: number;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
@ -128,7 +127,7 @@ export class AddonModWorkshopSubmissionComponent implements OnInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
CoreNavigator.navigateToSitePath(
|
CoreNavigator.navigateToSitePath(
|
||||||
AddonModWorkshopModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.module.id}/${this.submission.id}`,
|
`${ADDON_MOD_WORKSHOP_PAGE_NAME}/${this.courseId}/${this.module.id}/${this.submission.id}`,
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_COMPONENT = 'mmaModWorkshop';
|
||||||
|
|
||||||
|
// Routing.
|
||||||
|
export const ADDON_MOD_WORKSHOP_PAGE_NAME = 'mod_workshop';
|
||||||
|
|
||||||
|
// Handlers.
|
||||||
|
export const ADDON_MOD_WORKSHOP_PREFETCH_NAME = 'AddonModWorkshop';
|
||||||
|
export const ADDON_MOD_WORKSHOP_PREFETCH_MODNAME = 'workshop';
|
||||||
|
export const ADDON_MOD_WORKSHOP_PREFETCH_COMPONENT = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
|
export const ADDON_MOD_WORKSHOP_PREFETCH_UPDATE_NAMES = new RegExp(
|
||||||
|
[
|
||||||
|
'^configuration$',
|
||||||
|
'^.*files$',
|
||||||
|
'^completion',
|
||||||
|
'^gradeitems$',
|
||||||
|
'^outcomes$',
|
||||||
|
'^submissions$',
|
||||||
|
'^assessments$' +
|
||||||
|
'^assessmentgrades$',
|
||||||
|
'^usersubmissions$',
|
||||||
|
'^userassessments$',
|
||||||
|
'^userassessmentgrades$',
|
||||||
|
'^userassessmentgrades$',
|
||||||
|
].join('|'),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ADDON_MOD_WORKSHOP_SYNC_CRON_NAME = 'AddonModWorkshopSyncCronHandler';
|
|
@ -41,6 +41,7 @@ import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||||
import { AddonModWorkshopSyncProvider } from '../../services/workshop-sync';
|
import { AddonModWorkshopSyncProvider } from '../../services/workshop-sync';
|
||||||
import { CoreTime } from '@singletons/time';
|
import { CoreTime } from '@singletons/time';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a workshop assessment.
|
* Page that displays a workshop assessment.
|
||||||
|
@ -198,7 +199,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy, CanLea
|
||||||
if (this.assessmentId && (this.access.canallocate || this.access.canoverridegrades)) {
|
if (this.assessmentId && (this.access.canallocate || this.access.canoverridegrades)) {
|
||||||
if (!this.isDestroyed) {
|
if (!this.isDestroyed) {
|
||||||
// Block the workshop.
|
// Block the workshop.
|
||||||
CoreSync.blockOperation(AddonModWorkshopProvider.COMPONENT, this.workshopId);
|
CoreSync.blockOperation(ADDON_MOD_WORKSHOP_COMPONENT, this.workshopId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.evaluating = true;
|
this.evaluating = true;
|
||||||
|
@ -413,7 +414,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy, CanLea
|
||||||
|
|
||||||
this.syncObserver?.off();
|
this.syncObserver?.off();
|
||||||
// Restore original back functions.
|
// Restore original back functions.
|
||||||
CoreSync.unblockOperation(AddonModWorkshopProvider.COMPONENT, this.workshopId);
|
CoreSync.unblockOperation(ADDON_MOD_WORKSHOP_COMPONENT, this.workshopId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import {
|
||||||
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionDataWithOfflineData } from '../../services/workshop-helper';
|
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionDataWithOfflineData } from '../../services/workshop-helper';
|
||||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the workshop edit submission.
|
* Page that displays the workshop edit submission.
|
||||||
|
@ -59,7 +60,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
|
||||||
submission?: AddonModWorkshopSubmissionDataWithOfflineData;
|
submission?: AddonModWorkshopSubmissionDataWithOfflineData;
|
||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
component = AddonModWorkshopProvider.COMPONENT;
|
component = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
componentId!: number;
|
componentId!: number;
|
||||||
editForm: FormGroup; // The form group.
|
editForm: FormGroup; // The form group.
|
||||||
editorExtraParams: Record<string, unknown> = {}; // Extra params to identify the draft.
|
editorExtraParams: Record<string, unknown> = {}; // Extra params to identify the draft.
|
||||||
|
|
|
@ -49,6 +49,7 @@ import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||||
import { AddonModWorkshopSyncProvider, AddonModWorkshopAutoSyncData } from '../../services/workshop-sync';
|
import { AddonModWorkshopSyncProvider, AddonModWorkshopAutoSyncData } from '../../services/workshop-sync';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
import { CoreTime } from '@singletons/time';
|
import { CoreTime } from '@singletons/time';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a workshop submission.
|
* Page that displays a workshop submission.
|
||||||
|
@ -99,7 +100,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
|
||||||
};
|
};
|
||||||
|
|
||||||
protected hasOffline = false;
|
protected hasOffline = false;
|
||||||
protected component = AddonModWorkshopProvider.COMPONENT;
|
protected component = ADDON_MOD_WORKSHOP_COMPONENT;
|
||||||
protected forceLeave = false;
|
protected forceLeave = false;
|
||||||
protected obsAssessmentSaved: CoreEventObserver;
|
protected obsAssessmentSaved: CoreEventObserver;
|
||||||
protected syncObserver: CoreEventObserver;
|
protected syncObserver: CoreEventObserver;
|
||||||
|
|
|
@ -34,7 +34,7 @@ export interface AddonWorkshopAssessmentStrategyHandler extends CoreDelegateHand
|
||||||
* @param injector Injector.
|
* @param injector Injector.
|
||||||
* @returns The component (or promise resolved with component) to use, undefined if not found.
|
* @returns The component (or promise resolved with component) to use, undefined if not found.
|
||||||
*/
|
*/
|
||||||
getComponent?(): Type<unknown>;
|
getComponent?(): Promise<Type<unknown>> | Type<unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare original values to be shown and compared.
|
* Prepare original values to be shown and compared.
|
||||||
|
@ -58,7 +58,7 @@ export interface AddonWorkshopAssessmentStrategyHandler extends CoreDelegateHand
|
||||||
hasDataChanged?(
|
hasDataChanged?(
|
||||||
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
originalValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
|
||||||
): boolean;
|
): Promise<boolean> | boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare assessment data to be sent to the server depending on the strategy selected.
|
* Prepare assessment data to be sent to the server depending on the strategy selected.
|
||||||
|
@ -102,7 +102,7 @@ export class AddonWorkshopAssessmentStrategyDelegateService extends CoreDelegate
|
||||||
* @param workshopStrategy Assessment strategy name.
|
* @param workshopStrategy Assessment strategy name.
|
||||||
* @returns The component, undefined if not found.
|
* @returns The component, undefined if not found.
|
||||||
*/
|
*/
|
||||||
getComponentForPlugin(workshopStrategy: string): Type<unknown> | undefined {
|
getComponentForPlugin(workshopStrategy: string): Promise<Type<unknown>> | Type<unknown> | undefined {
|
||||||
return this.executeFunctionOnEnabled(workshopStrategy, 'getComponent');
|
return this.executeFunctionOnEnabled(workshopStrategy, 'getComponent');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler';
|
import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonModWorkshopProvider } from '../workshop';
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to treat links to workshop.
|
* Handler to treat links to workshop.
|
||||||
*/
|
*/
|
||||||
|
@ -25,7 +26,7 @@ export class AddonModWorkshopIndexLinkHandlerService extends CoreContentLinksMod
|
||||||
name = 'AddonModWorkshopLinkHandler';
|
name = 'AddonModWorkshopLinkHandler';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(AddonModWorkshopProvider.COMPONENT, 'workshop', 'w');
|
super(ADDON_MOD_WORKSHOP_COMPONENT, 'workshop', 'w');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CoreConstants, ModPurpose } from '@/core/constants';
|
import { CoreConstants, ModPurpose } from '@/core/constants';
|
||||||
|
import { ADDON_MOD_WORKSHOP_PAGE_NAME } from '@addons/mod/workshop/constants';
|
||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
||||||
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonModWorkshopIndexComponent } from '../../components/index';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to support workshop modules.
|
* Handler to support workshop modules.
|
||||||
|
@ -25,11 +25,9 @@ import { AddonModWorkshopIndexComponent } from '../../components/index';
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AddonModWorkshopModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
|
export class AddonModWorkshopModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
|
||||||
|
|
||||||
static readonly PAGE_NAME = 'mod_workshop';
|
|
||||||
|
|
||||||
name = 'AddonModWorkshop';
|
name = 'AddonModWorkshop';
|
||||||
modName = 'workshop';
|
modName = 'workshop';
|
||||||
protected pageName = AddonModWorkshopModuleHandlerService.PAGE_NAME;
|
protected pageName = ADDON_MOD_WORKSHOP_PAGE_NAME;
|
||||||
|
|
||||||
supportedFeatures = {
|
supportedFeatures = {
|
||||||
[CoreConstants.FEATURE_GROUPS]: true,
|
[CoreConstants.FEATURE_GROUPS]: true,
|
||||||
|
@ -47,6 +45,8 @@ export class AddonModWorkshopModuleHandlerService extends CoreModuleHandlerBase
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async getMainComponent(): Promise<Type<unknown>> {
|
async getMainComponent(): Promise<Type<unknown>> {
|
||||||
|
const { AddonModWorkshopIndexComponent } = await import('@addons/mod/workshop/components/index');
|
||||||
|
|
||||||
return AddonModWorkshopIndexComponent;
|
return AddonModWorkshopIndexComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { AddonModDataSyncResult } from '@addons/mod/data/services/data-sync';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course';
|
||||||
|
import { CoreCourses } from '@features/courses/services/courses';
|
||||||
|
import { CoreUser } from '@features/user/services/user';
|
||||||
|
import { CoreFilepool } from '@services/filepool';
|
||||||
|
import { CoreGroup, CoreGroups } from '@services/groups';
|
||||||
|
import { CoreSites, CoreSitesReadingStrategy, CoreSitesCommonWSOptions } from '@services/sites';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { CoreWSExternalFile, CoreWSFile } from '@services/ws';
|
||||||
|
import { makeSingleton } from '@singletons';
|
||||||
|
import {
|
||||||
|
AddonModWorkshop,
|
||||||
|
AddonModWorkshopPhase,
|
||||||
|
AddonModWorkshopGradesData,
|
||||||
|
AddonModWorkshopData,
|
||||||
|
AddonModWorkshopGetWorkshopAccessInformationWSResponse,
|
||||||
|
} from '../workshop';
|
||||||
|
import { AddonModWorkshopHelper } from '../workshop-helper';
|
||||||
|
import { AddonModWorkshopSync } from '../workshop-sync';
|
||||||
|
import { AddonModWorkshopPrefetchHandlerService } from '@addons/mod/workshop/services/handlers/prefetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to prefetch workshops.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopPrefetchHandlerLazyService extends AddonModWorkshopPrefetchHandlerService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getFiles(module: CoreCourseAnyModuleData, courseId: number): Promise<CoreWSFile[]> {
|
||||||
|
const info = await this.getWorkshopInfoHelper(module, courseId, { omitFail: true });
|
||||||
|
|
||||||
|
return info.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get all workshop info just once.
|
||||||
|
*
|
||||||
|
* @param module Module to get the files.
|
||||||
|
* @param courseId Course ID the module belongs to.
|
||||||
|
* @param options Other options.
|
||||||
|
* @returns Promise resolved with the info fetched.
|
||||||
|
*/
|
||||||
|
protected async getWorkshopInfoHelper(
|
||||||
|
module: CoreCourseAnyModuleData,
|
||||||
|
courseId: number,
|
||||||
|
options: AddonModWorkshopGetInfoOptions = {},
|
||||||
|
): Promise<{ workshop?: AddonModWorkshopData; groups: CoreGroup[]; files: CoreWSFile[]}> {
|
||||||
|
let groups: CoreGroup[] = [];
|
||||||
|
let files: CoreWSFile[] = [];
|
||||||
|
let workshop: AddonModWorkshopData;
|
||||||
|
let access: AddonModWorkshopGetWorkshopAccessInformationWSResponse | undefined;
|
||||||
|
|
||||||
|
const modOptions = {
|
||||||
|
cmId: module.id,
|
||||||
|
...options, // Include all options.
|
||||||
|
};
|
||||||
|
|
||||||
|
const site = await CoreSites.getSite(options.siteId);
|
||||||
|
options.siteId = options.siteId ?? site.getId();
|
||||||
|
const userId = site.getUserId();
|
||||||
|
|
||||||
|
try {
|
||||||
|
workshop = await AddonModWorkshop.getWorkshop(courseId, module.id, options);
|
||||||
|
} catch (error) {
|
||||||
|
if (options.omitFail) {
|
||||||
|
// Any error, return the info we have.
|
||||||
|
return {
|
||||||
|
groups: [],
|
||||||
|
files: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
files = this.getIntroFilesFromInstance(module, workshop);
|
||||||
|
files = files.concat(workshop.instructauthorsfiles || []).concat(workshop.instructreviewersfiles || []);
|
||||||
|
|
||||||
|
access = await AddonModWorkshop.getWorkshopAccessInformation(workshop.id, modOptions);
|
||||||
|
if (access.canviewallsubmissions) {
|
||||||
|
const groupInfo = await CoreGroups.getActivityGroupInfo(module.id, false, undefined, options.siteId);
|
||||||
|
if (!groupInfo.groups || groupInfo.groups.length == 0) {
|
||||||
|
groupInfo.groups = [{ id: 0, name: '' }];
|
||||||
|
}
|
||||||
|
groups = groupInfo.groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
const phases = await AddonModWorkshop.getUserPlanPhases(workshop.id, modOptions);
|
||||||
|
|
||||||
|
// Get submission phase info.
|
||||||
|
const submissionPhase = phases[AddonModWorkshopPhase.PHASE_SUBMISSION];
|
||||||
|
const canSubmit = AddonModWorkshopHelper.canSubmit(workshop, access, submissionPhase.tasks);
|
||||||
|
const canAssess = AddonModWorkshopHelper.canAssess(workshop, access);
|
||||||
|
|
||||||
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
if (canSubmit) {
|
||||||
|
promises.push(AddonModWorkshopHelper.getUserSubmission(workshop.id, {
|
||||||
|
userId,
|
||||||
|
cmId: module.id,
|
||||||
|
}).then((submission) => {
|
||||||
|
if (submission) {
|
||||||
|
files = files.concat(submission.contentfiles || []).concat(submission.attachmentfiles || []);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access.canviewallsubmissions && workshop.phase >= AddonModWorkshopPhase.PHASE_SUBMISSION) {
|
||||||
|
promises.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions).then(async (submissions) => {
|
||||||
|
|
||||||
|
await Promise.all(submissions.map(async (submission) => {
|
||||||
|
files = files.concat(submission.contentfiles || []).concat(submission.attachmentfiles || []);
|
||||||
|
|
||||||
|
const assessments = await AddonModWorkshop.getSubmissionAssessments(workshop.id, submission.id, {
|
||||||
|
cmId: module.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
assessments.forEach((assessment) => {
|
||||||
|
files = files.concat(assessment.feedbackattachmentfiles)
|
||||||
|
.concat(assessment.feedbackcontentfiles);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
||||||
|
await Promise.all(assessments.map((assessment) =>
|
||||||
|
AddonModWorkshopHelper.getReviewerAssessmentById(workshop.id, assessment.id)));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get assessment files.
|
||||||
|
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
||||||
|
promises.push(AddonModWorkshopHelper.getReviewerAssessments(workshop.id, modOptions).then((assessments) => {
|
||||||
|
assessments.forEach((assessment) => {
|
||||||
|
files = files.concat(<CoreWSExternalFile[]>assessment.feedbackattachmentfiles)
|
||||||
|
.concat(assessment.feedbackcontentfiles);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
return {
|
||||||
|
workshop,
|
||||||
|
groups,
|
||||||
|
files: files.filter((file) => file !== undefined),
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
if (options.omitFail) {
|
||||||
|
// Any error, return the info we have.
|
||||||
|
return {
|
||||||
|
workshop,
|
||||||
|
groups,
|
||||||
|
files: files.filter((file) => file !== undefined),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async invalidateContent(moduleId: number, courseId: number): Promise<void> {
|
||||||
|
await AddonModWorkshop.invalidateContent(moduleId, courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a module can be downloaded. If the function is not defined, we assume that all modules are downloadable.
|
||||||
|
*
|
||||||
|
* @param module Module.
|
||||||
|
* @param courseId Course ID the module belongs to.
|
||||||
|
* @returns Whether the module can be downloaded. The promise should never be rejected.
|
||||||
|
*/
|
||||||
|
async isDownloadable(module: CoreCourseAnyModuleData, courseId: number): Promise<boolean> {
|
||||||
|
const workshop = await AddonModWorkshop.getWorkshop(courseId, module.id, {
|
||||||
|
readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE,
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessData = await AddonModWorkshop.getWorkshopAccessInformation(workshop.id, { cmId: module.id });
|
||||||
|
|
||||||
|
// Check if workshop is setup by phase.
|
||||||
|
return accessData.canswitchphase || workshop.phase > AddonModWorkshopPhase.PHASE_SETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
||||||
|
return this.prefetchPackage(module, courseId, (siteId) => this.prefetchWorkshop(module, courseId, siteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the grades reports for all the groups and then returns only unique grades.
|
||||||
|
*
|
||||||
|
* @param workshopId Workshop ID.
|
||||||
|
* @param groups Array of groups in the activity.
|
||||||
|
* @param cmId Module ID.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @returns All unique entries.
|
||||||
|
*/
|
||||||
|
protected async getAllGradesReport(
|
||||||
|
workshopId: number,
|
||||||
|
groups: CoreGroup[],
|
||||||
|
cmId: number,
|
||||||
|
siteId: string,
|
||||||
|
): Promise<AddonModWorkshopGradesData[]> {
|
||||||
|
const promises: Promise<AddonModWorkshopGradesData[]>[] = [];
|
||||||
|
|
||||||
|
groups.forEach((group) => {
|
||||||
|
promises.push(AddonModWorkshop.fetchAllGradeReports(workshopId, { groupId: group.id, cmId, siteId }));
|
||||||
|
});
|
||||||
|
|
||||||
|
const grades = await Promise.all(promises);
|
||||||
|
const uniqueGrades: Record<number, AddonModWorkshopGradesData> = {};
|
||||||
|
|
||||||
|
grades.forEach((groupGrades) => {
|
||||||
|
groupGrades.forEach((grade) => {
|
||||||
|
if (grade.submissionid) {
|
||||||
|
uniqueGrades[grade.submissionid] = grade;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return CoreUtils.objectToArray(uniqueGrades);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch a workshop.
|
||||||
|
*
|
||||||
|
* @param module The module object returned by WS.
|
||||||
|
* @param courseId Course ID the module belongs to.
|
||||||
|
* @param siteId Site ID.
|
||||||
|
* @returns Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async prefetchWorkshop(module: CoreCourseAnyModuleData, courseId: number, siteId: string): Promise<void> {
|
||||||
|
const userIds: number[] = [];
|
||||||
|
const commonOptions = {
|
||||||
|
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
|
||||||
|
siteId,
|
||||||
|
};
|
||||||
|
const modOptions = {
|
||||||
|
cmId: module.id,
|
||||||
|
...commonOptions, // Include all common options.
|
||||||
|
};
|
||||||
|
|
||||||
|
const site = await CoreSites.getSite(siteId);
|
||||||
|
const currentUserId = site.getUserId();
|
||||||
|
|
||||||
|
// Prefetch the workshop data.
|
||||||
|
const info = await this.getWorkshopInfoHelper(module, courseId, commonOptions);
|
||||||
|
if (!info.workshop) {
|
||||||
|
// It would throw an exception so it would not happen.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workshop = info.workshop;
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
const assessmentIds: number[] = [];
|
||||||
|
|
||||||
|
promises.push(CoreFilepool.addFilesToQueue(siteId, info.files, this.component, module.id));
|
||||||
|
|
||||||
|
promises.push(AddonModWorkshop.getWorkshopAccessInformation(workshop.id, modOptions).then(async (access) => {
|
||||||
|
const phases = await AddonModWorkshop.getUserPlanPhases(workshop.id, modOptions);
|
||||||
|
|
||||||
|
// Get submission phase info.
|
||||||
|
const submissionPhase = phases[AddonModWorkshopPhase.PHASE_SUBMISSION];
|
||||||
|
const canSubmit = AddonModWorkshopHelper.canSubmit(workshop, access, submissionPhase.tasks);
|
||||||
|
const canAssess = AddonModWorkshopHelper.canAssess(workshop, access);
|
||||||
|
const promises2: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
if (canSubmit) {
|
||||||
|
promises2.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions));
|
||||||
|
// Add userId to the profiles to prefetch.
|
||||||
|
userIds.push(currentUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
let reportPromise: Promise<unknown> = Promise.resolve();
|
||||||
|
if (access.canviewallsubmissions && workshop.phase >= AddonModWorkshopPhase.PHASE_SUBMISSION) {
|
||||||
|
// eslint-disable-next-line promise/no-nesting
|
||||||
|
reportPromise = this.getAllGradesReport(workshop.id, info.groups, module.id, siteId).then((grades) => {
|
||||||
|
grades.forEach((grade) => {
|
||||||
|
userIds.push(grade.userid);
|
||||||
|
grade.submissiongradeoverby && userIds.push(grade.submissiongradeoverby);
|
||||||
|
|
||||||
|
grade.reviewedby && grade.reviewedby.forEach((assessment) => {
|
||||||
|
userIds.push(assessment.userid);
|
||||||
|
assessmentIds[assessment.assessmentid] = assessment.assessmentid;
|
||||||
|
});
|
||||||
|
|
||||||
|
grade.reviewerof && grade.reviewerof.forEach((assessment) => {
|
||||||
|
userIds.push(assessment.userid);
|
||||||
|
assessmentIds[assessment.assessmentid] = assessment.assessmentid;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
||||||
|
// Wait the report promise to finish to override assessments array if needed.
|
||||||
|
reportPromise = reportPromise.finally(async () => {
|
||||||
|
const revAssessments = await AddonModWorkshopHelper.getReviewerAssessments(workshop.id, {
|
||||||
|
userId: currentUserId,
|
||||||
|
cmId: module.id,
|
||||||
|
siteId,
|
||||||
|
});
|
||||||
|
|
||||||
|
let files: CoreWSExternalFile[] = []; // Files in each submission.
|
||||||
|
|
||||||
|
revAssessments.forEach((assessment) => {
|
||||||
|
if (assessment.submission?.authorid == currentUserId) {
|
||||||
|
promises.push(AddonModWorkshop.getAssessment(
|
||||||
|
workshop.id,
|
||||||
|
assessment.id,
|
||||||
|
modOptions,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
userIds.push(assessment.reviewerid);
|
||||||
|
userIds.push(assessment.gradinggradeoverby);
|
||||||
|
assessmentIds[assessment.id] = assessment.id;
|
||||||
|
|
||||||
|
files = files.concat(assessment.submission?.attachmentfiles || [])
|
||||||
|
.concat(assessment.submission?.contentfiles || []);
|
||||||
|
});
|
||||||
|
|
||||||
|
await CoreFilepool.addFilesToQueue(siteId, files, this.component, module.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reportPromise = reportPromise.finally(() => {
|
||||||
|
if (assessmentIds.length > 0) {
|
||||||
|
return Promise.all(assessmentIds.map((assessmentId) =>
|
||||||
|
AddonModWorkshop.getAssessmentForm(workshop.id, assessmentId, modOptions)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
promises2.push(reportPromise);
|
||||||
|
|
||||||
|
if (workshop.phase == AddonModWorkshopPhase.PHASE_CLOSED) {
|
||||||
|
promises2.push(AddonModWorkshop.getGrades(workshop.id, modOptions));
|
||||||
|
if (access.canviewpublishedsubmissions) {
|
||||||
|
promises2.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises2);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Add Basic Info to manage links.
|
||||||
|
promises.push(CoreCourse.getModuleBasicInfoByInstance(workshop.id, 'workshop', { siteId }));
|
||||||
|
promises.push(CoreCourse.getModuleBasicGradeInfo(module.id, siteId));
|
||||||
|
|
||||||
|
// Get course data, needed to determine upload max size if it's configured to be course limit.
|
||||||
|
promises.push(CoreUtils.ignoreErrors(CoreCourses.getCourseByField('id', courseId, siteId)));
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
// Prefetch user profiles.
|
||||||
|
await CoreUser.prefetchProfiles(userIds, courseId, siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModDataSyncResult> {
|
||||||
|
return AddonModWorkshopSync.syncWorkshop(module.instance, siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopPrefetchHandler = makeSingleton(AddonModWorkshopPrefetchHandlerLazyService);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options to pass to getWorkshopInfoHelper.
|
||||||
|
*/
|
||||||
|
export type AddonModWorkshopGetInfoOptions = CoreSitesCommonWSOptions & {
|
||||||
|
omitFail?: boolean; // True to always return even if fails.
|
||||||
|
};
|
|
@ -12,401 +12,38 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { AddonModDataSyncResult } from '@addons/mod/data/services/data-sync';
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
|
|
||||||
import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course';
|
|
||||||
import { CoreCourses } from '@features/courses/services/courses';
|
|
||||||
import { CoreUser } from '@features/user/services/user';
|
|
||||||
import { CoreFilepool } from '@services/filepool';
|
|
||||||
import { CoreGroup, CoreGroups } from '@services/groups';
|
|
||||||
import { CoreSites, CoreSitesReadingStrategy, CoreSitesCommonWSOptions } from '@services/sites';
|
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
|
||||||
import { CoreWSExternalFile, CoreWSFile } from '@services/ws';
|
|
||||||
import { makeSingleton } from '@singletons';
|
|
||||||
import {
|
import {
|
||||||
AddonModWorkshopProvider,
|
ADDON_MOD_WORKSHOP_PREFETCH_COMPONENT,
|
||||||
AddonModWorkshop,
|
ADDON_MOD_WORKSHOP_PREFETCH_MODNAME,
|
||||||
AddonModWorkshopPhase,
|
ADDON_MOD_WORKSHOP_PREFETCH_NAME,
|
||||||
AddonModWorkshopGradesData,
|
ADDON_MOD_WORKSHOP_PREFETCH_UPDATE_NAMES,
|
||||||
AddonModWorkshopData,
|
} from '@addons/mod/workshop/constants';
|
||||||
AddonModWorkshopGetWorkshopAccessInformationWSResponse,
|
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
|
||||||
} from '../workshop';
|
import { CoreCourseModulePrefetchHandler } from '@features/course/services/module-prefetch-delegate';
|
||||||
import { AddonModWorkshopHelper } from '../workshop-helper';
|
|
||||||
import { AddonModWorkshopSync } from '../workshop-sync';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler to prefetch workshops.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPrefetchHandlerBase {
|
export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPrefetchHandlerBase {
|
||||||
|
|
||||||
name = 'AddonModWorkshop';
|
name = ADDON_MOD_WORKSHOP_PREFETCH_NAME;
|
||||||
modName = 'workshop';
|
modName = ADDON_MOD_WORKSHOP_PREFETCH_MODNAME;
|
||||||
component = AddonModWorkshopProvider.COMPONENT;
|
component = ADDON_MOD_WORKSHOP_PREFETCH_COMPONENT;
|
||||||
updatesNames = new RegExp('^configuration$|^.*files$|^completion|^gradeitems$|^outcomes$|^submissions$|^assessments$' +
|
updatesNames = ADDON_MOD_WORKSHOP_PREFETCH_UPDATE_NAMES;
|
||||||
'|^assessmentgrades$|^usersubmissions$|^userassessments$|^userassessmentgrades$|^userassessmentgrades$');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async getFiles(module: CoreCourseAnyModuleData, courseId: number): Promise<CoreWSFile[]> {
|
|
||||||
const info = await this.getWorkshopInfoHelper(module, courseId, { omitFail: true });
|
|
||||||
|
|
||||||
return info.files;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to get all workshop info just once.
|
|
||||||
*
|
|
||||||
* @param module Module to get the files.
|
|
||||||
* @param courseId Course ID the module belongs to.
|
|
||||||
* @param options Other options.
|
|
||||||
* @returns Promise resolved with the info fetched.
|
|
||||||
*/
|
|
||||||
protected async getWorkshopInfoHelper(
|
|
||||||
module: CoreCourseAnyModuleData,
|
|
||||||
courseId: number,
|
|
||||||
options: AddonModWorkshopGetInfoOptions = {},
|
|
||||||
): Promise<{ workshop?: AddonModWorkshopData; groups: CoreGroup[]; files: CoreWSFile[]}> {
|
|
||||||
let groups: CoreGroup[] = [];
|
|
||||||
let files: CoreWSFile[] = [];
|
|
||||||
let workshop: AddonModWorkshopData;
|
|
||||||
let access: AddonModWorkshopGetWorkshopAccessInformationWSResponse | undefined;
|
|
||||||
|
|
||||||
const modOptions = {
|
|
||||||
cmId: module.id,
|
|
||||||
...options, // Include all options.
|
|
||||||
};
|
|
||||||
|
|
||||||
const site = await CoreSites.getSite(options.siteId);
|
|
||||||
options.siteId = options.siteId ?? site.getId();
|
|
||||||
const userId = site.getUserId();
|
|
||||||
|
|
||||||
try {
|
|
||||||
workshop = await AddonModWorkshop.getWorkshop(courseId, module.id, options);
|
|
||||||
} catch (error) {
|
|
||||||
if (options.omitFail) {
|
|
||||||
// Any error, return the info we have.
|
|
||||||
return {
|
|
||||||
groups: [],
|
|
||||||
files: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
files = this.getIntroFilesFromInstance(module, workshop);
|
|
||||||
files = files.concat(workshop.instructauthorsfiles || []).concat(workshop.instructreviewersfiles || []);
|
|
||||||
|
|
||||||
access = await AddonModWorkshop.getWorkshopAccessInformation(workshop.id, modOptions);
|
|
||||||
if (access.canviewallsubmissions) {
|
|
||||||
const groupInfo = await CoreGroups.getActivityGroupInfo(module.id, false, undefined, options.siteId);
|
|
||||||
if (!groupInfo.groups || groupInfo.groups.length == 0) {
|
|
||||||
groupInfo.groups = [{ id: 0, name: '' }];
|
|
||||||
}
|
|
||||||
groups = groupInfo.groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
const phases = await AddonModWorkshop.getUserPlanPhases(workshop.id, modOptions);
|
|
||||||
|
|
||||||
// Get submission phase info.
|
|
||||||
const submissionPhase = phases[AddonModWorkshopPhase.PHASE_SUBMISSION];
|
|
||||||
const canSubmit = AddonModWorkshopHelper.canSubmit(workshop, access, submissionPhase.tasks);
|
|
||||||
const canAssess = AddonModWorkshopHelper.canAssess(workshop, access);
|
|
||||||
|
|
||||||
const promises: Promise<void>[] = [];
|
|
||||||
|
|
||||||
if (canSubmit) {
|
|
||||||
promises.push(AddonModWorkshopHelper.getUserSubmission(workshop.id, {
|
|
||||||
userId,
|
|
||||||
cmId: module.id,
|
|
||||||
}).then((submission) => {
|
|
||||||
if (submission) {
|
|
||||||
files = files.concat(submission.contentfiles || []).concat(submission.attachmentfiles || []);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access.canviewallsubmissions && workshop.phase >= AddonModWorkshopPhase.PHASE_SUBMISSION) {
|
|
||||||
promises.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions).then(async (submissions) => {
|
|
||||||
|
|
||||||
await Promise.all(submissions.map(async (submission) => {
|
|
||||||
files = files.concat(submission.contentfiles || []).concat(submission.attachmentfiles || []);
|
|
||||||
|
|
||||||
const assessments = await AddonModWorkshop.getSubmissionAssessments(workshop.id, submission.id, {
|
|
||||||
cmId: module.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
assessments.forEach((assessment) => {
|
|
||||||
files = files.concat(assessment.feedbackattachmentfiles)
|
|
||||||
.concat(assessment.feedbackcontentfiles);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
|
||||||
await Promise.all(assessments.map((assessment) =>
|
|
||||||
AddonModWorkshopHelper.getReviewerAssessmentById(workshop.id, assessment.id)));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get assessment files.
|
|
||||||
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
|
||||||
promises.push(AddonModWorkshopHelper.getReviewerAssessments(workshop.id, modOptions).then((assessments) => {
|
|
||||||
assessments.forEach((assessment) => {
|
|
||||||
files = files.concat(<CoreWSExternalFile[]>assessment.feedbackattachmentfiles)
|
|
||||||
.concat(assessment.feedbackcontentfiles);
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
return {
|
|
||||||
workshop,
|
|
||||||
groups,
|
|
||||||
files: files.filter((file) => file !== undefined),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
if (options.omitFail) {
|
|
||||||
// Any error, return the info we have.
|
|
||||||
return {
|
|
||||||
workshop,
|
|
||||||
groups,
|
|
||||||
files: files.filter((file) => file !== undefined),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async invalidateContent(moduleId: number, courseId: number): Promise<void> {
|
|
||||||
await AddonModWorkshop.invalidateContent(moduleId, courseId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a module can be downloaded. If the function is not defined, we assume that all modules are downloadable.
|
|
||||||
*
|
|
||||||
* @param module Module.
|
|
||||||
* @param courseId Course ID the module belongs to.
|
|
||||||
* @returns Whether the module can be downloaded. The promise should never be rejected.
|
|
||||||
*/
|
|
||||||
async isDownloadable(module: CoreCourseAnyModuleData, courseId: number): Promise<boolean> {
|
|
||||||
const workshop = await AddonModWorkshop.getWorkshop(courseId, module.id, {
|
|
||||||
readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE,
|
|
||||||
});
|
|
||||||
|
|
||||||
const accessData = await AddonModWorkshop.getWorkshopAccessInformation(workshop.id, { cmId: module.id });
|
|
||||||
|
|
||||||
// Check if workshop is setup by phase.
|
|
||||||
return accessData.canswitchphase || workshop.phase > AddonModWorkshopPhase.PHASE_SETUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
|
||||||
return this.prefetchPackage(module, courseId, (siteId) => this.prefetchWorkshop(module, courseId, siteId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves all the grades reports for all the groups and then returns only unique grades.
|
|
||||||
*
|
|
||||||
* @param workshopId Workshop ID.
|
|
||||||
* @param groups Array of groups in the activity.
|
|
||||||
* @param cmId Module ID.
|
|
||||||
* @param siteId Site ID. If not defined, current site.
|
|
||||||
* @returns All unique entries.
|
|
||||||
*/
|
|
||||||
protected async getAllGradesReport(
|
|
||||||
workshopId: number,
|
|
||||||
groups: CoreGroup[],
|
|
||||||
cmId: number,
|
|
||||||
siteId: string,
|
|
||||||
): Promise<AddonModWorkshopGradesData[]> {
|
|
||||||
const promises: Promise<AddonModWorkshopGradesData[]>[] = [];
|
|
||||||
|
|
||||||
groups.forEach((group) => {
|
|
||||||
promises.push(AddonModWorkshop.fetchAllGradeReports(workshopId, { groupId: group.id, cmId, siteId }));
|
|
||||||
});
|
|
||||||
|
|
||||||
const grades = await Promise.all(promises);
|
|
||||||
const uniqueGrades: Record<number, AddonModWorkshopGradesData> = {};
|
|
||||||
|
|
||||||
grades.forEach((groupGrades) => {
|
|
||||||
groupGrades.forEach((grade) => {
|
|
||||||
if (grade.submissionid) {
|
|
||||||
uniqueGrades[grade.submissionid] = grade;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return CoreUtils.objectToArray(uniqueGrades);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefetch a workshop.
|
|
||||||
*
|
|
||||||
* @param module The module object returned by WS.
|
|
||||||
* @param courseId Course ID the module belongs to.
|
|
||||||
* @param siteId Site ID.
|
|
||||||
* @returns Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async prefetchWorkshop(module: CoreCourseAnyModuleData, courseId: number, siteId: string): Promise<void> {
|
|
||||||
const userIds: number[] = [];
|
|
||||||
const commonOptions = {
|
|
||||||
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
|
|
||||||
siteId,
|
|
||||||
};
|
|
||||||
const modOptions = {
|
|
||||||
cmId: module.id,
|
|
||||||
...commonOptions, // Include all common options.
|
|
||||||
};
|
|
||||||
|
|
||||||
const site = await CoreSites.getSite(siteId);
|
|
||||||
const currentUserId = site.getUserId();
|
|
||||||
|
|
||||||
// Prefetch the workshop data.
|
|
||||||
const info = await this.getWorkshopInfoHelper(module, courseId, commonOptions);
|
|
||||||
if (!info.workshop) {
|
|
||||||
// It would throw an exception so it would not happen.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const workshop = info.workshop;
|
|
||||||
const promises: Promise<unknown>[] = [];
|
|
||||||
const assessmentIds: number[] = [];
|
|
||||||
|
|
||||||
promises.push(CoreFilepool.addFilesToQueue(siteId, info.files, this.component, module.id));
|
|
||||||
|
|
||||||
promises.push(AddonModWorkshop.getWorkshopAccessInformation(workshop.id, modOptions).then(async (access) => {
|
|
||||||
const phases = await AddonModWorkshop.getUserPlanPhases(workshop.id, modOptions);
|
|
||||||
|
|
||||||
// Get submission phase info.
|
|
||||||
const submissionPhase = phases[AddonModWorkshopPhase.PHASE_SUBMISSION];
|
|
||||||
const canSubmit = AddonModWorkshopHelper.canSubmit(workshop, access, submissionPhase.tasks);
|
|
||||||
const canAssess = AddonModWorkshopHelper.canAssess(workshop, access);
|
|
||||||
const promises2: Promise<unknown>[] = [];
|
|
||||||
|
|
||||||
if (canSubmit) {
|
|
||||||
promises2.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions));
|
|
||||||
// Add userId to the profiles to prefetch.
|
|
||||||
userIds.push(currentUserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
let reportPromise: Promise<unknown> = Promise.resolve();
|
|
||||||
if (access.canviewallsubmissions && workshop.phase >= AddonModWorkshopPhase.PHASE_SUBMISSION) {
|
|
||||||
// eslint-disable-next-line promise/no-nesting
|
|
||||||
reportPromise = this.getAllGradesReport(workshop.id, info.groups, module.id, siteId).then((grades) => {
|
|
||||||
grades.forEach((grade) => {
|
|
||||||
userIds.push(grade.userid);
|
|
||||||
grade.submissiongradeoverby && userIds.push(grade.submissiongradeoverby);
|
|
||||||
|
|
||||||
grade.reviewedby && grade.reviewedby.forEach((assessment) => {
|
|
||||||
userIds.push(assessment.userid);
|
|
||||||
assessmentIds[assessment.assessmentid] = assessment.assessmentid;
|
|
||||||
});
|
|
||||||
|
|
||||||
grade.reviewerof && grade.reviewerof.forEach((assessment) => {
|
|
||||||
userIds.push(assessment.userid);
|
|
||||||
assessmentIds[assessment.assessmentid] = assessment.assessmentid;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workshop.phase >= AddonModWorkshopPhase.PHASE_ASSESSMENT && canAssess) {
|
|
||||||
// Wait the report promise to finish to override assessments array if needed.
|
|
||||||
reportPromise = reportPromise.finally(async () => {
|
|
||||||
const revAssessments = await AddonModWorkshopHelper.getReviewerAssessments(workshop.id, {
|
|
||||||
userId: currentUserId,
|
|
||||||
cmId: module.id,
|
|
||||||
siteId,
|
|
||||||
});
|
|
||||||
|
|
||||||
let files: CoreWSExternalFile[] = []; // Files in each submission.
|
|
||||||
|
|
||||||
revAssessments.forEach((assessment) => {
|
|
||||||
if (assessment.submission?.authorid == currentUserId) {
|
|
||||||
promises.push(AddonModWorkshop.getAssessment(
|
|
||||||
workshop.id,
|
|
||||||
assessment.id,
|
|
||||||
modOptions,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
userIds.push(assessment.reviewerid);
|
|
||||||
userIds.push(assessment.gradinggradeoverby);
|
|
||||||
assessmentIds[assessment.id] = assessment.id;
|
|
||||||
|
|
||||||
files = files.concat(assessment.submission?.attachmentfiles || [])
|
|
||||||
.concat(assessment.submission?.contentfiles || []);
|
|
||||||
});
|
|
||||||
|
|
||||||
await CoreFilepool.addFilesToQueue(siteId, files, this.component, module.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
reportPromise = reportPromise.finally(() => {
|
|
||||||
if (assessmentIds.length > 0) {
|
|
||||||
return Promise.all(assessmentIds.map((assessmentId) =>
|
|
||||||
AddonModWorkshop.getAssessmentForm(workshop.id, assessmentId, modOptions)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
promises2.push(reportPromise);
|
|
||||||
|
|
||||||
if (workshop.phase == AddonModWorkshopPhase.PHASE_CLOSED) {
|
|
||||||
promises2.push(AddonModWorkshop.getGrades(workshop.id, modOptions));
|
|
||||||
if (access.canviewpublishedsubmissions) {
|
|
||||||
promises2.push(AddonModWorkshop.getSubmissions(workshop.id, modOptions));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(promises2);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Add Basic Info to manage links.
|
|
||||||
promises.push(CoreCourse.getModuleBasicInfoByInstance(workshop.id, 'workshop', { siteId }));
|
|
||||||
promises.push(CoreCourse.getModuleBasicGradeInfo(module.id, siteId));
|
|
||||||
|
|
||||||
// Get course data, needed to determine upload max size if it's configured to be course limit.
|
|
||||||
promises.push(CoreUtils.ignoreErrors(CoreCourses.getCourseByField('id', courseId, siteId)));
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
// Prefetch user profiles.
|
|
||||||
await CoreUser.prefetchProfiles(userIds, courseId, siteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModDataSyncResult> {
|
|
||||||
return AddonModWorkshopSync.syncWorkshop(module.instance, siteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopPrefetchHandler = makeSingleton(AddonModWorkshopPrefetchHandlerService);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options to pass to getWorkshopInfoHelper.
|
* Get prefetch handler instance.
|
||||||
|
*
|
||||||
|
* @returns Prefetch handler.
|
||||||
*/
|
*/
|
||||||
export type AddonModWorkshopGetInfoOptions = CoreSitesCommonWSOptions & {
|
export function getPrefetchHandlerInstance(): CoreCourseModulePrefetchHandler {
|
||||||
omitFail?: boolean; // True to always return even if fails.
|
const lazyHandler = asyncInstance(async () => {
|
||||||
};
|
const { AddonModWorkshopPrefetchHandler } = await import('./prefetch-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopPrefetchHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopPrefetchHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CoreCronHandler } from '@services/cron';
|
||||||
|
import { makeSingleton } from '@singletons';
|
||||||
|
import { AddonModWorkshopSync } from '../workshop-sync';
|
||||||
|
import { AddonModWorkshopSyncCronHandlerService } from './sync-cron';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronization cron handler.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AddonModWorkshopSyncCronHandlerLazyService
|
||||||
|
extends AddonModWorkshopSyncCronHandlerService
|
||||||
|
implements CoreCronHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
execute(siteId?: string, force?: boolean): Promise<void> {
|
||||||
|
return AddonModWorkshopSync.syncAllWorkshops(siteId, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
getInterval(): number {
|
||||||
|
return AddonModWorkshopSync.syncInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const AddonModWorkshopSyncCronHandler = makeSingleton(AddonModWorkshopSyncCronHandlerLazyService);
|
|
@ -12,32 +12,29 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
|
import { ADDON_MOD_WORKSHOP_SYNC_CRON_NAME } from '@addons/mod/workshop/constants';
|
||||||
import { CoreCronHandler } from '@services/cron';
|
import { CoreCronHandler } from '@services/cron';
|
||||||
import { makeSingleton } from '@singletons';
|
|
||||||
import { AddonModWorkshopSync } from '../workshop-sync';
|
|
||||||
|
|
||||||
/**
|
export class AddonModWorkshopSyncCronHandlerService {
|
||||||
* Synchronization cron handler.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class AddonModWorkshopSyncCronHandlerService implements CoreCronHandler {
|
|
||||||
|
|
||||||
name = 'AddonModWorkshopSyncCronHandler';
|
name = ADDON_MOD_WORKSHOP_SYNC_CRON_NAME;
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
execute(siteId?: string, force?: boolean): Promise<void> {
|
|
||||||
return AddonModWorkshopSync.syncAllWorkshops(siteId, force);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
getInterval(): number {
|
|
||||||
return AddonModWorkshopSync.syncInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export const AddonModWorkshopSyncCronHandler = makeSingleton(AddonModWorkshopSyncCronHandlerService);
|
|
||||||
|
/**
|
||||||
|
* Get cron handler instance.
|
||||||
|
*
|
||||||
|
* @returns Cron handler.
|
||||||
|
*/
|
||||||
|
export function getCronHandlerInstance(): CoreCronHandler {
|
||||||
|
const lazyHandler = asyncInstance(async () => {
|
||||||
|
const { AddonModWorkshopSyncCronHandler } = await import('./sync-cron-lazy');
|
||||||
|
|
||||||
|
return AddonModWorkshopSyncCronHandler.instance;
|
||||||
|
});
|
||||||
|
|
||||||
|
lazyHandler.setEagerInstance(new AddonModWorkshopSyncCronHandlerService());
|
||||||
|
|
||||||
|
return lazyHandler;
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import {
|
||||||
AddonModWorkshopExampleMode,
|
AddonModWorkshopExampleMode,
|
||||||
AddonModWorkshopPhase,
|
AddonModWorkshopPhase,
|
||||||
AddonModWorkshopUserOptions,
|
AddonModWorkshopUserOptions,
|
||||||
AddonModWorkshopProvider,
|
|
||||||
AddonModWorkshopData,
|
AddonModWorkshopData,
|
||||||
AddonModWorkshop,
|
AddonModWorkshop,
|
||||||
AddonModWorkshopSubmissionData,
|
AddonModWorkshopSubmissionData,
|
||||||
|
@ -42,6 +41,7 @@ import {
|
||||||
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
AddonModWorkshopGetAssessmentFormFieldsParsedData,
|
||||||
} from './workshop';
|
} from './workshop';
|
||||||
import { AddonModWorkshopOffline, AddonModWorkshopOfflineSubmission } from './workshop-offline';
|
import { AddonModWorkshopOffline, AddonModWorkshopOfflineSubmission } from './workshop-offline';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to gather some common functions for workshop.
|
* Helper to gather some common functions for workshop.
|
||||||
|
@ -293,7 +293,7 @@ export class AddonModWorkshopHelperProvider {
|
||||||
return this.storeSubmissionFiles(workshopId, files, siteId);
|
return this.storeSubmissionFiles(workshopId, files, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreFileUploader.uploadOrReuploadFiles(files, AddonModWorkshopProvider.COMPONENT, workshopId, siteId);
|
return CoreFileUploader.uploadOrReuploadFiles(files, ADDON_MOD_WORKSHOP_COMPONENT, workshopId, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -403,7 +403,7 @@ export class AddonModWorkshopHelperProvider {
|
||||||
return this.storeAssessmentFiles(workshopId, assessmentId, files, siteId);
|
return this.storeAssessmentFiles(workshopId, assessmentId, files, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreFileUploader.uploadOrReuploadFiles(files, AddonModWorkshopProvider.COMPONENT, workshopId, siteId);
|
return CoreFileUploader.uploadOrReuploadFiles(files, ADDON_MOD_WORKSHOP_COMPONENT, workshopId, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,7 +28,6 @@ import { CoreEvents } from '@singletons/events';
|
||||||
import { AddonModWorkshop,
|
import { AddonModWorkshop,
|
||||||
AddonModWorkshopAction,
|
AddonModWorkshopAction,
|
||||||
AddonModWorkshopData,
|
AddonModWorkshopData,
|
||||||
AddonModWorkshopProvider,
|
|
||||||
AddonModWorkshopSubmissionType,
|
AddonModWorkshopSubmissionType,
|
||||||
} from './workshop';
|
} from './workshop';
|
||||||
import { AddonModWorkshopHelper } from './workshop-helper';
|
import { AddonModWorkshopHelper } from './workshop-helper';
|
||||||
|
@ -38,6 +37,7 @@ import { AddonModWorkshopOffline,
|
||||||
AddonModWorkshopOfflineEvaluateSubmission,
|
AddonModWorkshopOfflineEvaluateSubmission,
|
||||||
AddonModWorkshopOfflineSubmission,
|
AddonModWorkshopOfflineSubmission,
|
||||||
} from './workshop-offline';
|
} from './workshop-offline';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to sync workshops.
|
* Service to sync workshops.
|
||||||
|
@ -136,7 +136,7 @@ export class AddonModWorkshopSyncProvider extends CoreSyncBaseProvider<AddonModW
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that workshop isn't blocked.
|
// Verify that workshop isn't blocked.
|
||||||
if (CoreSync.isBlocked(AddonModWorkshopProvider.COMPONENT, workshopId, siteId)) {
|
if (CoreSync.isBlocked(ADDON_MOD_WORKSHOP_COMPONENT, workshopId, siteId)) {
|
||||||
this.logger.debug(`Cannot sync workshop '${workshopId}' because it is blocked.`);
|
this.logger.debug(`Cannot sync workshop '${workshopId}' because it is blocked.`);
|
||||||
|
|
||||||
throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
|
throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
|
||||||
|
@ -163,7 +163,7 @@ export class AddonModWorkshopSyncProvider extends CoreSyncBaseProvider<AddonModW
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sync offline logs.
|
// Sync offline logs.
|
||||||
await CoreUtils.ignoreErrors(CoreCourseLogHelper.syncActivity(AddonModWorkshopProvider.COMPONENT, workshopId, siteId));
|
await CoreUtils.ignoreErrors(CoreCourseLogHelper.syncActivity(ADDON_MOD_WORKSHOP_COMPONENT, workshopId, siteId));
|
||||||
|
|
||||||
// Get offline submissions to be sent.
|
// Get offline submissions to be sent.
|
||||||
const syncs = await Promise.all([
|
const syncs = await Promise.all([
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreFormFields } from '@singletons/form';
|
import { CoreFormFields } from '@singletons/form';
|
||||||
import { AddonModWorkshopOffline } from './workshop-offline';
|
import { AddonModWorkshopOffline } from './workshop-offline';
|
||||||
import { AddonModWorkshopAutoSyncData, AddonModWorkshopSyncProvider } from './workshop-sync';
|
import { AddonModWorkshopAutoSyncData, AddonModWorkshopSyncProvider } from './workshop-sync';
|
||||||
|
import { ADDON_MOD_WORKSHOP_COMPONENT } from '@addons/mod/workshop/constants';
|
||||||
|
|
||||||
const ROOT_CACHE_KEY = 'mmaModWorkshop:';
|
const ROOT_CACHE_KEY = 'mmaModWorkshop:';
|
||||||
|
|
||||||
|
@ -88,7 +89,6 @@ declare module '@singletons/events' {
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AddonModWorkshopProvider {
|
export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
static readonly COMPONENT = 'mmaModWorkshop';
|
|
||||||
static readonly PER_PAGE = 10;
|
static readonly PER_PAGE = 10;
|
||||||
|
|
||||||
static readonly SUBMISSION_CHANGED = 'addon_mod_workshop_submission_changed';
|
static readonly SUBMISSION_CHANGED = 'addon_mod_workshop_submission_changed';
|
||||||
|
@ -248,7 +248,7 @@ export class AddonModWorkshopProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getWorkshopDataCacheKey(courseId),
|
cacheKey: this.getWorkshopDataCacheKey(courseId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
const response = await site.read<AddonModWorkshopGetWorkshopsByCoursesWSResponse>(
|
const response = await site.read<AddonModWorkshopGetWorkshopsByCoursesWSResponse>(
|
||||||
|
@ -345,7 +345,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getWorkshopAccessInformationDataCacheKey(workshopId),
|
cacheKey: this.getWorkshopAccessInformationDataCacheKey(workshopId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -390,7 +390,7 @@ export class AddonModWorkshopProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getUserPlanDataCacheKey(workshopId),
|
cacheKey: this.getUserPlanDataCacheKey(workshopId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -437,7 +437,7 @@ export class AddonModWorkshopProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getSubmissionsDataCacheKey(workshopId, userId, groupId),
|
cacheKey: this.getSubmissionsDataCacheKey(workshopId, userId, groupId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -483,7 +483,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getSubmissionDataCacheKey(workshopId, submissionId),
|
cacheKey: this.getSubmissionDataCacheKey(workshopId, submissionId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -523,7 +523,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getGradesDataCacheKey(workshopId),
|
cacheKey: this.getGradesDataCacheKey(workshopId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -567,7 +567,7 @@ export class AddonModWorkshopProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getGradesReportDataCacheKey(workshopId, options.groupId),
|
cacheKey: this.getGradesReportDataCacheKey(workshopId, options.groupId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
updateFrequency: CoreSite.FREQUENCY_OFTEN,
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -663,7 +663,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getSubmissionAssessmentsDataCacheKey(workshopId, submissionId),
|
cacheKey: this.getSubmissionAssessmentsDataCacheKey(workshopId, submissionId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -967,7 +967,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getReviewerAssessmentsDataCacheKey(workshopId, options.userId),
|
cacheKey: this.getReviewerAssessmentsDataCacheKey(workshopId, options.userId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1017,7 +1017,7 @@ export class AddonModWorkshopProvider {
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getAssessmentDataCacheKey(workshopId, assessmentId),
|
cacheKey: this.getAssessmentDataCacheKey(workshopId, assessmentId),
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1065,7 +1065,7 @@ export class AddonModWorkshopProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getAssessmentFormDataCacheKey(workshopId, assessmentId, mode),
|
cacheKey: this.getAssessmentFormDataCacheKey(workshopId, assessmentId, mode),
|
||||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||||
component: AddonModWorkshopProvider.COMPONENT,
|
component: ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1454,7 +1454,7 @@ export class AddonModWorkshopProvider {
|
||||||
await CoreCourseLogHelper.log(
|
await CoreCourseLogHelper.log(
|
||||||
'mod_workshop_view_workshop',
|
'mod_workshop_view_workshop',
|
||||||
params,
|
params,
|
||||||
AddonModWorkshopProvider.COMPONENT,
|
ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
id,
|
id,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
@ -1476,7 +1476,7 @@ export class AddonModWorkshopProvider {
|
||||||
await CoreCourseLogHelper.log(
|
await CoreCourseLogHelper.log(
|
||||||
'mod_workshop_view_submission',
|
'mod_workshop_view_submission',
|
||||||
params,
|
params,
|
||||||
AddonModWorkshopProvider.COMPONENT,
|
ADDON_MOD_WORKSHOP_COMPONENT,
|
||||||
workshopId,
|
workshopId,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,32 +21,51 @@ import { CoreCourseModulePrefetchDelegate } from '@features/course/services/modu
|
||||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||||
import { CoreCronDelegate } from '@services/cron';
|
import { CoreCronDelegate } from '@services/cron';
|
||||||
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
||||||
import { AddonModWorkshopAssessmentStrategyModule } from './assessment/assessment.module';
|
import { AddonModWorkshopAssessmentStrategyModule } from '@addons/mod/workshop/assessment/assessment.module';
|
||||||
import { AddonModWorkshopComponentsModule } from './components/components.module';
|
|
||||||
import { AddonWorkshopAssessmentStrategyDelegateService } from './services/assessment-strategy-delegate';
|
|
||||||
import { ADDON_MOD_WORKSHOP_OFFLINE_SITE_SCHEMA } from './services/database/workshop';
|
import { ADDON_MOD_WORKSHOP_OFFLINE_SITE_SCHEMA } from './services/database/workshop';
|
||||||
import { AddonModWorkshopIndexLinkHandler } from './services/handlers/index-link';
|
import { AddonModWorkshopIndexLinkHandler } from './services/handlers/index-link';
|
||||||
import { AddonModWorkshopListLinkHandler } from './services/handlers/list-link';
|
import { AddonModWorkshopListLinkHandler } from './services/handlers/list-link';
|
||||||
import { AddonModWorkshopModuleHandler, AddonModWorkshopModuleHandlerService } from './services/handlers/module';
|
import { AddonModWorkshopModuleHandler } from './services/handlers/module';
|
||||||
import { AddonModWorkshopPrefetchHandler } from './services/handlers/prefetch';
|
import { ADDON_MOD_WORKSHOP_COMPONENT, ADDON_MOD_WORKSHOP_PAGE_NAME } from '@addons/mod/workshop/constants';
|
||||||
import { AddonModWorkshopSyncCronHandler } from './services/handlers/sync-cron';
|
import { getCronHandlerInstance } from '@addons/mod/workshop/services/handlers/sync-cron';
|
||||||
import { AddonModWorkshopProvider } from './services/workshop';
|
import { getPrefetchHandlerInstance } from '@addons/mod/workshop/services/handlers/prefetch';
|
||||||
import { AddonModWorkshopHelperProvider } from './services/workshop-helper';
|
|
||||||
import { AddonModWorkshopOfflineProvider } from './services/workshop-offline';
|
|
||||||
import { AddonModWorkshopSyncProvider } from './services/workshop-sync';
|
|
||||||
|
|
||||||
// List of providers (without handlers).
|
/**
|
||||||
export const ADDON_MOD_WORKSHOP_SERVICES: Type<unknown>[] = [
|
* Get workshop services.
|
||||||
AddonModWorkshopProvider,
|
*
|
||||||
AddonModWorkshopOfflineProvider,
|
* @returns Workshop services.
|
||||||
AddonModWorkshopSyncProvider,
|
*/
|
||||||
AddonModWorkshopHelperProvider,
|
export async function getWorkshopServices(): Promise<Type<unknown>[]> {
|
||||||
AddonWorkshopAssessmentStrategyDelegateService,
|
const { AddonModWorkshopProvider } = await import('@addons/mod/workshop/services/workshop');
|
||||||
];
|
const { AddonModWorkshopOfflineProvider } = await import('@addons/mod/workshop/services/workshop-offline');
|
||||||
|
const { AddonModWorkshopSyncProvider } = await import('@addons/mod/workshop/services/workshop-sync');
|
||||||
|
const { AddonModWorkshopHelperProvider } = await import('@addons/mod/workshop/services/workshop-helper');
|
||||||
|
const { AddonWorkshopAssessmentStrategyDelegateService } =
|
||||||
|
await import('@addons/mod/workshop/services/assessment-strategy-delegate');
|
||||||
|
|
||||||
|
return [
|
||||||
|
AddonModWorkshopProvider,
|
||||||
|
AddonModWorkshopOfflineProvider,
|
||||||
|
AddonModWorkshopSyncProvider,
|
||||||
|
AddonModWorkshopHelperProvider,
|
||||||
|
AddonWorkshopAssessmentStrategyDelegateService,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get workshop component modules.
|
||||||
|
*
|
||||||
|
* @returns Workshop component modules.
|
||||||
|
*/
|
||||||
|
export async function getWorkshopComponentModules(): Promise<unknown[]> {
|
||||||
|
const { AddonModWorkshopComponentsModule } = await import('@addons/mod/workshop/components/components.module');
|
||||||
|
|
||||||
|
return [AddonModWorkshopComponentsModule];
|
||||||
|
}
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: AddonModWorkshopModuleHandlerService.PAGE_NAME,
|
path: ADDON_MOD_WORKSHOP_PAGE_NAME,
|
||||||
loadChildren: () => import('./workshop-lazy.module').then(m => m.AddonModWorkshopLazyModule),
|
loadChildren: () => import('./workshop-lazy.module').then(m => m.AddonModWorkshopLazyModule),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -54,7 +73,6 @@ const routes: Routes = [
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CoreMainMenuTabRoutingModule.forChild(routes),
|
CoreMainMenuTabRoutingModule.forChild(routes),
|
||||||
AddonModWorkshopComponentsModule,
|
|
||||||
AddonModWorkshopAssessmentStrategyModule,
|
AddonModWorkshopAssessmentStrategyModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -68,12 +86,12 @@ const routes: Routes = [
|
||||||
multi: true,
|
multi: true,
|
||||||
useValue: () => {
|
useValue: () => {
|
||||||
CoreCourseModuleDelegate.registerHandler(AddonModWorkshopModuleHandler.instance);
|
CoreCourseModuleDelegate.registerHandler(AddonModWorkshopModuleHandler.instance);
|
||||||
CoreCourseModulePrefetchDelegate.registerHandler(AddonModWorkshopPrefetchHandler.instance);
|
CoreCourseModulePrefetchDelegate.registerHandler(getPrefetchHandlerInstance());
|
||||||
CoreCronDelegate.register(AddonModWorkshopSyncCronHandler.instance);
|
CoreCronDelegate.register(getCronHandlerInstance());
|
||||||
CoreContentLinksDelegate.registerHandler(AddonModWorkshopIndexLinkHandler.instance);
|
CoreContentLinksDelegate.registerHandler(AddonModWorkshopIndexLinkHandler.instance);
|
||||||
CoreContentLinksDelegate.registerHandler(AddonModWorkshopListLinkHandler.instance);
|
CoreContentLinksDelegate.registerHandler(AddonModWorkshopListLinkHandler.instance);
|
||||||
|
|
||||||
CoreCourseHelper.registerModuleReminderClick(AddonModWorkshopProvider.COMPONENT);
|
CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_WORKSHOP_COMPONENT);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -126,11 +126,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
this.compiling.emit(true);
|
this.compiling.emit(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const factory = await CoreCompile.createAndCompileComponent(
|
const componentClass = await this.getComponentClass();
|
||||||
this.text,
|
const factory = await CoreCompile.createAndCompileComponent(this.text, componentClass, this.extraImports);
|
||||||
this.getComponentClass(),
|
|
||||||
this.extraImports,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Destroy previous components.
|
// Destroy previous components.
|
||||||
this.componentRef?.destroy();
|
this.componentRef?.destroy();
|
||||||
|
@ -166,9 +163,10 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
*
|
*
|
||||||
* @returns The component class.
|
* @returns The component class.
|
||||||
*/
|
*/
|
||||||
protected getComponentClass(): Type<unknown> {
|
protected async getComponentClass(): Promise<Type<unknown>> {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
const compileInstance = this;
|
const compileInstance = this;
|
||||||
|
const lazyLibraries = await CoreCompile.getLazyLibraries();
|
||||||
|
|
||||||
// Create the component, using the text as the template.
|
// Create the component, using the text as the template.
|
||||||
return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy {
|
return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy {
|
||||||
|
@ -184,7 +182,10 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
this['dataArray'] = [];
|
this['dataArray'] = [];
|
||||||
|
|
||||||
// Inject the libraries.
|
// Inject the libraries.
|
||||||
CoreCompile.injectLibraries(this, compileInstance.extraProviders);
|
CoreCompile.injectLibraries(this, [
|
||||||
|
...lazyLibraries,
|
||||||
|
...compileInstance.extraProviders,
|
||||||
|
]);
|
||||||
|
|
||||||
// Always add these elements, they could be needed on component init (componentObservable).
|
// Always add these elements, they could be needed on component init (componentObservable).
|
||||||
this['ChangeDetectorRef'] = compileInstance.changeDetector;
|
this['ChangeDetectorRef'] = compileInstance.changeDetector;
|
||||||
|
|
|
@ -149,14 +149,13 @@ import { ADDON_MOD_SCORM_SERVICES } from '@addons/mod/scorm/scorm.module';
|
||||||
import { ADDON_MOD_SURVEY_SERVICES } from '@addons/mod/survey/survey.module';
|
import { ADDON_MOD_SURVEY_SERVICES } from '@addons/mod/survey/survey.module';
|
||||||
import { ADDON_MOD_URL_SERVICES } from '@addons/mod/url/url.module';
|
import { ADDON_MOD_URL_SERVICES } from '@addons/mod/url/url.module';
|
||||||
import { ADDON_MOD_WIKI_SERVICES } from '@addons/mod/wiki/wiki.module';
|
import { ADDON_MOD_WIKI_SERVICES } from '@addons/mod/wiki/wiki.module';
|
||||||
import { ADDON_MOD_WORKSHOP_SERVICES } from '@addons/mod/workshop/workshop.module';
|
import { getWorkshopComponentModules, getWorkshopServices } from '@addons/mod/workshop/workshop.module';
|
||||||
import { ADDON_NOTES_SERVICES } from '@addons/notes/notes.module';
|
import { ADDON_NOTES_SERVICES } from '@addons/notes/notes.module';
|
||||||
import { ADDON_NOTIFICATIONS_SERVICES } from '@addons/notifications/notifications.module';
|
import { ADDON_NOTIFICATIONS_SERVICES } from '@addons/notifications/notifications.module';
|
||||||
import { ADDON_PRIVATEFILES_SERVICES } from '@addons/privatefiles/privatefiles.module';
|
import { ADDON_PRIVATEFILES_SERVICES } from '@addons/privatefiles/privatefiles.module';
|
||||||
|
|
||||||
// Import some addon modules that define components, directives and pipes. Only import the important ones.
|
// Import some addon modules that define components, directives and pipes. Only import the important ones.
|
||||||
import { AddonModAssignComponentsModule } from '@addons/mod/assign/components/components.module';
|
import { AddonModAssignComponentsModule } from '@addons/mod/assign/components/components.module';
|
||||||
import { AddonModWorkshopComponentsModule } from '@addons/mod/workshop/components/components.module';
|
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
|
|
||||||
|
@ -180,7 +179,10 @@ export class CoreCompileProvider {
|
||||||
CoreSharedModule, CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreUserComponentsModule,
|
CoreSharedModule, CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreUserComponentsModule,
|
||||||
CoreCourseDirectivesModule, CoreQuestionComponentsModule, AddonModAssignComponentsModule,
|
CoreCourseDirectivesModule, CoreQuestionComponentsModule, AddonModAssignComponentsModule,
|
||||||
CoreBlockComponentsModule, CoreEditorComponentsModule, CoreSearchComponentsModule, CoreSitePluginsDirectivesModule,
|
CoreBlockComponentsModule, CoreEditorComponentsModule, CoreSearchComponentsModule, CoreSitePluginsDirectivesModule,
|
||||||
AddonModWorkshopComponentsModule,
|
];
|
||||||
|
|
||||||
|
protected readonly LAZY_IMPORTS = [
|
||||||
|
getWorkshopComponentModules,
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(protected injector: Injector, compilerFactory: JitCompilerFactory) {
|
constructor(protected injector: Injector, compilerFactory: JitCompilerFactory) {
|
||||||
|
@ -205,7 +207,9 @@ export class CoreCompileProvider {
|
||||||
// Create the component using the template and the class.
|
// Create the component using the template and the class.
|
||||||
const component = Component({ template })(componentClass);
|
const component = Component({ template })(componentClass);
|
||||||
|
|
||||||
|
const lazyImports = await Promise.all(this.LAZY_IMPORTS.map(getModules => getModules()));
|
||||||
const imports = [
|
const imports = [
|
||||||
|
...CoreArray.flatten(lazyImports),
|
||||||
...this.IMPORTS,
|
...this.IMPORTS,
|
||||||
...extraImports,
|
...extraImports,
|
||||||
];
|
];
|
||||||
|
@ -317,7 +321,6 @@ export class CoreCompileProvider {
|
||||||
...ADDON_MOD_SURVEY_SERVICES,
|
...ADDON_MOD_SURVEY_SERVICES,
|
||||||
...ADDON_MOD_URL_SERVICES,
|
...ADDON_MOD_URL_SERVICES,
|
||||||
...ADDON_MOD_WIKI_SERVICES,
|
...ADDON_MOD_WIKI_SERVICES,
|
||||||
...ADDON_MOD_WORKSHOP_SERVICES,
|
|
||||||
...ADDON_NOTES_SERVICES,
|
...ADDON_NOTES_SERVICES,
|
||||||
...ADDON_NOTIFICATIONS_SERVICES,
|
...ADDON_NOTIFICATIONS_SERVICES,
|
||||||
...ADDON_PRIVATEFILES_SERVICES,
|
...ADDON_PRIVATEFILES_SERVICES,
|
||||||
|
@ -388,6 +391,19 @@ export class CoreCompileProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get lazy libraries to inject.
|
||||||
|
*
|
||||||
|
* @returns Lazy libraries.
|
||||||
|
*/
|
||||||
|
async getLazyLibraries(): Promise<Type<unknown>[]> {
|
||||||
|
const ADDON_MOD_WORKSHOP_SERVICES = await getWorkshopServices();
|
||||||
|
|
||||||
|
return [
|
||||||
|
...ADDON_MOD_WORKSHOP_SERVICES,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a dynamic component.
|
* Instantiate a dynamic component.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { AsyncInstance, asyncInstance } from '@/core/utils/async-instance';
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CoreNativeService {
|
export class CoreNativeService {
|
||||||
|
|
||||||
private plugins: Partial<Record<keyof MoodleAppPlugins, AsyncInstance<unknown>>> = {};
|
private plugins: Partial<Record<keyof MoodleAppPlugins, AsyncInstance>> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a native plugin instance.
|
* Get a native plugin instance.
|
||||||
|
|
|
@ -268,11 +268,13 @@ export class CoreSitePluginsHelperProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a "fake" instance to hold all the libraries.
|
// Create a "fake" instance to hold all the libraries.
|
||||||
|
const lazyLibraries = await CoreCompile.getLazyLibraries();
|
||||||
const instance = {
|
const instance = {
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
HANDLER_DISABLED: HANDLER_DISABLED,
|
HANDLER_DISABLED: HANDLER_DISABLED,
|
||||||
};
|
};
|
||||||
CoreCompile.injectLibraries(instance);
|
|
||||||
|
CoreCompile.injectLibraries(instance, lazyLibraries);
|
||||||
|
|
||||||
// Add some data of the WS call result.
|
// Add some data of the WS call result.
|
||||||
const jsData = CoreSitePlugins.createDataForJS(result);
|
const jsData = CoreSitePlugins.createDataForJS(result);
|
||||||
|
|
|
@ -212,14 +212,14 @@ export class CoreCronDelegateService {
|
||||||
* @param name Handler's name.
|
* @param name Handler's name.
|
||||||
* @returns Handler's interval.
|
* @returns Handler's interval.
|
||||||
*/
|
*/
|
||||||
protected getHandlerInterval(name: string): number {
|
protected async getHandlerInterval(name: string): Promise<number> {
|
||||||
if (this.handlers[name] === undefined) {
|
if (this.handlers[name] === undefined) {
|
||||||
// Invalid, return default.
|
// Invalid, return default.
|
||||||
return CoreCronDelegateService.DEFAULT_INTERVAL;
|
return CoreCronDelegateService.DEFAULT_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow intervals lower than the minimum.
|
// Don't allow intervals lower than the minimum.
|
||||||
const handlerInterval = this.handlers[name].getInterval?.();
|
const handlerInterval = await this.handlers[name].getInterval?.();
|
||||||
|
|
||||||
if (!handlerInterval) {
|
if (!handlerInterval) {
|
||||||
return CoreCronDelegateService.DEFAULT_INTERVAL;
|
return CoreCronDelegateService.DEFAULT_INTERVAL;
|
||||||
|
@ -365,8 +365,7 @@ export class CoreCronDelegateService {
|
||||||
if (!timeToNextExecution) {
|
if (!timeToNextExecution) {
|
||||||
// Get last execution time to check when do we need to execute it.
|
// Get last execution time to check when do we need to execute it.
|
||||||
const lastExecution = await this.getHandlerLastExecutionTime(name);
|
const lastExecution = await this.getHandlerLastExecutionTime(name);
|
||||||
|
const interval = await this.getHandlerInterval(name);
|
||||||
const interval = this.getHandlerInterval(name);
|
|
||||||
|
|
||||||
timeToNextExecution = lastExecution + interval - Date.now();
|
timeToNextExecution = lastExecution + interval - Date.now();
|
||||||
}
|
}
|
||||||
|
@ -486,7 +485,7 @@ export interface CoreCronHandler {
|
||||||
*
|
*
|
||||||
* @returns Interval time (in milliseconds).
|
* @returns Interval time (in milliseconds).
|
||||||
*/
|
*/
|
||||||
getInterval?(): number;
|
getInterval?(): number | Promise<number>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the process uses network or not. True if not defined.
|
* Check whether the process uses network or not. True if not defined.
|
||||||
|
|
|
@ -14,19 +14,28 @@
|
||||||
|
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
type AsyncObject = object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a wrapper to hold an asynchronous instance.
|
* Create a wrapper to hold an asynchronous instance.
|
||||||
*
|
*
|
||||||
* @param lazyConstructor Constructor to use the first time the instance is needed.
|
* @param lazyConstructor Constructor to use the first time the instance is needed.
|
||||||
* @returns Asynchronous instance wrapper.
|
* @returns Asynchronous instance wrapper.
|
||||||
*/
|
*/
|
||||||
function createAsyncInstanceWrapper<T>(lazyConstructor?: () => T | Promise<T>): AsyncInstanceWrapper<T> {
|
function createAsyncInstanceWrapper<TEagerInstance extends AsyncObject, TInstance extends TEagerInstance>(
|
||||||
let promisedInstance: CorePromisedValue<T> | null = null;
|
lazyConstructor?: () => TInstance | Promise<TInstance>,
|
||||||
|
): AsyncInstanceWrapper<TEagerInstance, TInstance> {
|
||||||
|
let promisedInstance: CorePromisedValue<TInstance> | null = null;
|
||||||
|
let eagerInstance: TEagerInstance;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get instance() {
|
get instance() {
|
||||||
return promisedInstance?.value ?? undefined;
|
return promisedInstance?.value ?? undefined;
|
||||||
},
|
},
|
||||||
|
get eagerInstance() {
|
||||||
|
return eagerInstance;
|
||||||
|
},
|
||||||
async getInstance() {
|
async getInstance() {
|
||||||
if (!promisedInstance) {
|
if (!promisedInstance) {
|
||||||
promisedInstance = new CorePromisedValue();
|
promisedInstance = new CorePromisedValue();
|
||||||
|
@ -54,6 +63,9 @@ function createAsyncInstanceWrapper<T>(lazyConstructor?: () => T | Promise<T>):
|
||||||
|
|
||||||
promisedInstance.resolve(instance);
|
promisedInstance.resolve(instance);
|
||||||
},
|
},
|
||||||
|
setEagerInstance(instance) {
|
||||||
|
eagerInstance = instance;
|
||||||
|
},
|
||||||
setLazyConstructor(constructor) {
|
setLazyConstructor(constructor) {
|
||||||
if (!promisedInstance) {
|
if (!promisedInstance) {
|
||||||
lazyConstructor = constructor;
|
lazyConstructor = constructor;
|
||||||
|
@ -81,12 +93,14 @@ function createAsyncInstanceWrapper<T>(lazyConstructor?: () => T | Promise<T>):
|
||||||
/**
|
/**
|
||||||
* Asynchronous instance wrapper.
|
* Asynchronous instance wrapper.
|
||||||
*/
|
*/
|
||||||
export interface AsyncInstanceWrapper<T> {
|
export interface AsyncInstanceWrapper<TEagerInstance extends AsyncObject, TInstance extends TEagerInstance> {
|
||||||
instance?: T;
|
instance?: TInstance;
|
||||||
getInstance(): Promise<T>;
|
eagerInstance?: TEagerInstance;
|
||||||
getProperty<P extends keyof T>(property: P): Promise<T[P]>;
|
getInstance(): Promise<TInstance>;
|
||||||
setInstance(instance: T): void;
|
getProperty<P extends keyof TInstance>(property: P): Promise<TInstance[P]>;
|
||||||
setLazyConstructor(lazyConstructor: () => T | Promise<T>): void;
|
setInstance(instance: TInstance): void;
|
||||||
|
setEagerInstance(eagerInstance: TEagerInstance): void;
|
||||||
|
setLazyConstructor(lazyConstructor: () => TInstance | Promise<TInstance>): void;
|
||||||
resetInstance(): void;
|
resetInstance(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +121,10 @@ export type AsyncMethod<T> =
|
||||||
* All methods are converted to their asynchronous version, and properties are available asynchronously using
|
* All methods are converted to their asynchronous version, and properties are available asynchronously using
|
||||||
* the getProperty method.
|
* the getProperty method.
|
||||||
*/
|
*/
|
||||||
export type AsyncInstance<T> = AsyncInstanceWrapper<T> & {
|
export type AsyncInstance<TEagerInstance extends AsyncObject = AsyncObject, TInstance extends TEagerInstance = TEagerInstance> =
|
||||||
[k in keyof T]: AsyncMethod<T[k]>;
|
AsyncInstanceWrapper<TEagerInstance, TInstance> & TEagerInstance & {
|
||||||
};
|
[k in keyof TInstance]: AsyncMethod<TInstance[k]>;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an asynchronous instance proxy, where all methods will be callable directly but will become asynchronous. If the
|
* Create an asynchronous instance proxy, where all methods will be callable directly but will become asynchronous. If the
|
||||||
|
@ -118,8 +133,10 @@ export type AsyncInstance<T> = AsyncInstanceWrapper<T> & {
|
||||||
* @param lazyConstructor Constructor to use the first time the instance is needed.
|
* @param lazyConstructor Constructor to use the first time the instance is needed.
|
||||||
* @returns Asynchronous instance.
|
* @returns Asynchronous instance.
|
||||||
*/
|
*/
|
||||||
export function asyncInstance<T>(lazyConstructor?: () => T | Promise<T>): AsyncInstance<T> {
|
export function asyncInstance<TEagerInstance extends AsyncObject, TInstance extends TEagerInstance = TEagerInstance>(
|
||||||
const wrapper = createAsyncInstanceWrapper<T>(lazyConstructor);
|
lazyConstructor?: () => TInstance | Promise<TInstance>,
|
||||||
|
): AsyncInstance<TEagerInstance, TInstance> {
|
||||||
|
const wrapper = createAsyncInstanceWrapper<TEagerInstance, TInstance>(lazyConstructor);
|
||||||
|
|
||||||
return new Proxy(wrapper, {
|
return new Proxy(wrapper, {
|
||||||
get: (target, property, receiver) => {
|
get: (target, property, receiver) => {
|
||||||
|
@ -127,11 +144,19 @@ export function asyncInstance<T>(lazyConstructor?: () => T | Promise<T>): AsyncI
|
||||||
return Reflect.get(target, property, receiver);
|
return Reflect.get(target, property, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wrapper.instance && property in wrapper.instance) {
|
||||||
|
return Reflect.get(wrapper.instance, property, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrapper.eagerInstance && property in wrapper.eagerInstance) {
|
||||||
|
return Reflect.get(wrapper.eagerInstance, property, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
return async (...args: unknown[]) => {
|
return async (...args: unknown[]) => {
|
||||||
const instance = await wrapper.getInstance();
|
const instance = await wrapper.getInstance();
|
||||||
|
|
||||||
return instance[property](...args);
|
return instance[property](...args);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}) as AsyncInstance<T>;
|
}) as AsyncInstance<TEagerInstance, TInstance>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue