From dd6a53440f7c96d17a735d865f8fbb7d500ed331 Mon Sep 17 00:00:00 2001 From: Michael Breu <Michael.Breu@arctis.at> Date: Mon, 15 Jan 2024 17:15:07 +0100 Subject: [PATCH] Better navigation between children and parents --- angular.json | 2 +- .../exercise-card.component.html | 52 +++++++++---------- .../exercise-card.component.scss | 11 ++-- .../exercise-card/exercise-card.component.ts | 3 ++ .../exercise-details.component.ts | 44 ++++++++++++++-- .../exercise-body.component.html | 36 +++++++++---- .../content/scss/bootstrap4.5.2.min.scss | 2 +- src/main/webapp/i18n/de/exercise.json | 2 + 8 files changed, 106 insertions(+), 46 deletions(-) diff --git a/angular.json b/angular.json index 70abd265b..f768f3275 100644 --- a/angular.json +++ b/angular.json @@ -110,7 +110,7 @@ "analytics": false, "cache": { "enabled": true, - "path": "./target/", + "path": "./target/angular-cli-cache", "environment": "all" }, "packageManager": "npm" diff --git a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.html b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.html index beef1a76a..784f37494 100644 --- a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.html +++ b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.html @@ -19,36 +19,34 @@ " /> <h5 class="card-title">{{ exercise.metadata.title }}</h5> - <p class="card-text">{{ exercise.metadata.description }}</p> + <p class="card-text" style="text-align: left">{{ exercise.metadata.description }}</p> - <div style="margin-top: auto; width: 100%; padding-left: 30px; padding-right: 30px"> - <!-- card rating--> - <div style="margin-bottom: 20px"> - <div style="float: left"> - <p class="card-text" jhiTranslate="exercise.details.rating"></p> - </div> - <div *ngIf="hasChildren()" class="collection-info" jhiTranslate="exercise.collection" [ngbTooltip]="childrenTitles"> - Collection - <ng-template #childrenTitles> - Collection contains: - <table> - <tr *ngFor="let childInfo of getChildrenInfos()"> - <td>{{ childInfo.title }}</td> - </tr> - </table> - </ng-template> - </div> - <div class="star-container"> - <span - class="star" - *ngFor="let starNumber of [1, 2, 3, 4, 5]" - [ngClass]="{ 'star-marked': exercise.ranking5 >= starNumber, 'star-unmarked': exercise.ranking5 < starNumber }" - > - </span> - </div> + <!-- card rating--> + <div style="margin-left: 10px"> + <div *ngIf="hasChildren()" class="collection-info" [ngbTooltip]="childrenTitles"> + <span jhiTranslate="exercise.collection">Collection</span> + <fa-icon class="collection-icon" container="body" [icon]="bookIcon"></fa-icon> </div> - <!-- card rating end--> + <ng-template #childrenTitles + ><span jhiTranslate="exercise.collectionContains">Collection contains</span>: + <ul style="text-align: left"> + <li *ngFor="let childInfo of getChildrenInfos()"> + {{ childInfo.title }} + </li> + </ul> + </ng-template> + <div class="star-container"> + <span + class="star" + *ngFor="let starNumber of [1, 2, 3, 4, 5]" + [ngClass]="{ 'star-marked': exercise.ranking5 >= starNumber, 'star-unmarked': exercise.ranking5 < starNumber }" + > + </span> + </div> + </div> + <!-- card rating end--> + <div style="margin-top: auto; width: 100%; padding-left: 30px; padding-right: 30px"> <!-- card bookmark--> <jhi-bookmark-toggle [exercise]="exercise"></jhi-bookmark-toggle> <!-- card bookmark end--> diff --git a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.scss b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.scss index 5d3ac3ad9..ae7e2c94a 100644 --- a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.scss +++ b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.scss @@ -6,8 +6,7 @@ } .cardForCollection { - background: radial-gradient(closest-corner, white 80%, #cccccc 100%); - // border: 3px solid rgba(0, 0, 0, 0.5); + box-shadow: inset 0 0 10px #cccccc, 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .card-title { @@ -44,9 +43,15 @@ color: white; background-color: red; margin: 7px; - padding-left: 3px; + padding-top: 3px; + padding-left: 5px; padding-right: 3px; width: fit-content; border-width: 2px; border-radius: 0.2rem; } + +.collection-icon { + padding: 0px 0px 0px 0px; + float: left; +} diff --git a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.ts b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.ts index 2dd46ef07..34735555e 100644 --- a/src/main/webapp/app/exercise/exercise-card/exercise-card.component.ts +++ b/src/main/webapp/app/exercise/exercise-card/exercise-card.component.ts @@ -3,6 +3,7 @@ import { SearchService } from 'app/search/service/search-service'; import { WatchlistManager } from 'app/shared/watchlist/watchlist-manager'; import { ExerciseService } from '../service/exercise.service'; import { ChildInfo, ExtendedSearchResultDTO, hasChildren, SearchResultDTO } from 'app/shared/model/search/search-result-dto.model'; +import { faBook } from '@fortawesome/free-solid-svg-icons'; @Component({ selector: 'jhi-exercise-card', @@ -24,6 +25,8 @@ export class ExerciseCardComponent implements AfterViewChecked { exercise: ExtendedSearchResultDTO | undefined; + bookIcon = faBook; + constructor( protected searchService: SearchService, private watchlistManager: WatchlistManager, diff --git a/src/main/webapp/app/exercise/exercise-details/exercise-details.component.ts b/src/main/webapp/app/exercise/exercise-details/exercise-details.component.ts index cd5851b58..52c3d7f1c 100644 --- a/src/main/webapp/app/exercise/exercise-details/exercise-details.component.ts +++ b/src/main/webapp/app/exercise/exercise-details/exercise-details.component.ts @@ -1,7 +1,7 @@ import { HttpResponse } from '@angular/common/http'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { Router } from '@angular/router'; -import { faFolder } from '@fortawesome/free-solid-svg-icons'; +import { faArrowRight, faFolderOpen } from '@fortawesome/free-solid-svg-icons'; import { ReviewManagementService } from 'app/admin/review-management/review-management.service'; import { ApplicationInfoService } from 'app/core/application/applicationInfo.service'; import { Account } from 'app/core/auth/account.model'; @@ -12,7 +12,13 @@ import { ExerciseService } from 'app/exercise/service/exercise.service'; import { SearchService } from 'app/search/service/search-service'; import { ShoppingBasketInfo, ShoppingBasketRedirectInfoDTO } from 'app/shared/model/basket/shopping-basket-info.model'; import { Person } from 'app/shared/model/person.model'; -import { ExtendedSearchResultDTO, hasChildren, PluginActionInfo, SearchResultDTO } from 'app/shared/model/search/search-result-dto.model'; +import { + ChildInfo, + ExtendedSearchResultDTO, + hasChildren, + PluginActionInfo, + SearchResultDTO, +} from 'app/shared/model/search/search-result-dto.model'; import { PluginService } from 'app/shared/service/plugin-service'; import { WatchlistManager } from 'app/shared/watchlist/watchlist-manager'; import { Subscription } from 'rxjs'; @@ -92,7 +98,9 @@ export class ExerciseBodyComponent implements OnInit, OnDestroy { likeSubscription?: Subscription; authenticated = false; - treeIcon = faFolder; + treeIcon = faFolderOpen; + faArrowRight = faArrowRight; + oerLink?: string; oerExerciseMatch = /([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$/; @@ -120,6 +128,28 @@ export class ExerciseBodyComponent implements OnInit, OnDestroy { return hasChildren(this.exercise); } + getChildrenInfos(): ChildInfo[] { + if (this.exercise?.childInfos) { + return this.exercise?.childInfos; + } else { + this.loadChildrenInfoDisplayString(); + return []; + } + } + + loadChildrenInfoDisplayString(): string { + if (!this.exercise?.childInfos) { + this.exercise!.childInfos = []; + this.exerciseService.populateExerciseWithChildrenInfo(this.exercise!).subscribe({ + next: () => { + // nothing to do + }, + error: () => console.warn('Could not load children info'), + }); + } + return ''; + } + public startAction(action: PluginActionInfo, exercise: SearchResultDTO): void { const basketInfo: ShoppingBasketInfo = { plugin: action.plugin, @@ -175,13 +205,17 @@ export class ExerciseBodyComponent implements OnInit, OnDestroy { } toParent(parentId: string): void { - this.exerciseService.loadExercise(parentId).subscribe({ + this.toExercise(parentId); + } + + toExercise(exerciseId: string): void { + this.exerciseService.loadExercise(exerciseId).subscribe({ next: searchResult => { this.exercise = this.exerciseService.populateExerciseWithData(searchResult); this.exerciseChangedEvent.emit(this.exercise); }, error: () => { - alert('parent cannot be loaded'); + alert(`exercise ${exerciseId} cannot be loaded`); }, }); } diff --git a/src/main/webapp/app/exercise/exercise-details/exerciseComponents/exercise-body.component.html b/src/main/webapp/app/exercise/exercise-details/exerciseComponents/exercise-body.component.html index 749278916..0a3232412 100644 --- a/src/main/webapp/app/exercise/exercise-details/exerciseComponents/exercise-body.component.html +++ b/src/main/webapp/app/exercise/exercise-details/exerciseComponents/exercise-body.component.html @@ -147,15 +147,33 @@ <jhi-bookmark-toggle [exercise]="exercise"></jhi-bookmark-toggle> - <div *ngIf="exercise.file.parentId" style="float: left; width: 100%; padding-top: 15px; margin-bottom: 25px"> - <ng-template #helpToParent data-container="body"> {{ 'exercise.help.toParent' | translate }} </ng-template> - <fa-icon - style="padding: 5px 0px 0px 5px; float: left" - [ngbTooltip]="helpToParent" - container="body" - [icon]="treeIcon" - (click)="toParent(exercise.file.parentId)" - ></fa-icon> + <div + *ngIf="exercise.file.parentId" + style="float: left; width: 100%; padding-top: 15px; margin-bottom: 25px" + [ngbTooltip]="helpToParent" + (click)="toParent(exercise.file.parentId)" + > + <span jhiTranslate="exercise.containedIn">This exercise is contained in</span>: + <span> + <fa-icon style="padding: 5px 0px 0px 5px" container="body" [icon]="treeIcon"></fa-icon> + </span> + </div> + <ng-template #helpToParent data-container="body"> {{ 'exercise.help.toParent' | translate }} </ng-template> + + <div *ngIf="hasChildren()"> + <span jhiTranslate="exercise.collectionContains">Collection contains</span>: + <ul style="text-align: left"> + <li *ngFor="let childInfo of getChildrenInfos()" (click)="toExercise(childInfo.childId)" style="cursor: zoom-in"> + <span> + {{ childInfo.title }} + <!-- + <fa-icon + style="padding: 5px 0px 0px 5px; float: left" + [icon]="faArrowRight" + ></fa-icon>--> + </span> + </li> + </ul> </div> <button diff --git a/src/main/webapp/content/scss/bootstrap4.5.2.min.scss b/src/main/webapp/content/scss/bootstrap4.5.2.min.scss index 175a98cef..e53237999 100644 --- a/src/main/webapp/content/scss/bootstrap4.5.2.min.scss +++ b/src/main/webapp/content/scss/bootstrap4.5.2.min.scss @@ -5725,7 +5725,7 @@ a.close.disabled { border-left-color: #000; } .tooltip-inner { - max-width: 200px; + max-width: 250px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; diff --git a/src/main/webapp/i18n/de/exercise.json b/src/main/webapp/i18n/de/exercise.json index a7ac5582c..3ea6fac53 100644 --- a/src/main/webapp/i18n/de/exercise.json +++ b/src/main/webapp/i18n/de/exercise.json @@ -142,6 +142,8 @@ "open": "Aufgabe öffnen", "more": "Mehr ...", "collection": "Aufgabensammlung", + "collectionContains": "Diese Sammlung enthält", + "containedIn": "Diese Aufgabe ist enthalten in", "close": "Schließen", "import": { "pageTitle": "Aufgaben Import", -- GitLab