Skip to content

Commit

Permalink
feat: otter training - prepare training content (#2223)
Browse files Browse the repository at this point in the history
## Proposed change

Preparation for the training content

## Related issues

- 🐛 Fixes #(issue)
- 🚀 Feature #(issue)

<!-- Please make sure to follow the contributing guidelines on
https://github.com/amadeus-digital/Otter/blob/main/CONTRIBUTING.md -->
  • Loading branch information
sdo-1A authored Oct 9, 2024
2 parents 9a62adb + c36820a commit 992f1ff
Show file tree
Hide file tree
Showing 26 changed files with 505 additions and 55 deletions.
2 changes: 2 additions & 0 deletions apps/showcase/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ dist-e2e-playwright
playwright-reports
test-results
training-assets
src/assets/trainings/**/exercise.json
src/assets/trainings/**/solution.json
1 change: 1 addition & 0 deletions apps/showcase/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"start:no-translation": "ng serve",
"generate:translations:dev": "ng run showcase:generate-translations",
"generate:translations": "ng run showcase:generate-translations:production",
"prepare-training": "node scripts/prepare-training-exercises/index.cjs",
"cms-adapters:localizations": "ng run showcase:extract-translations",
"cms-adapters:metadata": "yarn run cms-adapters:localizations",
"update:otter": "ng update @o3r/core",
Expand Down
37 changes: 29 additions & 8 deletions apps/showcase/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@
"executor": "@angular-devkit/build-angular:application",
"inputs": [
"source",
"^source",
"^source-and-structure",
"{projectRoot}/dev-resources",
"{projectRoot}/training-assets",
"{projectRoot}/*.metadata.json",
"packages/@o3r/training-sdk/dist/*-structure.json"
"{projectRoot}/*.metadata.json"
],
"options": {
"outputPath": "apps/showcase/dist",
Expand Down Expand Up @@ -93,9 +92,9 @@
"output": "/assets/"
},
{
"glob": "*-structure.json",
"input": "packages/@o3r/training-sdk/dist",
"output": "/assets/@o3r/training-sdk"
"glob": "*.json",
"input": "packages/@o3r/training-sdk/dist/structure",
"output": "/assets/@o3r/training-sdk/structure"
}
],
"styles": [
Expand Down Expand Up @@ -145,7 +144,8 @@
"generate-theme",
"generate-dark-theme",
"generate-horizon-theme",
"copy-training-assets"
"copy-training-assets",
"prepare-training"
]
},
"serve": {
Expand All @@ -161,7 +161,9 @@
},
"dependsOn": [
"^build-builders",
"^build"
"^build",
"copy-training-assets",
"prepare-training"
]
},
"serve-app": {
Expand Down Expand Up @@ -380,7 +382,26 @@
},
"dependsOn": ["^build-builders"]
},
"prepare-training": {
"cache": true,
"executor": "nx:run-script",
"inputs": [
"global",
"{projectRoot}/package.json",
"{projectRoot}/src/assets/**/exercise/**",
"{projectRoot}/src/assets/**/solution/**",
"{projectRoot}/scripts/prepare-training-exercises/*.cjs"
],
"outputs": [
"{projectRoot}/src/assets/**/solution.json",
"{projectRoot}/src/assets/**/exercise.json"
],
"options": {
"script": "prepare-training"
}
},
"copy-training-assets": {
"cache": true,
"executor": "nx:run-script",
"inputs": [
"global",
Expand Down
28 changes: 28 additions & 0 deletions apps/showcase/scripts/prepare-training-exercises/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const {readdir, readFile, writeFile} = require('node:fs/promises');
const {getFilesTree} = require('@o3r/training-tools');
const {dirname, join, resolve} = require('node:path');
const glob = require('globby');

/**
* The purpose of this script is to generate the exercise and solution files for the code editor
*/

void (async () => {
const root = resolve(__dirname, '..', '..');
const files = await glob('src/assets/trainings/**/(exercise|solution)/**', {cwd: root, dot: true});
const paths = files.reduce((exercisePaths, file) => {
const exerciseDirectory = dirname(file).match('(.*/(?:exercise|solution))')?.[0];
if (exerciseDirectory) {
exercisePaths.add(exerciseDirectory);
}
return exercisePaths;
}, new Set());
for (const folder of paths) {
const filePath = join(root, folder);
const exerciseStructure = await getFilesTree([{isDir: true, path: `${filePath}`}], {readdir, readFile});
const [_, commonPath, folderName] = folder.match('(.*)/(exercise|solution)');
const targetPath = join(commonPath, `${folderName}.json`);
const content = JSON.stringify(exerciseStructure);
await writeFile(targetPath, content);
}
})();
1 change: 1 addition & 0 deletions apps/showcase/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const appRoutes: Routes = [
{path: 'run-app-locally', loadComponent: () => import('./run-app-locally/index').then((m) => m.RunAppLocallyComponent), title: 'Otter Showcase - Run App Locally'},
{path: 'sdk', loadComponent: () => import('./sdk/index').then((m) => m.SdkComponent), title: 'Otter Showcase - SDK'},
{path: 'placeholder', loadComponent: () => import('./placeholder/index').then((m) => m.PlaceholderComponent), title: 'Otter Showcase - Placeholder'},
{path: 'sdk-training', loadComponent: () => import('./sdk-training/index').then((m) => m.SdkTrainingComponent), title: 'Otter Showcase - SDK Training'},
{path: '**', redirectTo: '/home', pathMatch: 'full'}
];

Expand Down
40 changes: 21 additions & 19 deletions apps/showcase/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
<header class="navbar navbar-expand-lg flex-shrink-0">
<button class="navbar-toggler d-inline-block d-xl-none fa-bars" (click)="open(content)" title="Open side navigation">
</button>
<div class="header-title p-xl-3">
<div class="header-icon">
<img src="assets/otter-sticker.svg" width="48" height="48" alt="Otter logo" />
<div class="d-flex flex-column">
<header class="fw-bold w-100 d-flex align-items-center justify-content-start navbar navbar-expand-lg flex-shrink-0">
<button class="navbar-toggler d-inline-block d-xl-none fa-bars" (click)="open(content)" title="Open side navigation">
</button>
<div class="header-title d-flex p-xl-3">
<div class="d-flex me-3 header-icon">
<img src="assets/otter-sticker.svg" width="48" height="48" alt="Otter logo" />
</div>
<div class="d-block d-sm-none">Otter</div>
<div class="d-none d-sm-block">Otter Showcase</div>
</div>
<div class="d-block d-sm-none">Otter</div>
<div class="d-none d-sm-block">Otter Showcase</div>
</div>
</header>
<div class="container">
<div class="row">
<div class="left-nav col-2 d-none d-xl-block">
<o3r-sidenav-pres
</header>
<div class="flex-fill container">
<div class="row">
<div class="left-nav pt-5 col-2 d-none d-xl-block">
<o3r-sidenav-pres
[linksGroups]="linksGroups"
[activeUrl]="activeUrl$ | async"
></o3r-sidenav-pres>
</div>
<div class="page-content col-12 col-xl-10">
<router-outlet></router-outlet>
></o3r-sidenav-pres>
</div>
<div class="page-content col-12 col-xl-10">
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
<footer class="bg-body-tertiary">
<footer class="d-flex align-items-center w-100 text-body bg-body-tertiary">
<div class="container">
<div class="row">
<div class="col-12 col-md-8">
Expand Down
6 changes: 6 additions & 0 deletions apps/showcase/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export class AppComponent implements OnDestroy {
links: [
{ url: '/sdk', label: 'Generator' }
]
},
{
label: 'Training',
links: [
{ url: '/sdk-training', label: 'SDK Training' }
]
}
];

Expand Down
4 changes: 3 additions & 1 deletion apps/showcase/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ConsoleLogger, Logger, LOGGER_CLIENT_TOKEN, LoggerService } from '@o3r/
import { OTTER_RULES_ENGINE_DEVTOOLS_OPTIONS, RulesEngineRunnerModule } from '@o3r/rules-engine';
import { OTTER_STYLING_DEVTOOLS_OPTIONS, StylingDevtoolsModule } from '@o3r/styling';
import { HIGHLIGHT_OPTIONS } from 'ngx-highlightjs';
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
import { DatePickerHebrewInputPresComponent, ScrollBackTopPresComponent, SidenavPresComponent } from '../components/utilities';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand Down Expand Up @@ -108,7 +109,8 @@ export function registerCustomComponents(): Map<string, any> {
C11nModule.forRoot({registerCompFunc: registerCustomComponents}),
StylingDevtoolsModule,
LocalizationDevtoolsModule,
ConfigurationDevtoolsModule
ConfigurationDevtoolsModule,
MonacoEditorModule.forRoot()
],
providers: [
{provide: MESSAGE_FORMAT_CONFIG, useValue: {}},
Expand Down
1 change: 1 addition & 0 deletions apps/showcase/src/app/sdk-training/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './sdk-training.component';
14 changes: 14 additions & 0 deletions apps/showcase/src/app/sdk-training/sdk-training.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {TrainingComponent} from '../../components';

@Component({
selector: 'o3r-sdk-training',
standalone: true,
imports: [
TrainingComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './sdk-training.template.html',
styleUrls: ['./sdk-training.style.scss']
})
export class SdkTrainingComponent {}
22 changes: 22 additions & 0 deletions apps/showcase/src/app/sdk-training/sdk-training.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SdkTrainingComponent } from './sdk-training.component';

describe('SdkTrainingComponent', () => {
let component: SdkTrainingComponent;
let fixture: ComponentFixture<SdkTrainingComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SdkTrainingComponent]
})
.compileComponents();

