Refactor dashboard tiles into core (#1329)

* Refactor dashboard tiles into core

Move the tile concept from the dashboard UI to the
org.openhab.core.ui bundle, and add a REST resource
(/rest/ui/tiles) to retrieve the list of tiles i.e.
registered UIs.

Signed-off-by: Yannick Schaus <github@schaus.net>
This commit is contained in:
Yannick Schaus 2020-01-17 15:28:05 +01:00 committed by Kai Kreuzer
parent cc3f1407bd
commit cc702266fe
13 changed files with 511 additions and 0 deletions

View File

@ -256,6 +256,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.ui</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.voice</artifactId>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.io.rest.ui</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,14 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-core

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.io.rest.ui</artifactId>
<name>openHAB Core :: Bundles :: UI REST Interface</name>
<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.ui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.io.rest.ui;
/**
* This is an data transfer object for a UI tile.
*
* @author Yannick Schaus - Initial contribution
*/
public class TileDTO {
public String name;
public String url;
public String overlay;
public String imageUrl;
public TileDTO(String name, String url, String overlay, String imageUrl) {
super();
this.name = name;
this.url = url;
this.overlay = overlay;
this.imageUrl = imageUrl;
}
}

View File

@ -0,0 +1,89 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.io.rest.ui.internal;
import java.util.stream.Stream;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.openhab.core.io.rest.RESTResource;
import org.openhab.core.io.rest.Stream2JSONInputStream;
import org.openhab.core.io.rest.ui.TileDTO;
import org.openhab.core.ui.tiles.Tile;
import org.openhab.core.ui.tiles.TileProvider;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
/**
* This class acts as a REST resource for the UI resources and is registered with the
* Jersey servlet.
*
* @author Yannick Schaus - Initial contribution
*/
@Path(UIResource.PATH_UI)
@Api(value = UIResource.PATH_UI)
@Component(service = { RESTResource.class, UIResource.class })
public class UIResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(UIResource.class);
/** The URI path to this resource */
public static final String PATH_UI = "ui";
@Context
private UriInfo uriInfo;
private TileProvider tileProvider;
@GET
@Path("/tiles")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Get all registered UI tiles.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Tile.class) })
public Response getAll() {
Stream<TileDTO> tiles = tileProvider.getTiles().map(this::toTileDTO);
return Response.ok(new Stream2JSONInputStream(tiles)).build();
}
@Override
public boolean isSatisfied() {
return tileProvider != null;
}
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
protected void setTileProvider(TileProvider tileProvider) {
this.tileProvider = tileProvider;
}
protected void unsetTileProvider(TileProvider tileProvider) {
this.tileProvider = null;
}
private TileDTO toTileDTO(Tile tile) {
return new TileDTO(tile.getName(), tile.getUrl(), tile.getOverlay(), tile.getImageUrl());
}
}

View File

@ -0,0 +1,111 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.ui.internal.tiles;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Stream;
import org.openhab.core.ui.tiles.ExternalServiceTile;
import org.openhab.core.ui.tiles.Tile;
import org.openhab.core.ui.tiles.TileProvider;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This component registers the UI tiles.
*
* @author Kai Kreuzer - Initial contribution
* @author Laurent Garnier - internationalization
* @author Hilbrand Bouwkamp - internationalization
* @author Yannick Schaus - refactor into tile service, remove dashboard components
*/
@Component(immediate = true, name = "org.openhab.core.ui.tiles")
public class TileService implements TileProvider {
private static final Logger logger = LoggerFactory.getLogger(TileService.class);
protected ConfigurationAdmin configurationAdmin;
protected Set<Tile> tiles = new CopyOnWriteArraySet<>();
private final static String LINK_NAME = "link-name";
private final static String LINK_URL = "link-url";
private final static String LINK_IMAGEURL = "link-imageurl";
@Activate
protected void activate(ComponentContext componentContext, Map<String, Object> properties) {
addTilesForExternalServices(properties);
}
@Deactivate
protected void deactivate(ComponentContext componentContext) {
}
@Reference
protected void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
this.configurationAdmin = configurationAdmin;
}
protected void unsetConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
this.configurationAdmin = null;
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected void addTile(Tile tile) {
tiles.add(tile);
}
protected void removeTile(Tile tile) {
tiles.remove(tile);
}
@Override
public Stream<Tile> getTiles() {
return tiles.stream();
}
private void addTilesForExternalServices(Map<String, Object> properties) {
for (String key : properties.keySet()) {
if (key.endsWith(LINK_NAME)) {
if (key.length() > LINK_NAME.length()) {
// get prefix from link name
String linkname = key.substring(0, key.length() - LINK_NAME.length());
String name = (String) properties.get(linkname + LINK_NAME);
String url = (String) properties.get(linkname + LINK_URL);
String imageUrl = (String) properties.get(linkname + LINK_IMAGEURL);
Tile newTile = new ExternalServiceTile.TileBuilder().withName(name).withUrl(url)
.withImageUrl(imageUrl).build();
if (name != null && url != null && !name.isEmpty() && !url.isEmpty()) {
addTile(newTile);
logger.debug("Tile added: {}", newTile);
} else {
logger.warn("Ignore invalid tile '{}': {}", linkname, newTile);
}
}
}
}
}
}

