diff --git a/TeachingAssistantUltimate/ClientApp/Services/students.service.ts b/TeachingAssistantUltimate/ClientApp/Services/students.service.ts new file mode 100644 index 0000000..beac30d --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/Services/students.service.ts @@ -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; + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/app.shared.module.ts b/TeachingAssistantUltimate/ClientApp/app/app.shared.module.ts index c179e4a..52cf2a1 100644 --- a/TeachingAssistantUltimate/ClientApp/app/app.shared.module.ts +++ b/TeachingAssistantUltimate/ClientApp/app/app.shared.module.ts @@ -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: [ @@ -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, @@ -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' } ]) ] diff --git a/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Ex Ass.png b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Ex Ass.png new file mode 100644 index 0000000..1e9d7b5 Binary files /dev/null and b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Ex Ass.png differ diff --git a/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Teaching Assistant Banner.png b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Teaching Assistant Banner.png new file mode 100644 index 0000000..764f3e7 Binary files /dev/null and b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/Teaching Assistant Banner.png differ diff --git a/TeachingAssistantUltimate/ClientApp/app/assets/imgs/bStudio.png b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/bStudio.png new file mode 100644 index 0000000..611415a Binary files /dev/null and b/TeachingAssistantUltimate/ClientApp/app/assets/imgs/bStudio.png differ diff --git a/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.css b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.css new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.css @@ -0,0 +1 @@ + diff --git a/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.html b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.html new file mode 100644 index 0000000..f634e83 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.html @@ -0,0 +1,60 @@ +
+
+
+
+

Setting up

+

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

+

+ Add the Subjects and the Classes you teach +

+

Once the above steps are done, you are more than ready to explore the application in full

+
+
+

Adding students

+

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

+
    +
  • Uploading students data instructions
  • +
  • Have an excel sheets that contains the list of students
  • +
  • There must be no header of any sort. They will be included as students. Do not provide a header
  • +
  • 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
  • +
  • To make life easier for yourself and the system, follow the instructions given
  • +
+
+
+
+
+
+
+

Managing the classes

+

When adding classes, you need to supply some parameter which will be used later by the application to help you do things easily

+
+
Class Name
+
The name of the class as know in your school or institution. The user interface will tell you on the valid values
+
Prefix
+
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.
+
+

+ 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 +

+
+
+
+
+
+
+

Adding results

+

From the classes page, you will have two options "Add results" button and "Smart Entry"

+
+
+

Add Results

+

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.

+

This is suitable for small number of students or when the index number of the students do not follow a particular patter

+
+
+

Smart Entry

+

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

+

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

+
+
+
+
\ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.spec.ts b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.spec.ts new file mode 100644 index 0000000..904eaf3 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.spec.ts @@ -0,0 +1,25 @@ +/// +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; + +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); + })); +}); \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.ts new file mode 100644 index 0000000..db0b2c4 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/about/about.component.ts @@ -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() { + + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.css b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.css new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.css @@ -0,0 +1 @@ + diff --git a/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.html b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.html new file mode 100644 index 0000000..3d8edcb --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.html @@ -0,0 +1,105 @@ +Add results +

Add student results

+
+
Class
+
{{_class.className}}
+
Prefix
+
{{_class.indexPrefix}}
+
+
+
+ Select the initial data +
+ +
+ +
+ The maximum length is {{form.controls.subjectsID.errors.max.max}} characters: Current is {{form.controls.subjectsID.errors.max.max}} + Enter subjectsID + The minimum length is {{form.controls.subjectsID.errors.min.min}} characters: Current is {{form.controls.subjectsID.errors.min.min}} +
+
+ +
+ +
+ The maximum length is {{form.controls.tag.errors.maxlength.requiredLength}} characters: Current is {{form.controls.tag.errors.maxlength.actualLength}} + Enter tag + The minimum length is {{form.controls.tag.errors.minlength.requiredLength}} characters: Current is {{form.controls.tag.errors.minlength.actualLength}} +
+
+ +
+ +
+ The maximum length is {{form.controls.assessmentTypesID.errors.max.max}} characters: Current is {{form.controls.assessmentTypesID.errors.max.max}} + Select assessment type + The minimum length is {{form.controls.assessmentTypesID.errors.min.min}} characters: Current is {{form.controls.assessmentTypesID.errors.min.min}} +
+
+ +
+ +
+ The maximum {{form.controls.max.errors.max.max}} + Enter maximum score + The minimum length is {{form.controls.max.errors.min.min}} characters: Current is {{form.controls.max.errors.min.min}} +
+
+
+
+ +
+
ID
+
Index Number
+
Name
+
Score
+
+
+
+ +
+
+ +
+
+ +
+
+ + The maximum {{f.controls.score.errors.max.max}} + Enter score + The minimum is {{f.controls.score.errors.min.min}} +
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.spec.ts b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.spec.ts new file mode 100644 index 0000000..d9e5545 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.spec.ts @@ -0,0 +1,25 @@ +/// +import { TestBed, async, ComponentFixture, ComponentFixtureAutoDetect } from '@angular/core/testing'; +import { BrowserModule, By } from "@angular/platform-browser"; +import { AddResultsComponent } from './add-results.component'; + +let component: AddResultsComponent; +let fixture: ComponentFixture; + +describe('add-results component', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AddResultsComponent ], + imports: [ BrowserModule ], + providers: [ + { provide: ComponentFixtureAutoDetect, useValue: true } + ] + }); + fixture = TestBed.createComponent(AddResultsComponent); + component = fixture.componentInstance; + })); + + it('should do something', async(() => { + expect(true).toEqual(true); + })); +}); \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.ts new file mode 100644 index 0000000..64f96b7 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/add-results/add-results.component.ts @@ -0,0 +1,79 @@ +import { Component } from '@angular/core'; +import { IStudents } from '../../model/IStudents'; +import { IClasses } from '../../model/IClasses'; +import { StudentsService } from '../../../Services/students.service'; +import { StudentsHttpProvider } from '../../providers/students-http-provider'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Router, ActivatedRoute } from '@angular/router'; +import { HttpHandler } from '../../providers/HttpHandler'; +import { ISubjects } from '../../model/ISubjects'; +import { IAssTypes } from '../../model/IAssTypes'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { IResults } from '../../model/IResults'; +import { ResultsHttpProvider } from '../../providers/results-http-provider'; +import { IResultsDisplay } from '../../model/IResultsDisplay'; + +@Component({ + selector: 'bs-add-results', + templateUrl: './add-results.component.html', + styleUrls: ['./add-results.component.css'] +}) +/** add-results component*/ +export class AddResultsComponent { + students: IStudents[]; + _class: IClasses; + subjects: ISubjects[]; + types: IAssTypes[]; + form: FormGroup; + res_form: FormGroup[]; + max: number = 20; + status: boolean = true; + constructor(stds: StudentsService, private http: ResultsHttpProvider, private hand: HttpHandler, private router: Router, route: ActivatedRoute) { + this.students = route.snapshot.data["students"]; + this._class = route.snapshot.data["class"]; + this.subjects = route.snapshot.data["subjects"]; + this.types = route.snapshot.data["types"]; + this.res_form = this.initResForm(new FormBuilder()); + this.form = this.initForm(new FormBuilder()); + } + + initForm(fb: FormBuilder): FormGroup { + return fb.group({ + subjectsID: ['', Validators.compose([Validators.required])], + assessmentTypesID: ['', Validators.compose([Validators.required])], + tag: ["", Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(20)])], + max: [this.max, Validators.compose([Validators.required, Validators.max(100), Validators.min(5)])] + }); + } + + initResForm(fb: FormBuilder): FormGroup[] { + let form: FormGroup[] = []; + this.students.forEach(x => { + form.push(fb.group({ + score: [0, Validators.compose([Validators.required, Validators.min(0), Validators.max(this.max)])], + name: [x.name], + indexNumber: [x.indexNumber], + studentsID: [x.studentsID] + })) + }); + return form; + } + save(fm: FormGroup, fgs: FormGroup[]) { + let res: IResults[] = []; + fgs.forEach(x => res.push({ + assessmentTypesID: fm.value["assessmentTypesID"], + score: x.value["score"], + studentsID: x.value["studentsID"], + subjectsID: fm.value["subjectsID"], + totalScore: fm.value["max"], + tag:fm.value['tag'] + } as IResults)); + this.http.add(res).subscribe((res: IResultsDisplay[]) => { + this.router.navigate(['/classes']); + }, (err: HttpErrorResponse) => this.hand.handleError(err)); + } + + form_valid(): boolean { + return this.form.valid && this.res_form.every(x => x.valid); + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.css b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.css new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.css @@ -0,0 +1 @@ + diff --git a/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.html b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.html new file mode 100644 index 0000000..4f1a5a8 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.html @@ -0,0 +1,65 @@ +Assessment Types +

Assessment Types

+
+

Assessment types refers to the types of assessment that are organized for students e.g. quiz, midsem etc. If your school does not have an exam processing you, you can add exam as an assessment type in order to compile the final score sheet for you

+
+
+
+ Add a new subject +
+ +
+ +
+ The maximum length is {{form.controls.assessmentType.errors.maxlength.requiredLength}} characters: Current is {{form.controls.assessmentType.errors.maxlength.actualLength}} + Enter assessmentType + The minimum length is {{form.controls.assessmentType.errors.minlength.requiredLength}} characters: Current is {{form.controls.assessmentType.errors.minlength.actualLength}} +
+
+ +
+ +
+ The maximum allowed is {{form.controls.total.errors.max.max}} + Enter total + The minimum value allowed is {{form.controls.total.errors.min.min}} +
+
+ +
+
{{hand.message}}
+
+
+ + + + + + + + + + + + + + + + + + +
TypeTotalEditDelete
{{t.assessmentType}}{{t.total}} + + + +
\ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.spec.ts b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.spec.ts new file mode 100644 index 0000000..163f05b --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.spec.ts @@ -0,0 +1,25 @@ +/// +import { TestBed, async, ComponentFixture, ComponentFixtureAutoDetect } from '@angular/core/testing'; +import { BrowserModule, By } from "@angular/platform-browser"; +import { AssTypesComponent } from './ass-types.component'; + +let component: AssTypesComponent; +let fixture: ComponentFixture; + +describe('ass-types component', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AssTypesComponent ], + imports: [ BrowserModule ], + providers: [ + { provide: ComponentFixtureAutoDetect, useValue: true } + ] + }); + fixture = TestBed.createComponent(AssTypesComponent); + component = fixture.componentInstance; + })); + + it('should do something', async(() => { + expect(true).toEqual(true); + })); +}); \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.ts new file mode 100644 index 0000000..2c8327a --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/ass-types/ass-types.component.ts @@ -0,0 +1,60 @@ +import { Component } from '@angular/core'; +import { IAssTypes } from '../../model/IAssTypes'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { HttpErrorResponse } from '@angular/common/http'; +import { HttpHandler } from '../../providers/HttpHandler'; +import { AssessTypeHttpProvider } from '../../providers/ass-types-http-provider'; + +@Component({ + selector: 'bs-ass-types', + templateUrl: './ass-types.component.html', + styleUrls: ['./ass-types.component.css'] +}) +/** ass-types component*/ +export class AssTypesComponent { + types: IAssTypes[]; + form: FormGroup; + constructor(private route: ActivatedRoute, fb: FormBuilder, private htpp: AssessTypeHttpProvider, public hand: HttpHandler) { + this.form = this.InitForm(fb); + this.types = this.route.snapshot.data["types"] as IAssTypes[]; + } + + + InitForm(fb: FormBuilder): FormGroup { + return fb.group({ + assessmentType: ["", Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(20)])], + total: ["", Validators.compose([Validators.required, Validators.min(5), Validators.max(70)])] + }) + } + + add(sub: IAssTypes) { + this.hand.processing = true; + this.hand.error = false; + this.htpp.addAssTypes(sub).subscribe((res:IAssTypes) => { + this.types.unshift(res); + this.hand.message = `${res.assessmentType} was added successfully`; + this.form = this.InitForm(new FormBuilder()); + }, (err: HttpErrorResponse) => { + this.hand.handleError(err); + }); + this.hand.processing = false; + } + + delete(ass: IAssTypes) { + if (confirm(`Are you sure you want to delete ${ass.assessmentType} from the list?`)) { + this.hand.processing = true; + this.hand.error = false; + this.hand.message = ""; + this.htpp.deleteAssTypes(ass).subscribe(res => { + this.hand.error = false; + let ix: number = this.types.findIndex(q => q.assessmentTypesID === ass.assessmentTypesID); + this.types.splice(ix, 1); + this.hand.message = `${ass.assessmentType} was deleted`; + }, ((err: HttpErrorResponse) => { + this.hand.handleError(err); + })); + this.hand.processing = false; + } + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.css b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.css new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.css @@ -0,0 +1 @@ + diff --git a/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.html b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.html new file mode 100644 index 0000000..8d860af --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.html @@ -0,0 +1,100 @@ +Classes +

Classes

+
+
+ Add a new class +
+ +
+ +
+ The maximum length is {{form.controls.className.errors.maxlength.requiredLength}} characters: Current is {{form.controls.className.errors.maxlength.actualLength}} + Enter class name + The minimum length is {{form.controls.className.errors.minlength.requiredLength}} characters: Current is {{form.controls.className.errors.minlength.actualLength}} +
+
+ +
+ +
+ The maximum length is {{form.controls.indexPrefix.errors.maxlength.requiredLength}} characters: Current is {{form.controls.indexPrefix.errors.maxlength.actualLength}} + Enter index number prefix + The minimum length is {{form.controls.indexPrefix.errors.minlength.requiredLength}} characters: Current is {{form.controls.indexPrefix.errors.minlength.actualLength}} +
+
+ +
+ +
+ The maximum is {{form.controls.padding.errors.max.max}} + Enter index number prefix + The minimum length is {{form.controls.padding.errors.min.min}} +
+
+ +
+
{{hand.message}}
+
+
+ +

Your saved subjects

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassPrefixPaddingStudentsUpload Excel FileAdd singleAdd ResultsEditDelete
{{c.className}}{{c.indexPrefix}}{{c.padding}}{{c.count}} + + + + + + + + + + + + + +
diff --git a/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.spec.ts b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.spec.ts new file mode 100644 index 0000000..e2fc28a --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.spec.ts @@ -0,0 +1,25 @@ +/// +import { TestBed, async, ComponentFixture, ComponentFixtureAutoDetect } from '@angular/core/testing'; +import { BrowserModule, By } from "@angular/platform-browser"; +import { ClassesComponent } from './classes.component'; + +let component: ClassesComponent; +let fixture: ComponentFixture; + +describe('classes component', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ClassesComponent ], + imports: [ BrowserModule ], + providers: [ + { provide: ComponentFixtureAutoDetect, useValue: true } + ] + }); + fixture = TestBed.createComponent(ClassesComponent); + component = fixture.componentInstance; + })); + + it('should do something', async(() => { + expect(true).toEqual(true); + })); +}); \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.ts new file mode 100644 index 0000000..d56bd43 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/classes/classes.component.ts @@ -0,0 +1,93 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { HttpHandler } from '../../providers/HttpHandler'; +import { ActivatedRoute, Router } from '@angular/router'; +import { HttpErrorResponse } from '@angular/common/http'; +import { IClasses } from '../../model/IClasses'; +import { ClassessHttpProvider } from '../../providers/classes-http-provider'; +import * as XLSX from 'xlsx'; +import { IStudents } from '../../model/IStudents'; +import { StudentsService } from '../../../Services/students.service'; + +@Component({ + selector: 'bs-classes', + templateUrl: './classes.component.html', + styleUrls: ['./classes.component.css'] +}) +/** classes component*/ +export class ClassesComponent { + data: Array> = []; + form: FormGroup; + classes: IClasses[]; + ngOnInit(): void { + + } + constructor(private route: ActivatedRoute, fb: FormBuilder, private htpp: ClassessHttpProvider, public hand: HttpHandler, private router: Router, private stds_serv: StudentsService) { + this.form = this.InitForm(fb); + this.classes = this.route.snapshot.data["classes"] as IClasses[]; + } + + + InitForm(fb: FormBuilder): FormGroup { + return fb.group({ + className: ["", Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(10)])], + indexPrefix: ["", Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(20)])], + padding:[0,Validators.compose([Validators.required, Validators.min(0), Validators.max(5)])] + }) + } + + add(cl: IClasses) { + this.hand.processing = true; + this.hand.error = false; + this.htpp.add(cl).subscribe(res => { + this.classes.unshift(res); + this.hand.message = `${cl.className} was added successfully`; + this.form = this.InitForm(new FormBuilder()); + }, (err: HttpErrorResponse) => { + this.hand.handleError(err); + }); + this.hand.processing = false; + } + + delete(cl: IClasses) { + if (confirm(`Are you sure you want to delete ${cl.className} from the list?`)) { + this.hand.processing = true; + this.hand.error = false; + this.hand.message = ""; + this.htpp.delete(cl).subscribe(res => { + this.hand.error = false; + let ix: number = this.classes.findIndex(q => q.classesID === cl.classesID); + this.classes.splice(ix, 1); + this.hand.message = `${cl.className} was deleted`; + }, ((err: HttpErrorResponse) => { + this.hand.handleError(err); + })); + this.hand.processing = false; + } + } + + onFileChange(evt: any, c: IClasses) { + /* wire up file reader */ + const target: DataTransfer = (evt.target); + if (target.files.length !== 1) throw new Error('Cannot use multiple files'); + const reader: FileReader = new FileReader(); + reader.onload = (e: any) => { + /* read workbook */ + const bstr: string = e.target.result; + const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' }); + + /* grab first sheet */ + const wsname: string = wb.SheetNames[0]; + const ws: XLSX.WorkSheet = wb.Sheets[wsname]; + /* save data */ + this.data = (XLSX.utils.sheet_to_json(ws, { header: 1 })); + let stds: IStudents[] = []; + this.data.forEach(x => stds.push({ + classesID: c.classesID, indexNumber: x[1], name: x[0] + } as IStudents)); + this.stds_serv.set(stds); + this.router.navigate(['/preview-students', c.classesID]); + }; + reader.readAsBinaryString(target.files[0]); + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.css b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.css new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.css @@ -0,0 +1 @@ + diff --git a/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.html b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.html new file mode 100644 index 0000000..a24ca3b --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.html @@ -0,0 +1,41 @@ +Edit {{type.assessmentType}} +

Edit {{type.assessmentType}}

+
+
+ Make your changes as appropriate +
+ +
+ +
+ The maximum length is {{form.controls.assessmentType.errors.maxlength.requiredLength}} characters: Current is {{form.controls.assessmentType.errors.maxlength.actualLength}} + Enter assessmentType + The minimum length is {{form.controls.assessmentType.errors.minlength.requiredLength}} characters: Current is {{form.controls.assessmentType.errors.minlength.actualLength}} +
+
+ +
+ +
+ The maximum allowed is {{form.controls.total.errors.max.max}} + Enter total + The minimum value allowed is {{form.controls.total.errors.min.min}} +
+
+ + +
+
{{hand.message}}
+ +
+
\ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.spec.ts b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.spec.ts new file mode 100644 index 0000000..43d2026 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.spec.ts @@ -0,0 +1,25 @@ +/// +import { TestBed, async, ComponentFixture, ComponentFixtureAutoDetect } from '@angular/core/testing'; +import { BrowserModule, By } from "@angular/platform-browser"; +import { EditAssTypeComponent } from './edit-ass-type.component'; + +let component: EditAssTypeComponent; +let fixture: ComponentFixture; + +describe('edit-ass-type component', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EditAssTypeComponent ], + imports: [ BrowserModule ], + providers: [ + { provide: ComponentFixtureAutoDetect, useValue: true } + ] + }); + fixture = TestBed.createComponent(EditAssTypeComponent); + component = fixture.componentInstance; + })); + + it('should do something', async(() => { + expect(true).toEqual(true); + })); +}); \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.ts new file mode 100644 index 0000000..e2baf57 --- /dev/null +++ b/TeachingAssistantUltimate/ClientApp/app/components/edit-ass-type/edit-ass-type.component.ts @@ -0,0 +1,64 @@ +import { Component } from '@angular/core'; +import { IAssTypes } from '../../model/IAssTypes'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { HttpErrorResponse } from '@angular/common/http'; +import { HttpHandler } from '../../providers/HttpHandler'; +import { AssessTypeHttpProvider } from '../../providers/ass-types-http-provider'; + +@Component({ + selector: 'bs-edit-ass-type', + templateUrl: './edit-ass-type.component.html', + styleUrls: ['./edit-ass-type.component.css'] +}) +/** edit-ass-type component*/ +export class EditAssTypeComponent { + type: IAssTypes; + form: FormGroup; + constructor(private route: ActivatedRoute, private router: Router, fb: FormBuilder, private htpp: AssessTypeHttpProvider, public hand: HttpHandler) { + this.type = this.route.snapshot.data["type"] as IAssTypes; + this.form = this.InitForm(fb); + } + + InitForm(fb: FormBuilder): FormGroup { + return fb.group({ + assessmentType: [this.type.assessmentType, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(20)])], + total: [this.type.total, Validators.compose([Validators.required, Validators.min(5), Validators.max(70)])] + }) + } + + edit(sub: IAssTypes) { + this.hand.processing = true; + this.hand.error = false; + if (this.type.assessmentType === sub.assessmentType && this.type.total === sub.total) { + alert("Nothing has changed. Operation was aborted"); + } + else { + this.type.assessmentType = sub.assessmentType; + this.type.total == sub.total; + this.htpp.editAssTypes(this.type).subscribe((res: IAssTypes) => { + this.hand.message = `${res.assessmentType} was edited successfully`; + this.router.navigate(['/types']) + }, (err: HttpErrorResponse) => { + this.hand.handleError(err); + }); + } + this.hand.processing = false; + } + + delete() { + if (confirm(`Are you sure you want to delete ${this.type.assessmentType} from the list?`)) { + this.hand.processing = true; + this.hand.error = false; + this.hand.message = ""; + this.htpp.deleteAssTypes(this.type).subscribe(res => { + this.hand.error = false; + this.hand.message = `${this.type.assessmentType} was deleted`; + this.router.navigate(['/types']) + }, ((err: HttpErrorResponse) => { + this.hand.handleError(err); + })); + this.hand.processing = false; + } + } +} \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.html b/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.html index 617b932..d00036c 100644 --- a/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.html +++ b/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.html @@ -15,26 +15,6 @@ - @@ -62,7 +42,6 @@
Set number of questions to fetch from each topic
-
Header diff --git a/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.ts b/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.ts index 1b5d646..e3efc18 100644 --- a/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.ts +++ b/TeachingAssistantUltimate/ClientApp/app/components/generator/generator.component.ts @@ -45,8 +45,4 @@ export class GeneratorComponent { print(head: string): void { this.printer.print(head); } - - serverPrint() { - this.http.print(parseInt(this.route.snapshot.paramMap.get('id') as string)).subscribe(res => console.log(res)); - } } \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/home/home.component.html b/TeachingAssistantUltimate/ClientApp/app/components/home/home.component.html index dcdc6f9..8d00ef1 100644 --- a/TeachingAssistantUltimate/ClientApp/app/components/home/home.component.html +++ b/TeachingAssistantUltimate/ClientApp/app/components/home/home.component.html @@ -1,16 +1,39 @@ -

Hello, world!

-

Welcome to your new single-page application, built with:

- -

To help you get started, we've also set up:

-
    -
  • Client-side navigation. For example, click Counter then Back to return here.
  • -
  • Server-side prerendering. For faster initial loading and improved SEO, your Angular app is prerendered on the server. The resulting HTML is then transferred to the browser where a client-side copy of the app takes over.
  • -
  • Webpack dev middleware. In development mode, there's no need to run the webpack build tool. Your client-side resources are dynamically built on demand. Updates are available as soon as you modify any file.
  • -
  • Hot module replacement. In development mode, you don't even need to reload the page after making most changes. Within seconds of saving changes to files, your Angular app will be rebuilt and a new instance injected into the page.
  • -
  • Efficient production builds. In production mode, development-time features are disabled, and the webpack build tool produces minified static CSS and JavaScript files.
  • -
+Home Page + +

Welcome to bStudio Teaching Assistant Ultimate

+ \ No newline at end of file diff --git a/TeachingAssistantUltimate/ClientApp/app/components/navmenu/navmenu.component.html b/TeachingAssistantUltimate/ClientApp/app/components/navmenu/navmenu.component.html index aa30acf..149a1cf 100644 --- a/TeachingAssistantUltimate/ClientApp/app/components/navmenu/navmenu.component.html +++ b/TeachingAssistantUltimate/ClientApp/app/components/navmenu/navmenu.component.html @@ -1,3 +1,4 @@ +