Skip to content

Commit

Permalink
Introduce content only scenarios and courses to UI (hobbyfarm#198)
Browse files Browse the repository at this point in the history
* Introduce content only scenarios to UI

* remove import

* Adjust to also allow content-only courses

* Fix small logic errors that hide scenarios
  • Loading branch information
jggoebel authored Apr 4, 2024
1 parent cf38581 commit 0ff5cf6
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/app/course/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export class Course {
// These are Scenario IDs
scenarios: string[];
keep_vm: boolean;
virtualmachines: Map<string, string>[];
}
76 changes: 39 additions & 37 deletions src/app/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ <h1>Active session</h1>
</div>
</div>

<div class="clr-row" *ngIf="!ctx.valid">
<div class="clr-col-12">
<h1>Add AccessCode</h1>
Add AccessCodes to your account by clicking on your username on the top
right.
</div>
</div>

<div class="clr-row" *ngIf="ctx.valid">
<div class="clr-col">
<h1>{{ ctx.scheduledEvent.name }}</h1>
Expand All @@ -65,13 +73,7 @@ <h3>Select a scenario</h3>
</div>
</div>

<div class="clr-row" *ngIf="isTimeLeft()">
<div class="clr-col-12" *ngIf="!ctx.valid">
<h1>Add AccessCode</h1>
Add AccessCodes to your account by clicking on your username on the top
right.
</div>

<div class="clr-row" *ngIf="ctx.valid && isTimeLeft()">
<div class="clr-col-12">
<div
*ngIf="
Expand Down Expand Up @@ -101,38 +103,38 @@ <h1>Add AccessCode</h1>
></app-scenario-card>
</div>
</ng-container>
</div>

<div class="clr-row" *ngIf="courses.length > 0 && ctx.valid">
<div class="clr-col-12">
<ng-container *ngFor="let c of courses">
<h3 class="course-header">{{ c.name | atob }}</h3>
<hr />
<p class="course-description">{{ c.description | atob }}</p>
<div class="clr-row" *ngIf="courses.length > 0 && ctx.valid">
<div class="clr-col-12">
<ng-container *ngFor="let c of courses">
<h3 class="course-header">{{ c.name | atob }}</h3>
<hr />
<p class="course-description">{{ c.description | atob }}</p>

<div class="clr-row">
<ng-container *ngIf="c.scenarios.length > 0; else no_scenarios">
<div
class="clr-col-12 clr-col-sm-6 clr-col-md-4 clr-col-lg-3"
*ngFor="let sId of c?.scenarios"
>
<app-scenario-card
[scenarioid]="sId"
[activeSession]="
(!!activeSession && c.id !== activeSession.course) ||
(!c.keep_vm && !!activeSession)
"
(scenarioModal)="toggleScenarioModal(sId, c.id)"
></app-scenario-card>
</div>
</ng-container>
<ng-template #no_scenarios>
<div class="clr-col-12">
<p>No scenarios found.</p>
</div>
</ng-template>
</div>
</ng-container>
<div class="clr-row">
<ng-container *ngIf="c.scenarios.length > 0; else no_scenarios">
<div
class="clr-col-12 clr-col-sm-6 clr-col-md-4 clr-col-lg-3"
*ngFor="let sId of c?.scenarios"
>
<app-scenario-card
[scenarioid]="sId"
[activeSession]="
(!!activeSession && c.id !== activeSession.course) ||
(!c.keep_vm && !!activeSession)
"
(scenarioModal)="toggleScenarioModal(sId, c.id)"
></app-scenario-card>
</div>
</ng-container>
<ng-template #no_scenarios>
<div class="clr-col-12">
<p>No scenarios found.</p>
</div>
</ng-template>
</div>
</ng-container>
</div>
</div>
</div>
</div>
Expand Down
26 changes: 26 additions & 0 deletions src/app/scenario/scenario.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { ScenarioService } from '../services/scenario.service';
import { SessionService } from '../services/session.service';
import { VMClaimService } from '../services/vmclaim.service';
import { VMClaim } from '../VMClaim';
import { Router } from '@angular/router';
import { CourseService } from '../services/course.service';
import { Course } from '../course/course';

@Component({
selector: 'app-scenario',
Expand All @@ -25,14 +28,17 @@ export class ScenarioComponent implements OnInit {
public scenarioModal = new EventEmitter();

public scenario: Scenario = new Scenario();
public course: Course = new Course();
public session: Session = new Session();
public vmclaims: VMClaim[] = [];
public error = false;

constructor(
private scenarioService: ScenarioService,
private courseService: CourseService,
private ssService: SessionService,
private vmClaimService: VMClaimService,
private router: Router,
) {}

onReady(vmc: VMClaim) {
Expand All @@ -58,6 +64,26 @@ export class ScenarioComponent implements OnInit {
this.scenario = s;
});

if (this.courseid) {
this.courseService.get(this.courseid).subscribe((c: Course) => {
this.course = c;
});
}

// Cotent-only scenario or courses do not require VMclaims to be fetched and we can navigate directly to the content
if (
this.scenario.virtualmachines.length == 0 ||
(this.courseid && this.course.virtualmachines.length == 0)
) {
this.showScenarioModal = false;
this.ssService
.new(this.scenarioid, this.courseid, this.accessCode)
.subscribe((s: Session) => {
this.router.navigateByUrl('/app/session/' + s.id + '/steps/0');
});
return;
}

this.ssService
.new(this.scenarioid, this.courseid, this.accessCode)
.pipe(
Expand Down
12 changes: 8 additions & 4 deletions src/app/scenario/step.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ <h3 id="scenario-name">{{ scenario.name | atob }}</h3>
[class.btn-success-outline]="!isLastStepActive"
[class.btn-success]="isLastStepActive"
(click)="goFinish()"
*ngIf="!isContentOnly"
>
<cds-icon shape="check"></cds-icon>
Finish
</button>

<ng-container *ngIf="scenario.pauseable">
<ng-container *ngIf="scenario.pauseable && !isContentOnly">
<button class="btn btn-pause" (click)="pause()">
<cds-icon shape="pause" solid></cds-icon> Pause
</button>
Expand Down Expand Up @@ -88,7 +89,7 @@ <h4 class="card-title">
</div>
</div>
</as-split-area>
<as-split-area [size]="60" class="split-area-2">
<as-split-area [size]="60" class="split-area-2" [visible]="!isContentOnly">
<div id="terminal-column">
<clr-tabs class="tab-container">
<clr-tab *ngFor="let v of vms | keyvalue" #tab>
Expand Down Expand Up @@ -235,7 +236,7 @@ <h3 class="modal-title">Are you sure you want to close this scenario?</h3>
<clr-modal [(clrModalOpen)]="finishOpen">
<h3 class="modal-title">Are you sure you want to finish?</h3>
<div class="modal-body">
<p *ngIf="shouldKeepVmOnFinish; else no_course">
<p *ngIf="shouldKeepVmOnFinish && !isContentOnly; else no_course">
Your virtual machines will be kept until they expire or the course is
marked as "complete". Selecting "FORCE" will immediately deprovision and
delete your resources.
Expand All @@ -246,7 +247,10 @@ <h3 class="modal-title">Are you sure you want to finish?</h3>
</div>
<div class="modal-footer">
<button class="btn btn-outline" (click)="finishOpen = false">Cancel</button>
<div *ngIf="shouldKeepVmOnFinish" style="display: inline-block">
<div
*ngIf="shouldKeepVmOnFinish && !isContentOnly"
style="display: inline-block"
>
<button class="btn btn-danger-outline" (click)="actuallyFinish(true)">
Force
</button>
Expand Down
29 changes: 29 additions & 0 deletions src/app/scenario/step.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import { GuacTerminalComponent } from './guacTerminal.component';
import { JwtHelperService } from '@auth0/angular-jwt';
import { SplitComponent } from 'angular-split';
import { SettingsService } from '../services/settings.service';
import { Course } from '../course/course';
import { CourseService } from '../services/course.service';

type Service = {
name: string;
Expand All @@ -72,6 +74,7 @@ export type webinterfaceTabIdentifier = {
})
export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
public scenario: Scenario = new Scenario();
public course: Course = new Course();
public step: Step = new Step();
public stepnumber = 0;
public stepcontent = '';
Expand Down Expand Up @@ -121,6 +124,7 @@ export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
private ctr: CtrService,
private ssService: SessionService,
private scenarioService: ScenarioService,
private courseService: CourseService,
private stepService: StepService,
private vmClaimService: VMClaimService,
private vmService: VMService,
Expand Down Expand Up @@ -172,6 +176,17 @@ export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
return this.stepnumber + 1 === this.scenario.stepcount;
}

get isContentOnly() {
return (
(this.scenario &&
this.scenario.virtualmachines &&
this.scenario.virtualmachines.length == 0) ||
(this.session.course &&
this.course.virtualmachines &&
this.course.virtualmachines.length == 0)
);
}

getProgress() {
return Math.floor(((this.stepnumber + 1) / this.scenario.stepcount) * 100);
}
Expand All @@ -191,6 +206,11 @@ export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
.pipe(
switchMap((s: Session) => {
this.session = s;
if (this.session.course) {
this.courseService.get(s.course).subscribe((c: Course) => {
this.course = c;
});
}
return this.scenarioService.get(s.scenario).pipe(first());
}),
tap((s: Scenario) => {
Expand Down Expand Up @@ -359,6 +379,10 @@ export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
}

public goFinish() {
if (this.isContentOnly) {
this.actuallyFinish(true);
return;
}
this.finishOpen = true;
}

Expand All @@ -377,6 +401,11 @@ export class StepComponent implements OnInit, AfterViewInit, OnDestroy {
}

goClose() {
if (this.isContentOnly) {
this.closeOpen = false;
this.actuallyFinish(true);
return;
}
this.closeOpen = true;
}

Expand Down

0 comments on commit 0ff5cf6

Please sign in to comment.