Skip to content

Commit

Permalink
[BasicUI] Add a new header line for image, chart and video elements. (#…
Browse files Browse the repository at this point in the history
…2010)

Header line for video element contains icon and label.

Header line for image element contains icon, label and a button to
switch between no upscale and upscale of the image. Header line for
chart element contains icon, label and 4 buttons:
 - one button to show or hide the legend
 - one button to change the time range
 - one button to switch between no upscale and upscale of the chart
 - one button to refresh the chart

Fix handling of iconcolor and labelcolor parameters for mapview and
webview elements.

For image and chart elements, the header line is always present so that
user has an access to its buttons.
For video, mapview and webview elements, if the label is empty, the
header line is hidden.

For chart and image elements, there is now no upscale applied by default
(tablet/phone devices) but a button allows upscaling.

Closes #1939
Fixes #1367
Also related to #1930

Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo authored Sep 9, 2023
1 parent 1ee7a2f commit 08a2d80
Show file tree
Hide file tree
Showing 13 changed files with 365 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.items.GroupItem;
Expand Down Expand Up @@ -91,7 +93,9 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
}

// if legend parameter is given, add corresponding GET parameter
boolean legend = item instanceof GroupItem && !forceAsItem;
if (chart.getLegend() != null) {
legend = chart.getLegend();
if (chart.getLegend()) {
chartUrl += "&legend=true";
} else {
Expand Down Expand Up @@ -123,7 +127,10 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
}

String snippet = getSnippet("chart");
snippet = preprocessSnippet(snippet, w);
snippet = preprocessSnippet(snippet, w, true);

// Process the color tags
snippet = processColor(w, snippet);

if (chart.getRefresh() > 0) {
snippet = snippet.replace("%update_interval%", Integer.toString(chart.getRefresh()));
Expand All @@ -136,11 +143,43 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
snippet = snippet.replace("%valid_url%", "true");
snippet = snippet.replace("%ignore_refresh%", ignoreRefresh ? "true" : "false");
snippet = snippet.replace("%url%", url);
snippet = snippet.replace("%legend%", Boolean.valueOf(legend).toString());

List<List<String>> periods = List.of(List.of("Last hour", "h"), List.of("Last 4 hours", "4h"),
List.of("Last 8 hours", "8h"), List.of("Last 12 hours", "12h"), List.of("Last day", "D"),
List.of("Last 2 days", "2D"), List.of("Last 3 days", "3D"), List.of("Last week", "W"),
List.of("Last 2 weeks", "2W"), List.of("Last month", "M"), List.of("Last 2 months", "2M"),
List.of("Last 4 months", "4M"), List.of("Last year", "Y"));
StringBuilder rowSB = new StringBuilder();
for (List<String> period : periods) {
buildRow(chart, period.get(0), period.get(1), chart.getPeriod(), rowSB);
}
snippet = snippet.replace("%period_rows%", rowSB.toString());

sb.append(snippet);
} catch (ItemNotFoundException e) {
logger.warn("Chart cannot be rendered as item '{}' does not exist.", chart.getItem());
}
return ECollections.emptyEList();
}

