Skip to content
This repository has been archived by the owner on Jun 18, 2023. It is now read-only.

Commit

Permalink
Feature/add message binding to channel documentation (#35)
Browse files Browse the repository at this point in the history
* feat: Add new tab with message binding to channel documentation and add header and message binding example to example tab

* Add message binding to the request made by PublisherService so that the backend can use the message binding to construct a message

* Improve mapping of message bindings to be more resilient if a backend creates a specification without message binding

* Rename Binding in example tab to Message Binding and add full payload to log statement when producing messages

* Display raw message bindings

Regression: Previously included mapped ui attributes
chore: Improve [protocol: string]: any typings

Co-authored-by: [email protected]

---------

Co-authored-by: Timon Back <[email protected]>
  • Loading branch information
sam0r040 and timonback authored Mar 10, 2023
1 parent 9c3cf8e commit bca7d2b
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 83 deletions.
4 changes: 4 additions & 0 deletions src/app/channels/channel-main/channel-main.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ button {
padding: 6px;
font-weight: normal;
}

[hidden] {
display: none !important;
}
60 changes: 44 additions & 16 deletions src/app/channels/channel-main/channel-main.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,51 @@ <h4>{{ operation.message.description }}</h4>
<mat-tab-group animationDuration="0ms">
<mat-tab label="Example">
<div fxLayout="column">
<textarea spellcheck="false"
#exampleTextArea
[rows]="exampleTextAreaLineCount"
[value]="defaultExample?.value"
(keyup)="recalculateLineCount('example', exampleTextArea.value)"
></textarea>
<div [hidden]="isEmptyObject(operation.message.bindings.get(protocolName))" fxLayout="column" fxLayoutGap="5px">
<h4>Message Binding</h4>
<textarea spellcheck="false"
#bindingTextArea
[rows]="messageBindingExampleTextAreaLineCount"
[value]="createMessageBindingExample(operation.message.bindings.get(protocolName))?.value"
(keyup)="recalculateLineCount('massageBindingExample', bindingTextArea.value)"
></textarea>
</div>
<div [hidden]="!(headersExample?.lineCount > 1)" fxLayout="column" fxLayoutGap="0px">

<h4>Header</h4>
<textarea spellcheck="false"
#headersTextArea
[rows]="headersTextAreaLineCount"
[value]="headersExample?.value"
(keyup)="recalculateLineCount('headers', headersTextArea.value)"
></textarea>

</div>
<div fxLayout="column" fxLayoutGap="5px">
<h4>Message</h4>
<textarea spellcheck="false"
#messageTextArea
[rows]="exampleTextAreaLineCount"
[value]="defaultExample?.value"
(keyup)="recalculateLineCount('example', messageTextArea.value)"
></textarea>
</div>
<div fxLayout fxLayoutGap="8px">
<button mat-raised-button color="primary" (click)="publish(exampleTextArea.value, headersTextArea.value)">
<button mat-raised-button color="primary"
(click)="publish(messageTextArea.value, headersTextArea?.value, bindingTextArea?.value)">
Publish
</button>
<button mat-raised-button color="primary"
(click)="exampleTextArea.value = defaultExample.value; exampleTextAreaLineCount=defaultExample.lineCount">
(click)="
messageTextArea.value = defaultExample.value;
exampleTextAreaLineCount = defaultExample.lineCount || 0;
headersTextArea.value = headersExample?.value;
headersTextAreaLineCount = headersExample?.lineCount || 0;
bindingTextArea.value = createMessageBindingExample(operation.message.bindings.get(protocolName))?.value;
messageBindingExampleTextAreaLineCount = messageBindingExample?.lineCount || 0">
Default
</button>
<button mat-raised-button color="primary" [cdkCopyToClipboard]="exampleTextArea.value">Copy</button>
<button mat-raised-button color="primary" [cdkCopyToClipboard]="messageTextArea.value">Copy</button>
</div>
</div>
</mat-tab>
Expand All @@ -43,16 +73,14 @@ <h4>
</h4>
<app-schema *ngIf="headers" [schema]="headers"></app-schema>
<div fxLayout="column">
<textarea spellcheck="false"
#headersTextArea
[rows]="headersTextAreaLineCount"
[value]="headersExample?.value"
(keyup)="recalculateLineCount('headers', headersTextArea.value)"
></textarea>
<app-json [json]="headersExample?.value"></app-json>
</div>
</mat-tab>
<mat-tab label="Bindings">
<mat-tab label="Operation Bindings">
<app-json [data]="operation.bindings[protocolName]"></app-json>
</mat-tab>
<mat-tab label="Message Bindings">
<app-json [data]="operation.message.rawBindings[protocolName]"></app-json>
</mat-tab>
</mat-tab-group>
</section>
58 changes: 48 additions & 10 deletions src/app/channels/channel-main/channel-main.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Example } from 'src/app/shared/models/example.model';
import { Schema } from 'src/app/shared/models/schema.model';
import { PublisherService } from 'src/app/shared/publisher.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Operation } from 'src/app/shared/models/channel.model';
import {MessageBinding, Operation} from 'src/app/shared/models/channel.model';
import { STATUS } from 'angular-in-memory-web-api';

