Skip to content

Commit

Permalink
chore(tryme): use strictly typed reactive forms
Browse files Browse the repository at this point in the history
  • Loading branch information
k-genov committed Feb 4, 2025
1 parent e29d37a commit 71e1a29
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,45 @@ <h3>Login to the Solace Messaging Broker</h3>
<!-- URL -->
<mat-form-field>
<mat-label>Url</mat-label>
<input matInput [formControlName]="URL">
<input matInput [formControl]="form.controls.url">
</mat-form-field>

<!-- VPN -->
<mat-form-field>
<mat-label>VPN</mat-label>
<input matInput [formControlName]="VPN_NAME">
<input matInput [formControl]="form.controls.vpnName">
</mat-form-field>

@if (form.get(AUTHENTICATION_SCHEME)!.value === AuthenticationScheme.BASIC) {
@if (form.controls.authenticationScheme.value === AuthenticationScheme.BASIC) {
<!-- Username -->
<mat-form-field>
<mat-label>Username</mat-label>
<input matInput [formControlName]="USER_NAME">
<input matInput [formControl]="form.controls.userName">
</mat-form-field>

<!-- Password -->
<mat-form-field>
<mat-label>Password</mat-label>
<input matInput [formControlName]="PASSWORD" type="password">
<input matInput [formControl]="form.controls.password" type="password">
</mat-form-field>
}

<!-- Authentication Scheme -->
<mat-form-field>
<mat-label>Authentication Scheme</mat-label>
<mat-select [formControlName]="AUTHENTICATION_SCHEME">
<mat-select [formControl]="form.controls.authenticationScheme">
<mat-option [value]="AuthenticationScheme.BASIC">BASIC</mat-option>
<mat-option [value]="AuthenticationScheme.OAUTH2">OAUTH2</mat-option>
</mat-select>
</mat-form-field>

<!-- Reapply Subscription -->
<mat-checkbox [formControlName]="REAPPLY_SUBSCRIPTIONS">Reapply Subscriptions</mat-checkbox>
<mat-checkbox [formControl]="form.controls.reapplySubscriptions">Reapply Subscriptions</mat-checkbox>

<!-- Reconnect Retries -->
<mat-form-field>
<mat-label>Reconnect Retries</mat-label>
<input matInput type="number" [formControlName]="RECONNECT_RETRIES"/>
<input matInput type="number" [formControl]="form.controls.reconnectRetries"/>
</mat-form-field>

<!-- Buttons -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, inject} from '@angular/core';
import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {NonNullableFormBuilder, ReactiveFormsModule, Validators} from '@angular/forms';
import {LocationService} from '../location.service';
import {SolaceMessageClientConfig} from '@solace-community/angular-solace-message-client';
import {SessionConfigStore} from '../session-config-store';
Expand All @@ -14,14 +14,6 @@ import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatButtonModule} from '@angular/material/button';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

export const URL = 'url';
export const VPN_NAME = 'vpnName';
export const AUTHENTICATION_SCHEME = 'authenticationScheme';
export const USER_NAME = 'userName';
export const PASSWORD = 'password';
export const REAPPLY_SUBSCRIPTIONS = 'reapplySubscriptions';
export const RECONNECT_RETRIES = 'reconnectRetries';