private void buildRow(Chart w, @Nullable String lab, String cmd, String current, StringBuilder rowSB)
throws RenderException {
String rowSnippet = getSnippet("selection_row");

String command = cmd;
String label = lab == null ? cmd : lab;

rowSnippet = rowSnippet.replace("%item%", w.getItem() != null ? w.getItem() : "");
rowSnippet = rowSnippet.replace("%cmd%", escapeHtml(command));
rowSnippet = rowSnippet.replace("%label%", escapeHtml(label));

if (command.equals(current)) {
rowSnippet = rowSnippet.replace("%checked%", "checked=\"true\"");
} else {
rowSnippet = rowSnippet.replace("%checked%", "");
}

rowSB.append(rowSnippet);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th

String widgetId = itemUIRegistry.getWidgetId(w);
snippet = snippet.replace("%id%", widgetId);
snippet = preprocessSnippet(snippet, w);
snippet = preprocessSnippet(snippet, w, true);

// Process the color tags
snippet = processColor(w, snippet);

boolean validUrl = isValidURL(image.getUrl());
String proxiedUrl = "../proxy?sitemap=" + sitemap + "&amp;widgetId=" + widgetId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ public boolean canRender(Widget w) {
public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
Mapview mapview = (Mapview) w;
String snippet = getSnippet("mapview");

boolean showHeaderRow = !getLabel(w).isEmpty();
snippet = snippet.replace("%header_visibility_class%",
showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden");
snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString());

snippet = preprocessSnippet(snippet, mapview, true);

// Process the color tags
snippet = processColor(w, snippet);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,16 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
&& videoWidget.getEncoding().toLowerCase().contains("mjpeg")) ? "image" : "video";

snippet = getSnippet(snippetName);
snippet = preprocessSnippet(snippet, w);

boolean showHeaderRow = !getLabel(w).isEmpty();
snippet = snippet.replace("%header_visibility_class%",
showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden");
snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString());

snippet = preprocessSnippet(snippet, w, true);

// Process the color tags
snippet = processColor(w, snippet);

State state = itemUIRegistry.getState(w);
String url;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ public boolean canRender(Widget w) {
public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
Webview webview = (Webview) w;
String snippet = getSnippet("webview");

boolean showHeaderRow = !getLabel(w).isEmpty();
snippet = snippet.replace("%header_visibility_class%",
showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden");
snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString());

snippet = preprocessSnippet(snippet, webview, true);

// Process the color tags
snippet = processColor(w, snippet);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
<div class="mdl-form__row mdl-form__row--header mdl-cell mdl-cell--12-col %visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
<div class="mdl-form__header">
<button id="button1-%widget_id%" class="mdl-button mdl-button--raised mdl-js-button mdl-js-ripple-effect chart-legend-button">
<!-- legend_toggle -->
<i class="material-icons">&#xF11B;</i>
</button>
<spam class="mdl-tooltip mdl-tooltip--top" for="button1-%widget_id%">Show or hde legend</spam>
<button id="button2-%widget_id%" class="mdl-button mdl-button--raised mdl-js-button mdl-js-ripple-effect chart-period-button">
<!-- more_time -->
<i class="material-icons">&#xEA5D;</i>
</button>
<spam class="mdl-tooltip mdl-tooltip--top" for="button2-%widget_id%">Choose time frame</spam>
<script type="text/html" class="mdl-form__header-rows">
<div class="mdl-radio__group">
%period_rows%
</div>
</script>
<button id="button3-%widget_id%" class="mdl-button mdl-button--raised mdl-js-button mdl-js-ripple-effect image-upscale-button">
<!-- fullscreen -->
<i class="material-icons">&#xE5D0;</i>
</button>
<spam class="mdl-tooltip mdl-tooltip--top" for="button3-%widget_id%">Upscale chart or not</spam>
<button id="button4-%widget_id%" class="mdl-button mdl-button--raised mdl-js-button mdl-js-ripple-effect chart-refresh-button">
<!-- refresh -->
<i class="material-icons">&#xE5D5;</i>
</button>
<spam class="mdl-tooltip mdl-tooltip--top" for="button4-%widget_id%">Refresh chart</spam>
</div>
</div>
<div class="mdl-form__row mdl-form__row--height-auto mdl-cell mdl-cell--12-col %visibility_class%">
<div
class="mdl-form__control mdl-form__image"
Expand All @@ -7,6 +42,8 @@
data-proxied-url="%proxied_url%"
data-valid-url="%valid_url%"
data-ignore-refresh="%ignore_refresh%"
data-header-row="true"
data-legend="%legend%"
>
<img src="%url%" />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
<div class="mdl-form__row mdl-form__row--header mdl-cell mdl-cell--12-col %visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
<div class="mdl-form__header">
<button id="button-%widget_id%" class="mdl-button mdl-button--raised mdl-js-button mdl-js-ripple-effect image-upscale-button">
<!-- fullscreen -->
<i class="material-icons">&#xE5D0;</i>
</button>
<spam class="mdl-tooltip mdl-tooltip--top" for="button-%widget_id%">Upscale image or not</spam>
</div>
</div>
<div class="mdl-form__row mdl-form__row--height-auto mdl-cell mdl-cell--12-col %visibility_class%">
<div
class="mdl-form__control mdl-form__image"
Expand All @@ -8,6 +23,7 @@
data-proxied-url="%proxied_url%"
data-valid-url="%valid_url%"
data-ignore-refresh="%ignore_refresh%"
data-header-row="true"
>
<img src="%url%" />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div class="mdl-form__row mdl-cell mdl-cell--12-col %visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
<div class="mdl-form__row mdl-form__row--header mdl-cell mdl-cell--12-col %header_visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
</div>
<div class="mdl-form__row mdl-form__row--height-auto mdl-cell mdl-cell--12-col %visibility_class%">
<div
Expand All @@ -13,6 +13,7 @@
data-widget-id="%widget_id%"
data-map-url="%map_url%"
data-map-zoom="%map_zoom%"
data-header-row="%header_row%"
>
<iframe src="%url%" height="%height%"></iframe>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
<div class="mdl-form__row mdl-form__row--header mdl-cell mdl-cell--12-col %header_visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
</div>
<div class="mdl-form__row mdl-form__row--height-auto mdl-cell mdl-cell--12-col %visibility_class%">
<div
class="mdl-form__control mdl-form__video"
data-control-type="video"
data-widget-id="%widget_id%"
data-header-row="%header_row%"
>
<video autoplay controls src="%url%" %media_type%></video>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<div class="mdl-form__row mdl-cell mdl-cell--12-col %visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
<div class="mdl-form__row mdl-form__row--header mdl-cell mdl-cell--12-col %header_visibility_class%">
<span %iconstyle% class="mdl-form__icon">
%icon_snippet%
</span>
<span %labelstyle% class="mdl-form__label">
%label%
</span>
</div>
<div class="mdl-form__row mdl-form__row--height-auto mdl-cell mdl-cell--12-col %visibility_class%">
<div
class="mdl-form__control mdl-form__webview"
data-control-type="webview"
data-widget-id="%widget_id%"
data-header-row="%header_row%"
>
<iframe src="%url%" height="%height%"></iframe>
</div>
Expand Down
40 changes: 31 additions & 9 deletions bundles/org.openhab.ui.basic/web-src/_layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
@include align-items-2011(center);
white-space: nowrap;
height: $form-row-desktop-height;
html.ui-layout-condensed & {
height: $form-row-desktop-height-condensed;
}
box-sizing: content-box;
padding: 4px 0;
margin: 0 $mdl-grid-spacing;
Expand All @@ -79,7 +82,7 @@
padding: 4px $mdl-grid-spacing;
margin: 0;
html.ui-layout-condensed & {
height: $form-row-desktop-height-condensed;
height: $form-row-mobile-height-condensed;
}
}
@media screen and (min-width: $layout-tablet-size-threshold) {
Expand All @@ -98,12 +101,19 @@
height: auto;
}
}
&--header {
border-bottom: none;
padding-bottom: 0;
padding-left: 48px;
padding-right: 48px;
@media screen and (max-width: $layout-tablet-size-threshold) {
padding-left: $mdl-grid-spacing + 16px;
padding-right: $mdl-grid-spacing + 16px;
}
}
&--hidden {
display: none;
}
html.ui-layout-condensed & {
height: $form-row-desktop-height-condensed;
}
}
&__image {
&.mdl-form__control {
Expand All @@ -114,11 +124,7 @@
max-width: 100%;
}
}
@media screen and (max-width: $layout-tablet-size-threshold) {
&.mdl-form__control {
padding-left: 0;
padding-right: 0;
}
&-upscale {
width: 100%;
img {
height: auto;
Expand Down Expand Up @@ -264,6 +270,22 @@
padding-top: 6px;
}
}
&__header {
padding-left: 8px;
padding-right: $form-row-desktop-padding;
@media screen and (max-width: $layout-tablet-size-threshold) {
padding-right: $form-row-mobile-padding;
}
.mdl-button {
box-shadow: none;
-webkit-box-shadow: none;
min-width: 0;
padding-top: 6px;
}
&-rows {
display: none;
}
}
&__group {
padding-top: 4px;
}
Expand Down
4 changes: 4 additions & 0 deletions bundles/org.openhab.ui.basic/web-src/_theming.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ body {
color: var(--container-text-color, #616161) !important;
}

.mdl-form__row--header {
border-bottom: none;
}

.mdl-switch .mdl-switch__track {
background: rgba(0,0,0,.26);
background: var(--switch-off-track-bg, rgba(0,0,0,.26));
Expand Down
Loading

0 comments on commit 08a2d80

Please sign in to comment.