fixture = TestBed.createComponent(SdkTrainingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
4 changes: 4 additions & 0 deletions apps/showcase/src/app/sdk-training/sdk-training.style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
o3r-training {
// full visible height on the screen (with removal of the showcase header height of 4rem)
height: calc(100vh - 4rem);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<o3r-training [title]="'SDK Training'" [trainingPath]="'trainings/sdk'"></o3r-training>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
code-editor-control {
transition: min-height 100ms ease;

&:has(.command-panel.d-none) {
min-height: 3rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,4 @@ export class CodeEditorViewComponent implements OnDestroy, OnChanges {
public ngOnDestroy() {
this.webContainerService.runner.killContainer();
}

/**
* Log web container file tree for the project folder in the console
*/
public logTree() {
void this.webContainerService.logTree();
}
}
3 changes: 1 addition & 2 deletions apps/showcase/src/components/training/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './code-editor-view/index';
export * from './training-step/index';
export * from './training.component';
46 changes: 46 additions & 0 deletions apps/showcase/src/components/training/training.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@if (steps()[currentStepIndex()]; as currentStep){
<div class="mt-7 mb-3 d-flex justify-content-between">
<div class="align-self-center">
<h1 class="m-0">{{title()}}</h1>
<div ngbDropdown class="mt-2">
<button type="button" class="btn btn-outline-primary" id="training-exercise-selection" ngbDropdownToggle>
{{currentStep.description.title}}
</button>
<div ngbDropdownMenu aria-labelledby="training-exercise-selection">
@for (label of stepNames(); track label; let id = $index) {
<button type="button" ngbDropdownItem class="dropdown-item" [class.active]="id === currentStepIndex()" (click)="setCurrentStep(id)">
{{label}}
</button>
}
</div>
</div>
</div>
<div class="align-self-center d-flex flex-wrap">
@if (currentStep.dynamicContent.project() || currentStep.dynamicContent.solutionProject()) {
<button type="button" class="btn btn-outline-primary mb-2 mb-md-0 me-5" (click)="toggleDisplayInstructions()">
{{showInstructions() ? 'Hide instructions' : 'Show instructions'}}
</button>
<button type="button" class="btn btn-outline-danger mb-2 mb-md-0 me-5"
(click)="toggleDisplaySolution()"
[disabled]="!showSolution() && !currentStep.dynamicContent.solutionProject() || showSolution() && !currentStep.dynamicContent.project()"
>
{{showSolution() ? 'Show exercise' : 'Show solution'}}
</button>
}
<div>
<button type="button" class="btn btn-outline-secondary df-btn-icononly fa-chevron-left me-2" [disabled]="currentStepIndex() <= 0"
aria-label="Previous step" (click)="setCurrentStep(currentStepIndex() - 1)"></button>
<button type="button" class="btn btn-outline-secondary df-btn-icononly fa-chevron-right ms-2" [disabled]="currentStepIndex() >= steps().length - 1"
aria-label="Next step" (click)="setCurrentStep(currentStepIndex() + 1)"></button>
</div>
</div>
</div>
<o3r-training-step-pres
class="flex-fill overflow-hidden mb-5"
[class.constrained]="!!(currentStep.dynamicContent.solutionProject() || currentStep.dynamicContent.project())"
[instructions]="showInstructions() ? currentStep.dynamicContent.htmlContent() : ''"
[title]="currentStep.description.title"
[project]="showSolution() ? currentStep.dynamicContent.solutionProject() : currentStep.dynamicContent.project()"
[editorMode]="currentStep.description.filesConfiguration?.mode">
</o3r-training-step-pres>
}
8 changes: 8 additions & 0 deletions apps/showcase/src/components/training/training.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:host {
display: flex;
flex-direction: column;

&:not(:has(.constrained)) {
height: 100% !important;
}
}
22 changes: 22 additions & 0 deletions apps/showcase/src/components/training/training.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TrainingComponent } from './training.component';

describe('SdkTrainingComponent', () => {
let component: TrainingComponent;
let fixture: ComponentFixture<TrainingComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TrainingComponent]
})
.compileComponents();

fixture = TestBed.createComponent(TrainingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 992f1ff

Please sign in to comment.