@Component({
selector: 'app-login',
templateUrl: './login.component.html',
Expand All @@ -39,42 +31,35 @@ export const RECONNECT_RETRIES = 'reconnectRetries';
export class LoginComponent {

private readonly _locationService = inject(LocationService);
private readonly _formBuilder = inject(FormBuilder);
private readonly _formBuilder = inject(NonNullableFormBuilder);

protected readonly URL = URL;
protected readonly VPN_NAME = VPN_NAME;
protected readonly AUTHENTICATION_SCHEME = AUTHENTICATION_SCHEME;
protected readonly USER_NAME = USER_NAME;
protected readonly PASSWORD = PASSWORD;
protected readonly REAPPLY_SUBSCRIPTIONS = REAPPLY_SUBSCRIPTIONS;
protected readonly RECONNECT_RETRIES = RECONNECT_RETRIES;
protected readonly AuthenticationScheme = AuthenticationScheme;

protected readonly form = new FormGroup({
[URL]: this._formBuilder.control('wss://public.messaging.solace.cloud:443', {validators: Validators.required, nonNullable: true}),
[VPN_NAME]: this._formBuilder.control('public', {validators: Validators.required, nonNullable: true}),
[AUTHENTICATION_SCHEME]: this._formBuilder.control(AuthenticationScheme.BASIC),
[USER_NAME]: this._formBuilder.control('angular'),
[PASSWORD]: this._formBuilder.control('public'),
[REAPPLY_SUBSCRIPTIONS]: this._formBuilder.control(true),
[RECONNECT_RETRIES]: this._formBuilder.control(-1),
protected readonly form = this._formBuilder.group({
url: this._formBuilder.control('wss://public.messaging.solace.cloud:443', {validators: Validators.required}),
vpnName: this._formBuilder.control('public', {validators: Validators.required}),
authenticationScheme: this._formBuilder.control(AuthenticationScheme.BASIC, {validators: Validators.required}),
userName: this._formBuilder.control('angular'),
password: this._formBuilder.control('public'),
reapplySubscriptions: this._formBuilder.control(true),
reconnectRetries: this._formBuilder.control(-1),
});

constructor() {
this.installAuthenticationSchemeChangeListener();
}

protected onLogin(): void {
const oAuthEnabled = this.form.get(AUTHENTICATION_SCHEME)!.value === AuthenticationScheme.OAUTH2;
const oAuthEnabled = this.form.controls.authenticationScheme.value === AuthenticationScheme.OAUTH2;
const sessionConfig: SolaceMessageClientConfig = {
url: this.form.get(URL)!.value,
vpnName: this.form.get(VPN_NAME)!.value as string | undefined,
userName: this.form.get(USER_NAME)!.value as string | undefined,
password: this.form.get(PASSWORD)!.value as string | undefined,
reapplySubscriptions: this.form.get(REAPPLY_SUBSCRIPTIONS)!.value as boolean | undefined,
reconnectRetries: this.form.get(RECONNECT_RETRIES)!.value as number | undefined,
connectRetries: this.form.get(RECONNECT_RETRIES)!.value as number | undefined,
authenticationScheme: this.form.get(AUTHENTICATION_SCHEME)!.value as AuthenticationScheme | undefined,
url: this.form.controls.url.value,
vpnName: this.form.controls.vpnName.value,
userName: this.form.controls.userName.value,
password: this.form.controls.password.value,
reapplySubscriptions: this.form.controls.reapplySubscriptions.value,
reconnectRetries: this.form.controls.reconnectRetries.value,
connectRetries: this.form.controls.reconnectRetries.value,
authenticationScheme: this.form.controls.authenticationScheme.value,
accessToken: oAuthEnabled ? promptForAccessToken : undefined,
};

Expand All @@ -87,14 +72,14 @@ export class LoginComponent {
}

private installAuthenticationSchemeChangeListener(): void {
this.form.get(AUTHENTICATION_SCHEME)!.valueChanges
this.form.controls.authenticationScheme.valueChanges
.pipe(
startWith(undefined),
takeUntilDestroyed(),
)
.subscribe(() => {
const basicAuthFormControls = [this.form.get(USER_NAME)!, this.form.get(PASSWORD)!];
const basicAuthEnabled = this.form.get(AUTHENTICATION_SCHEME)!.value === AuthenticationScheme.BASIC;
const basicAuthFormControls = [this.form.controls.userName, this.form.controls.password];
const basicAuthEnabled = this.form.controls.authenticationScheme.value === AuthenticationScheme.BASIC;

basicAuthFormControls.forEach(formControl => {
basicAuthEnabled ? formControl.addValidators(Validators.required) : formControl.removeValidators(Validators.required);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
<!-- Destination -->
<mat-form-field class="destination">
<mat-label>Destination</mat-label>
<input matInput [formControlName]="DESTINATION">
<input matInput [formControl]="form.controls.destination">
</mat-form-field>

<!-- Destination Type -->
<mat-form-field class="destination-type">
<mat-label>Destination Type</mat-label>
<mat-select [formControlName]="DESTINATION_TYPE">
<mat-select [formControl]="form.controls.destinationType">
<mat-option [value]="DestinationType.TOPIC">Topic</mat-option>
<mat-option [value]="DestinationType.QUEUE">Queue</mat-option>
</mat-select>
Expand All @@ -23,13 +23,13 @@
<!-- Message -->
<mat-form-field>
<mat-label>Message</mat-label>
<textarea matInput [formControlName]="MESSAGE" class="message"></textarea>
<textarea matInput [formControl]="form.controls.message" class="message"></textarea>
</mat-form-field>

<!-- Message Type -->
<mat-form-field class="message-type">
<mat-label>Message Type</mat-label>
<mat-select [formControlName]="MESSAGE_TYPE">
<mat-select [formControl]="form.controls.messageType">
<mat-option [value]="MessageType.BINARY">Binary</mat-option>
<mat-option [value]="MessageType.TEXT">Text</mat-option>
</mat-select>
Expand All @@ -38,7 +38,7 @@
<!-- Message Delivery Mode -->
<mat-form-field class="message-delivery-mode">
<mat-label>Message Delivery Mode</mat-label>
<mat-select [formControlName]="DELIVERY_MODE">
<mat-select [formControl]="form.controls.deliveryMode">
<mat-option [value]="MessageDeliveryModeType.DIRECT">Direct (default)</mat-option>
<mat-option [value]="MessageDeliveryModeType.PERSISTENT">Persistent</mat-option>
</mat-select>
Expand All @@ -47,16 +47,15 @@
<!-- Headers -->
<mat-form-field>
<mat-label>Headers</mat-label>
<input matInput [formControlName]="HEADERS" placeholder="name->value;name->value">
<input matInput [formControl]="form.controls.headers" placeholder="name->value;name->value">
</mat-form-field>

<!-- Request/Reply -->
<mat-checkbox [formControlName]="REQUEST_REPLY">Request/Reply</mat-checkbox>
<mat-checkbox [formControl]="form.controls.requestReply">Request/Reply</mat-checkbox>

@if (publishing) {
<button mat-stroked-button color="primary" (click)="onCancelPublish()">Cancel</button>
}
@else {
} @else {
<button mat-stroked-button color="primary" (click)="onPublish()" [disabled]="form.invalid">Publish</button>
}
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject} from '@angular/core';
import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {NonNullableFormBuilder, ReactiveFormsModule, Validators} from '@angular/forms';
import {DestinationType, MessageDeliveryModeType, MessageType, SDTField, SDTFieldType, SolclientFactory} from 'solclientjs';
import {Data, MessageEnvelope, PublishOptions, SolaceMessageClient} from '@solace-community/angular-solace-message-client';
import {defer, Observable, Subscription, tap, throwError} from 'rxjs';
Expand All @@ -15,14 +15,6 @@ import {MatInputModule} from '@angular/material/input';
import {MatButtonModule} from '@angular/material/button';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

export const DESTINATION = 'destination';
export const DESTINATION_TYPE = 'destinationType';
export const DELIVERY_MODE = 'deliveryMode';
export const MESSAGE = 'message';
export const MESSAGE_TYPE = 'messageType';
export const HEADERS = 'headers';
export const REQUEST_REPLY = 'request/reply';

@Component({
selector: 'app-publisher',
templateUrl: './publisher.component.html',
Expand All @@ -44,29 +36,21 @@ export class PublisherComponent {

private readonly _solaceMessageClient = inject(SolaceMessageClient);
private readonly _cd = inject(ChangeDetectorRef);
private readonly _formBuilder = inject(FormBuilder);
private readonly _formBuilder = inject(NonNullableFormBuilder);
private readonly _destroyRef = inject(DestroyRef);

protected readonly DESTINATION = DESTINATION;
protected readonly DESTINATION_TYPE = DESTINATION_TYPE;
protected readonly DELIVERY_MODE = DELIVERY_MODE;
protected readonly MESSAGE = MESSAGE;
protected readonly MESSAGE_TYPE = MESSAGE_TYPE;
protected readonly HEADERS = HEADERS;
protected readonly REQUEST_REPLY = REQUEST_REPLY;

protected readonly MessageType = MessageType;
protected readonly DestinationType = DestinationType;
protected readonly MessageDeliveryModeType = MessageDeliveryModeType;

protected readonly form = new FormGroup({
[DESTINATION]: this._formBuilder.control('', Validators.required),
[DESTINATION_TYPE]: this._formBuilder.control(DestinationType.TOPIC, Validators.required),
[DELIVERY_MODE]: this._formBuilder.control(undefined),
[MESSAGE]: this._formBuilder.control(''),
[MESSAGE_TYPE]: this._formBuilder.control(MessageType.BINARY, Validators.required),
[HEADERS]: this._formBuilder.control(''),
[REQUEST_REPLY]: this._formBuilder.control(false),
protected readonly form = this._formBuilder.group({
destination: this._formBuilder.control('', Validators.required),
destinationType: this._formBuilder.control(DestinationType.TOPIC, Validators.required),
deliveryMode: this._formBuilder.control(MessageDeliveryModeType.DIRECT),
message: this._formBuilder.control(''),
messageType: this._formBuilder.control(MessageType.BINARY, Validators.required),
headers: this._formBuilder.control(''),
requestReply: this._formBuilder.control(false),
});

private _publishSubscription: Subscription | null = null;
Expand Down Expand Up @@ -107,8 +91,8 @@ export class PublisherComponent {

private publish$(): Observable<any> {
try {
const destination = this.form.get(DESTINATION)!.value!;
const destinationType = this.form.get(DESTINATION_TYPE)!.value;
const destination = this.form.controls.destination.value;
const destinationType = this.form.controls.destinationType.value;
const message: Data | undefined = this.readMessageFromUI();
const publishOptions: PublishOptions = this.readPublishOptionsFromUI();

Expand Down Expand Up @@ -148,7 +132,7 @@ export class PublisherComponent {
}

protected get requestReply(): boolean {
return this.form.get(REQUEST_REPLY)!.value!;
return this.form.controls.requestReply.value;
}

protected get publishing(): boolean {
Expand All @@ -158,17 +142,17 @@ export class PublisherComponent {
private readPublishOptionsFromUI(): PublishOptions {
return {
headers: this.readHeadersFromUI(),
deliveryMode: this.form.get(DELIVERY_MODE)!.value! as MessageDeliveryModeType,
deliveryMode: this.form.controls.deliveryMode.value,
};
}

private readMessageFromUI(): Data | undefined {
const message = this.form.get(MESSAGE)!.value as string | undefined;
const message = this.form.controls.message.value;
if (!message) {
return undefined;
}

if (this.form.get(MESSAGE_TYPE)!.value === MessageType.TEXT) {
if (this.form.controls.messageType.value === MessageType.TEXT) {
return SDTField.create(SDTFieldType.STRING, message); // structuredTextMessage
}
else {
Expand All @@ -177,7 +161,7 @@ export class PublisherComponent {
}

private readHeadersFromUI(): Map<string, string | boolean | number> | undefined {
const headers = this.form.get(HEADERS)!.value!;
const headers = this.form.controls.headers.value;
if (!headers.length) {
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
<ng-container [formGroup]="form">
<section class="subscription" [formGroupName]="SUBSCRIPTION">
<section class="subscription" [formGroup]="form.controls.subscription">
<!-- Destination -->
<mat-form-field>
<mat-label>Destination</mat-label>
<input matInput [formControlName]="DESTINATION" appAutoFocus>
<input matInput [formControl]="form.controls.subscription.controls.destination" appAutoFocus>
</mat-form-field>

<!-- Destination Type -->
<mat-form-field>
<mat-label>Destination Type</mat-label>
<mat-select [formControlName]="DESTINATION_TYPE">
<mat-option [value]="SubscriptionDestinationType.TOPIC" [matTooltip]="tooltips.topic" matTooltipClass="large">Topic</mat-option>
<mat-option [value]="SubscriptionDestinationType.QUEUE" [matTooltip]="tooltips.queue" matTooltipClass="large">Queue</mat-option>
<mat-option [value]="SubscriptionDestinationType.TOPIC_ENDPOINT" [matTooltip]="tooltips.topicEndpoint" matTooltipClass="large">Topic Endpoint</mat-option>
<mat-option [value]="SubscriptionDestinationType.QUEUE_BROWSER" [matTooltip]="tooltips.queueBrowser" matTooltipClass="large">Queue Browser</mat-option>
<mat-select [formControl]="form.controls.subscription.controls.destinationType">
<mat-option value="TOPIC" [matTooltip]="tooltips.topic" matTooltipClass="large">Topic</mat-option>
<mat-option value="QUEUE" [matTooltip]="tooltips.queue" matTooltipClass="large">Queue</mat-option>
<mat-option value="TOPIC_ENDPOINT" [matTooltip]="tooltips.topicEndpoint" matTooltipClass="large">Topic Endpoint</mat-option>
<mat-option value="QUEUE_BROWSER" [matTooltip]="tooltips.queueBrowser" matTooltipClass="large">Queue Browser</mat-option>
</mat-select>
</mat-form-field>

<!-- Subscribe/Unsubscribe -->
@if (isSubscribed) {
<button mat-stroked-button color="primary" (click)="onUnsubscribe()" [disabled]="form.invalid" class="unsubscribe">Unsubscribe</button>
}
@else {
} @else {
<button mat-stroked-button color="primary" (click)="onSubscribe()" [disabled]="form.invalid" class="subscribe">Subscribe</button>
}
</section>
Expand All @@ -37,7 +36,7 @@
</sci-viewport>

<!-- Follow tail -->
<mat-checkbox [formControlName]="FOLLOW_TAIL" color="primary" class="follow-tail">Follow tail</mat-checkbox>
<mat-checkbox [formControl]="form.controls.followTail" color="primary" class="follow-tail">Follow tail</mat-checkbox>

<footer>
@if (envelopes.length) {
Expand Down
Loading

0 comments on commit 71e1a29

Please sign in to comment.