View File

@ -0,0 +1,97 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.ui.tiles;
/**
* The dashboard tile for external services.
*
* @author Pauli Anttila - Initial contribution
* @author Yannick Schaus - moved into core, remove references to dashboard
*/
public class ExternalServiceTile implements Tile {
private String name;
private String url;
private String overlay;
private String imageUrl;
private ExternalServiceTile(TileBuilder builder) {
this.name = builder.name;
this.url = builder.url;
this.overlay = builder.overlay;
this.imageUrl = builder.imageUrl;
}
@Override
public String getName() {
return name;
}
@Override
public String getUrl() {
return url;
}
@Override
public String getOverlay() {
return overlay;
}
@Override
public String getImageUrl() {
return imageUrl;
}
@Override
public String toString() {
final int MAXLEN = 100;
String limitedImageUrl = imageUrl;
if (limitedImageUrl != null && limitedImageUrl.length() > MAXLEN) {
limitedImageUrl = imageUrl.substring(0, MAXLEN) + "...";
}
return "[name=" + name + ", url=" + url + ", overlay=" + overlay + ", imageUrl=" + limitedImageUrl + "]";
}
public static class TileBuilder {
private String name;
private String url;
private String overlay;
private String imageUrl;
public TileBuilder withName(String name) {
this.name = name;
return this;
}
public TileBuilder withUrl(String url) {
this.url = url;
return this;
}
public TileBuilder withOverlay(String overlay) {
this.overlay = overlay;
return this;
}
public TileBuilder withImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
return this;
}
public ExternalServiceTile build() {
return new ExternalServiceTile(this);
}
}
}

View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.ui.tiles;
/**
* A tile can be registered by an UI as a service in order to appear on the main openHAB UI.
*
* @author Kai Kreuzer - initial contribution
* @author Yannick Schaus - refactored into core, remove references to dashboard
*
*/
public interface Tile {
/**
* The name that should appear on the tile
*
* @return name of the tile
*/
String getName();
/**
* The url to point to (if it is a local UI, it should be a relative path starting with "../")
*
* @return the url
*/
String getUrl();
/**
* The url to point to for the tile.
* (if it is a local UI, it should be a relative path starting with "../")
*
* @return the tile url
*/
String getImageUrl();
/**
* An HTML5 overlay icon to use for the tile, e.g. "html5", "android" or "apple".
*
* @return the overlay to use
*/
String getOverlay();
}

View File

@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.ui.tiles;
import java.util.stream.Stream;
/**
* Interface for a component providing UI tiles.
*
* @author Yannick Schaus - initial contribution
*/
public interface TileProvider {
public Stream<Tile> getTiles();
}

View File

@ -67,6 +67,7 @@
<module>org.openhab.core.io.rest.optimize</module>
<module>org.openhab.core.io.rest.sitemap</module>
<module>org.openhab.core.io.rest.sse</module>
<module>org.openhab.core.io.rest.ui</module>
<module>org.openhab.core.io.rest.voice</module>
<module>org.openhab.core.io.transport.dbus</module>
<module>org.openhab.core.io.transport.mdns</module>

View File

@ -415,6 +415,7 @@
<feature>openhab-core-model-item</feature>
<feature>openhab-core-model-sitemap</feature>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.ui/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest.ui/${project.version}</bundle>
</feature>
<feature name="openhab-core-ui-icon" version="${project.version}">