diff --git a/FrontEnd/package.json b/FrontEnd/package.json index 260fa5f..f701bf9 100644 --- a/FrontEnd/package.json +++ b/FrontEnd/package.json @@ -41,6 +41,7 @@ "popper.js": "^1.12.9", "primeicons": "^1.0.0", "primeng": "^6.1.7", + "ngx-csv": "^0.3.1", "rxjs": "^5.5.2", "zone.js": "^0.8.14" }, diff --git a/FrontEnd/src/app/app-routing.module.ts b/FrontEnd/src/app/app-routing.module.ts index b9a7e19..0b1ce1e 100644 --- a/FrontEnd/src/app/app-routing.module.ts +++ b/FrontEnd/src/app/app-routing.module.ts @@ -46,6 +46,7 @@ import { BagdesComponent } from './user/bagdes/bagdes.component'; import { RankingComponent } from './groups/ranking/ranking.component'; import { HistoryOfActivityInGroupComponent } from './groups/history-of-activity-in-group/history-of-activity-in-group.component'; import { LoginUsosComponent } from './login/login-usos/login-usos.component'; +import { TestsInGroupResultsComponent } from './groups/tests-in-group-results/tests-in-group-results.component'; const routes: Routes = [ @@ -87,7 +88,8 @@ const routes: Routes = [ { path: 'groups/ranking/:id', component: RankingComponent , canActivate: [AuthGuard] }, { path: 'groups/waiting-resources/:id', component: WaitingResourcesComponent, canActivate: [AuthGuard] }, { path: 'groups/waiting-resources/:id', component: WaitingResourcesComponent, canActivate: [AuthGuard] }, - { path: 'groups/history/:id', component: HistoryOfActivityInGroupComponent, canActivate: [AuthGuard] } + { path: 'groups/history/:id', component: HistoryOfActivityInGroupComponent, canActivate: [AuthGuard] }, + { path: 'groups/tests-results/:id', component: TestsInGroupResultsComponent, canActivate: [AuthGuard] } ]; @NgModule({ diff --git a/FrontEnd/src/app/groups/group-details/group-details.component.html b/FrontEnd/src/app/groups/group-details/group-details.component.html index 9881f36..77fff7f 100644 --- a/FrontEnd/src/app/groups/group-details/group-details.component.html +++ b/FrontEnd/src/app/groups/group-details/group-details.component.html @@ -6,6 +6,9 @@ + +

diff --git a/FrontEnd/src/app/groups/group-details/group-details.component.ts b/FrontEnd/src/app/groups/group-details/group-details.component.ts index 0670d8a..2bf54a4 100644 --- a/FrontEnd/src/app/groups/group-details/group-details.component.ts +++ b/FrontEnd/src/app/groups/group-details/group-details.component.ts @@ -249,6 +249,10 @@ export class GroupDetailsComponent implements OnInit, OnDestroy { this.router.navigate(['groups/ranking', this.id]); } + goToTestsResults() { + this.router.navigate(['groups/tests-results', this.id]); + } + goToHistory() { this.router.navigate(['groups/history', this.id]); } diff --git a/FrontEnd/src/app/groups/group.ts b/FrontEnd/src/app/groups/group.ts index f9a5516..fc4290e 100644 --- a/FrontEnd/src/app/groups/group.ts +++ b/FrontEnd/src/app/groups/group.ts @@ -30,3 +30,20 @@ export class ActivityHistory { constructor() {} } + +export class TestsInGroup { + public id: number; + public title: string; + public maxScore: number; + + constructor() {} +} + +export class TestsInGroupResults { + public name: string; + public surname: string; + public userScore: number; + public percent: number; + + constructor() {} +} diff --git a/FrontEnd/src/app/groups/groups.module.ts b/FrontEnd/src/app/groups/groups.module.ts index 9a2d1b5..9657517 100644 --- a/FrontEnd/src/app/groups/groups.module.ts +++ b/FrontEnd/src/app/groups/groups.module.ts @@ -30,6 +30,7 @@ import { MaterialToGroupPreviewComponent } from './waiting-resources/material-to import { FlashcardsToGroupPreviewComponent } from './waiting-resources/flashcards-to-group-preview/flashcards-to-group-preview.component'; import { RankingComponent } from './ranking/ranking.component'; import { HistoryOfActivityInGroupComponent } from './history-of-activity-in-group/history-of-activity-in-group.component'; +import { TestsInGroupResultsComponent } from './tests-in-group-results/tests-in-group-results.component'; @NgModule({ @@ -63,7 +64,8 @@ import { HistoryOfActivityInGroupComponent } from './history-of-activity-in-grou MaterialToGroupPreviewComponent, FlashcardsToGroupPreviewComponent, RankingComponent, - HistoryOfActivityInGroupComponent + HistoryOfActivityInGroupComponent, + TestsInGroupResultsComponent ], providers: [GroupsService, ConfirmationService] diff --git a/FrontEnd/src/app/groups/groups.service.ts b/FrontEnd/src/app/groups/groups.service.ts index 33a1a4a..97a9b78 100644 --- a/FrontEnd/src/app/groups/groups.service.ts +++ b/FrontEnd/src/app/groups/groups.service.ts @@ -28,6 +28,9 @@ export class GroupsService { private getActivityHistoryURL = 'groups/{groupId}/users/activity?sort={sort}'; + private getTestsInGroupsURL = 'groups/{groupId}/tests'; + private getResultsInTestsURL = 'groups/{groupId}/tests/{testId}/results'; + constructor(private httpClient: HttpClient, private authenticationService: AuthenticationService) { this.setHeaders(); } @@ -45,6 +48,18 @@ export class GroupsService { } } + getTestsInGroups(groupId: number): Observable { + this.setHeaders(); + const url = this.getTestsInGroupsURL.replace('{groupId}', groupId.toString()); + return this.httpClient.get(url, { headers: this.headers }); + } + + getResultsInTests(groupId: number, testId: number): Observable { + this.setHeaders(); + const url = this.getResultsInTestsURL.replace('{groupId}', groupId.toString()).replace('{testId}', testId.toString()); + return this.httpClient.get(url, { headers: this.headers }); + } + getGroups(): Observable { this.setHeaders(); const url = this.getGroupsURL; diff --git a/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.css b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.css new file mode 100644 index 0000000..722b21b --- /dev/null +++ b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.css @@ -0,0 +1,24 @@ +.wrapper{ + width: 100%; + padding: 30px; + min-height: 100%; + margin-bottom: 40px; +} + +.content{ + background-color: #181616; + padding: 30px; + margin-top: 2rem; + margin-bottom: 2rem; + text-align: center; + margin-left: auto; + margin-right: auto; +} + +ag-grid-angular{ + margin: 10px; +} + +.buttons-container > div{ + margin: 10px; +} diff --git a/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.html b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.html new file mode 100644 index 0000000..41b0b55 --- /dev/null +++ b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.html @@ -0,0 +1,28 @@ +
+
+

{{group?.name}}

+
+
+

Wybierz test aby zobaczyć wyniki:

+
+ + +
+

+
+

Wybrany test: {{selectedTest.title}}

+
+ +
+
+ + +
+
+
\ No newline at end of file diff --git a/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.spec.ts b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.spec.ts new file mode 100644 index 0000000..565ba78 --- /dev/null +++ b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestsInGroupResultsComponent } from './tests-in-group-results.component'; + +describe('TestsInGroupResultsComponent', () => { + let component: TestsInGroupResultsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TestsInGroupResultsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TestsInGroupResultsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.ts b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.ts new file mode 100644 index 0000000..507de21 --- /dev/null +++ b/FrontEnd/src/app/groups/tests-in-group-results/tests-in-group-results.component.ts @@ -0,0 +1,189 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { GroupsService } from '../groups.service'; +import { Group, TestsInGroup, TestsInGroupResults } from '../group'; +import { Subscription } from 'rxjs/Subscription'; +import localeText from './../../../assets/localeText'; +import { GridOptions, RowDoubleClickedEvent } from 'ag-grid-community/main'; +import { MatSnackBar } from '@angular/material'; + +import { ngxCsv } from 'ngx-csv/ngx-csv'; + + +@Component({ + selector: 'app-tests-in-group-results', + templateUrl: './tests-in-group-results.component.html', + styleUrls: ['./tests-in-group-results.component.css'] +}) +export class TestsInGroupResultsComponent implements OnInit, OnDestroy { + + id: number; + currentUser; + subs: Subscription[] = []; + public group: Group; + public selectedTest: TestsInGroup; + + public localeText = localeText; + + // chooseTests + public data: TestsInGroup[] = []; + public gridApi; + public gridOptions: GridOptions; + public columnDefs = [ + { headerName: 'ID', field: 'id', headerTooltip: 'ID' }, + { headerName: 'Nazwa', field: 'title', headerTooltip: 'Nazwa' }, + { headerName: 'Liczba punktów do zdobycia', field: 'maxScore', headerTooltip: 'Liczba punktów do zdobycia', hide: false } + ]; + + // showTestResult + public testdata: TestsInGroupResults[] = []; + public testgridApi; + public testgridOptions: GridOptions; + public testcolumnDefs = [ + { headerName: 'Imię', field: 'name', headerTooltip: 'Imię' }, + { headerName: 'Nazwisko', field: 'surname', headerTooltip: 'Nazwisko' }, + { headerName: 'Wynik', field: 'userScore', headerTooltip: 'Wynik', hide: false }, + { headerName: 'Wynik (%)', field: 'percent', headerTooltip: 'Wynik (%)', hide: false } + ]; + + constructor(private route: ActivatedRoute, + private groupService: GroupsService, + public snackBar: MatSnackBar) { } + + ngOnInit() { + this.id = this.route.snapshot.params.id; + this.currentUser = JSON.parse(localStorage.getItem('currentUser')); + this.subs.push( + this.groupService.getGroupDetails(this.id) + .subscribe( + data => { + this.group = data; + this.getTests(); + localStorage.setItem('groupOwnerUsername', this.group.owner); + } + ) + ); + + this.gridOptions = { + rowHeight: 50, + headerHeight: 25, + getRowStyle: function (params) { + return { + cursor: 'pointer' + }; + }, + }; + + this.testgridOptions = { + rowHeight: 50, + headerHeight: 25, + getRowStyle: function (params) { + return { + cursor: 'pointer' + }; + }, + }; + } + + getTests() { + this.subs.push(this.groupService.getTestsInGroups(this.id).subscribe( + success => { + this.data = success; + }, + error => { + console.log(error); + this.snackBar.open('Nie udało się załadować listy testów!', null, + { duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] }); + } + )); + } + + goTo(event: RowDoubleClickedEvent) { + this.selectedTest = event.data; + this.getResults(event.data.id); + } + + downloadCSVResults() { + // tslint:disable-next-line:no-unused-expression + new ngxCsv(this.testdata, this.selectedTest.title + '_wyniki'); + } + + getResults(id: number) { + this.subs.push(this.groupService.getResultsInTests(this.id, id).subscribe( + success => { + this.testdata = success; + }, + error => { + console.log(error); + this.snackBar.open('Nie udało się załadować wyników za test!', null, + { duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] }); + } + )); + } + + ngOnDestroy() { + if (this.subs) { + this.subs.forEach(x => x.unsubscribe()); + } + + localStorage.removeItem('groupOwnerUsername'); + } + + // chooseTests + public onRowClicked(e) { + if (e.event.target !== undefined) { + this.goTo(e); + } + } + + onGridReady(params) { + this.gridApi = params.api; + this.gridApi.sizeColumnsToFit(); + } + + onGridColumnsChanged(params) { + params.api.sizeColumnsToFit(); + } + + onGridSizeChanged(params) { + this.columnDefs = [ + { headerName: 'ID', field: 'id', headerTooltip: 'ID' }, + { headerName: 'Nazwa', field: 'title', headerTooltip: 'Nazwa' }, + { headerName: 'Liczba punktów do zdobycia', field: 'maxScore', headerTooltip: 'Liczba punktów do zdobycia', hide: false } + ]; + + params.api.sizeColumnsToFit(); + } + + onGidColumnsChanged(params) { + params.api.sizeColumnsToFit(); + } + + // showTestResult + public testonRowClicked(e) {} + + testonGridReady(params) { + this.testgridApi = params.api; + this.testgridApi.sizeColumnsToFit(); + } + + testonGridColumnsChanged(params) { + params.api.sizeColumnsToFit(); + } + + testonGridSizeChanged(params) { + this.testcolumnDefs = [ + { headerName: 'Imię', field: 'name', headerTooltip: 'Imię' }, + { headerName: 'Nazwisko', field: 'surname', headerTooltip: 'Nazwisko' }, + { headerName: 'Wynik', field: 'userScore', headerTooltip: 'Wynik', hide: false }, + { headerName: 'Wynik (%)', field: 'percent', headerTooltip: 'Wynik (%)', hide: false } + ]; + + params.api.sizeColumnsToFit(); + } + + testonGidColumnsChanged(params) { + params.api.sizeColumnsToFit(); + } + +} diff --git a/FrontEnd/src/assets/localeText.ts b/FrontEnd/src/assets/localeText.ts index 36df79e..6c291e9 100644 --- a/FrontEnd/src/assets/localeText.ts +++ b/FrontEnd/src/assets/localeText.ts @@ -49,7 +49,7 @@ const localeText = { toolPanelButton: 'Narzędzia', // other - noRowsToShow: 'Brak testów do wyświetlenia', + noRowsToShow: 'Brak elementów do wyświetlenia', // enterprise menu pinColumn: 'Przypiąta kolumna',