Skip to content

Commit

Permalink
feat: add slots and refactoring methods
Browse files Browse the repository at this point in the history
  • Loading branch information
andrejpetras committed Apr 24, 2024
1 parent b91026a commit e78d9f2
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 16 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
<goal>wget</goal>
</goals>
<configuration>
<url>https://raw.githubusercontent.com/onecx/onecx-product-store-svc/main/src/main/openapi/onecx-product-store-v1.yaml</url>
<url>https://raw.githubusercontent.com/onecx/onecx-product-store-svc/feat/add-slots/src/main/openapi/onecx-product-store-v1.yaml</url>
<outputDirectory>target/tmp/openapi</outputDirectory>
<outputFileName>onecx-product-store-svc-v1.yaml</outputFileName>
<skipCache>true</skipCache>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
import org.tkit.quarkus.log.cdi.LogService;

import gen.org.tkit.onecx.product.store.client.api.ProductsApi;
import gen.org.tkit.onecx.product.store.client.model.MicrofrontendTypePSV1;
import gen.org.tkit.onecx.product.store.client.model.ProductPSV1;
import gen.org.tkit.onecx.product.store.client.model.*;
import gen.org.tkit.onecx.shell.bff.rs.internal.WorkspaceConfigApiService;
import gen.org.tkit.onecx.shell.bff.rs.internal.model.*;
import gen.org.tkit.onecx.theme.client.api.ThemesApi;
import gen.org.tkit.onecx.theme.client.model.Theme;
import gen.org.tkit.onecx.workspace.client.api.WorkspaceExternalApi;
import gen.org.tkit.onecx.workspace.client.model.Workspace;
import gen.org.tkit.onecx.workspace.client.model.WorkspaceLoad;
import gen.org.tkit.onecx.workspace.client.model.*;

@ApplicationScoped
@Transactional(value = Transactional.TxType.NOT_SUPPORTED)
Expand Down Expand Up @@ -123,6 +121,37 @@ public Response getWorkspaceConfig(GetWorkspaceConfigRequestDTO getWorkspaceConf
}
}

@Override
public Response loadWorkspaceConfig(LoadWorkspaceConfigRequestDTO loadWorkspaceConfigRequestDTO) {
try (Response response = workspaceClient.loadWorkspaceByRequest(mapper.createRequest(loadWorkspaceConfigRequestDTO))) {
var wrapper = response.readEntity(WorkspaceWrapper.class);
if (wrapper == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}

var result = mapper.createResponse(wrapper);

// load products and create corresponding module and components
if (wrapper.getProducts() != null) {
try (Response psResponse = productStoreClient.loadProductsByNames(mapper.create(wrapper))) {
var productResponse = psResponse.readEntity(LoadProductResponsePSV1.class);
mapper.createMfeAndComponents(result, wrapper, productResponse);
}
}

// create slots
result.setSlots(mapper.createSlots(wrapper.getSlots()));

//get theme info
try (Response themeResponse = themeClient.getThemeByName(wrapper.getTheme())) {
var theme = themeResponse.readEntity(Theme.class);
result.setTheme(mapper.createTheme(theme, uriInfo.getPath()));
}

return Response.ok(result).build();
}
}

