Skip to content

Commit

Permalink
fix(workbench/message-box): open message box in a dialog
Browse files Browse the repository at this point in the history
A message box is a standardized dialog for presenting a message to the user, such as an info, warning or alert, or for prompting the user for confirmation. The message can be plain text or a component, allowing for structured content or input prompts.

closes #438

BREAKING CHANGE: Consolidation of the MessageBox API has introduced a breaking change.

Refer to the documentation for migration examples: https://github.com/SchweizerischeBundesbahnen/scion-workbench/blob/master/docs/site/howto/how-to-open-message-box.md

To migrate:
- `MessageBoxService` is now `WorkbenchMessageBoxService`.
- `MessageBoxConfig` is now `WorkbenchMessageBoxOptions`.
- Signature of `WorkbenchMessageBoxService#open` method has changed. Pass the message (text or component) as the first argument, not via options object.
- `injector` option has been moved to a top-level property (previously `MessageBoxConfig#componentConstructOptions`).
- `viewContainerRef` option has been removed (no replacement).
- `componentInput` option has been renamed to `inputs` with the type changed to a dictionary. Inputs are now available as input properties in the component, previously via `MessageBox#input` handle.
- `MessageBox` handle has been removed. Configure the message box when opening the message box.
- Registration of custom action handlers has been removed (no replacement).
- Button with the action key 'close' is no longer bound to the escape keystroke.
  • Loading branch information
