This repository contains the web user interface of the Nuvla solution. It is built as a modern single page application.
The ui is built entirely in Clojurescript (that's cool), using re-frame and reagent as foundation, and Semantic UI for basic widgets and styling.
Our aim is to build a user experience such that users can start capturing, deploying and managing containers on any virtualised environments (e.g. public cloud, private cloud and infrastructure, as well as NuvlaEdge devices). And all this with no or minimum training.
More details on the overall Nuvla eco-system is available here.
nuvla/ui
- A Docker container containing the static content of
the UI served by nginx. Available from the nuvla/ui
repository on Docker Hub.For development you need nodejs, leiningen and caddy
On Mac OS, the npm
command comes with the Node.js distribution of
Homebrew. Just run the command brew install node
.
brew install node
brew install leiningen
brew install caddy
For other distributions or for direct installation on Mac OS, take a look at tools website for instructions.
The ui can be installed on its own or as part of a full Nuvla stack. Stand alone installations must be configured to point to an existing Nuvla server.
You can also run your own Nuvla test server locally, which is great for testing. You'll find instructions here.
You will need to point your development ui environment to a Nuvla server. For that you have a few choices:
You then need to configure your local Nuvla ui to point to the Nuvla server (next section).
To run your UI dev server and your backend server from the same host address we use Caddy as a reverse-proxy during development. Caddy installs local certificates automatically, so we can run the development environment on a "real" URL.
First, create a new file called Caddyfile
with this content:
# this is a comment
{
local_certs
}
nui.localhost {
reverse_proxy localhost:8280
reverse_proxy /api/* {
to https://nuvla.io # this points to a server of your chosing
# uncomment following lines if your api server is using an untrusted certificate
# transport http {
# tls_insecure_skip_verify
# }
}
}
From the same directory where the Caddyfile
is located, you run the command caddy run
(or caddy start
to run it in
the background).
If you want to point the API somewhere else, you can change your Caddyfile
from reverse_proxy /api/* https://nuvla.io
to e.g. reverse_proxy /api/* localhost:8200
and run the
command caddy reload
(no need to restart anything else).
Run npm ci --legacy-peer-deps
inside code
folder of the cloned repository. This only needs to be done once at the beginning and
then whenever dependencies change.
When you now run lein dev
from the code
folder, you can visit the Nuvla-Ui at https://nui.localhost.
We use Portfolio
for component showcasing and
playwright
for component testing.
By running lein dev
a Porfolio server is started automatically on port 8281.
To execute all component tests run the following command (Portfolio needs to be running for this command to work):
npm run test:components
or for headed mode:
npm run test:components:headed
We use playwright
for e2e-testing.
To run playwright locally, inside the code directory, you cp .env.e2e.TEMPLATE .env.e2e
and set the environment
variables specified in that file.
Tests are located in the code/test/e2e/
directory.
npm run test:e2e:gen
you open the playwright Test Generator.
It allows you to visit a website, record all interactions and let playwright
generate all code necessary to replay
those interactions.
Copy the generated code into a new file.
You can remove the code used to log in, as all tests run with a logged-in user (you can change the user in
the .env.e2e
file).
Adjust the code to suit your needs, e.g., writing assertions using expect
.
As an alternative, you can save the output of the code generation directly to a file:
npm run test:e2e:gen -- -o test.spec.js
Put new tests inside the code/test/e2e/loggedin
directory.
The file has to end with .spec.js
(.ts
for typescript files is possible).
Four additional commands are configured in package.json
to run the tests (all starting with test:e2e
).
Run all tests:
npm run test:e2e
Run a single file by specifying a path, treated as a regex:
npm run test:e2e logout
Watch the test folder and run a test if the test file changes:
npm run test:e2e:watch
Run tests in headed mode, i.e. a browser window opens and you can see the test run.
You have to specify a path; this example runs all tests:
npm run test:e2e:headed
The headed test runs are also available in watch mode. You do not have to provide a path regex: the path is provided by the watching process.
npm run test:e2e:headed:watch
It is possible to run the tests in parallel.
Because they share the same logged in session (through global-setup.js
), it could be that tests fail if
the logout.spec.js
tests runs first.
To prevent this, only run tests inside the loggedin folder.
npm run test:e2e loggedin -- --workers 5
By adding a page.pause()
inside a test file and running in headed
mode, you can stop and open an inspector view.
When a test fails, you find a trace.zip
file inside the respective directory in the code/test-report
folder. You can
open it by
npx playwright show-trace test-results/<path-to-test-file>-<test-name>-retry<retrynumber>/trace.zip
npx playwright --help
and
npx playwright test --help
npm run test:unit
lein dev
shadow-cljs - nREPL server started on port 60325
code/.shadow-cljs/nrepl.port
(shadow/repl :nuvla-ui)
(load-file "test/cljs/sixsq/nuvla/ui/edges/utils_test.cljs")
(cljs.test/run-tests 'sixsq.nuvla.ui.edges.utils-test)
shadow-cljs can create a bundle size report.
npx shadow-cljs run shadow.cljs.build-report nuvla-ui report.html
This saves the report as report.html
in resources/public/ui/js
.
To contribute code to this repository, please follow these steps:
Create a branch from master with a descriptive, kebab-cased name to hold all your changes.
Follow the developer guidelines concerning formatting, etc. when modifying the code.
Once the changes are ready to be reviewed, create a GitHub pull request. With the pull request, provide a description of the changes and links to any relevant issues (in this repository or others).
Ensure that the triggered CI checks all pass. These are triggered automatically with the results shown directly in the pull request.
Once the checks pass, assign the pull request to the repository coordinator (who may then assign it to someone else).
Interact with the reviewer to address any comments.
When the reviewer is happy with the pull request, he/she will "squash & merge" the pull request and delete the corresponding branch.
The bulk of the code in this repository is written in Clojurescript.
The formatting follows the standard formatting provided by the Cursive IntelliJ plugin with all the default settings except that map and let entries should be aligned.
Additional, formatting guidelines, not handled by the Cursive plugin:
Use a new line after the :require
and :import
keys in namespace
declarations.
Alphabetize the required namespaces. This can be automated with
lein nsorg --replace
.
Use 2 blank lines between top-level forms.
Use a single blank line between a block comment and the following code.
IntelliJ (with Cursive) can format easily whole directories of source code. Do not hesitate to use this feature to keep the source code formatting standardized.
You can import the repository through IntelliJ, using the "leiningen" method in the dialog.
If you have the IntelliJ command line installed, the shadow-cljs heads-up display, should open files in the IntelliJ editor.
The command for opening Chrome with the security disabled, can be configured as an "external tool" in IntelliJ. In "Preferences", go to the "Tools" -> "External Tools" panel.
You can reset the logging level for kvlt from the REPL when running in development mode. From the REPL do:
=> (require '[taoensso.timbre :as timbre])
=> (timbre/set-level! :info)
The default value is :debug
which will log all the HTTP requests
and responses. This is useful when debugging interactions with
Nuvla, but annoying otherwise.
Release process instructions are available here.
Copyright © 2019-2024, SixSq SA
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.