Skip to content

Commit

Permalink
Merge pull request #419 from holly-cummins/migrate-to-react
Browse files Browse the repository at this point in the history
Migrate UI from Angular to React
  • Loading branch information
holly-cummins authored Oct 27, 2023
2 parents 7fb2e09 + b40f15d commit 8add9b2
Show file tree
Hide file tree
Showing 68 changed files with 24,128 additions and 22,830 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Then, we focused on developing several isolated microservices.
Some written in pure JAX-RS (such as the Villain) others with Reactive JAX-RS and Reactive Hibernate (such as the Hero).
These microservices return data in JSON, validate data thanks to Bean Validation, store and retrieve data from a relational database with the help of JPA, Panache and JTA.

You then installed an already coded Angular application on another instance of Quarkus.
At this stage, the Angular application couldn't access the microservices because of CORS issues that we quickly fixed.
You then installed an already coded React application on another instance of Quarkus.
At this stage, the React application couldn't access the microservices because of CORS issues that we quickly fixed.

Then, we made the microservices communicate with each other in HTTP thanks to REST Client.
But HTTP-related technologies usually use synchronous communication and therefore need to deal with invocation failure.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ quarkus-workshop-super-heroes
++ rest-heroes | Reactive REST API for CRUD operations on Heroes (you will create it)
++ rest-narration | REST API invoking an AI to narrate the fight (you will create it)
++ rest-villains | REST API for CRUD operations on Villains (you will create it)
++ ui-super-heroes | Angular application so we can fight visually
++ ui-super-heroes | React application so we can fight visually
}
}
@endsalt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endif::give-solution[]
In this workshop, you will develop an application that allows superheroes to fight against supervillains.
You will be developing several microservices communicating with each other:

* _Super Hero UI_: an Angular application to pick up a random superhero, a random supervillain, and makes them fight.
* _Super Hero UI_: a React application to pick up a random superhero, a random supervillain, and makes them fight.
The Super Hero UI is exposed via Quarkus and invokes the Fight REST API
* _Villain REST API_: A classical HTTP microservice exposing CRUD operations on Villains, stored in a PostgreSQL database
* _Hero REST API_: A reactive HTTP microservice exposing CRUD operations on Heroes, stored in a Postgres database
Expand Down Expand Up @@ -70,16 +70,16 @@ endif::use-ai[]
The table at the bottom shows the list of the previous fights.

ifdef::use-ai[]
image::angular-ui-ai.png[role=half-size]
image::react-ui-ai.png[role=half-size]
endif::use-ai[]
ifndef::use-ai[]
image::angular-ui.png[role=half-size]
image::react-ui.png[role=half-size]
endif::use-ai[]


The Statistics UI shows the number of fights per hero and villain.

image::angular-ui-stats.png[role=half-size]
image::react-ui-stats.png[role=half-size]

== How Does This Workshop Work?

Expand All @@ -89,7 +89,7 @@ The structure of this workshop is as follows:
* _Installing all the needed tools_:
in this section, you will install all the tools and code to be able to develop, compile and execute our application
* _Developing microservices with Quarkus_:
in this section, you will develop a microservice architecture by creating several Maven projects, write some Java code, add JPA entities, JAX-RS REST endpoints, write some tests, use an Angular web application, and all that on Quarkus
in this section, you will develop a microservice architecture by creating several Maven projects, write some Java code, add JPA entities, JAX-RS REST endpoints, write some tests, use a React web application, and all that on Quarkus
ifdef::use-ai[]
* _Artificial Intelligence_:
in this section, you will use OpenAI or Azure OpenAI to invoke an AI so you can generate a random narration of the fight
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

So far we've built two microservices: the villains and heroes microservices.
In the following sections you will develop an extra microservice: a _fight_ microservice where heroes and villains fight.
We will also add an Angular front-end, so we can fight graphically.
We will also add a React front-end, so we can fight graphically.
But as you can notice in the diagram below, these microservices still not communicate with each other.
You will have to wait the next chapter for that ;o)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,4 @@ You can shutdown the hero and villain services to verify that the tests still pa
Time to play.
Start the Hero, Villain and Fight microservices as well as the user interface (using `./mvnw quarkus:dev` on each project) and select random fighters.

image::angular-ui.png[role=half-size]
image::react-ui.png[role=half-size]
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

