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

Feature/333 test table sorting #400

Merged
merged 12 commits into from
May 13, 2022
10 changes: 5 additions & 5 deletions src/app/events/components/grade/grade.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { DropDownItem } from 'src/app/shared/models/drop-down-item.model';
import { Grade, NoResult } from 'src/app/shared/models/student-grades';
import { GradeKind, NoResult } from 'src/app/shared/models/student-grades';
import { byTestId } from 'src/specs/utils';
import {
buildResult,
Expand Down Expand Up @@ -51,7 +51,7 @@ describe('GradeComponent', () => {

describe('tests without point grading', () => {
let gradingScaleOptions: DropDownItem[];
let grade: Grade;
let grade: GradeKind;

beforeEach(() => {
gradingScaleOptions = [
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('GradeComponent', () => {

it('should show points in input field', () => {
// given
const grade: Grade = {
const grade: GradeKind = {
kind: 'grade',
result,
test,
Expand All @@ -168,7 +168,7 @@ describe('GradeComponent', () => {
});
});
describe('points input validation', () => {
let grade: Grade;
let grade: GradeKind;

beforeEach(() => {
grade = {
Expand Down Expand Up @@ -209,7 +209,7 @@ describe('GradeComponent', () => {
});

describe('enable and disable grading scale options', () => {
let grade: Grade;
let grade: GradeKind;

beforeEach(() => {
grade = {
Expand Down
9 changes: 8 additions & 1 deletion src/app/events/components/grade/grade.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Component,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
Expand Down Expand Up @@ -33,7 +34,7 @@ const DEBOUNCE_TIME = 500;
templateUrl: './grade.component.html',
styleUrls: ['./grade.component.scss'],
})
export class GradeComponent implements OnInit, OnDestroy {
export class GradeComponent implements OnInit, OnDestroy, OnChanges {
@Input() grade: GradeOrNoResult;
@Input() student: Student;
@Input() tabIndex: number;
Expand Down Expand Up @@ -94,6 +95,12 @@ export class GradeComponent implements OnInit, OnDestroy {
.subscribe((body) => this.gradeChanged.emit(body));
}

ngOnChanges() {
if (this.grade.kind === 'grade')
this.pointsInput.setValue(this.grade.result.Points);
if (this.grade.kind === 'no-result') this.pointsInput.setValue(null);
}

ngOnDestroy() {
this.destroy$.next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,30 @@
</th>
<th
class="secondary-column-width sticky sticky-col-2 desktop"
(click)="state.sortBy('FinalGrade')"
[ngClass]="{ selected: selectedTest === undefined }"
>
<div class="d-flex">
<div class="column-title">
{{ 'tests.grade' | translate }}
</div>
<div class="sort-direction ml-1">
{{ state.getSortingChar$('FinalGrade') | async }}
</div>
</div>
</th>
<th
class="secondary-column-width border-right sticky sticky-col-3 desktop"
(click)="state.sortBy('TestsMean')"
[ngClass]="{ selected: selectedTest === undefined }"
>
<div class="d-flex">
<div class="column-title">
{{ 'tests.mean' | translate }}
</div>
<div class="sort-direction ml-1">
{{ state.getSortingChar$('TestsMean') | async }}
</div>
</div>
</th>
<th
Expand Down
48 changes: 34 additions & 14 deletions src/app/shared/models/student-grades.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type FinalGrade = {
canGrade: boolean;
};

export type Grade = {
export type GradeKind = {
kind: 'grade';
result: Result;
test: Test;
Expand All @@ -28,9 +28,9 @@ export type NoResult = {
test: Test;
};

export type GradeOrNoResult = Grade | NoResult;
export type GradeOrNoResult = GradeKind | NoResult;

export type SortKeys = 'FullName' | Test;
export type SortKeys = 'FullName' | Test | 'FinalGrade' | 'TestsMean';

export function transform(
students: Student[],
Expand Down Expand Up @@ -102,6 +102,20 @@ export const compareFn = ({ key, ascending }: Sorting<SortKeys>) => (
return (
modificator * sg1.student.FullName.localeCompare(sg2.student.FullName)
);
case 'FinalGrade':
if (!sg1.finalGrade.finalGradeId || !sg2.finalGrade.finalGradeId)
return modificator * -1;
return (
modificator *
compareNumbers(sg1.finalGrade.finalGradeId, sg2.finalGrade.finalGradeId)
);
case 'TestsMean':
if (!sg1.finalGrade.average || !sg2.finalGrade.average)
return modificator * -1;
return (
modificator *
compareNumbers(sg1.finalGrade.average, sg2.finalGrade.average)
);
}

return modificator * compareGrades(key, sg1, sg2);
Expand All @@ -112,25 +126,31 @@ const compareGrades = (
sg1: StudentGrade,
sg2: StudentGrade
): number => {
const grades1: Grade | undefined = sg1.grades
const grades1: GradeKind | undefined = sg1.grades
.filter(isGrade)
.find((g: Grade) => g.test.Id === test.Id);
.find((g: GradeKind) => g.test.Id === test.Id);

const grades2: Grade | undefined = sg2.grades
const grades2: GradeKind | undefined = sg2.grades
.filter(isGrade)
.find((g: Grade) => g.test.Id === test.Id);
.find((g: GradeKind) => g.test.Id === test.Id);

if (test.IsPointGrading)
return (grades1?.result.Points ?? 0) - (grades2?.result.Points ?? 0);

// oh boy - typescript is really nice /s
if (test.IsPointGrading) {
return (grades2?.result?.Points ?? 0) - (grades1?.result?.Points ?? 0);
}
return (
(grades2?.result?.GradeValue?.valueOf() ?? 0) -
(grades1?.result?.GradeValue?.valueOf() ?? 0)
((grades1?.result.GradeId ?? Number.POSITIVE_INFINITY) -
(grades2?.result.GradeId ?? Number.POSITIVE_INFINITY)) *
-1
);
};

function isGrade(g: GradeOrNoResult): g is Grade {
function compareNumbers(nr1: number, nr2: number) {
if (nr1 === nr2) return 0;
if (nr1 < nr2) return -1;
return 1;
}

function isGrade(g: GradeOrNoResult): g is GradeKind {
return g.kind === 'grade';
}

Expand Down
38 changes: 38 additions & 0 deletions src/spec-builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ import {
import { Result, Test } from './app/shared/models/test.model';
import { StudyClass } from './app/shared/models/study-class.model';
import { Grade } from './app/shared/models/grading-scale.model';
import {
FinalGrade,
GradeKind,
GradeOrNoResult,
StudentGrade,
} from './app/shared/models/student-grades';
/*import { TokenPayload } from './app/shared/models/token-payload.model';*/

export function buildReference(id = 123, href?: string): Reference {
Expand Down Expand Up @@ -603,3 +609,35 @@ export function buildFinalGrading(id: number): FinalGrading {
Id: id,
};
}

export function buildStudentGrade(
student: Student,
gradesOrNoResults: GradeOrNoResult[]
): StudentGrade {
return {
student: student,
finalGrade: buildFinalGrade(),
grades: gradesOrNoResults,
};
}

export function buildGradeKind(
kind: any,
result: Result,
test: Test
): GradeKind {
return {
kind: kind,
result: result,
test: test,
};
}

function buildFinalGrade(): FinalGrade {
return {
id: 12,
average: 4,
finalGradeId: 20,
canGrade: true,
};
}