-
Notifications
You must be signed in to change notification settings - Fork 71
Creating new unit types
The following steps must be taken to correctly implement a new type of unit:
Create a new interface in /shared/models/units extending the unit base interface IUnit. Assuming your unit would be called example this could look like this:
import {IUnit} from './IUnit';
export interface IExampleUnit extends IUnit {
unitData1: string;
unitData2: number;
}Create a file for the mongoose schema and the document model interface for your unit in /api/src/models/units. The interface extends your previous interface from step 1 and mongoose.Document. The mongoose schema in your file contains the additional data you defined in your interface from step 1. Your defined schema gets attached to the unit schema using a discriminator after definition.
Following the example from before your file would look like this:
import * as mongoose from 'mongoose';
import {Unit} from './Unit';
import {IExampleUnit} from '../../../../shared/models/units/IExampleUnit';
interface IExampleUnitModel extends IExampleUnit, mongoose.Document {
}
const exampleUnitSchema = new mongoose.Schema({
unitData1: {
type: String,
},
unitData2: {
type: number
}
});
const ExampleUnit = Unit.discriminator('example', exampleUnitSchema);
export {ExampleUnit, IExampleUnitModel}Implement your interface in the angular frontend. Create the implementation file in /app/webFrontend/src/app/models. Here you have to decide if your unit will be progressable, which means that your unit is able to provide a challenge for students. For the example unit this implementation would look something like this:
import {ICourse} from '../../../../../shared/models/ICourse';
import {IExampleUnit} from '../../../../../shared/models/units/IExampleUnit';
export class ExampleUnit implements IExampleUnit {
name: string;
description: string;
updatedAt: string;
createdAt: string;
_course: any;
_id: any;
type: string;
progressable: boolean;
weight: number;
unitData1: string;
unitData2: number;
constructor(_course: ICourse) {
this._course = _course;
this.progressable = false; // this.progressable = true; if this unit is progressable
this.weight = 0;
}
}- Create
your-typecomponent in theunit-formdirectory for the teachers' editor and anotheryour-typecomponent for the students' view in theunitdirectory above.- Inject
UnitFormServiceandFormBuilderin constructor. - Use
unitFormService.headlineto set the headline andunitFormService.unitInfoTextfor info text, both displayed by theunit-general-info-formcomponent.
- Inject
- Add new type to
createNewUnitin unit-factory.service.ts. -
(Optional) IF you want to add extra buttons (e.g. fullscreen for the
'free-text'type) includeyour-typein unit-form.component.ts asViewChild(see the existing components).- Add Button (important:
type="button",ng-ifto your type) below inapp-button-save-cancelyour desired position. - Connect your button action with
ViewChild. E.g.:(click)="freeTextUnitFormComponent.openFullscreen()
- Add Button (important:
- Include
your-typein the unit-form.component.html (ng-iftype) and pass any parameters you need. - Register
your-typecontrols inyour-type.ts(e.g.this.unitForm.addControl('my_control_name', new FormControl(this.model.MYFIELD));(this.modelis your type model) and passmodel.fieldas default value. (Think about form-validation, and read Angular Reactive Forms.) - In
your-type.component.htmlwrite your form within an element with[formGroup]="unitForm", e.g.:<ng-container [formGroup]="unitForm">...</ng-container> - Write your form-html, form fields:
formControlName="my_control_name" -
(Optional) If you want actions (e.g validation) before submit, use an
asyncfunctionunitFormService.beforeSubmit = async () => {/*my checks here*/}. By returning false, the submit will canceled.
Architecture:
<unit-form> <!-- holds the unitForm -->
<general-info-form/> <!-- for headline, name, description, visibility -->
<type-specific-form/> <!-- place everything type specific here -->
<buttons> <!-- create custom buttons on bottom of form -->
<left> <!-- left position from save/cancel --> </left>
<right> <!-- right from save/cancel --> </right>
</buttons>
</unit-form>Note that this is pseudo-html, see existing components for concrete examples.