Repository: chukwa Updated Branches: refs/heads/master a13bc5ae0 -> 0e518f8d7
CHUKWA-785. Added banner, pie chart, gauge chart to graph explorer. (Eric Yang) Project: http://git-wip-us.apache.org/repos/asf/chukwa/repo Commit: http://git-wip-us.apache.org/repos/asf/chukwa/commit/5e66273f Tree: http://git-wip-us.apache.org/repos/asf/chukwa/tree/5e66273f Diff: http://git-wip-us.apache.org/repos/asf/chukwa/diff/5e66273f Branch: refs/heads/master Commit: 5e66273f6f5960f01eae97d8b719f50e1e394fd1 Parents: a13bc5a Author: Eric Yang <[email protected]> Authored: Sun Oct 25 19:05:22 2015 -0700 Committer: Eric Yang <[email protected]> Committed: Sun Nov 22 17:16:32 2015 -0800 ---------------------------------------------------------------------- CHANGES.txt | 2 + .../chukwa/datastore/ChukwaHBaseStore.java | 56 +++++- .../apache/hadoop/chukwa/hicc/bean/Chart.java | 37 ++++ .../hadoop/chukwa/hicc/bean/ChartType.java | 22 +++ .../chukwa/hicc/rest/CirclesController.java | 54 ++++-- .../chukwa/hicc/rest/PieChartController.java | 131 +++++++++++++ .../hadoop/chukwa/hicc/rest/TileController.java | 128 +++++++++++++ src/main/web/hicc/WEB-INF/vm/circles.vm | 15 +- src/main/web/hicc/WEB-INF/vm/pie.vm | 64 +++++++ src/main/web/hicc/WEB-INF/vm/tile.vm | 133 +++++++++++++ .../hicc/home/css/bootstrap-iconpicker.min.css | 9 + src/main/web/hicc/home/css/jquery.gridster.css | 12 +- src/main/web/hicc/home/graph-explorer.html | 186 ++++++++++++++++--- .../hicc/home/js/bootstrap-iconpicker.min.js | 19 ++ .../home/js/iconset/iconset-glyphicon.min.js | 21 +++ src/main/web/hicc/home/tile.html | 54 +++++- src/main/web/hicc/images/loading.svg | 18 ++ src/main/web/hicc/js/pie.js | 79 ++++++++ src/main/web/hicc/loading.html | 49 +++++ 19 files changed, 1026 insertions(+), 63 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 03b0fe8..718d869 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,8 @@ Trunk (unreleased changes) NEW FEATURES + CHUKWA-785. Added banner, pie chart, gauge chart to graph explorer. (Eric Yang) + CHUKWA-778. Added pie chart, circle chart and timeline javascripts. (Eric Yang) CHUKWA-777. Added Home page and some widgets for the demo purpose. (Eric Yang) http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/datastore/ChukwaHBaseStore.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/datastore/ChukwaHBaseStore.java b/src/main/java/org/apache/hadoop/chukwa/datastore/ChukwaHBaseStore.java index 4c6ccdb..fec9281 100644 --- a/src/main/java/org/apache/hadoop/chukwa/datastore/ChukwaHBaseStore.java +++ b/src/main/java/org/apache/hadoop/chukwa/datastore/ChukwaHBaseStore.java @@ -638,6 +638,43 @@ public class ChukwaHBaseStore { return list; } + public static synchronized List<String> getData(ArrayList<SeriesMetaData> series, long startTime, long endTime) { + ArrayList<String> data = new ArrayList<String>(); + try { + getHBaseConnection(); + Table table = connection.getTable(TableName.valueOf(CHUKWA)); + Scan scan = new Scan(); + for(SeriesMetaData s : series) { + String snapshot = ""; + String[] parts = s.getUrl().toString().split("/"); + String metric = parts[5]; + String source = parts[6]; + long currentDay = startTime; + byte[] rowKey = HBaseUtil.buildKey(currentDay, metric, source); + scan.addFamily(COLUMN_FAMILY); + scan.setStartRow(rowKey); + scan.setStopRow(rowKey); + scan.setTimeRange(startTime, endTime); + scan.setBatch(10000); + ResultScanner rs = table.getScanner(scan); + Iterator<Result> it = rs.iterator(); + while(it.hasNext()) { + Result result = it.next(); + for(Cell kv : result.rawCells()) { + snapshot = new String(CellUtil.cloneValue(kv)); + } + } + data.add(snapshot); + rs.close(); + } + table.close(); + } catch(Exception e) { + closeHBase(); + LOG.error(ExceptionUtil.getStackTrace(e)); + } + return data; + } + /** * Find widget by title prefix in HBase. * @@ -861,6 +898,16 @@ public class ChukwaHBaseStore { Dashboard dashboard = new Dashboard(); widget = new Widget(); + widget.setTitle("Welcome Page"); + widget.setSrc(new URI("/hicc/welcome.html")); + widget.setCol(1); + widget.setRow(1); + widget.setSize_x(9); + widget.setSize_y(5); + createWidget(widget); + dashboard.add(widget); + + widget = new Widget(); widget.setTitle("Trial Downloading"); widget.setSrc(new URI("/hicc/home/downloads.html")); widget.setCol(1); @@ -868,7 +915,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(1); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Cluster Running"); @@ -878,7 +924,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(1); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Users Working"); @@ -888,7 +933,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(1); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Applications Running"); @@ -898,7 +942,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(1); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Trial Abandon Rate"); @@ -908,7 +951,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(2); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Clusters Health"); @@ -918,7 +960,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(2); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Top Active Clusters"); @@ -928,7 +969,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(2); createWidget(widget); - dashboard.add(widget); widget = new Widget(); widget.setTitle("Top Applications"); @@ -938,7 +978,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(2); createWidget(widget); -// dashboard.add(widget); widget = new Widget(); widget.setTitle("Applications Usage"); @@ -948,7 +987,6 @@ public class ChukwaHBaseStore { widget.setSize_x(2); widget.setSize_y(2); createWidget(widget); - dashboard.add(widget); updateDashboard("default", "", dashboard); http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/hicc/bean/Chart.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/hicc/bean/Chart.java b/src/main/java/org/apache/hadoop/chukwa/hicc/bean/Chart.java index 19cde5f..06b2bd5 100644 --- a/src/main/java/org/apache/hadoop/chukwa/hicc/bean/Chart.java +++ b/src/main/java/org/apache/hadoop/chukwa/hicc/bean/Chart.java @@ -24,6 +24,7 @@ import java.util.List; public class Chart { private String id; + private ChartType type; private String title; private List<SeriesMetaData> series; private boolean xLabelOn; @@ -42,9 +43,13 @@ public class Chart { private boolean userDefinedMax = true; private boolean userDefinedMin = true; private String yUnitType = ""; + private String icon = ""; + private String bannerText = ""; + private String suffixText = ""; public Chart(String id) { this.id = id; + this.type = ChartType.TIME_SERIES; this.title = "Untitled Chart"; this.xLabelOn = true; this.yLabelOn = true; @@ -56,6 +61,14 @@ public class Chart { this.userDefinedMin = false; } + public ChartType getType() { + return this.type; + } + + public void setType(ChartType type) { + this.type = type; + } + public void setYMax(double max) { this.max = max; this.userDefinedMax = true; @@ -196,4 +209,28 @@ public class Chart { public String getYUnitType() { return this.yUnitType; } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getIcon() { + return this.icon; + } + + public void setBannerText(String bannerText) { + this.bannerText = bannerText; + } + + public String getBannerText() { + return this.bannerText; + } + + public void setSuffixText(String suffixText) { + this.suffixText = suffixText; + } + + public String getSuffixText() { + return this.suffixText; + } } http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/hicc/bean/ChartType.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/hicc/bean/ChartType.java b/src/main/java/org/apache/hadoop/chukwa/hicc/bean/ChartType.java new file mode 100644 index 0000000..26d87ea --- /dev/null +++ b/src/main/java/org/apache/hadoop/chukwa/hicc/bean/ChartType.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.hadoop.chukwa.hicc.bean; + +public enum ChartType { + TIME_SERIES, PIE, CIRCLE, TILE, BAR, DONUT; +} http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/hicc/rest/CirclesController.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/hicc/rest/CirclesController.java b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/CirclesController.java index 62b4b71..5127b1c 100644 --- a/src/main/java/org/apache/hadoop/chukwa/hicc/rest/CirclesController.java +++ b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/CirclesController.java @@ -90,6 +90,28 @@ public class CirclesController { } @PUT + @Path("preview") + public String preview(String buffer) { + VelocityContext context = new VelocityContext(); + StringWriter sw = null; + try { + Gson gson = new Gson(); + Chart chart = gson.fromJson(buffer, Chart.class); + List<SeriesMetaData> series = chart.getSeries(); + String seriesMetaData = gson.toJson(series); + context.put("chart", chart); + context.put("seriesMetaData", seriesMetaData); + Template template = velocity.getTemplate("circles.vm"); + sw = new StringWriter(); + template.merge(context, sw); + } catch (Exception e) { + e.printStackTrace(); + return e.getMessage(); + } + return sw.toString(); + } + + @PUT @Path("preview/series") @Produces("application/json") public String previewSeries(@Context HttpServletRequest request, String buffer) { @@ -98,31 +120,33 @@ public class CirclesController { long startTime = 0; long endTime = 0; TimeHandler time = new TimeHandler(request); - startTime = time.getEndTime() - TimeUnit.SECONDS.toMillis(300); + startTime = time.getStartTime(); endTime = time.getEndTime(); Gson gson = new Gson(); ArrayList<SeriesMetaData> series = gson.fromJson(buffer, listType); double percent; - long timestamp; - series = ChukwaHBaseStore.getChartSeries(series, startTime, endTime); + List<String> data = ChukwaHBaseStore.getData(series, startTime, endTime); if(series.size()>=2) { - ArrayList<ArrayList<Number>> a = series.get(0).getData(); - ArrayList<Number> b = a.get(a.size()-1); - timestamp = b.get(0).longValue(); - double x = b.get(b.size()-1).doubleValue(); - a = series.get(1).getData(); - b = a.get(a.size()-1); - double y = b.get(b.size()-1).doubleValue(); + double x = 0; + double y = 1; + try { + x = Double.parseDouble(data.get(0)); + } catch(NumberFormatException e) { + x = 0; + } + try { + y = Double.parseDouble(data.get(1)); + } catch(NumberFormatException e) { + y = 1; + } percent = x / y * 100d; } else { - ArrayList<ArrayList<Number>> a = series.get(0).getData(); - ArrayList<Number> b = a.get(a.size()-1); - timestamp = b.get(0).longValue(); - percent = b.get(b.size()-1).doubleValue(); + double x = Double.parseDouble(data.get(0)); + percent = x; } percent = Math.round(percent * 100d) / 100d; Series answer = new Series("circle"); - answer.add(timestamp, percent); + answer.add(endTime, percent); String result = gson.toJson(answer); return result; } http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/hicc/rest/PieChartController.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/hicc/rest/PieChartController.java b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/PieChartController.java new file mode 100644 index 0000000..8f33af8 --- /dev/null +++ b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/PieChartController.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.hadoop.chukwa.hicc.rest; + +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.apache.hadoop.chukwa.datastore.ChukwaHBaseStore; +import org.apache.hadoop.chukwa.hicc.TimeHandler; +import org.apache.hadoop.chukwa.hicc.bean.Chart; +import org.apache.hadoop.chukwa.hicc.bean.ChartType; +import org.apache.hadoop.chukwa.hicc.bean.SeriesMetaData; +import org.apache.log4j.Logger; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +@Path("/piechart") +public class PieChartController extends ChartController{ + static Logger LOG = Logger.getLogger(ChartController.class); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + + @Context + VelocityEngine velocity; + + /** + * Render pie chart using chartist.js + * + * @param id Reference ID of Chart stored in HBase chukwa_meta table. + * @return html chart widget + */ + @GET + @Path("draw/{id}") + @Produces(MediaType.TEXT_HTML) + public String draw(@PathParam("id") String id) { + VelocityContext context = new VelocityContext(); + StringWriter sw = null; + try { + Chart chart = ChukwaHBaseStore.getChart(id); + List<SeriesMetaData> series = chart.getSeries(); + Gson gson = new Gson(); + String seriesMetaData = gson.toJson(series); + + context.put("chart", chart); + context.put("seriesMetaData", seriesMetaData); + context.put("chartTypeDonut", ChartType.DONUT); + Template template = velocity.getTemplate("pie.vm"); + sw = new StringWriter(); + template.merge(context, sw); + } catch (Exception e) { + e.printStackTrace(); + return e.getMessage(); + } + return sw.toString(); + } + + /** + * Preview a pie chart + */ + @PUT + @Path("preview") + public String preview(String buffer) { + VelocityContext context = new VelocityContext(); + StringWriter sw = null; + try { + Gson gson = new Gson(); + Chart chart = gson.fromJson(buffer, Chart.class); + List<SeriesMetaData> series = chart.getSeries(); + String seriesMetaData = gson.toJson(series); + + context.put("chart", chart); + context.put("seriesMetaData", seriesMetaData); + context.put("chartTypeDonut", ChartType.DONUT); + Template template = velocity.getTemplate("pie.vm"); + sw = new StringWriter(); + template.merge(context, sw); + } catch (Exception e) { + e.printStackTrace(); + return e.getMessage(); + } + return sw.toString(); + } + + @PUT + @Path("preview/series") + @Produces("application/json") + public String previewSeries(@Context HttpServletRequest request, String buffer) { + Type listType = new TypeToken<ArrayList<SeriesMetaData>>() { + }.getType(); + long startTime = 0; + long endTime = 0; + TimeHandler time = new TimeHandler(request); + startTime = time.getStartTime(); + endTime = time.getEndTime(); + Gson gson = new Gson(); + ArrayList<SeriesMetaData> series = gson.fromJson(buffer, listType); + List<String> data = ChukwaHBaseStore.getData(series, startTime, endTime); + String result = gson.toJson(data); + return result; + } +} http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/java/org/apache/hadoop/chukwa/hicc/rest/TileController.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/hadoop/chukwa/hicc/rest/TileController.java b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/TileController.java new file mode 100644 index 0000000..8e259a9 --- /dev/null +++ b/src/main/java/org/apache/hadoop/chukwa/hicc/rest/TileController.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.hadoop.chukwa.hicc.rest; + +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.apache.hadoop.chukwa.datastore.ChukwaHBaseStore; +import org.apache.hadoop.chukwa.hicc.TimeHandler; +import org.apache.hadoop.chukwa.hicc.bean.Chart; +import org.apache.hadoop.chukwa.hicc.bean.SeriesMetaData; +import org.apache.log4j.Logger; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +@Path("/tile") +public class TileController extends ChartController{ + static Logger LOG = Logger.getLogger(ChartController.class); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + + @Context + VelocityEngine velocity; + + /** + * Render a banner + * + * @param id Reference ID of Chart stored in HBase chukwa_meta table. + * @return html chart widget + */ + @GET + @Path("draw/{id}") + @Produces(MediaType.TEXT_HTML) + public String draw(@PathParam("id") String id) { + VelocityContext context = new VelocityContext(); + StringWriter sw = null; + try { + Chart chart = ChukwaHBaseStore.getChart(id); + List<SeriesMetaData> series = chart.getSeries(); + Gson gson = new Gson(); + String seriesMetaData = gson.toJson(series); + + context.put("chart", chart); + context.put("seriesMetaData", seriesMetaData); + Template template = velocity.getTemplate("tile.vm"); + sw = new StringWriter(); + template.merge(context, sw); + } catch (Exception e) { + e.printStackTrace(); + return e.getMessage(); + } + return sw.toString(); + } + + /** + * Preview a banner tile + */ + @PUT + @Path("preview") + public String preview(String buffer) { + VelocityContext context = new VelocityContext(); + StringWriter sw = null; + try { + Gson gson = new Gson(); + Chart chart = gson.fromJson(buffer, Chart.class); + List<SeriesMetaData> series = chart.getSeries(); + String seriesMetaData = gson.toJson(series); + + context.put("chart", chart); + context.put("seriesMetaData", seriesMetaData); + Template template = velocity.getTemplate("tile.vm"); + sw = new StringWriter(); + template.merge(context, sw); + } catch (Exception e) { + e.printStackTrace(); + return e.getMessage(); + } + return sw.toString(); + } + + @PUT + @Path("preview/series") + @Produces("application/json") + public String previewSeries(@Context HttpServletRequest request, String buffer) { + Type listType = new TypeToken<ArrayList<SeriesMetaData>>() { + }.getType(); + long startTime = 0; + long endTime = 0; + TimeHandler time = new TimeHandler(request); + startTime = time.getStartTime(); + endTime = time.getEndTime(); + Gson gson = new Gson(); + ArrayList<SeriesMetaData> series = gson.fromJson(buffer, listType); + List<String> data = ChukwaHBaseStore.getData(series, startTime, endTime); + String result = gson.toJson(data); + return result; + } +} http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/WEB-INF/vm/circles.vm ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/WEB-INF/vm/circles.vm b/src/main/web/hicc/WEB-INF/vm/circles.vm index 76acfda..76d9b41 100644 --- a/src/main/web/hicc/WEB-INF/vm/circles.vm +++ b/src/main/web/hicc/WEB-INF/vm/circles.vm @@ -15,16 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. *# -<html> +<!DOCTYPE html> +<html lang="en" class="no-js"> <head> <title>Circliful</title> <link href="/hicc/css/jquery.circliful.css" rel="stylesheet" type="text/css" /> <link href="/hicc/css/font-awesome.min.css" rel="stylesheet" type="text/css" /> -<script src="/hicc/js/jquery.js"></script> -<script src="/hicc/js/jquery.circliful.min.js"></script> - <style> body { font-family: arial,verdana, sans-serif; @@ -57,6 +55,9 @@ body { </div> </div> +<script src="/hicc/js/jquery.js" type="text/javascript"></script> +<script src="/hicc/js/jquery.circliful.min.js" type="text/javascript"></script> + <script> var tracker; @@ -78,6 +79,7 @@ function load() { render(result); } }); + tracker = setTimeout(load, 3000); } function render(result) { @@ -85,7 +87,7 @@ function render(result) { var width = 30; var fontsize = 38; var percent = result.series.data[0][1]; - var text = percent+"%"; + var text = percent+"$chart.getSuffixText()"; var color = "#70cac8"; if(percent > 75) { color = "#fc6e64"; @@ -103,11 +105,10 @@ function render(result) { attr('data-fgcolor', color). attr('data-text', text).circliful(); document.body.style.overflow = 'hidden'; - tracker = setTimeout(load, 3000); } $( document ).ready(function() { - load(); + load(); }); </script> </body> http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/WEB-INF/vm/pie.vm ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/WEB-INF/vm/pie.vm b/src/main/web/hicc/WEB-INF/vm/pie.vm new file mode 100644 index 0000000..5bb74d2 --- /dev/null +++ b/src/main/web/hicc/WEB-INF/vm/pie.vm @@ -0,0 +1,64 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. + --> +<!DOCTYPE html> +<html lang="en"> + <head> + <title>$chart.getTitle()</title> + <link href="/hicc/css/bootstrap-theme.min.css" type="text/css" rel="stylesheet" /> + <link href="/hicc/css/bootstrap.min.css" type="text/css" rel="stylesheet" /> + <link href="/hicc/css/chartist.css" type="text/css" rel="stylesheet" /> + <script src="/hicc/js/jquery.js"></script> + <script src="/hicc/js/bootstrap.min.js" type="text/javascript"></script> + <script src="/hicc/js/chartist.min.js" type="text/javascript"></script> +<style> +.outer { + display: table; + position: absolute; + height: 100%; + width: 100%; +} + +.middle { + display: table-cell; + vertical-align: middle; +} + +.inner { + margin-left: auto; + margin-right: auto; +} + +</style> + </head> + <body> + <div class="outer"> + <div class="middle"> + <div class="ct-chart ct-perfect-fourth inner"></div> + </div> + </div> + <script> + var _series=$seriesMetaData; + #if ( $chart.getType() == $chartTypeDonut ) + var donut=true; + #else + var donut=false; + #end + </script> + <script src="/hicc/js/pie.js"></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/WEB-INF/vm/tile.vm ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/WEB-INF/vm/tile.vm b/src/main/web/hicc/WEB-INF/vm/tile.vm new file mode 100644 index 0000000..edb157d --- /dev/null +++ b/src/main/web/hicc/WEB-INF/vm/tile.vm @@ -0,0 +1,133 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> +<!DOCTYPE html> +<html lang="en" class="no-js"> + <head> + <title>$chart.getTitle()</title> + <link href="/hicc/css/bootstrap-theme.min.css" type="text/css" rel="stylesheet" /> + <link href="/hicc/css/bootstrap.min.css" type="text/css" rel="stylesheet" /> + <script src="/hicc/js/jquery.js" type="text/javascript"></script> + <script src="/hicc/js/bootstrap.min.js" type="text/javascript"></script> + <style> + .tile { + color: #ffffff; + background-color: #5bc0de; + } + .container { + width: 100%; + } + .row { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + } + + .jumbotron.vertical-center { + margin-bottom: 0; /* Remove the default bottom margin of .jumbotron */ + } + + .vertical-center { + min-height: 100%; /* Fallback for vh unit */ + min-height: 100vh; /* You might also want to use + 'height' property instead. + + Note that for percentage values of + 'height' or 'min-height' properties, + the 'height' of the parent element + should be specified explicitly. + + In this case the parent of '.vertical-center' + is the <body> element */ + + /* Make it a flex container */ + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + /* Align the bootstrap's container vertically */ + -webkit-box-align : center; + -webkit-align-items : center; + -moz-box-align : center; + -ms-flex-align : center; + align-items : center; + + /* In legacy web browsers such as Firefox 9 + we need to specify the width of the flex container */ + width: 100%; + + /* Also 'margin: 0 auto' doesn't have any effect on flex items in such web browsers + hence the bootstrap's container won't be aligned to the center anymore. + + Therefore, we should use the following declarations to get it centered again */ + -webkit-box-pack : center; + -moz-box-pack : center; + -ms-flex-pack : center; + -webkit-justify-content : center; + justify-content : center; + } + + </style> + </head> + <body onResize="resize()"> + <div class="vertical-center"> + <div class="container"> + <div class="row"> + <div class="col-xs-5 col-md-5 text-center tile"> + <h2><span class="glyphicon $chart.getIcon()" aria-hidden="true"></span></h2> + $chart.getBannerText() + </div> + <div class="col-xs-7 col-md-7 text-center"> + <p><h1 id="value"></h1> $chart.getSuffixText()</p> + </div> + </div> + </div> + </div> + + <script src="/hicc/js/jquery.js"></script> + <script> + var tracker; + + function resize() { + clearTimeout(tracker); + tracker = setTimeout(render, 50); + } + + function render() { + var _series=$seriesMetaData; + var buffer=JSON.stringify(_series); + $.ajax({ + type: "PUT", + url: "/hicc/v1/tile/preview/series", + dataType: "json", + data: buffer, + success: function(data) { + $("#value").html(data.join("/")); + } + }); + tracker = setTimeout(render, 3000); + } + + $( document ).ready(function() { + render(); + }); + </script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/css/bootstrap-iconpicker.min.css ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/css/bootstrap-iconpicker.min.css b/src/main/web/hicc/home/css/bootstrap-iconpicker.min.css new file mode 100644 index 0000000..fd0160c --- /dev/null +++ b/src/main/web/hicc/home/css/bootstrap-iconpicker.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap-iconpicker v1.7.0 + * + * Copyright 2013-2015 Victor Valencia Rico. + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @recktoner. + */.iconpicker .caret{margin-left:10px!important}.iconpicker{min-width:60px}.iconpicker input.search-control{margin-bottom:6px;margin-top:6px}div.iconpicker.left .table-icons{margin-right:auto}div.iconpicker.center .table-icons{margin-left:auto;margin-right:auto}div.iconpicker.right .table-icons{margin-left:auto}.table-icons .btn{min-height:30px;min-width:35px;text-align:center;padding:0;margin:2px}.table-icons td{min-width:39px}.popover{max-width:inherit!important}.iconpicker-popover{z-index:1050!important}.iconpicker-popover .search-control{margin-bottom:6px;margin-top:6px} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/css/jquery.gridster.css ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/css/jquery.gridster.css b/src/main/web/hicc/home/css/jquery.gridster.css index ee40430..9251929 100755 --- a/src/main/web/hicc/home/css/jquery.gridster.css +++ b/src/main/web/hicc/home/css/jquery.gridster.css @@ -35,7 +35,7 @@ ul, ol { } body { - background-color: #EEEEEE; + background-color: #ffffff; font-family: 'Helvetica Neue', Arial, sans-serif; -webkit-font-smoothing: antialiased; font-size: x-small; @@ -44,10 +44,12 @@ body { .gridster { margin-top: 70px; - margin-left: 0 auto; - margin-right: 0 auto; - margin-bottom: 0 auto; + margin-left: auto; + margin-right: auto; + margin-bottom: auto; /*position:relative;*/ + padding: 10px; + width: 99%; } .gridster > * { @@ -87,7 +89,7 @@ body { .gridster .preview-holder { z-index: 1; position: absolute; - background-color: #fff; + background-color: #ccc; border-color: #fff; opacity: 0.3; } http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/graph-explorer.html ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/graph-explorer.html b/src/main/web/hicc/home/graph-explorer.html index 73580d5..03ede7c 100644 --- a/src/main/web/hicc/home/graph-explorer.html +++ b/src/main/web/hicc/home/graph-explorer.html @@ -23,9 +23,7 @@ <link href="../css/bootstrap.min.css" type="text/css" rel="stylesheet" /> <link href="../css/bootstrap-theme.min.css" type="text/css" rel="stylesheet" /> <link href="css/select2.min.css" rel="stylesheet" /> - <script src="../js/jquery.js" type="text/javascript"></script> - <script src="../js/bootstrap.min.js" type="text/javascript"></script> - <script src="js/select2.min.js"></script> + <link href="css/bootstrap-iconpicker.min.css"/> <style> .nowrap td { white-space: nowrap; @@ -50,24 +48,59 @@ <label>Metrics</label> <select class="metrics form-control" multiple="multiple"></select> <label>Sources</label> <select class="sources form-control" multiple="multiple"></select> <label>Title</label> <input type=text id="title" class="form-control" /> - <label>Y-axis Min</label> <input type="text" id="ymin" class="form-control" /> - <label>Y-axis Max</label> <input type="text" id="ymax" class="form-control" /> - <label>Y-axis Unit</label> - <select id="yunit" class="form-control"> - <option>generic</option> - <option>bytes</option> - <option>bytes-decimal</option> - <option value="ops">op/s</option> - <option value="percent">%</option> - </select> - <div id="chartType"></div> - <input type=button name="action" value="Plot" class="btn btn-default" onClick="plot()"> - <input type=button name="action" value="Publish" class="btn btn-default" onClick="publishChart()"> + <ul id="view" class="nav nav-pills"> + <li role="presentation" class="active"><a data-toggle="pill" href="#time">Time Series</a></li> + <li role="presentation"><a data-toggle="pill" href="#tile">Tile</a></li> + <li role="presentation"><a data-toggle="pill" href="#pie">Pie Chart</a></li> + <li role="presentation"><a data-toggle="pill" href="#ring">Ring Chart</a></li> + </ul> + + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="time"> + <label>Y-axis Min</label> <input type="text" id="ymin" class="form-control" /> + <label>Y-axis Max</label> <input type="text" id="ymax" class="form-control" /> + <label>Y-axis Unit</label> + <select id="yunit" class="form-control"> + <option>generic</option> + <option>bytes</option> + <option>bytes-decimal</option> + <option value="ops">op/s</option> + <option value="percent">%</option> + </select> + <div id="chartType"></div> + </div> + <div role="tabpanel" class="tab-pane" id="tile"> + <label>Banner Icon</label><button name="icon" class="btn btn-default form-control" role="iconpicker"></button> + <label>Banner Text</label><input type="text" id="banner" class="form-control" /> + <label>Suffix Label</label><input type="text" id="suffix" class="form-control" /> + </div> + <div role="tabpanel" class="tab-pane" id="pie"> + <div class="checkbox"> + <label><input type="checkbox" id="donut"/>Donut</label> + </div> + </div> + <div role="tabpanel" class="tab-pane" id="ring"> + <label>Threshold</label> + <select id="threshold" class="form-control"> + <option>Upper bound</option> + <option>Lower bound</option> + </select> + <label>Suffix Label</label><input type="text" id="ringSuffix" class="form-control" /> + </div> + </div> + + <input type=button name="action" value="Plot" class="btn btn-default" onClick="preview()"> + <input type=button name="action" value="Publish" class="btn btn-default" onClick="publishChart()"> </div> <div class="col-md-8 col-lg-8"> <iframe id="graph" width="100%" height="700px" frameBorder="0" scrolling="no"></iframe> </div> </form> + <script src="../js/jquery.js" type="text/javascript"></script> + <script src="../js/bootstrap.min.js" type="text/javascript"></script> + <script src="js/select2.min.js"></script> + <script src="js/iconset/iconset-glyphicon.min.js"></script> + <script src="js/bootstrap-iconpicker.min.js"></script> <script> function status(type, message) { $('#status').html('<div class="alert alert-'+type+' alert-dismissible" role="alert">'+ @@ -162,6 +195,7 @@ $(function() { $metricsEventSelect.on("select2:unselect", function(e) { $('#chartType').html(""); }); + }); @@ -171,7 +205,6 @@ $(function() { $('.sources option:eq(0)').attr('selected',true); } var url = []; - var idx = 0; $('.metrics :selected').each(function(i, selected) { var id = '#ctype' + i; var chartType = $(id).val(); @@ -186,24 +219,59 @@ $(function() { } else { s[chartType]=chartTypeOption; } - url[idx++] = s; + url.push(s); }); }); var title = $('#title').val(); + var icon = $('input[name="icon"]').val(); var ymin = $('#ymin').val() ; var ymax = $('#ymax').val(); var yunit = $('#yunit').val(); - var data = { 'title' : title, 'yUnitType' : yunit, 'width' : 300, 'height' : 200, 'series' : url }; + var banner = $('#banner').val(); + var suffix = $('#suffix').val(); + var view = $("ul#view li.active"); + if(view.text()=="Ring Chart") { + suffix = $('#ringSuffix').val(); + } + + var data = { + 'title' : title, + 'icon' : icon, + 'bannerText' : banner, + 'suffixText' : suffix, + 'yUnitType' : yunit, + 'width' : 300, + 'height' : 200, + 'series' : url + }; if(ymin!='') { data['min']=ymin; } if(ymax!='') { data['max']=ymax; } + + if( document.getElementById('donut').checked) { + data['type']="DONUT"; + } + return data; } - function plot() { + function preview() { + var view = $("ul#view li.active"); + if(view.text()=="Time Series") { + plotTimeSeries(); + } else if(view.text()=="Tile") { + plotTile(); + } else if(view.text()=="Pie Chart") { + plotPie(); + } else if(view.text()=="Ring Chart") { + plotCircle(); + } + } + + function plotTimeSeries() { var data = buildChart(); $.ajax({ url: '/hicc/v1/chart/preview', @@ -211,10 +279,67 @@ $(function() { contentType: 'application/json', data: JSON.stringify(data), success: function(result) { - $('#graph')[0].src="about:blank"; - $('#graph')[0].contentWindow.document.open(); - $('#graph')[0].contentWindow.document.write(result); - $('#graph')[0].contentWindow.document.close(); + $('#graph')[0].src="/hicc/loading.html"; + setTimeout(function() { + $('#graph')[0].contentWindow.document.open(); + $('#graph')[0].contentWindow.document.write(result); + $('#graph')[0].contentWindow.document.close(); + }, 500); + } + }); + } + + function plotTile() { + var data = buildChart(); + $.ajax({ + url: '/hicc/v1/tile/preview', + type: 'PUT', + contentType: 'application/json', + data: JSON.stringify(data), + success: function(result) { + $('#graph')[0].src="/hicc/loading.html"; + setTimeout(function() { + $('#graph')[0].contentWindow.document.open(); + $('#graph')[0].contentWindow.document.write(result); + $('#graph')[0].contentWindow.document.close(); + }, 500); + } + }); + } + + function plotPie() { + var data = buildChart(); + $.ajax({ + url: '/hicc/v1/piechart/preview', + type: 'PUT', + contentType: 'application/json', + data: JSON.stringify(data), + success: function(result) { + $('#graph')[0].src="/hicc/loading.html"; + setTimeout(function() { + $('#graph')[0].contentWindow.document.open(); + $('#graph')[0].contentWindow.document.write(result); + $('#graph')[0].contentWindow.document.close(); + }, 500); + } + }); + } + + function plotCircle() { + var data = buildChart(); + $.ajax({ + url: '/hicc/v1/circles/preview', + type: 'PUT', + contentType: 'application/json', + data: JSON.stringify(data), + success: function(result) { + console.log(result); + $('#graph')[0].src="/hicc/loading.html"; + setTimeout(function() { + $('#graph')[0].contentWindow.document.open(); + $('#graph')[0].contentWindow.document.write(result); + $('#graph')[0].contentWindow.document.close(); + }, 500); } }); } @@ -263,7 +388,18 @@ $(function() { contentType : "application/json", data: JSON.stringify(json), success: function(data) { - buildWidget(json.title, '/hicc/v1/chart/draw/'+data); + var view = $("ul#view li.active"); + if(view.text()=="Time Series") { + type="chart"; + } else if(view.text()=="Tile") { + type="tile"; + } else if(view.text()=="Pie Chart") { + type="piechart"; + } else if(view.text()=="Ring Chart") { + type="circles"; + } + var target = '/hicc/v1/'+type+'/draw/'+data + buildWidget(json.title, target); }, error: function(data) { alert("failed"); http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/js/bootstrap-iconpicker.min.js ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/js/bootstrap-iconpicker.min.js b/src/main/web/hicc/home/js/bootstrap-iconpicker.min.js new file mode 100644 index 0000000..66513f9 --- /dev/null +++ b/src/main/web/hicc/home/js/bootstrap-iconpicker.min.js @@ -0,0 +1,19 @@ +/*!======================================================================== + * Bootstrap: bootstrap-iconpicker.js v1.7.0 by @recktoner + * https://victor-valencia.github.com/bootstrap-iconpicker + * ======================================================================== + * Copyright 2013-2015 Victor Valencia Rico. + * + * 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. + * ======================================================================== */ +!function($){"use strict";var Iconpicker=function(element,options){this.$element=$(element),this.options=$.extend({},Iconpicker.DEFAULTS,this.$element.data()),this.options=$.extend({},this.options,options)};Iconpicker.ICONSET_EMPTY={iconClass:"",iconClassFix:"",icons:[]},Iconpicker.ICONSET={_custom:null,elusiveicon:$.iconset_elusiveicon||Iconpicker.ICONSET_EMPTY,fontawesome:$.iconset_fontawesome||Iconpicker.ICONSET_EMPTY,ionicon:$.iconset_ionicon||Iconpicker.ICONSET_EMPTY,glyphicon:$.iconset_glyphicon||Iconpicker.ICONSET_EMPTY,mapicon:$.iconset_mapicon||Iconpicker.ICONSET_EMPTY,materialdesign:$.iconset_materialdesign||Iconpicker.ICONSET_EMPTY,octicon:$.iconset_octicon||Iconpicker.ICONSET_EMPTY,typicon:$.iconset_typicon||Iconpicker.ICONSET_EMPTY,weathericon:$.iconset_weathericon||Iconpicker.ICONSET_EMPTY},Iconpicker.DEFAULTS={align:"center",arrowClass:"btn-primary",arrowNextIconClass:"glyphicon glyphicon-arrow-right",arrowPrevIconClass:"glyphicon glyphicon-arrow-left",cols:4,icon:"", iconset:"glyphicon",header:!0,labelHeader:"{0} / {1}",footer:!0,labelFooter:"{0} - {1} of {2}",placement:"bottom",rows:4,search:!0,searchText:"Search icon",selectedClass:"btn-warning",unselectedClass:"btn-default"},Iconpicker.prototype.bindEvents=function(){var op=this.options,el=this;op.table.find(".btn-previous, .btn-next").off("click").on("click",function(e){e.preventDefault();var inc=parseInt($(this).val(),10);el.changeList(op.page+inc)}),op.table.find(".btn-icon").off("click").on("click",function(e){e.preventDefault(),el.select($(this).val()),op.inline===!1?el.$element.popover("destroy"):op.table.find("i."+$(this).val()).parent().addClass(op.selectedClass)}),op.table.find(".search-control").off("keyup").on("keyup",function(){el.changeList(1)})},Iconpicker.prototype.changeList=function(page){this.filterIcons(),this.updateLabels(page),this.updateIcons(page),this.options.page=page,this.bindEvents()},Iconpicker.prototype.filterIcons=function(){var op=this.options,search=op.table.fi nd(".search-control").val();if(""===search)op.icons=Iconpicker.ICONSET[op.iconset].icons;else{var result=[];$.each(Iconpicker.ICONSET[op.iconset].icons,function(i,v){v.indexOf(search)>-1&&result.push(v)}),op.icons=result}},Iconpicker.prototype.removeAddClass=function(target,remove,add){return this.options.table.find(target).removeClass(remove).addClass(add),add},Iconpicker.prototype.reset=function(){this.updatePicker(),this.changeList(1)},Iconpicker.prototype.select=function(icon){var op=this.options,el=this.$element;op.selected=$.inArray(icon.replace(op.iconClassFix,""),op.icons),-1===op.selected&&(op.selected=0,icon=op.iconClassFix+op.icons[op.selected]),""!==icon&&op.selected>=0&&(op.icon=icon,op.inline===!1&&(el.find("input").val(icon),el.find("i").attr("class","").addClass(op.iconClass).addClass(icon)),icon===op.iconClassFix?el.trigger({type:"change",icon:"empty"}):el.trigger({type:"change",icon:icon}),op.table.find("button."+op.selectedClass).removeClass(op.selectedClass))},Ic onpicker.prototype.switchPage=function(icon){var op=this.options;if(op.selected=$.inArray(icon.replace(op.iconClassFix,""),op.icons),op.selected>=0){var page=Math.ceil((op.selected+1)/this.totalIconsPerPage());this.changeList(page)}""===icon?op.table.find("i."+op.iconClassFix).parent().addClass(op.selectedClass):op.table.find("i."+icon).parent().addClass(op.selectedClass)},Iconpicker.prototype.totalPages=function(){return Math.ceil(this.totalIcons()/this.totalIconsPerPage())},Iconpicker.prototype.totalIcons=function(){return this.options.icons.length},Iconpicker.prototype.totalIconsPerPage=function(){return 0===this.options.rows?this.options.icons.length:this.options.cols*this.options.rows},Iconpicker.prototype.updateArrows=function(page){var op=this.options,total_pages=this.totalPages();1===page?op.table.find(".btn-previous").addClass("disabled"):op.table.find(".btn-previous").removeClass("disabled"),page===total_pages||0===total_pages?op.table.find(".btn-next").addClass("disabled" ):op.table.find(".btn-next").removeClass("disabled")},Iconpicker.prototype.updateIcons=function(page){var op=this.options,tbody=op.table.find("tbody").empty(),offset=(page-1)*this.totalIconsPerPage(),length=op.rows;0===op.rows&&(length=op.icons.length);for(var i=0;length>i;i++){for(var tr=$("<tr></tr>"),j=0;j<op.cols;j++){var pos=offset+i*op.cols+j,btn=$('<button class="btn '+op.unselectedClass+' btn-icon"></button>').hide();if(pos<op.icons.length){var v=op.iconClassFix+op.icons[pos];btn.val(v).attr("title",v).append('<i class="'+op.iconClass+" "+v+'"></i>').show(),op.icon===v&&btn.addClass(op.selectedClass).addClass("btn-icon-selected")}tr.append($("<td></td>").append(btn))}tbody.append(tr)}},Iconpicker.prototype.updateIconsCount=function(){var op=this.options;if(op.footer===!0){var icons_count=["<tr>",' <td colspan="'+op.cols+'" class="text-center">',' <span class="icons-count"></span>'," </td>","</tr>"];op.table.find("tfoot").empty().append(icons_count.join(""))}},Iconp icker.prototype.updateLabels=function(page){var op=this.options,total_icons=this.totalIcons(),total_pages=this.totalPages();op.table.find(".page-count").html(op.labelHeader.replace("{0}",0===total_pages?0:page).replace("{1}",total_pages));var offset=(page-1)*this.totalIconsPerPage(),total=page*this.totalIconsPerPage();op.table.find(".icons-count").html(op.labelFooter.replace("{0}",offset+1).replace("{1}",total_icons>total?total:total_icons).replace("{2}",total_icons)),this.updateArrows(page)},Iconpicker.prototype.updatePagesCount=function(){var op=this.options;if(op.header===!0){for(var tr=$("<tr></tr>"),i=0;i<op.cols;i++){var td=$('<td class="text-center"></td>');if(0===i||i===op.cols-1){var arrow=['<button class="btn btn-arrow '+(0===i?"btn-previous":"btn-next")+" "+op.arrowClass+'" value="'+(0===i?-1:1)+'">','<span class="'+(0===i?op.arrowPrevIconClass:op.arrowNextIconClass)+'"></span>',"</button>"];td.append(arrow.join("")),tr.append(td)}else 0===tr.find(".page-count").length&&( td.attr("colspan",op.cols-2).append('<span class="page-count"></span>'),tr.append(td))}op.table.find("thead").empty().append(tr)}},Iconpicker.prototype.updatePicker=function(){var op=this.options;if(op.cols<4)throw"Iconpicker => The number of columns must be greater than or equal to 4. [option.cols = "+op.cols+"]";if(op.rows<0)throw"Iconpicker => The number of rows must be greater than or equal to 0. [option.rows = "+op.rows+"]";this.updatePagesCount(),this.updateSearch(),this.updateIconsCount()},Iconpicker.prototype.updateSearch=function(){var op=this.options,search=["<tr>",' <td colspan="'+op.cols+'">',' <input type="text" class="form-control search-control" style="width: '+39*op.cols+'px;" placeholder="'+op.searchText+'">'," </td>","</tr>"];search=$(search.join("")),op.search===!0?search.show():search.hide(),op.table.find("thead").append(search)},Iconpicker.prototype.setAlign=function(value){this.$element.removeClass(this.options.align).addClass(value),this.options.alig n=value},Iconpicker.prototype.setArrowClass=function(value){this.options.arrowClass=this.removeAddClass(".btn-arrow",this.options.arrowClass,value)},Iconpicker.prototype.setArrowNextIconClass=function(value){this.options.arrowNextIconClass=this.removeAddClass(".btn-next > span",this.options.arrowNextIconClass,value)},Iconpicker.prototype.setArrowPrevIconClass=function(value){this.options.arrowPrevIconClass=this.removeAddClass(".btn-previous > span",this.options.arrowPrevIconClass,value)},Iconpicker.prototype.setCols=function(value){this.options.cols=value,this.reset()},Iconpicker.prototype.setFooter=function(value){var footer=this.options.table.find("tfoot");value===!0?footer.show():footer.hide(),this.options.footer=value},Iconpicker.prototype.setHeader=function(value){var header=this.options.table.find("thead");value===!0?header.show():header.hide(),this.options.header=value},Iconpicker.prototype.setIcon=function(value){this.select(value)},Iconpicker.prototype.setIconset=function(v alue){var op=this.options;$.isPlainObject(value)?(Iconpicker.ICONSET._custom=$.extend(Iconpicker.ICONSET_EMPTY,value),op.iconset="_custom"):Iconpicker.ICONSET.hasOwnProperty(value)?op.iconset=value:op.iconset=Iconpicker.DEFAULTS.iconset,op=$.extend(op,Iconpicker.ICONSET[op.iconset]),this.reset(),this.select(op.icon)},Iconpicker.prototype.setLabelHeader=function(value){this.options.labelHeader=value,this.updateLabels(this.options.page)},Iconpicker.prototype.setLabelFooter=function(value){this.options.labelFooter=value,this.updateLabels(this.options.page)},Iconpicker.prototype.setPlacement=function(value){this.options.placement=value},Iconpicker.prototype.setRows=function(value){this.options.rows=value,this.reset()},Iconpicker.prototype.setSearch=function(value){var search=this.options.table.find(".search-control");value===!0?search.show():search.hide(),search.val(""),this.changeList(1),this.options.search=value},Iconpicker.prototype.setSearchText=function(value){this.options.table.fi nd(".search-control").attr("placeholder",value),this.options.searchText=value},Iconpicker.prototype.setSelectedClass=function(value){this.options.selectedClass=this.removeAddClass(".btn-icon-selected",this.options.selectedClass,value)},Iconpicker.prototype.setUnselectedClass=function(value){this.options.unselectedClass=this.removeAddClass(".btn-icon",this.options.unselectedClass,value)};var old=$.fn.iconpicker;$.fn.iconpicker=function(option,params){return this.each(function(){var $this=$(this),data=$this.data("bs.iconpicker"),options="object"==typeof option&&option;if(data||$this.data("bs.iconpicker",data=new Iconpicker(this,options)),"string"==typeof option){if("undefined"==typeof data[option])throw'Iconpicker => The "'+option+'" method does not exists.';data[option](params)}else{var op=data.options;op=$.extend(op,{inline:!1,page:1,selected:-1,table:$('<table class="table-icons"><thead></thead><tbody></tbody><tfoot></tfoot></table>')});var name="undefined"!=typeof $this.attr("name ")?'name="'+$this.attr("name")+'"':"";"BUTTON"===$this.prop("tagName")?($this.empty().append("<i></i>").append('<input type="hidden" '+name+"></input>").append('<span class="caret"></span>').addClass("iconpicker"),data.setIconset(op.iconset),$this.on("click",function(e){e.preventDefault(),$this.popover({animation:!1,trigger:"manual",html:!0,content:op.table,container:"body",placement:op.placement}).on("shown.bs.popover",function(){data.switchPage(op.icon),data.bindEvents()}),$this.data("bs.popover").tip().addClass("iconpicker-popover"),$this.popover("show")})):(op.inline=!0,data.setIconset(op.iconset),$this.empty().append('<input type="hidden" '+name+"></input>").append(op.table).addClass("iconpicker").addClass(op.align),data.switchPage(op.icon),data.bindEvents())}})},$.fn.iconpicker.Constructor=Iconpicker,$.fn.iconpicker.noConflict=function(){return $.fn.iconpicker=old,this},$(document).on("click","body",function(e){$(".iconpicker").each(function(){$(this).is(e.target)||0!==$(this) .has(e.target).length||0!==$(".popover").has(e.target).length||$(this).popover("destroy")})}),$('button[role="iconpicker"],div[role="iconpicker"]').iconpicker()}(jQuery); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/js/iconset/iconset-glyphicon.min.js ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/js/iconset/iconset-glyphicon.min.js b/src/main/web/hicc/home/js/iconset/iconset-glyphicon.min.js new file mode 100644 index 0000000..da6b9fb --- /dev/null +++ b/src/main/web/hicc/home/js/iconset/iconset-glyphicon.min.js @@ -0,0 +1,21 @@ +/*!======================================================================== + * Bootstrap: iconset-glyphicon.js by @recktoner + * https://victor-valencia.github.com/bootstrap-iconpicker + * + * Iconset: Glyphicons + * ======================================================================== + * Copyright 2013-2015 Victor Valencia Rico. + * + * 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. + * ======================================================================== */ +!function($){$.iconset_glyphicon={iconClass:"glyphicon",iconClassFix:"glyphicon-",icons:["","adjust","align-center","align-justify","align-left","align-right","arrow-down","arrow-left","arrow-right","arrow-up","asterisk","backward","ban-circle","barcode","bell","bold","book","bookmark","briefcase","bullhorn","calendar","camera","certificate","check","chevron-down","chevron-left","chevron-right","chevron-up","circle-arrow-down","circle-arrow-left","circle-arrow-right","circle-arrow-up","cloud","cloud-download","cloud-upload","cog","collapse-down","collapse-up","comment","compressed","copyright-mark","credit-card","cutlery","dashboard","download","download-alt","earphone","edit","eject","envelope","euro","exclamation-sign","expand","export","eye-close","eye-open","facetime-video","fast-backward","fast-forward","file","film","filter","fire","flag","flash","floppy-disk","floppy-open","floppy-remove","floppy-save","floppy-saved","folder-close","folder-open","font","forward","fullscreen", "gbp","gift","glass","globe","hand-down","hand-left","hand-right","hand-up","hd-video","hdd","header","headphones","heart","heart-empty","home","import","inbox","indent-left","indent-right","info-sign","italic","leaf","link","list","list-alt","lock","log-in","log-out","magnet","map-marker","minus","minus-sign","move","music","new-window","off","ok","ok-circle","ok-sign","open","paperclip","pause","pencil","phone","phone-alt","picture","plane","play","play-circle","plus","plus-sign","print","pushpin","qrcode","question-sign","random","record","refresh","registration-mark","remove","remove-circle","remove-sign","repeat","resize-full","resize-horizontal","resize-small","resize-vertical","retweet","road","save","saved","screenshot","sd-video","search","send","share","share-alt","shopping-cart","signal","sort","sort-by-alphabet","sort-by-alphabet-alt","sort-by-attributes","sort-by-attributes-alt","sort-by-order","sort-by-order-alt","sound-5-1","sound-6-1","sound-7-1","sound-dolby","sound -stereo","star","star-empty","stats","step-backward","step-forward","stop","subtitles","tag","tags","tasks","text-height","text-width","th","th-large","th-list","thumbs-down","thumbs-up","time","tint","tower","transfer","trash","tree-conifer","tree-deciduous","unchecked","upload","usd","user","volume-down","volume-off","volume-up","warning-sign","wrench","zoom-in","zoom-out"]}}(jQuery); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/home/tile.html ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/home/tile.html b/src/main/web/hicc/home/tile.html index cf1aa91..729462f 100644 --- a/src/main/web/hicc/home/tile.html +++ b/src/main/web/hicc/home/tile.html @@ -27,6 +27,10 @@ .tile { color: #ffffff; background-color: #5bc0de; + text-overflow: hidden; + } + .container { + width: 100%; } .row { display: -webkit-box; @@ -34,15 +38,60 @@ display: -ms-flexbox; display: flex; } +.jumbotron.vertical-center { + margin-bottom: 0; /* Remove the default bottom margin of .jumbotron */ +} + +.vertical-center { + min-height: 100%; /* Fallback for vh unit */ + min-height: 100vh; /* You might also want to use + 'height' property instead. + + Note that for percentage values of + 'height' or 'min-height' properties, + the 'height' of the parent element + should be specified explicitly. + + In this case the parent of '.vertical-center' + is the <body> element */ + + /* Make it a flex container */ + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + /* Align the bootstrap's container vertically */ + -webkit-box-align : center; + -webkit-align-items : center; + -moz-box-align : center; + -ms-flex-align : center; + align-items : center; + + /* In legacy web browsers such as Firefox 9 + we need to specify the width of the flex container */ + width: 100%; + + /* Also 'margin: 0 auto' doesn't have any effect on flex items in such web browsers + hence the bootstrap's container won't be aligned to the center anymore. + + Therefore, we should use the following declarations to get it centered again */ + -webkit-box-pack : center; + -moz-box-pack : center; + -ms-flex-pack : center; + -webkit-justify-content : center; + justify-content : center; +} </style> </head> <body onResize="resize()"> - <div class="jumbotron"> + <div class="jumbotron vertical-center"> <div class="container"> <div class="row"> <div class="col-xs-5 col-md-5 text-center tile"> <h2><span class="glyphicon glyphicon-picture" aria-hidden="true"></span></h2> - Applications + <div class="tile">Applications</div> </div> <div class="col-xs-7 col-md-7 text-center"> <p><h1>4</h1> Running</p> @@ -67,6 +116,7 @@ $( document ).ready(function() { render(); }); + document.body.style.overflow = 'hidden'; </script> </body> </html> http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/images/loading.svg ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/images/loading.svg b/src/main/web/hicc/images/loading.svg new file mode 100644 index 0000000..a8a7070 --- /dev/null +++ b/src/main/web/hicc/images/loading.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<svg width='120px' height='120px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-ring"><rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><defs><filter id="uil-ring-shadow" x="-100%" y="-100%" width="300%" height="300%"><feOffset result="offOut" in="SourceGraphic" dx="0" dy="0"></feOffset><feGaussianBlur result="blurOut" in="offOut" stdDeviation="0"></feGaussianBlur><feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend></filter></defs><path d="M10,50c0,0,0,0.5,0.1,1.4c0,0.5,0.1,1,0.2,1.7c0,0.3,0.1,0.7,0.1,1.1c0.1,0.4,0.1,0.8,0.2,1.2c0.2,0.8,0.3,1.8,0.5,2.8 c0.3,1,0.6,2.1,0.9,3.2c0.3,1.1,0.9,2.3,1.4,3.5c0.5,1.2,1.2,2.4,1.8,3.7c0.3,0.6,0.8,1.2,1.2,1.9c0.4,0.6,0.8,1.3,1.3,1.9 c1,1.2,1.9,2.6,3.1,3.7c2.2,2.5,5,4.7,7.9,6.7c3,2,6.5,3.4,10.1,4.6c3.6,1.1,7.5,1.5,11.2,1.6c4-0.1,7.7-0.6,11.3-1.6 c3.6-1.2,7-2.6,10-4.6c3-2,5.8-4.2,7.9-6.7c1.2-1.2,2.1-2.5,3.1-3.7c0.5-0.6,0.9-1.3,1.3-1.9c0.4-0.6,0.8-1.3,1.2-1.9 c 0.6-1.3,1.3-2.5,1.8-3.7c0.5-1.2,1-2.4,1.4-3.5c0.3-1.1,0.6-2.2,0.9-3.2c0.2-1,0.4-1.9,0.5-2.8c0.1-0.4,0.1-0.8,0.2-1.2 c0-0.4,0.1-0.7,0.1-1.1c0.1-0.7,0.1-1.2,0.2-1.7C90,50.5,90,50,90,50s0,0.5,0,1.4c0,0.5,0,1,0,1.7c0,0.3,0,0.7,0,1.1 c0,0.4-0.1,0.8-0.1,1.2c-0.1,0.9-0.2,1.8-0.4,2.8c-0.2,1-0.5,2.1-0.7,3.3c-0.3,1.2-0.8,2.4-1.2,3.7c-0.2,0.7-0.5,1.3-0.8,1.9 c-0.3,0.7-0.6,1.3-0.9,2c-0.3,0.7-0.7,1.3-1.1,2c-0.4,0.7-0.7,1.4-1.2,2c-1,1.3-1.9,2.7-3.1,4c-2.2,2.7-5,5-8.1,7.1 c-0.8,0.5-1.6,1-2.4,1.5c-0.8,0.5-1.7,0.9-2.6,1.3L66,87.7l-1.4,0.5c-0.9,0.3-1.8,0.7-2.8,1c-3.8,1.1-7.9,1.7-11.8,1.8L47,90.8 c-1,0-2-0.2-3-0.3l-1.5-0.2l-0.7-0.1L41.1,90c-1-0.3-1.9-0.5-2.9-0.7c-0.9-0.3-1.9-0.7-2.8-1L34,87.7l-1.3-0.6 c-0.9-0.4-1.8-0.8-2.6-1.3c-0.8-0.5-1.6-1-2.4-1.5c-3.1-2.1-5.9-4.5-8.1-7.1c-1.2-1.2-2.1-2.7-3.1-4c-0.5-0.6-0.8-1.4-1.2-2 c-0.4-0.7-0.8-1.3-1.1-2c-0.3-0.7-0.6-1.3-0.9-2c-0.3-0.7-0.6-1.3-0.8-1.9c-0.4-1.3-0.9-2.5-1.2-3.7c-0.3-1.2-0.5-2.3-0.7-3.3 c-0.2-1-0.3-2-0.4-2.8c-0.1-0.4-0.1-0.8-0.1-1.2c0-0.4,0-0.7,0-1. 1c0-0.7,0-1.2,0-1.7C10,50.5,10,50,10,50z" fill="#5a707a" filter="url(#uil-ring-shadow)"><animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" repeatCount="indefinite" dur="1s"></animateTransform></path></svg> http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/js/pie.js ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/js/pie.js b/src/main/web/hicc/js/pie.js new file mode 100644 index 0000000..b2656cb --- /dev/null +++ b/src/main/web/hicc/js/pie.js @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +var pieChart = null; +var labels = []; +var series = []; + +for (var i = 0; i < _series.length; i++) { + labels[i] = _series[i].label; + series[i] = 1; +} + +var data = { + labels: labels, + series: series +}; + +var options = { + donut: donut, + labelInterpolationFnc: function(value) { + return value[0] + } +}; + +var responsiveOptions = [ + ['screen and (min-width: 200px)', { + chartPadding: 20, + labelOffset: 20, + labelDirection: 'explode', + labelInterpolationFnc: function(value) { + return value; + } + }], + ['screen and (min-width: 400px)', { + labelOffset: 80, + chartPadding: 20 + }] +]; + +var timer = null; + +function refresh() { + var buffer=JSON.stringify(_series); + $.ajax({ + url: "/hicc/v1/piechart/preview/series", + type: 'PUT', + contentType: 'application/json', + data: buffer, + dataType: 'json', + success: function(result) { + var data = { + labels: labels, + series: result + }; + if(pieChart == null) { + pieChart = new Chartist.Pie('.ct-chart', data, options, responsiveOptions); + timer = setTimeout(refresh, 3000); + } else { + pieChart.update(data, options, true); + } + } + }); +} + +refresh(); http://git-wip-us.apache.org/repos/asf/chukwa/blob/5e66273f/src/main/web/hicc/loading.html ---------------------------------------------------------------------- diff --git a/src/main/web/hicc/loading.html b/src/main/web/hicc/loading.html new file mode 100644 index 0000000..3ac7855 --- /dev/null +++ b/src/main/web/hicc/loading.html @@ -0,0 +1,49 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<!DOCTYPE html> +<html lang="en"> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link href="css/bootstrap-theme.min.css" type="text/css" rel="stylesheet" /> + <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet" /> + <style> + .vertical-center { + min-height: 100%; /* Fallback for browsers do NOT support vh unit */ + min-height: 100vh; /* These two lines are counted as one :-) */ + display: flex; + align-items: center; + } + .col-centered{ + float: none; + margin: 0 auto; + } + </style> + <script src="js/jquery.js" type="text/javascript"></script> + <script src="js/bootstrap.min.js" type="text/javascript"></script> + </head> + <body> + <div class="jumbotron vertical-center"> + <div class="container"> + <div class="row"> + <div class="col-lg-1 col-centered"> + <center><img src="images/loading.svg"/></center> + </div> + </div> + </div> + </div> + </body> +</html>
