Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Results #1

Merged
merged 16 commits into from
Jul 10, 2018
Merged
17 changes: 17 additions & 0 deletions TeachingAssistantUltimate/ClientApp/Services/students.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Injectable } from '@angular/core';
import { IStudents } from '../app/model/IStudents';

@Injectable()
export class StudentsService {
private stds!: IStudents[];
constructor() {
}

get():IStudents[] {
return this.stds;
}

set(stds: IStudents[]) {
this.stds = stds;
}
}
59 changes: 57 additions & 2 deletions TeachingAssistantUltimate/ClientApp/app/app.shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ import { QuillEditorModule } from './Editor';
import { TopicsResolver } from './resolvers/TopicsResolver';
import { HttpClientModule } from '@angular/common/http';
import { PrintProviderService } from './providers/print-provider.service';
import { AssTypesComponent } from './components/ass-types/ass-types.component';
import { AssTypesResolver } from './resolvers/AssTypesResolver';
import { EditAssTypeComponent } from './components/edit-ass-type/edit-ass-type.component';
import { AssTypeResolver } from './resolvers/AssTypeResolver';
import { ClassesComponent } from './components/classes/classes.component';
import { ClassessHttpProvider } from './providers/classes-http-provider';
import { AssessTypeHttpProvider } from './providers/ass-types-http-provider';
import { ClassesResolver } from './resolvers/ClassesResolver';
import { PreviewStudentsComponent } from './components/preview-students/preview-students.component';
import { StudentsService } from '../Services/students.service';
import { StudentsHttpProvider } from './providers/students-http-provider';
import { ClassResolver } from './resolvers/ClassResolver';
import { AddResultsComponent } from './components/add-results/add-results.component';
import { StudentsResolver } from './resolvers/StudentsResolver';
import { ResultsHttpProvider } from './providers/results-http-provider';
import { ClassSubjectsResolver } from './resolvers/ClassSubjectsResolver';
import { ViwResultsComponent } from './components/viw-results/viw-results.component';
import { SmartEntryComponent } from './components/smart-entry/smart-entry.component';
import { TagResultsComponent } from './components/tag-results/tag-results.component';
import { TagsResolver } from './resolvers/TagsResolver';