@Override
public Response getThemeFaviconByName(String name) {
Response.ResponseBuilder responseBuilder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.tkit.onecx.shell.bff.rs.mappers;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;

import gen.org.tkit.onecx.product.store.client.model.MicrofrontendPSV1;
import gen.org.tkit.onecx.product.store.client.model.ProductPSV1;
import gen.org.tkit.onecx.product.store.client.model.*;
import gen.org.tkit.onecx.shell.bff.rs.internal.model.*;
import gen.org.tkit.onecx.theme.client.model.Theme;
import gen.org.tkit.onecx.workspace.client.model.GetWorkspaceByUrlRequest;
import gen.org.tkit.onecx.workspace.client.model.Microfrontend;
import gen.org.tkit.onecx.workspace.client.model.Workspace;
import gen.org.tkit.onecx.workspace.client.model.*;

@Mapper
public interface WorkspaceConfigMapper {
Expand Down Expand Up @@ -41,4 +42,126 @@ default RouteDTO mapRoute(MicrofrontendPSV1 mfe, ProductPSV1 product,
}
return route;
}

WorkspaceLoadRequest createRequest(LoadWorkspaceConfigRequestDTO dto);

default LoadWorkspaceConfigResponseDTO createResponse(WorkspaceWrapper workspaceWrapper) {
return new LoadWorkspaceConfigResponseDTO().workspace(createWorkspace(workspaceWrapper));
}

WorkspaceDTO createWorkspace(WorkspaceWrapper workspaceWrapper);

@Mapping(target = "name", ignore = true)
@Mapping(target = "baseUrl", source = "mfe.remoteBaseUrl")
@Mapping(target = "remoteEntryUrl", source = "mfe.remoteEntry")
@Mapping(target = "productName", source = "product.name")
RemoteComponentDTO createComponent(LoadProductItemPSV1 product, LoadProductMicrofrontendPSV1 mfe);

@AfterMapping
default void componentName(@MappingTarget RemoteComponentDTO target, LoadProductItemPSV1 product,
LoadProductMicrofrontendPSV1 mfe) {
target.setName(componentName(product, mfe));
}

default String componentName(LoadProductItemPSV1 product, LoadProductMicrofrontendPSV1 mfe) {
String name = "";
if (product != null) {
name = product.getName();
}
if (mfe == null) {
return name;
}
return componentName(name, mfe.getAppId(), mfe.getExposedModule());
}

default String componentName(String productName, String appId, String exposedModule) {
return productName + "#" + appId + "#" + exposedModule;
}

@Mapping(target = "technology", constant = "ANGULAR")
@Mapping(target = "url", source = "mfe.remoteBaseUrl")
@Mapping(target = "pathMatch", constant = "PREFIX")
@Mapping(target = "baseUrl", ignore = true)
@Mapping(target = "remoteEntryUrl", source = "mfe.remoteEntry")
@Mapping(target = "displayName", source = "product.displayName")
@Mapping(target = "productName", source = "product.name")
@Mapping(target = "appId", source = "mfe.appId")
@Mapping(target = "exposedModule", source = "mfe.exposedModule")
@Mapping(target = "remoteName", source = "mfe.remoteName")
RouteDTO createRoute(LoadProductItemPSV1 product, LoadProductMicrofrontendPSV1 mfe, Map<String, String> pathMapping,
WorkspaceWrapper workspace);

@AfterMapping
default void createRouteAfter(@MappingTarget RouteDTO target, Map<String, String> pathMapping, WorkspaceWrapper workspace) {
var modulePath = pathMapping.get(target.getAppId());
if (modulePath != null) {
target.setBaseUrl(workspace.getBaseUrl() + modulePath);
}
}

List<SlotDTO> createSlots(List<WorkspaceWrapperSlot> slots);

default SlotDTO createSlot(WorkspaceWrapperSlot slot) {
if (slot == null) {
return null;
}

SlotDTO result = new SlotDTO().name(slot.getName());
if (slot.getComponents() != null) {
slot.getComponents().forEach(c -> {
result.addComponentsItem(componentName(c.getProductName(), c.getAppId(), c.getName()));
});
}
return result;
}

@Mapping(target = "properties", ignore = true)
ThemeDTO createTheme(Theme themeInfo, String path);

@AfterMapping
default void createThemeAfter(@MappingTarget ThemeDTO target, Theme themeInfo, String path) {
if (themeInfo != null) {
target.setProperties(String.valueOf(themeInfo.getProperties()));
}
if (target.getFaviconUrl() == null) {
target.setFaviconUrl(path + "/themes/" + target.getName() + "/favicon");
}
if (target.getLogoUrl() == null) {
target.setLogoUrl(path + "/themes/" + target.getName() + "/logo");
}
}

default LoadProductRequestPSV1 create(WorkspaceWrapper wrapper) {
return new LoadProductRequestPSV1().productNames(wrapper.getProducts().stream().map(Product::getProductName).toList());
}

default void createMfeAndComponents(LoadWorkspaceConfigResponseDTO result, WorkspaceWrapper wrapper,
LoadProductResponsePSV1 loadProducts) {
if (loadProducts == null || loadProducts.getProducts() == null) {
return;
}

var workspaceProducts = wrapper.getProducts().stream().collect(Collectors.toMap(Product::getProductName, p -> p));

loadProducts.getProducts().forEach(product -> {

var workspaceProduct = workspaceProducts.get(product.getName());

// create mapping APP_ID -> PATH
var pathMapping = workspaceProduct.getMicrofrontends().stream()
.collect(Collectors.toMap(Microfrontend::getMfeId, Microfrontend::getBasePath));

if (product.getMicrofrontends() != null) {
product.getMicrofrontends().forEach(mfe -> {
switch (mfe.getType()) {
case MODULE -> result
.addRoutesItem(createRoute(product, mfe, pathMapping, wrapper));
case COMPONENT -> result.addComponentsItem(createComponent(product, mfe));
}
});
}

});
}

}
70 changes: 70 additions & 0 deletions src/main/openapi/openapi-bff.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@ servers:
- url: http://onecx-shell-bff:8080/

paths:
/workspaceConfig/load:
post:
tags:
- "WorkspaceConfig"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoadWorkspaceConfigRequest'
operationId: loadWorkspaceConfig
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LoadWorkspaceConfigResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetailResponse'
'404':
description: 'Not Found'
/workspaceConfig:
post:
tags:
Expand Down Expand Up @@ -135,6 +161,50 @@ paths:

components:
schemas:
LoadWorkspaceConfigRequest:
type: object
required:
- path
properties:
path:
type: string
LoadWorkspaceConfigResponse:
type: object
required:
- 'routes'
- 'theme'
- 'workspace'
- 'components'
- 'slots'
properties:
routes:
type: array
items:
$ref: '#/components/schemas/Route'
theme:
$ref: '#/components/schemas/Theme'
workspace:
$ref: '#/components/schemas/Workspace'
components:
type: array
items:
$ref: '#/components/schemas/RemoteComponent'
slots:
type: array
items:
$ref: '#/components/schemas/Slot'
Slot:
type: object
required:
- 'name'
- 'components'
properties:
name:
type: string
components:
type: array
items:
type: string
GetWorkspaceConfigResponse:
type: object
required:
Expand Down
Loading

0 comments on commit e78d9f2

Please sign in to comment.