Now that we have the three main microservices, time to have a decent user interface to start fighting.
The purpose of this workshop is not to develop a web interface and learn _yet another web framework_.
This time you will just execute another Quarkus instance with an already Angular application.
This time you will just execute another Quarkus instance with an already React application.
We will be using https://quarkiverse.github.io/quarkiverse-docs/quarkus-quinoa/dev/[Quinoa]
to handle building and serving the Angular application.
to handle building and serving the React application.

== Quinoa?

Expand All @@ -23,13 +23,13 @@ Quinoa is framework-agnostic, and works with React, Angular, Vue, Lit, and other
Navigate to the `super-heroes/ui-super-heroes` directory.
It contains the code of the application.

The Angular application is in `src/main/webui`.
Being an Angular application, you will find a `package.json` file which defines all the needed dependencies.
All the Angular code (graphical components, model, services) is located under `src/main/webui/src/app`.
The React application is in `src/main/webui`.
Being a React application, you will find a `package.json` file which defines all the needed dependencies.
All the React code (graphical components, model, services) is located under `src/main/webui/src/app`.

=== Running the Web Application

We don't need to worry too much about the Angular code.
We don't need to worry too much about the React code.

[example, role="cta"]
--
Expand All @@ -51,8 +51,8 @@ You should see console output like the following

[source,shell,subs="attributes+"]
----
2023-05-18 14:22:02,745 INFO [io.qua.qui.dep.ForwardedDevProcessor] (build-5) Quinoa package manager live coding is up and running on port: 4200 (in 18118ms)
2023-05-18 14:22:02,749 INFO [io.qua.qui.dep.ForwardedDevProcessor] (build-40) Quinoa is forwarding unhandled requests to port: 4200
2023-05-18 14:22:02,745 INFO [io.qua.qui.dep.ForwardedDevProcessor] (build-5) Quinoa package manager live coding is up and running on port: 3000 (in 18118ms)
2023-05-18 14:22:02,749 INFO [io.qua.qui.dep.ForwardedDevProcessor] (build-40) Quinoa is forwarding unhandled requests to port: 3000
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
Expand All @@ -66,8 +66,8 @@ because we need to fix a few things and add some more implementation.

image::blank-ui.png[]

If you want, you can visit http://localhost:4200 (the usual Angular port) to confirm that Quinoa is forwarding what's on port 4200 to port 8080.
The version of the application on http://localhost:4200 will always stay disappointingly blank,
If you want, you can visit http://localhost:3000 (the usual React port) to confirm that Quinoa is forwarding what's on port 3000 to port 8080.
The version of the application on http://localhost:3000 will always stay disappointingly blank,
because it's looking for its config on the wrong port. So don't use that one!

You might want to create a fuller Quarkus BFF for the UI, and use something like https://quarkus.io/guides/stork[Stork] for service discovery.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,4 @@ The result of the fight is displayed, and below, you have a "Narrate the fight"
Click on it, wait a few seconds (remember that the Narration microservice access a remote AI service that takes time) and the narration of the fight is displayed.
Being _Generative AI_, you can click several times on the button and you will get different narrations.

image::angular-ui-ai.png[role=half-size]
image::react-ui-ai.png[role=half-size]
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ include::{projectdir}/infrastructure/azure-deploy-aca.sh[tags=adocAppFightLogs]
=== Super Hero UI

Like for the previous microservices, we will be deploying the UI as Docker image as we did for the previous microservices.
But we could have also deployed the Super Hero UI using Azure Static Webapps which is suited for Angular applications.
But we could have also deployed the Super Hero UI using Azure Static Webapps which is suited for React applications.
If you are interested in this approach, you can check https://azure.microsoft.com/services/app-service/static/[Azure Static Webapps].