@NgModule({
declarations: [
Expand All @@ -34,9 +54,36 @@ import { PrintProviderService } from './providers/print-provider.service';
EditSubjectComponent,
GeneratorComponent,
QuestionsComponent,
ViewQuestionComponent
ViewQuestionComponent,
AssTypesComponent,
EditAssTypeComponent,
ClassesComponent,
PreviewStudentsComponent,
AddResultsComponent,
ViwResultsComponent,
SmartEntryComponent,
TagResultsComponent
],
providers: [
HttpProvider,
AssessTypeHttpProvider,
HttpHandler,
SubjectsResolver,
SubjectResolver,
TopicsResolver,
PrintProviderService,
AssTypesResolver,
AssTypeResolver,
ClassessHttpProvider,
ClassesResolver,
StudentsService,
StudentsHttpProvider,
ClassResolver,
StudentsResolver,
ResultsHttpProvider,
ClassSubjectsResolver,
TagsResolver
],
providers: [HttpProvider, HttpHandler, SubjectsResolver, SubjectResolver, TopicsResolver, PrintProviderService],
exports: [RouterModule],
imports: [
CommonModule,
Expand All @@ -51,6 +98,14 @@ import { PrintProviderService } from './providers/print-provider.service';
{ path: 'edit-subject/:id', component: EditSubjectComponent, resolve: { subject: SubjectResolver } },
{ path: 'add-question/:id', component: QuestionsComponent, resolve: { subject: SubjectResolver } },
{ path: 'generate/:id', component: GeneratorComponent, resolve: { subject: SubjectResolver, topics: TopicsResolver } },
{ path: 'types', component: AssTypesComponent, resolve: { types: AssTypesResolver } },
{ path: 'edit-type/:id', component: EditAssTypeComponent, resolve: { type: AssTypeResolver } },
{ path: 'classes', component: ClassesComponent, resolve: { classes: ClassesResolver } },
{ path: 'preview-students/:id', component: PreviewStudentsComponent, resolve: { "class": ClassResolver } },
{ path: 'add-results/:id', component: AddResultsComponent, resolve: { "class": ClassResolver, 'students': StudentsResolver, 'types': AssTypesResolver, 'subjects': SubjectsResolver } },
{ path: 'smart-entry/:id', component: SmartEntryComponent, resolve: { "class": ClassResolver, 'students': StudentsResolver, 'types': AssTypesResolver, 'subjects': SubjectsResolver } },
{ path: 'view-results/:id', component: ViwResultsComponent, resolve: { "class": ClassResolver, 'subjects': ClassSubjectsResolver } },
{ path: 'tag-results/:id', component: TagResultsComponent, resolve: { "class": ClassResolver, 'subjects': ClassSubjectsResolver, 'tags': TagsResolver, 'types': AssTypesResolver } },
{ path: '**', redirectTo: 'home' }
])
]
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<div class="row">
<div class="col-md-4">
<article>
<section class="">
<h2 class="h2">Setting up</h2>
<p>The database is first created when the application first launches and subsequently recreated if the database is missing. There is no need to do anything thereof</p>
<p>
Add the <a [routerLink]="['/subjects']">Subjects</a> and the <a [routerLink]="['/classes']">Classes</a> you teach
</p>
<p>Once the above steps are done, you are more than ready to explore the application in full</p>
</section>
<section>
<h2 class="h2">Adding students</h2>
<p>Upload the list of students with an excel file. Simple as that . However a pattern must be observed to create the understanding between you and the software</p>
<ul class="list-group">
<li class="list-group-item-heading">Uploading students data instructions</li>
<li class="list-group-item">Have an excel sheets that contains the list of students</li>
<li class="list-group-item-warning">There must be no header of any sort. They will be included as students. Do not provide a header</li>
<li class="list-group-item-success">The system reads all cells for which it can read data in the cell from columns A and B. All other columns will be ignored</li>
<li class="list-group-item">To make life easier for yourself and the system, follow the instructions given</li>
</ul>
</section>
</article>
</div>
<div class="col-md-4">
<article>
<section>
<h2>Managing the classes</h2>
<p>When adding classes, you need to supply some parameter which will be used later by the application to help you do things easily</p>
<dl class="dl-horizontal">
<dt>Class Name</dt>
<dd>The name of the class as know in your school or institution. The user interface will tell you on the valid values</dd>
<dt>Prefix</dt>
<dd>The prefix is all the characters that precede the actual number of the student. E.g. "MS/2019/045" where "MS/2019/" is the prefix for all students in that class and the 045 is the actual number of the student. You would therefore store the "MS/2019/" as the prefix for all students in that class.</dd>
</dl>
<p>
The padding is the number of zeros that precede the actual number. While the developer does not personally find that behavior useful, it is a common practice. Depending on the estimated number of students, some institution pad the numbers of the students with zeros as in the example given above. The number of the student was given as 045; a padding of 1. This can be inferred that if the number ranged between 1 and 9, two zeros would have been padded to the left of the number. The user is expected to provide the padding that is used in the institution where he/she works. Default is 0, meaning no padding
</p>
</section>
</article>
</div>
<div class="col-md-4">
<article>
<section>
<h2>Adding results</h2>
<p>From the classes page, you will have two options "Add results" button and "Smart Entry"</p>
</section>
<section>
<h2>Add Results</h2>
<p>This give the old familiar excel interface to add your results. The names and index number of the students in the class are generated and text boxes for the score added. The list is generated orderly for entry. Validation rules are enforced before saving the data is allowed.</p>
<p>This is suitable for small number of students or when the index number of the students do not follow a particular patter</p>
</section>
<section>
<h2>Smart Entry</h2>
<p>Based on the number part, the index number of the student can be inferred and used to enter the score. The user simply provides the number part, say 45, and the program will infer that, it should pad two zeros and attach the prefix of the class. Should the number match a valid student, the results are added, else you will be prompted to correct the anomaly</p>
<p>Smart entry is faster when processing large numbers of students where most of them have a predictable index number. In those occasions where some of the students do not have the class pattern, the full index number should be provided and there would be no smart inference</p>
</section>
</article>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/// <reference path="../../../../node_modules/@types/jasmine/index.d.ts" />
import { TestBed, async, ComponentFixture, ComponentFixtureAutoDetect } from '@angular/core/testing';
import { BrowserModule, By } from "@angular/platform-browser";
import { AboutComponent } from './about.component';

