Skip to content

Commit

Permalink
feat(ui): show group in ui settings
Browse files Browse the repository at this point in the history
  • Loading branch information
timonback committed Nov 3, 2024
1 parent 56ca9df commit 5616f27
Show file tree
Hide file tree
Showing 27 changed files with 473 additions and 78 deletions.
12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ allprojects {

doLast { // ensure that the code is not executed as part of a gradle refresh
plugins.forEach {
project
.file('springwolf-examples/' + it + '-example/src/test/resources/asyncapi.actual.json')
.renameTo('springwolf-examples/' + it + '-example/src/test/resources/asyncapi.json')
project
.file('springwolf-examples/' + it + '-example/src/test/resources/asyncapi.actual.yaml')
.renameTo('springwolf-examples/' + it + '-example/src/test/resources/asyncapi.yaml')
project.fileTree(dir: project.projectDir, include: '**/src/test/resources/**/*.actual.json').forEach { file ->
file.renameTo(file.path.replace('.actual.json', '.json'))
}
project.fileTree(dir: project.projectDir, include: '**/src/test/resources/**/*.actual.yaml').forEach { file ->
file.renameTo(file.path.replace('.actual.yaml', '.yaml'))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Map<String, AsyncAPI> group(AsyncAPI asyncAPI) {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

private Stream<AsyncApiGroup> getAsyncApiGroups() {
public Stream<AsyncApiGroup> getAsyncApiGroups() {
return springwolfConfigProperties.getDocket().getGroupConfigs().stream()
.map(AsyncApiGroupService::toGroupConfigAndValidate);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ private void markChannels(AsyncAPI fullAsyncApi, AsyncApiGroup asyncApiGroup, Ma

markOperationsInChannel(fullAsyncApi, markingContext, channel);

markingContext.markedComponentMessageIds.addAll(
channel.getMessages().keySet());
channel.getMessages().keySet().forEach(markingContext.markedComponentMessageIds::add);
});
}

Expand Down Expand Up @@ -93,11 +92,10 @@ private void markOperations(AsyncAPI fullAsyncApi, AsyncApiGroup asyncApiGroup,

markChannelsForOperation(fullAsyncApi, markingContext, operationEntry.getValue());

Set<String> messageIds = operationEntry.getValue().getMessages().stream()
operationEntry.getValue().getMessages().stream()
.map(MessageReference::getRef)
.map(ReferenceUtil::getLastSegment)
.collect(Collectors.toSet());
markingContext.markedComponentMessageIds.addAll(messageIds);
.forEach(markingContext.markedComponentMessageIds::add);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import io.github.springwolf.asyncapi.v3.jackson.DefaultAsyncApiSerializerService;
import io.github.springwolf.core.asyncapi.AsyncApiService;
import io.github.springwolf.core.asyncapi.components.ComponentsService;
import io.github.springwolf.core.asyncapi.grouping.AsyncApiGroupService;
import io.github.springwolf.core.controller.ActuatorAsyncApiController;
import io.github.springwolf.core.controller.AsyncApiController;
import io.github.springwolf.core.controller.PublishingPayloadCreator;
import io.github.springwolf.core.controller.UiConfigController;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -47,6 +49,13 @@ public ActuatorAsyncApiController actuatorAsyncApiController(
return new ActuatorAsyncApiController(asyncApiService, asyncApiSerializerService);
}

@Bean
@ConditionalOnProperty(name = SPRINGWOLF_ENDPOINT_ACTUATOR_ENABLED, havingValue = "false", matchIfMissing = true)
@ConditionalOnMissingBean
public UiConfigController uiConfigController(AsyncApiGroupService asyncApiGroupService) {
return new UiConfigController(asyncApiGroupService);
}

@Bean
@ConditionalOnMissingBean
public AsyncApiSerializerService asyncApiSerializerService() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.controller;

import io.github.springwolf.core.asyncapi.grouping.AsyncApiGroupService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
public class UiConfigController {

private final AsyncApiGroupService asyncApiGroupService;

@GetMapping(
path = {"${springwolf.path.base:/springwolf}/ui-config"},
produces = MediaType.APPLICATION_JSON_VALUE)
public UiConfig getUiConfig() {
return new UiConfig(asyncApiGroupService
.getAsyncApiGroups()
.map(el -> new UiConfig.UiConfigGroup(el.getGroupName()))
.toList());
}

private record UiConfig(List<UiConfigGroup> groups) {
private record UiConfigGroup(String name) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -56,12 +55,28 @@ void asyncApiResourceArtifactYamlTest() throws IOException {
}

@Test
void asyncApiResourceForGroupArtifactTest() {
// when
void asyncApiResourceForVehicleGroupArtifactTest() throws IOException {
String url = "/springwolf/docs/Only Vehicles";
ResponseEntity<String> actual = restTemplate.getForEntity(url, String.class);
String actual = restTemplate.getForObject(url, String.class);
// When running with EmbeddedKafka, the kafka bootstrap server does run on random ports
String actualPatched = actual.replace(bootstrapServers, "kafka:29092").trim();
Files.writeString(Path.of("src", "test", "resources", "groups", "vehicles.actual.json"), actualPatched);

InputStream s = this.getClass().getResourceAsStream("/groups/vehicles.json");
String expected = new String(s.readAllBytes(), StandardCharsets.UTF_8).trim();

assertEquals(expected, actualPatched);
}

@Test
void uiConfigTest() throws IOException {
String url = "/springwolf/ui-config";
String actual = restTemplate.getForObject(url, String.class);
Files.writeString(Path.of("src", "test", "resources", "ui-config.actual.json"), actual);

InputStream s = this.getClass().getResourceAsStream("/ui-config.json");
String expected = new String(s.readAllBytes(), StandardCharsets.UTF_8).trim();

// then
assertEquals(200, actual.getStatusCode().value());
assertEquals(expected, actual);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{
"asyncapi": "3.0.0",
"info": {
"title": "Springwolf example project - Kafka",
"version": "1.0.0",
"description": "Springwolf example project to demonstrate springwolfs abilities, including **markdown** support for descriptions.",
"contact": {
"name": "springwolf",
"url": "https://github.com/springwolf/springwolf-core",
"email": "example@example.com"
},
"license": {
"name": "Apache License 2.0"
},
"x-generator": "springwolf"
},
"defaultContentType": "application/json",
"servers": {
"kafka-server": {
"host": "kafka:29092",
"protocol": "kafka"
}
},
"channels": {
"vehicle-topic": {
"address": "vehicle-topic",
"messages": {
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase": {
"$ref": "#/components/messages/io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
}
},
"bindings": {
"kafka": {
"bindingVersion": "0.5.0"
}
}
}
},
"components": {
"schemas": {
"SpringKafkaDefaultHeaders-VehicleBase": {
"title": "SpringKafkaDefaultHeaders-VehicleBase",
"type": "object",
"properties": {
"__TypeId__": {
"type": "string",
"description": "Spring Type Id Header",
"enum": [
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
],
"examples": [
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
]
}
},
"examples": [
{
"__TypeId__": "io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
}
],
"x-json-schema": {
"$schema": "https://json-schema.org/draft-04/schema#",
"properties": {
"__TypeId__": {
"description": "Spring Type Id Header",
"enum": [
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
],
"type": "string"
}
},
"title": "SpringKafkaDefaultHeaders-VehicleBase",
"type": "object"
}
},
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase": {
"discriminator": "vehicleType",
"title": "VehicleBase",
"type": "object",
"properties": {
"powerSource": {
"type": "string"
},
"topSpeed": {
"type": "integer",
"format": "int32"
},
"vehicleType": {
"type": "string"
}
},
"description": "Demonstrates the use of discriminator for polymorphic deserialization (not publishable)",
"examples": [
{
"powerSource": "string",
"topSpeed": 0,
"vehicleType": "string"
}
],
"x-json-schema": {
"$schema": "https://json-schema.org/draft-04/schema#",
"description": "Demonstrates the use of discriminator for polymorphic deserialization (not publishable)",
"properties": {
"powerSource": {
"type": "string"
},
"topSpeed": {
"format": "int32",
"type": "integer"
},
"vehicleType": { }
},
"title": "VehicleBase",
"type": "object"
}
}
},
"messages": {
"io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase": {
"headers": {
"$ref": "#/components/schemas/SpringKafkaDefaultHeaders-VehicleBase"
},
"payload": {
"schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0",
"schema": {
"$ref": "#/components/schemas/io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
}
},
"name": "io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase",
"title": "VehicleBase",
"bindings": {
"kafka": {
"bindingVersion": "0.5.0"
}
}
}
}
},
"operations": {
"vehicle-topic_receive_receiveExamplePayload": {
"action": "receive",
"channel": {
"$ref": "#/channels/vehicle-topic"
},
"bindings": {
"kafka": {
"bindingVersion": "0.5.0"
}
},
"messages": [
{
"$ref": "#/channels/vehicle-topic/messages/io.github.springwolf.examples.kafka.dtos.discriminator.VehicleBase"
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"groups":[{"name":"Only Vehicles"}]}
3 changes: 1 addition & 2 deletions springwolf-ui/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 */
import { Component, OnInit } from "@angular/core";
import { UiService } from "./service/ui.service";
import { Component } from "@angular/core";

@Component({
selector: "app-root",
Expand Down
4 changes: 2 additions & 2 deletions springwolf-ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { FormsModule } from "@angular/forms";
import { JsonComponent } from "./components/json/json.component";
import { AsyncApiMapperService } from "./service/asyncapi/asyncapi-mapper.service";
import { MarkdownModule, provideMarkdown } from "ngx-markdown";
import { UiService } from "./service/ui.service";
import { IUiService, UiService } from "./service/ui.service";
import { provideAnimationsAsync } from "@angular/platform-browser/animations/async";
import { SidenavComponent } from "./components/sidenav/sidenav.component";
import { NavigationTargetDirective } from "./components/sidenav/navigation.directive";
Expand Down Expand Up @@ -80,7 +80,7 @@ export const providers = [
AsyncApiMapperService,
{ provide: INotificationService, useClass: NotificationService },
PublisherService,
UiService,
{ provide: IUiService, useClass: UiService },
];

export const ngModule = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
mockedAsyncApiService,
mockedExampleSchemaMapped,
} from "../../../service/mock/mock-asyncapi.service";
import { mockedUiService } from "../../../service/mock/mock-ui.service";
import {
MockAppJson,
MockAppSchemaNewComponent,
MockPrismEditorComponent,
} from "../../mock-components.spec";
import { IUiService } from "../../../service/ui.service";

describe("ChannelOperationComponent", () => {
const mockData = mockedExampleSchemaMapped.channelOperations
Expand All @@ -31,6 +33,7 @@ describe("ChannelOperationComponent", () => {
],
imports: [MaterialModule, MarkdownModule.forRoot()],
providers: [
{ provide: IUiService, useValue: mockedUiService },
{ provide: AsyncApiService, useValue: mockedAsyncApiService },
{ provide: PublisherService, useValue: {} },
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
initSchema,
noExample,
} from "../../../service/mock/init-values";
import { UiService } from "../../../service/ui.service";
import { IUiService } from "../../../service/ui.service";

@Component({
selector: "app-channel-operation",
Expand All @@ -39,14 +39,14 @@ export class ChannelOperationComponent implements OnInit {
operationBindingExampleString?: string;
messageBindingExampleString?: string;

isShowBindings: boolean = UiService.DEFAULT_SHOW_BINDINGS;
isShowHeaders: boolean = UiService.DEFAULT_SHOW_HEADERS;
isShowBindings: boolean = IUiService.DEFAULT_SHOW_BINDINGS;
isShowHeaders: boolean = IUiService.DEFAULT_SHOW_HEADERS;
canPublish: boolean = false;

constructor(
private asyncApiService: AsyncApiService,
private publisherService: PublisherService,
private uiService: UiService,
private uiService: IUiService,
private snackBar: MatSnackBar
) {}

Expand Down
Loading

0 comments on commit 5616f27

Please sign in to comment.