@Component({
Expand All @@ -27,6 +27,8 @@ export class ChannelMainComponent implements OnInit {
headersExample: Example;
headersTextAreaLineCount: number;
protocolName: string;
messageBindingExample?: Example;
messageBindingExampleTextAreaLineCount: number;

constructor(
private asyncApiService: AsyncApiService,
Expand All @@ -38,47 +40,83 @@ export class ChannelMainComponent implements OnInit {
ngOnInit(): void {
this.asyncApiService.getAsyncApi().subscribe(
asyncapi => {
let schemas: Map<string, Schema> = asyncapi.components.schemas;
this.schemaName = this.operation.message.payload.name.slice(this.operation.message.payload.name.lastIndexOf('/') + 1)
const schemas: Map<string, Schema> = asyncapi.components.schemas;
this.schemaName = this.operation.message.payload.name.slice(this.operation.message.payload.name.lastIndexOf('/') + 1);
this.schema = schemas.get(this.schemaName);

this.defaultExample = this.schema.example;
this.exampleTextAreaLineCount = this.defaultExample?.lineCount || 0;

this.headersSchemaName = this.operation.message.headers.name.slice(this.operation.message.headers.name.lastIndexOf('/') + 1)
this.headersSchemaName = this.operation.message.headers.name.slice(this.operation.message.headers.name.lastIndexOf('/') + 1);
this.headers = schemas.get(this.headersSchemaName);
this.headersExample = this.headers.example;
this.headersTextAreaLineCount = this.headersExample?.lineCount || 0;
this.messageBindingExampleTextAreaLineCount = this.messageBindingExample?.lineCount || 0;
}
);

this.protocolName = Object.keys(this.operation.bindings)[0];
}

isEmptyObject(object?: any): boolean {
return (object === undefined || object === null) || Object.keys(object).length === 0;
}

createMessageBindingExample(messageBinding?: MessageBinding): Example | undefined {
if (messageBinding === undefined || messageBinding === null) {
return undefined;
}

const bindingExampleObject = {};
Object.keys(messageBinding).forEach((bindingKey) => {
if (bindingKey !== 'bindingVersion') {
bindingExampleObject[bindingKey] = this.getExampleValue(messageBinding[bindingKey]);
}
});

const bindingExample = new Example(bindingExampleObject);

this.messageBindingExampleTextAreaLineCount = bindingExample.lineCount;

return bindingExample;
}

getExampleValue(bindingValue: string | Schema): any {
if (typeof bindingValue === 'string') {
return bindingValue;
} else {
return bindingValue.example.value;
}
}

recalculateLineCount(field: string, text: string): void {
switch (field) {
case 'example':
this.exampleTextAreaLineCount = text.split('\n').length;
break;
case 'headers':
this.headersTextAreaLineCount = text.split('\n').length
this.headersTextAreaLineCount = text.split('\n').length;
break;
case 'massageBindingExample':
this.messageBindingExampleTextAreaLineCount = text.split('\n').length;
break;
}
}

publish(example: string, headers: string): void {
publish(example: string, headers?: string, bindings?: string): void {
try {
const payloadJson = JSON.parse(example);
const headersJson = JSON.parse(headers)
const headersJson = JSON.parse(headers);
const bindingsJson = JSON.parse(bindings);

this.publisherService.publish(this.protocolName, this.channelName, payloadJson, headersJson).subscribe(
this.publisherService.publish(this.protocolName, this.channelName, payloadJson, headersJson, bindingsJson).subscribe(
_ => this.handlePublishSuccess(),
err => this.handlePublishError(err)
);
} catch(error) {
} catch (error) {
this.snackBar.open('Example payload is not valid', 'ERROR', {
duration: 3000
})
});
}
}

Expand Down
Loading

0 comments on commit bca7d2b

Please sign in to comment.