k-genov authored and danielwiehl committed Jan 18, 2024
1 parent 019a4d2 commit fe690d4
Show file tree
Hide file tree
Showing 62 changed files with 1,322 additions and 2,752 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export default class PopupOpenerPageComponent {
value: this._formBuilder.control('popup'),
}),
this._formBuilder.group({
key: this._formBuilder.control('app'),
value: this._formBuilder.control('app1'),
},
)], Validators.required),
key: this._formBuilder.control('app'),
value: this._formBuilder.control('app1'),
}),
], Validators.required),
params: this._formBuilder.array<FormGroup<KeyValueEntry>>([]),
anchor: this._formBuilder.group({
position: this._formBuilder.control<Position | 'element'>('element', Validators.required),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import {EnvironmentProviders, Injectable, makeEnvironmentProviders} from '@angular/core';
import {MessageBoxService, MICROFRONTEND_PLATFORM_POST_STARTUP} from '@scion/workbench';
import {InspectMessageBoxComponent} from './inspect-message-box.component';
import {MICROFRONTEND_PLATFORM_POST_STARTUP, WorkbenchMessageBoxService} from '@scion/workbench';
import {WorkbenchCapabilities, WorkbenchMessageBoxConfig} from '@scion/workbench-client';
import {IntentClient} from '@scion/microfrontend-platform';
import {Maps} from '@scion/toolkit/util';
import {InspectMessageBoxComponent} from './inspect-message-box.component';

/**
* Displays a custom message box for microfrontends to inspect message box properties.
*/
@Injectable(/* DO NOT PROVIDE via 'providedIn' metadata as registered via workbench startup hook. */)
class InspectMessageBoxIntentHandler {

constructor(intentClient: IntentClient, messageBoxService: MessageBoxService) {
constructor(intentClient: IntentClient, messageBoxService: WorkbenchMessageBoxService) {
intentClient.onIntent<WorkbenchMessageBoxConfig, string>({type: WorkbenchCapabilities.MessageBox, qualifier: {component: 'inspector'}}, request => {
const config: WorkbenchMessageBoxConfig = request.body!;
return messageBoxService.open({
const params = request.intent.params!;
return messageBoxService.open(InspectMessageBoxComponent, {
...config,
content: InspectMessageBoxComponent,
componentInput: new Map([
...request.headers,
...request.intent.params ?? [],
...Maps.coerce(request.intent.qualifier),
['$implicit', config.content],
]),
inputs: {
input: config.content,
param1: params.get('param1'),
param2: params.get('param2'),
},
});
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
<sci-form-field label="Instance ID" title="Unique identifier of this component instance">
<span class="e2e-component-instance-id">{{uuid}}</span>
</sci-form-field>
<section>
<header>Inputs</header>

<sci-form-field label="Input" direction="column" *ngIf="messageBox.input">
<section class="input">
<sci-viewport>
<output class="e2e-input">{{messageBox.input | appStringify}}</output>
</sci-viewport>
</section>
</sci-form-field>

<ng-container [formGroup]="form">
<sci-form-field label="Title" direction="column">
<input [formControl]="form.controls.title" class="e2e-title">
</sci-form-field>

<sci-form-field label="Severity" direction="column">
<select [formControl]="form.controls.severity" class="e2e-severity">
<option value="info">info</option>
<option value="warn">warn</option>
<option value="error">error</option>
</select>
</sci-form-field>

<sci-form-field label="CSS Class(es)" direction="column">
<input [formControl]="form.controls.cssClass" class="e2e-class" placeholder="Separate multiple CSS classes by space">
<sci-form-field label="Input">
<output class="e2e-input">{{ input }}</output>
</sci-form-field>

<sci-form-field label="Actions" direction="column">
<sci-key-value-field [keyValueFormArray]="form.controls.actions" [addable]="true" [removable]="true" class="e2e-actions"></sci-key-value-field>
<sci-form-field label="Param1">
<output class="e2e-param1">{{ param1 }}</output>
</sci-form-field>

<sci-form-field label="Return Value" direction="column">
<input [formControl]="form.controls.returnValue" class="e2e-return-value">
<sci-form-field label="Param2">
<output class="e2e-param2">{{ param2 }}</output>
</sci-form-field>
</ng-container>
</section>
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
:host {
display: grid;
grid-row-gap: 1em;
display: flex;
flex-direction: column;
gap: 1em;

> sci-form-field section.input {
> section {
display: flex;
flex-direction: column;
gap: .5em;
border: 1px solid var(--sci-color-border);
border-radius: var(--sci-corner);
padding: 1em;
max-height: 200px;

> sci-viewport {
white-space: pre;
font-family: monospace;
font-size: smaller;
> header {
margin-bottom: 1em;
font-weight: bold;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,26 @@
* SPDX-License-Identifier: EPL-2.0
*/

import {Component} from '@angular/core';
import {MessageBox} from '@scion/workbench';
import {FormGroup, NonNullableFormBuilder, ReactiveFormsModule} from '@angular/forms';
import {UUID} from '@scion/toolkit/uuid';
import {NgIf} from '@angular/common';
import {SciViewportComponent} from '@scion/components/viewport';
import {StringifyPipe} from '../common/stringify.pipe';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {filter} from 'rxjs/operators';
import {Component, Input} from '@angular/core';
import {SciFormFieldComponent} from '@scion/components.internal/form-field';
import {KeyValueEntry, SciKeyValueFieldComponent} from '@scion/components.internal/key-value-field';

@Component({
selector: 'app-inspect-message-box',
templateUrl: './inspect-message-box.component.html',
styleUrls: ['./inspect-message-box.component.scss'],
standalone: true,
imports: [
NgIf,
StringifyPipe,
ReactiveFormsModule,
SciFormFieldComponent,
SciViewportComponent,
SciKeyValueFieldComponent,
],
})
export class InspectMessageBoxComponent {

public uuid = UUID.randomUUID();
public form = this._formBuilder.group({
title: this._formBuilder.control(''),
severity: this._formBuilder.control<'info' | 'warn' | 'error' | undefined>(undefined),
cssClass: this._formBuilder.control(''),
actions: this._formBuilder.array<FormGroup<KeyValueEntry>>([]),
returnValue: this._formBuilder.control(''),
});
@Input()
public input: string | undefined;

constructor(public messageBox: MessageBox<Map<string, any>>, private _formBuilder: NonNullableFormBuilder) {
this.form.controls.title.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(title => {
this.messageBox.setTitle(title || undefined);
});
@Input()
public param1: string | undefined;

this.form.controls.severity.valueChanges
.pipe(
filter(Boolean),
takeUntilDestroyed(),
)
.subscribe(severity => {
this.messageBox.setSeverity(severity);
});

this.form.controls.cssClass.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(cssClass => {
this.messageBox.setCssClass(cssClass.split(/\s+/).filter(Boolean));
});

this.form.controls.actions.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(actions => {
this.messageBox.setActions(actions.map(action => ({
key: action.key!,
label: action.value!,
onAction: () => `${action.key} => ${this.form.controls.returnValue.value}`,
})),
);
});
}
@Input()
public param2: string | undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@
</select>
</sci-form-field>

<sci-form-field label="Content" *ngIf="!isUseComponent()">
<input [formControl]="form.controls.content" class="e2e-content">
<sci-form-field label="Message" *ngIf="!isUseComponent()">
<input [formControl]="form.controls.message" class="e2e-message">
</sci-form-field>

<sci-form-field label="Component Input" *ngIf="isUseComponent()">
<input [formControl]="form.controls.componentInput" class="e2e-component-input">
<sci-form-field label="Inputs" *ngIf="isUseComponent()">
<sci-key-value-field [keyValueFormArray]="form.controls.options.controls.inputs" [addable]="true" [removable]="true" class="e2e-inputs"/>
</sci-form-field>
</section>

<section>
<sci-form-field label="Title">
<input [formControl]="form.controls.title" class="e2e-title">
<input [formControl]="form.controls.options.controls.title" class="e2e-title">
</sci-form-field>

<sci-form-field label="Actions">
<sci-key-value-field [keyValueFormArray]="form.controls.actions" [addable]="true" [removable]="true" class="e2e-actions"></sci-key-value-field>
<sci-key-value-field [keyValueFormArray]="form.controls.options.controls.actions" [addable]="true" [removable]="true" class="e2e-actions"></sci-key-value-field>
</sci-form-field>

<sci-form-field label="Severity">
<select [formControl]="form.controls.severity" class="e2e-severity">
<select [formControl]="form.controls.options.controls.severity" class="e2e-severity">
<option value="info">info</option>
<option value="warn">warn</option>
<option value="error">error</option>
Expand All @@ -35,34 +35,19 @@
</sci-form-field>

<sci-form-field label="Modality">
<select [formControl]="form.controls.modality" class="e2e-modality">
<select [formControl]="form.controls.options.controls.modality" class="e2e-modality">
<option value="application">application</option>
<option value="view">view</option>
<option value="">default</option>
</select>
</sci-form-field>

<sci-form-field label="Contextual View ID">
<input [formControl]="form.controls.contextualViewId" class="e2e-contextual-view-id">
</sci-form-field>

<sci-form-field label="Content Selectable">
<sci-checkbox [formControl]="form.controls.contentSelectable" class="e2e-content-selectable"></sci-checkbox>
<sci-checkbox [formControl]="form.controls.options.controls.contentSelectable" class="e2e-content-selectable"></sci-checkbox>
</sci-form-field>

<sci-form-field label="CSS Class(es)">
<input [formControl]="form.controls.cssClass" class="e2e-class" placeholder="Separate multiple CSS classes by space">
</sci-form-field>

<sci-form-field label="Count">
<input [formControl]="form.controls.count" class="e2e-count"
placeholder="Number of message boxes to open (1 by default). For every message box, an 'index-$1' CSS class is added, where $1 is the index of the message box, starting with 0.">
</sci-form-field>
</section>

<section>
<sci-form-field label="View Context Active">
<sci-checkbox [formControl]="form.controls.viewContext" class="e2e-view-context"></sci-checkbox>
<input [formControl]="form.controls.options.controls.cssClass" class="e2e-class" placeholder="Separate multiple CSS classes by space">
</sci-form-field>
</section>
</form>
Expand All @@ -75,7 +60,6 @@
{{closeAction}}
</output>

<output class="open-error e2e-open-error" *ngIf="openError">
{{openError}}
<output class="open-error e2e-message-box-error" *ngIf="messageBoxError">
{{messageBoxError}}
</output>

Loading

0 comments on commit fe690d4

Please sign in to comment.