[example, role="cta"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,18 @@ endif::use-messaging[]
On http://localhost:8080 you should see the user interface, and you should be able to fight super heroes against super villains:

ifdef::use-ai[]
image::angular-ui-ai.png[]
image::react-ui-ai.png[]
endif::use-ai[]
ifndef::use-ai[]
image::angular-ui.png[]
image::react-ui.png[]
endif::use-ai[]


On http://localhost:8085 you should see the statistics of the fights.
When super heroes and super heroes are fights, the statistics shows which one has won the most fights, and the percentage of fights won by the two groups.
The UI is automatically updated at each fight:

image::angular-ui-stats.png[]
image::react-ui-stats.png[]

You should see the user interface and everything should work.
Remember to shutdown the entire application with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The heroes, villains, and fights tests should all be running clean.
A successful refactoring!
--

Now visit the UI at http://localhost:4200/.
Now visit the UI at http://localhost:8080/.
What's going on?
The hero's level is always 0. Why didn't the tests catch this?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Time to start the application using:
Then, open `http://localhost:8085` in a new browser window.
Trigger some fights, and you should see the live statistics moving.

image::angular-ui-stats.png[role=half-size]
image::react-ui-stats.png[role=half-size]
--

Quarkus automatically reuse the Kafka broker from the fight service.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Angular UI
# React UI

## Introduction

This is the main user interface for the application. The application is an Angular application served via Quarkus
This is the main user interface for the application. The application is a React application served via Quarkus
Quinoa.

## TLDR
Expand All @@ -13,8 +13,8 @@ mvn quarkus:dev

## Building and running the application

Builds are served using a Quarkus server. This server serves the compiled Angular application and an `env.js` file.
This `env.js` file is generated at startup, and adds a `window.NG_CONFIG` property that the Angular application can read
Builds are served using a Quarkus server. This server serves the compiled React application and an `env.js` file.
This `env.js` file is generated at startup, and adds a `window.APP_CONFIG` property that the React application can read
from.

### Configuration
Expand Down Expand Up @@ -49,8 +49,8 @@ Then use the following command:
quarkus dev
```

This starts the Angular hot reloading server at http://localhost:4200, and the Quarkus server to supply the `env.js`
file. The Quarkus server will proxy requests to the Angular development server.
This starts the React hot reloading server at http://localhost:3000, and the Quarkus server to supply the `env.js`
file. The Quarkus server will proxy requests to the React development server.

You can then access the application on http://localhost:8080.

Expand Down Expand Up @@ -114,71 +114,18 @@ system, [follow these instructions](../README.md#deploying-to-kubernetes).

### Routing

There are 2 environment variables that can be set on this application to control how the Angular UI communicates with
There are 2 environment variables that can be set on this application to control how the React UI communicates with
the [`rest-fights`](../rest-fights) application:

| Env Var | Default Value | Description |
|--------------------------|------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `API_BASE_URL` | `http://localhost:8082` | The base URL for the [`rest-fights`](../rest-fights) application. Set this to a fully qualified URL (i.e. http://www.example.com or http://somehost.com:someport) to define the URL for the [`rest-fights`](../rest-fights) application. |
| `CALCULATE_API_BASE_URL` | `false` on Minikube/Kubernetes. `true` on OpenShift. | If `true`, look at the URL in the browser and replace the `ui-super-heroes` host name with

# Under the covers with Angular
# Under the covers with React

Although you don't need to know Angular to run this component, the following commands may be helpful for making changes.

## Angular CLI commands

### Initiliaze

```
$ ng new super-heroes --directory super-heroes-ui --prefix hero --routing false --skipTests true --inlineStyle true --commit false --minimal true --style css
```

### Admin components

```
$ ng generate component fight-list --spec false --inline-style true
$ ng generate component fight --spec false --inline-style true
```

### Material design

```
$ ng add @angular/material
```

### Swagger Codegen

```
$ swagger-codegen generate -i http://localhost:8082/openapi -l typescript-angular -o src/app/shared
```

## Angular CLI documentation

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change
any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also
use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag
for a production build.
Although you don't need to know React to run this component, the following commands may be helpful for making changes.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).

## Further help

To get more help on the Angular CLI use `ng help` or go check out
the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
Run `npm test` to execute the unit tests via Jest.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public String getConfig() throws JsonProcessingException {
calculateApiBaseUrl);
// We could just return the Config object, but that would be json, and we want a
// javascript snippet we can include with <script src="..."/>
return "window.NG_CONFIG=" + objectMapper.writeValueAsString(config);
return "window.APP_CONFIG=" + objectMapper.writeValueAsString(config);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
quarkus.quinoa.package-manager-install=true
quarkus.quinoa.package-manager-install.node-version=16.16.0
quarkus.quinoa.build-dir=dist/super-heroes
quarkus.quinoa.dev-server.port=4200
api.base.url=http://localhost:8082
Loading

0 comments on commit 8add9b2

Please sign in to comment.