Skip to content

Commit

Permalink
Integrate new UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse White committed Jun 5, 2022
1 parent 983b8ee commit a15b8a5
Show file tree
Hide file tree
Showing 28 changed files with 1,675 additions and 1 deletion.
2 changes: 1 addition & 1 deletion DEVEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Run the Karaf container:

In the Karaf shell, add the features repository:
```
feature:repo-add mvn:org.opennms.alec/alec-karaf-features/1.0.0-SNAPSHOT/xml
feature:repo-add mvn:org.opennms.alec/alec-karaf-features/2.0.0-SNAPSHOT/xml
```

## Usage
Expand Down
164 changes: 164 additions & 0 deletions UI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# ALEC UI

## ALEC is a plugin

ALEC extends the OpenNMS UI by leveraging facilities exposed by the [Plugin API (OIA)](https://github.com/OpenNMS/opennms-integration-api).

ALEC is the first supported plugin to take advantage of these facilities and is intended to serve as a functional example of an externally managed plugin providing a sophisticated experience.

## Structure

The tree for the frontend (FeatherDS + Vue3) code, can be found is located in the `ui/` folder at the root of the repository.

REST APIs and integration code that exposes the static assets to the runtime are located in `features/ui/`.

A Karaf feature named `alec-ui` is provided to install the UI OSGi bundle.
This is installed automatically with `alec-opennms-standalone`.

## Running in OpenNMS (Horizon 30.x)

From terminal:
```
% ssh -p 8101 admin@localhost
Warning: Permanently added '[localhost]:8101' (RSA) to the list of known hosts.
Password authentication
(admin@localhost) Password:
____ _ _ __ __ _____
/ __ \ | \ | | \/ |/ ____|
| | | |_ __ ___ _ __ | \| | \ / | (___
| | | | '_ \ / _ \ '_ \| . ` | |\/| |\___ \
| |__| | |_) | __/ | | | |\ | | | |____) |
\____/| .__/ \___|_| |_|_| \_|_| |_|_____/
| |
|_|
OpenNMS (30.0.0-SNAPSHOT) on Apache Karaf (4.3.6)
Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' to exit this console.
admin@opennms()>
```

In OpenNMS Karaf shell:
```
admin@opennms()> feature:repo-add mvn:org.opennms.alec/alec-karaf-features/2.0.0-SNAPSHOT/xml
Adding feature url mvn:org.opennms.alec/alec-karaf-features/2.0.0-SNAPSHOT/xml
admin@opennms()> feature:install alec-opennms-standalone
admin@opennms()> health-check
Verifying the health of the container
Verifying installed bundles [ Success ]
ALEC :: Driver [ Success ] => Tick duration (99 percentile): 0 ms
Connecting to ElasticSearch ReST API (Flows) [ Success ] => Not configured
=> Everything is awesome
admin@opennms()>
```

## Updating the UI in OpenNMS

In OpenNMS Karaf shell:
```
admin@opennms()> bundle:watch *
Watched URLs/IDs:
*
```

From terminal:
```
% cd ui/
% yarn build
yarn run v1.22.18
warning package.json: No license field
$ vue-tsc --noEmit && vite build
vite v2.9.5 building for production...
✓ 8 modules transformed.
dist/style.css 0.46 KiB / gzip: 0.27 KiB
dist/uiextension.es.js 745.10 KiB / gzip: 561.74 KiB
dist/uiextension.umd.js 742.92 KiB / gzip: 561.49 KiB
✨ Done in 15.34s.
% cp -R dist/* ../features/ui/src/main/resources/ui-ext
% cd ../features/ui
% mvn clean install
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.570 s
[INFO] Finished at: 2022-06-03T21:44:26-04:00
[INFO] ------------------------------------------------------------------------
```

In browser:
Refresh page

## Running UI standalone

Ensure CORS is configured in OpenNMS to be able to make API calls

```
% yarn dev
vite v2.9.5 dev server running at:
> Local: http://localhost:3000/
> Network: use `--host` to expose
ready in 318ms.
```

In browser:
http://localhost:3000/

> This is currently broken, but worth fixing
## Enabling CORS

Uncomment this block in `jetty-webapps/opennms/WEB-INF/web.xml` and restart OpenNMS:
```
<!--
<filter-mapping>
<filter-name>CORS Filter</filter-name>
<url-pattern>/api/v2/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CORS Filter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CORS Filter</filter-name>
<url-pattern>/nrt/*</url-pattern>
</filter-mapping>
-->
```

## Updating UI artifacts during development

After running `yarn build` in `ui/`, copy the artifacts from `ui/dist/` to `features/ui/src/main/resources/ui-ext/`.

Then rebuild the `features/ui/` bundle and reload it in the runtime.

> Use `bundle:watch` in the Karaf shell for hot reloads.
## TODO

### Standalone UI

*Success criteria*

Be able to run the UI standalone outside of OpenNMS with `vite` or similar

### Integrate UI into build pipeline

*Success criteria*

We don't need to commit compile and minified UI artifacts to the tree

*Ideas*

We can integrate with the Maven build so that everything builds cleanly when running `mvn clean install`

We use [frontend-maven-plugin](https://github.com/eirslett/frontend-maven-plugin) to do this in OpenNMS
1 change: 1 addition & 0 deletions features/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
<module>graph</module>
<module>score</module>
<module>shell</module>
<module>ui</module>
</modules>
</project>
48 changes: 48 additions & 0 deletions features/ui/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opennms.alec</groupId>
<artifactId>features</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.opennms.alec.features</groupId>
<artifactId>org.opennms.alec.features.ui</artifactId>
<name>ALEC :: Features :: UI</name>
<packaging>bundle</packaging>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-RequiredExecutionEnvironment>JavaSE-1.8</Bundle-RequiredExecutionEnvironment>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.opennms.alec.datasource</groupId>
<artifactId>org.opennms.alec.datasource.common</artifactId>
</dependency>
<dependency>
<groupId>org.opennms.integration.api</groupId>
<artifactId>api</artifactId>
</dependency>
<dependency>
<groupId>org.opennms.integration.api</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
</dependencies>
</project>
23 changes: 23 additions & 0 deletions features/ui/src/main/java/rest/ALECRest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package rest;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("alec")
public interface ALECRest {

@GET
@Path("/ping")
Response ping();

@POST
@Path("/hook")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
Response handleWebhook(String body);
}
26 changes: 26 additions & 0 deletions features/ui/src/main/java/rest/ALECRestImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package rest;

import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ALECRestImpl implements ALECRest {
private static final Logger LOG = LoggerFactory.getLogger(ALECRestImpl.class);

@Override
public Response ping() {
// How do I identify the user?



return Response.ok("pong!!").build();
}

@Override
public Response handleWebhook(String body) {
LOG.debug("Got payload: {}", body);
return Response.ok().build();
}

}
78 changes: 78 additions & 0 deletions features/ui/src/main/java/ui/UIExtension.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2022 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2022 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/

package ui;

public class UIExtension implements org.opennms.integration.api.v1.ui.UIExtension {
private String id;
private String menuEntry;
private String moduleFileName;
private String resourceRoot;

@Override
public String getExtensionId() {
return id;
}

@Override
public String getMenuEntry() {
return menuEntry;
}

@Override
public String getResourceRootPath() {
return resourceRoot;
}

@Override
public String getModuleFileName() {
return moduleFileName;
}

@Override
public Class<? extends UIExtension> getExtensionClass() {
return this.getClass();
}

public void setId(String id) {
this.id = id;
}

public void setMenuEntry(String menuEntry) {
this.menuEntry = menuEntry;
}

public void setModuleFileName(String moduleFileName) {
this.moduleFileName = moduleFileName;
}

public void setResourceRoot(String resourceRoot) {
this.resourceRoot = resourceRoot;
}

}
23 changes: 23 additions & 0 deletions features/ui/src/main/resources/OSGI-INF/blueprint/blueprint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0" >

<!-- Expose our UI Extension -->
<service id="uiExtension" interface="org.opennms.integration.api.v1.ui.UIExtension">
<bean class="ui.UIExtension">
<property name="id" value="uiExtension"/>
<property name="menuEntry" value="ALEC"/>
<property name="resourceRoot" value="ui-ext"/>
<property name="moduleFileName" value="uiextension.es.js"/>
</bean>
</service>

<!-- Build and expose the JAX-RS annotated webhook handler.
This will automatically mount the endpoint over the REST API. -->
<bean id="restImpl" class="rest.ALECRestImpl" />
<service interface="rest.ALECRest" ref="restImpl">
<service-properties>
<entry key="application-path" value="/rest" />
</service-properties>
</service>

</blueprint>
Binary file added features/ui/src/main/resources/ui-ext/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions features/ui/src/main/resources/ui-ext/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions features/ui/src/main/resources/ui-ext/uiextension.es.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions features/ui/src/main/resources/ui-ext/uiextension.umd.js

Large diffs are not rendered by default.

Loading

0 comments on commit a15b8a5

Please sign in to comment.