From 05cc9e80a8b28d34140c9ccdcbf6c9ac1478349e Mon Sep 17 00:00:00 2001 From: PhPrinz <48761034+PhPrinz@users.noreply.github.com> Date: Mon, 13 May 2024 10:44:11 +0200 Subject: [PATCH] Allow for the creation of Tasks in the Scenario-Wizard UI (#207) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add components to allow for the creation of Tasks in the Scenario UI * add tasks to scenario detail view * fix create new scenario with empty task list * add validation for tasks to scenario wizard --------- Co-authored-by: Philip Prinz Co-authored-by: Jan-Gerrit Goebel Co-authored-by: Jan-Gerrit Göbel <86782124+jggoebel@users.noreply.github.com> --- src/app/app.module.ts | 16 +- ...de-with-syntax-highlighting.component.html | 4 +- ...de-with-syntax-highlighting.component.scss | 4 +- ...code-with-syntax-highlighting.component.ts | 141 ++++++++++++++---- .../vmtemplate-service-form.component.html | 1 + src/app/data/scenario.service.ts | 6 +- src/app/data/scenario.ts | 2 + src/app/data/vm-tasks.ts | 20 +++ src/app/scenario/md-editor/markdownActions.ts | 7 + .../scenario-detail.component.html | 15 +- .../scenario-detail.component.scss | 15 ++ .../scenario-wizard.component.html | 24 ++- .../scenario-wizard.component.ts | 78 +++++++++- .../task-form/task-form.component.html | 113 ++++++++++++++ .../task-form/task-form.component.scss | 11 ++ .../scenario/task-form/task-form.component.ts | 111 ++++++++++++++ .../readonly-task.component.html | 94 ++++++++++++ .../readonly-task.component.scss | 5 + .../readonly-task/readonly-task.component.ts | 29 ++++ src/app/scenario/task/task.component.html | 45 ++++++ src/app/scenario/task/task.component.scss | 29 ++++ src/app/scenario/task/task.component.ts | 129 ++++++++++++++++ src/app/step/hf-markdown.component.ts | 8 + ...-task-verification-markdown.component.html | 45 ++++++ ...-task-verification-markdown.component.scss | 74 +++++++++ ...le-task-verification-markdown.component.ts | 51 +++++++ 26 files changed, 1038 insertions(+), 39 deletions(-) create mode 100644 src/app/data/vm-tasks.ts create mode 100644 src/app/scenario/task-form/task-form.component.html create mode 100644 src/app/scenario/task-form/task-form.component.scss create mode 100644 src/app/scenario/task-form/task-form.component.ts create mode 100644 src/app/scenario/task/readonly-task/readonly-task.component.html create mode 100644 src/app/scenario/task/readonly-task/readonly-task.component.scss create mode 100644 src/app/scenario/task/readonly-task/readonly-task.component.ts create mode 100644 src/app/scenario/task/task.component.html create mode 100644 src/app/scenario/task/task.component.scss create mode 100644 src/app/scenario/task/task.component.ts create mode 100644 src/app/step/single-task-verification-markdown/single-task-verification-markdown.component.html create mode 100644 src/app/step/single-task-verification-markdown/single-task-verification-markdown.component.scss create mode 100644 src/app/step/single-task-verification-markdown/single-task-verification-markdown.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index f891077f..e7a9b69f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -107,6 +107,10 @@ import { ScenarioWizardComponent } from './scenario/scenario-wizard/scenario-wiz import { ScenarioDetailComponent } from './scenario/scenario-detail/scenario-detail.component'; import { StepsScenarioComponent } from './scenario/steps-scenario/steps-scenario.component'; import { DashboardDetailsComponent } from './dashboards/dashboard-details/dashboard-details.component'; +import { TaskComponent } from './scenario/task/task.component'; +import { TaskFormComponent } from './scenario/task-form/task-form.component'; +import { SingleTaskVerificationMarkdownComponent } from './step/single-task-verification-markdown/single-task-verification-markdown.component'; + import '@cds/core/icon/register.js'; import { ClarityIcons, @@ -146,8 +150,10 @@ import { timesIcon, buildingIcon, numberListIcon, + syncIcon, downloadIcon, } from '@cds/core/icon'; +import { ReadonlyTaskComponent } from './scenario/task/readonly-task/readonly-task.component'; ClarityIcons.addIcons( plusIcon, @@ -186,6 +192,7 @@ ClarityIcons.addIcons( timesIcon, buildingIcon, numberListIcon, + syncIcon, downloadIcon ); @@ -281,6 +288,10 @@ export function jwtOptionsFactory(): JwtConfig { ScenarioDetailComponent, StepsScenarioComponent, DashboardDetailsComponent, + TaskComponent, + TaskFormComponent, + ReadonlyTaskComponent, + SingleTaskVerificationMarkdownComponent, ], imports: [ BrowserModule, @@ -306,7 +317,10 @@ export function jwtOptionsFactory(): JwtConfig { sanitize: false, convertHTMLEntities: false, }, - globalParsers: [{ component: CtrComponent }], + globalParsers: [ + { component: CtrComponent }, + { component: SingleTaskVerificationMarkdownComponent }, + ], }), BrowserAnimationsModule, DragulaModule.forRoot(), diff --git a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.html b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.html index 7281db8f..bd457f7e 100644 --- a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.html +++ b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.html @@ -1,5 +1,5 @@
- - +
\ No newline at end of file diff --git a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.scss b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.scss index a70bbb84..49b17685 100644 --- a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.scss +++ b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.scss @@ -19,14 +19,14 @@ top: 0px; left: 0px; width: 100%; - height: 100%; + height: auto; padding: 10px; margin: 0; font-size: inherit; font-family: inherit; line-height: inherit; border: none; - overflow: hidden + overflow: hidden; } .code-editor textarea:focus { diff --git a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.ts b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.ts index 56f05d5c..0f7fccf9 100644 --- a/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.ts +++ b/src/app/configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component.ts @@ -1,24 +1,73 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, Output, SimpleChanges, ViewChild } from '@angular/core'; -import 'prismjs' -import 'prismjs/components/prism-yaml' +import { + AfterViewInit, + Component, + ElementRef, + EventEmitter, + Input, + OnDestroy, + Output, + SimpleChanges, + ViewChild, +} from '@angular/core'; +import 'prismjs'; +import 'prismjs/components/prism-yaml'; +import 'prismjs/components/prism-bash'; +import 'prismjs/components/prism-regex'; declare var Prism: any; +export enum supportedLanguages { //To allow for more Languages the prism Components have to be imported also. For a list of all Supported Languages see: https://prismjs.com/#supported-languages + YAML = 'language-yaml', + BASH = 'language-bash', + REGEX = 'language-regex', +} + @Component({ selector: 'app-code-with-syntax-highlighting', templateUrl: './code-with-syntax-highlighting.component.html', - styleUrls: ['./code-with-syntax-highlighting.component.scss'] + styleUrls: ['./code-with-syntax-highlighting.component.scss'], }) -export class CodeWithSyntaxHighlightingComponent implements AfterViewInit, OnDestroy { +export class CodeWithSyntaxHighlightingComponent + implements AfterViewInit, OnDestroy +{ + @Input('textValue') set textValue(value: string) { + this._textValue = value; + this.count++ + if (!this.resizeable) { + this.previousScrollHeight = 0; + this.setStyleValues(); + } + } + + count: number = 0 + + _textValue: string = ''; + + @Input() + height: string = '500px'; @Input() - textValue: string; + width: string = '100%'; + + @Input() + resizeable: boolean = false; + + @Input() + readonly: boolean = false; + + @Input() + outline: string = 'solid 1px'; + + @Input() + language: supportedLanguages = supportedLanguages.YAML; + + private lang: string = 'yaml'; @Output() - textChanged: EventEmitter = new EventEmitter() + textChanged: EventEmitter = new EventEmitter(); @ViewChild('codeEditor') - codeEditor: ElementRef + codeEditor: ElementRef; @ViewChild('code') codeBlock: ElementRef; @@ -28,43 +77,83 @@ export class CodeWithSyntaxHighlightingComponent implements AfterViewInit, OnDes public highlightedText: string; - private observer = new MutationObserver(() => this.resize()) + private observer = new MutationObserver(() => { + this.resize(); + }); + private previousScrollHeight = 0; + + private initialized: boolean = false; // Prevent Errors when Parent sets the text before initialization, i.e. in a clarity accordeon element. ngAfterViewInit() { - this.setHighlightedText(this.textValue) - this.observer.observe(this.textarea.nativeElement, {attributes: true}) + this.initialized = true + this.setStyleValues(); + this.lang = this.language.split('-')[1]; + this.setHighlightedText(this._textValue); + this.observer.observe(this.textarea.nativeElement, { attributes: true }); + } + + setStyleValues() { + if (!!this.initialized) { + this.codeEditor.nativeElement.style.outline = this.outline; + this.codeEditor.nativeElement.style.height = this.height; + this.codeEditor.nativeElement.style.width = this.width; + this.codeEditor.nativeElement.style.maxWidth = this.width; + this.codeBlock.nativeElement.style.height = this.height; + this.textarea.nativeElement.style.height = this.height; + this.textarea.nativeElement.style.resize = this.resizeable + ? 'vertical' + : 'none'; + } } setHighlightedText(textValue) { - this.highlightedText = Prism.highlight(textValue, Prism.languages.yaml, 'yaml') + this.highlightedText = Prism.highlight( + textValue, + Prism.languages[this.lang], + this.lang + ); } ngOnChanges(changes: SimpleChanges) { - this.textValue = changes.textValue.currentValue - this.setHighlightedText(changes.textValue.currentValue) - + if (!!changes.textValue) { + this._textValue = changes.textValue.currentValue; + this.setHighlightedText(changes.textValue.currentValue); + } } onValueChange(event) { - let newText: string = event.target.value - this.textChanged.emit(newText) + this.count++ + let newText: string = event.target.value; + this.textChanged.emit(newText); + } + + manualResizeEvent(event) { + if (this.previousScrollHeight > event.height) { + this.previousScrollHeight = event.height; + } + this.resizeEvent(event); } resizeEvent(event) { - this.codeEditor.nativeElement.style.height = event.height + 'px' - this.codeBlock.nativeElement.style.height = event.height + 'px' + let newHeight = event.height + 'px'; + this.codeEditor.nativeElement.style.height = newHeight; + this.codeBlock.nativeElement.style.height = newHeight; + this.textarea.nativeElement.style.height = newHeight; } resize() { - const scrollHeight = this.textarea.nativeElement.scrollHeight - if (scrollHeight > 0) { - this.resizeEvent({height: scrollHeight}) + const scrollHeight = this.textarea.nativeElement.scrollHeight; + if (scrollHeight > 0 && scrollHeight > this.previousScrollHeight) { + this.previousScrollHeight = scrollHeight; + if (!this.resizeable) { + this.textarea.nativeElement.style.height = 0; + } + this.resizeEvent({ height: scrollHeight, isResize: true }); } } ngOnDestroy() { - this.observer.disconnect() + this._textValue = null; + this.observer.disconnect(); } -} - - +} \ No newline at end of file diff --git a/src/app/configuration/vmtemplates/edit-vmtemplate/vmtemplate-service-form/vmtemplate-service-form.component.html b/src/app/configuration/vmtemplates/edit-vmtemplate/vmtemplate-service-form/vmtemplate-service-form.component.html index 48291561..cde79a9a 100644 --- a/src/app/configuration/vmtemplates/edit-vmtemplate/vmtemplate-service-form/vmtemplate-service-form.component.html +++ b/src/app/configuration/vmtemplates/edit-vmtemplate/vmtemplate-service-form/vmtemplate-service-form.component.html @@ -249,6 +249,7 @@