let component: AboutComponent;
let fixture: ComponentFixture<AboutComponent>;

describe('about component', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AboutComponent ],
imports: [ BrowserModule ],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
});
fixture = TestBed.createComponent(AboutComponent);
component = fixture.componentInstance;
}));

it('should do something', async(() => {
expect(true).toEqual(true);
}));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component } from '@angular/core';

@Component({
selector: 'bs-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.css']
})
/** about component*/
export class AboutComponent {
/** about ctor */
constructor() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<title>Add results</title>
<h1>Add student results</h1>
<dl class="dl-horizontal">
<dt>Class</dt>
<dd>{{_class.className}}</dd>
<dt>Prefix</dt>
<dd>{{_class.indexPrefix}}</dd>
</dl>
<form id="form" [hidden]="!status" name="form" [formGroup]="form" class="form-horizontal">
<fieldset>
<legend>Select the initial data</legend>
<div class="form-group">
<label class="col-md-2 control-label" aria-label="" for="subjectsID">Subject</label>
<div class="col-md-6" aria-labelledby="subjectsID" [ngClass]="form.controls.subjectsID?.errors ? 'has-error' : 'has-success'">
<select class="form-control"
id="subjectsID"
title="select the subject for which you are recording this score"
formControlName="subjectsID"
placeholder="subjectsID">
<option [ngValue]="s.subjectsID" *ngFor="let s of subjects">{{s.subject}} - Code:{{s.subjectCode}}</option>
</select>
</div>
<span [ngClass]="form.controls.subjectsID.errors?.maxlength ? 'text-danger' : ''" *ngIf="form.controls.subjectsID.errors?.maxlength">The maximum length is {{form.controls.subjectsID.errors.max.max}} characters: Current is {{form.controls.subjectsID.errors.max.max}}</span>
<span [ngClass]="form.controls.subjectsID.errors?.required ? 'text-danger' : ''" *ngIf="form.controls.subjectsID.errors?.required">Enter subjectsID</span>
<span [ngClass]="form.controls.subjectsID.errors?.minlength ? 'text-danger' : ''" *ngIf="form.controls.subjectsID.errors?.minlength">The minimum length is {{form.controls.subjectsID.errors.min.min}} characters: Current is {{form.controls.subjectsID.errors.min.min}}</span>
</div>
<div class="form-group">
<label class="col-md-2 control-label" aria-label="" for="tag">Tag</label>
<div class="col-md-6" aria-labelledby="tag" [ngClass]="form.controls.tag?.errors ? 'has-error' : 'has-success'">
<input type="text"
class="form-control"
id="tag"
title="Add a tag for this assessment. This tags will be used to recollect this exams from the list. Since you can add more than one quiz, the tag will be used to find this session"
formControlName="tag"
placeholder="tag for the examination">
</div>
<span [ngClass]="form.controls.tag.errors?.maxlength ? 'text-danger' : ''" *ngIf="form.controls.tag.errors?.maxlength">The maximum length is {{form.controls.tag.errors.maxlength.requiredLength}} characters: Current is {{form.controls.tag.errors.maxlength.actualLength}}</span>
<span [ngClass]="form.controls.tag.errors?.required ? 'text-danger' : ''" *ngIf="form.controls.tag.errors?.required">Enter tag</span>
<span [ngClass]="form.controls.tag.errors?.minlength ? 'text-danger' : ''" *ngIf="form.controls.tag.errors?.minlength">The minimum length is {{form.controls.tag.errors.minlength.requiredLength}} characters: Current is {{form.controls.tag.errors.minlength.actualLength}}</span>
</div>
<div class="form-group">
<label class="col-md-2 control-label" aria-label="" for="assessmentTypesID">Exam Type</label>
<div class="col-md-6" aria-labelledby="assessmentTypesID" [ngClass]="form.controls.assessmentTypesID?.errors ? 'has-error' : 'has-success'">
<select class="form-control"
id="assessmentTypesID"
title="select the exams type for which you are recording this score"
formControlName="assessmentTypesID"
placeholder="assessmentTypesID">
<option [ngValue]="s.assessmentTypesID" *ngFor="let s of types">{{s.assessmentType}}</option>
</select>
</div>
<span [ngClass]="form.controls.assessmentTypesID.errors?.maxlength ? 'text-danger' : ''" *ngIf="form.controls.assessmentTypesID.errors?.maxlength">The maximum length is {{form.controls.assessmentTypesID.errors.max.max}} characters: Current is {{form.controls.assessmentTypesID.errors.max.max}}</span>
<span [ngClass]="form.controls.assessmentTypesID.errors?.required ? 'text-danger' : ''" *ngIf="form.controls.assessmentTypesID.errors?.required">Select assessment type</span>
<span [ngClass]="form.controls.assessmentTypesID.errors?.minlength ? 'text-danger' : ''" *ngIf="form.controls.assessmentTypesID.errors?.minlength">The minimum length is {{form.controls.assessmentTypesID.errors.min.min}} characters: Current is {{form.controls.assessmentTypesID.errors.min.min}}</span>
</div>
<div class="form-group">
<label class="col-md-2 control-label" aria-label="" for="max">Max Score</label>
<div class="col-md-6" aria-labelledby="max" [ngClass]="form.controls.max?.errors ? 'has-error' : 'has-success'">
<input type="number" class="form-control"
id="max"
title="maximum score for which you are recording this score"
formControlName="max"
placeholder="max score" />
</div>
<span [ngClass]="form.controls.max.errors?.max ? 'text-danger' : ''" *ngIf="form.controls.max.errors?.max">The maximum {{form.controls.max.errors.max.max}}</span>
<span [ngClass]="form.controls.max.errors?.required ? 'text-danger' : ''" *ngIf="form.controls.max.errors?.required">Enter maximum score</span>
<span [ngClass]="form.controls.max.errors?.min ? 'text-danger' : ''" *ngIf="form.controls.max.errors?.min">The minimum length is {{form.controls.max.errors.min.min}} characters: Current is {{form.controls.max.errors.min.min}}</span>
</div>
</fieldset>
</form>
<div class="col-md-offset-2"><button class="btn" (click)="this.status=!this.status" [disabled]="form.invalid" [ngClass]="status ? 'btn-primary' : 'btn-secondary'">{{status ? 'Continue' : 'Back'}}</button></div>

<div class="row" [hidden]="status">
<div class="col-md-2">ID</div>
<div class="col-md-2">Index Number</div>
<div class="col-md-5">Name</div>
<div class="col-md-3">Score</div>
</div>
<form [hidden]="status" *ngFor="let f of res_form;let ix=index" [formGroup]="f" class="row table-striped form-horizontal">
<div class="col-md-2">
<input type="number" [attr.disabled]="true" formControlName="studentsID" class="form-control" />
</div>
<div class="col-md-2">
<input type="text" [attr.disabled]="true" class="form-control" formControlName="indexNumber" />
</div>
<div class="col-md-5">
<input type="text" [attr.disabled]="true" class="form-control" formControlName="name" />
</div>
<div class="col-md-3" aria-labelledby="score" [ngClass]="f.controls.score?.errors ? 'has-error' : 'has-success'">
<input type="number" class="form-control"
id="score"
title="Enter the student score for the exam"
formControlName="score"
placeholder="score for {{students[ix].name}}" />
<span [ngClass]="f.controls.score.touched && f.controls.score.errors?.max ? 'text-danger' : ''" *ngIf="f.controls.score.touched && f.controls.score.errors?.max">The maximum {{f.controls.score.errors.max.max}}</span>
<span [ngClass]="f.controls.score.touched && f.controls.score.errors?.required ? 'text-danger' : ''" *ngIf="f.controls.score.touched && f.controls.score.errors?.required">Enter score</span>
<span [ngClass]="f.controls.score.touched && f.controls.score.errors?.minlength ? 'text-danger' : ''" *ngIf="f.controls.score.touched && f.controls.score.errors?.min">The minimum is {{f.controls.score.errors.min.min}}</span>
</div>
<br />
<br />
<br />
</form>
<div class="btn-group" [hidden]="status">
<button title="Save button. If the actions are successful after clicking this button, you will be routed to the class page" aria-label="Save the results button" (click)="save(form,res_form)" class="btn" [ngClass]="form_valid() ? 'btn-success' : 'btn-danger'" [disabled]="!form_valid()"><span class="glyphicon glyphicon-floppy-save"></span> Save</button>
</div>
Loading