ui update (#879)

* caravel ui update

* make headings bold on /explore

* bump back pagination color
This commit is contained in:
Alanna Scott 2016-08-08 10:55:03 -07:00 committed by GitHub
parent cb23362a5b
commit b0a1f07818
19 changed files with 375 additions and 332 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -14,7 +14,7 @@ const ace = require('brace');
require('bootstrap'); require('bootstrap');
require('brace/mode/css'); require('brace/mode/css');
require('brace/theme/crimson_editor'); require('brace/theme/crimson_editor');
require('./main.css'); require('../../stylesheets/dashboard.css');
require('../caravel-select2.js'); require('../caravel-select2.js');
// Injects the passed css string into a style sheet with the specified className // Injects the passed css string into a style sheet with the specified className

View File

@ -11,19 +11,17 @@ function SliceCell({ expandedSlices, removeSlice, slice }) {
<div> <div>
<div className="chart-header"> <div className="chart-header">
<div className="row"> <div className="row">
<div className="col-md-12 text-center header"> <div className="col-md-12 header">
{slice.slice_name} <span>{slice.slice_name}</span>
</div> </div>
<div className="col-md-12 chart-controls"> <div className="col-md-12 chart-controls">
<div className="pull-left"> <div className="pull-right">
<a title="Move chart" data-toggle="tooltip"> <a title="Move chart" data-toggle="tooltip">
<i className="fa fa-arrows drag" /> <i className="fa fa-arrows drag" />
</a> </a>
<a className="refresh" title="Force refresh data" data-toggle="tooltip"> <a className="refresh" title="Force refresh data" data-toggle="tooltip">
<i className="fa fa-repeat" /> <i className="fa fa-repeat" />
</a> </a>
</div>
<div className="pull-right">
{slice.description && {slice.description &&
<a title="Toggle chart description"> <a title="Toggle chart description">
<i <i

View File

@ -13,7 +13,7 @@ export default function QueryAndSaveBtns({ canAdd, onQuery }) {
return ( return (
<div className="btn-group query-and-save"> <div className="btn-group query-and-save">
<button type="button" className="btn btn-primary" onClick={onQuery}> <button type="button" className="btn btn-default" onClick={onQuery}>
<i className="fa fa-bolt"></i>Query <i className="fa fa-bolt"></i>Query
</button> </button>
<button <button

View File

@ -3,10 +3,10 @@
// nb: to add a new vis, you must also add a Python fn in viz.py // nb: to add a new vis, you must also add a Python fn in viz.py
// //
// js // js
var $ = window.$ = require('jquery'); const $ = window.$ = require('jquery');
var jQuery = window.jQuery = $; const jQuery = window.jQuery = $;
var px = require('./../modules/caravel.js'); const px = require('./../modules/caravel.js');
var showModal = require('./../modules/utils.js').showModal; const showModal = require('./../modules/utils.js').showModal;
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
@ -25,21 +25,21 @@ require('../../vendor/pygments.css');
require('../../stylesheets/explore.css'); require('../../stylesheets/explore.css');
require('../../node_modules/bootstrap-toggle/css/bootstrap-toggle.min.css'); require('../../node_modules/bootstrap-toggle/css/bootstrap-toggle.min.css');
var slice; let slice;
var getPanelClass = function (fieldPrefix) { const getPanelClass = function (fieldPrefix) {
return (fieldPrefix === 'flt' ? 'filter' : 'having') + '_panel'; return (fieldPrefix === 'flt' ? 'filter' : 'having') + '_panel';
}; };
function prepForm() { function prepForm() {
// Assigning the right id to form elements in filters // Assigning the right id to form elements in filters
var fixId = function ($filter, fieldPrefix, i) { const fixId = function ($filter, fieldPrefix, i) {
$filter.attr('id', function () { $filter.attr('id', function () {
return fieldPrefix + '_' + i; return fieldPrefix + '_' + i;
}); });
['col', 'op', 'eq'].forEach(function (fieldMiddle) { ['col', 'op', 'eq'].forEach(function (fieldMiddle) {
var fieldName = fieldPrefix + '_' + fieldMiddle; const fieldName = fieldPrefix + '_' + fieldMiddle;
$filter.find('[id^=' + fieldName + '_]') $filter.find('[id^=' + fieldName + '_]')
.attr('id', function () { .attr('id', function () {
return fieldName + '_' + i; return fieldName + '_' + i;
@ -51,7 +51,7 @@ function prepForm() {
}; };
['flt', 'having'].forEach(function (fieldPrefix) { ['flt', 'having'].forEach(function (fieldPrefix) {
var i = 1; let i = 1;
$('#' + getPanelClass(fieldPrefix) + ' #filters > div').each(function () { $('#' + getPanelClass(fieldPrefix) + ' #filters > div').each(function () {
fixId($(this), fieldPrefix, i); fixId($(this), fieldPrefix, i);
i++; i++;
@ -59,7 +59,8 @@ function prepForm() {
}); });
} }
function query(force, pushState) { function query(forceUpdate, pushState) {
let force = forceUpdate;
if (force === undefined) { if (force === undefined) {
force = false; force = false;
} }
@ -470,29 +471,19 @@ function saveSlice() {
} }
$(document).ready(function () { $(document).ready(function () {
const data = $('.slice').data('slice');
initExploreView(); initExploreView();
// Dynamically register this visualization // Dynamically register this visualization
var visType = window.viz_type.value; px.registerViz(data.viz_name);
px.registerViz(visType);
var data = $('.slice').data('slice');
slice = px.Slice(data); slice = px.Slice(data);
//
$('.slice').data('slice', slice); $('.slice').data('slice', slice);
// call vis render method, which issues ajax // call vis render method, which issues ajax
query(false, false); query(false, false);
// make checkbox inputs display as toggles
$(':checkbox')
.addClass('pull-right')
.attr('data-onstyle', 'default')
.bootstrapToggle({
size: 'mini',
});
$('div.toggle').addClass('pull-right');
slice.bindResizeToWindowResize(); slice.bindResizeToWindowResize();
}); });

View File

@ -68,11 +68,13 @@ $(document).ready(function () {
'#D6E685', '#D6E685',
'#1E6823', '#1E6823',
], ],
// Based on github's colors
domain: 'month', domain: 'month',
subDomain: 'day', subDomain: 'day',
itemName: 'action', itemName: 'action',
tooltip: true, tooltip: true,
cellSize: 10,
cellPadding: 2,
domainGutter: 22,
}); });
}); });
modelViewTable('#dash_table', 'DashboardModelViewAsync', 'changed_on', 'desc'); modelViewTable('#dash_table', 'DashboardModelViewAsync', 'changed_on', 'desc');

View File

@ -38,7 +38,6 @@
"autobind-decorator": "^1.3.3", "autobind-decorator": "^1.3.3",
"bootstrap": "^3.3.6", "bootstrap": "^3.3.6",
"bootstrap-datepicker": "^1.6.0", "bootstrap-datepicker": "^1.6.0",
"bootstrap-toggle": "^2.2.1",
"brace": "^0.7.0", "brace": "^0.7.0",
"brfs": "^1.4.3", "brfs": "^1.4.3",
"cal-heatmap": "3.5.4", "cal-heatmap": "3.5.4",

View File

@ -28,6 +28,12 @@ body {
input.form-control { input.form-control {
background-color: white; background-color: white;
} }
input.form-control[type=text], input.form-control[type=search] {
border: 1px solid #ccc!important;
box-shadow: none!important;
padding: 2px;
border-radius: 2px;
}
.chart-header a.danger { .chart-header a.danger {
color: red; color: red;
@ -50,6 +56,8 @@ input.form-control {
margin-right: 10px; margin-right: 10px;
opacity: 0.5; opacity: 0.5;
cursor: pointer; cursor: pointer;
float: left;
margin-top: 13px;
} }
.slice_description{ .slice_description{
@ -83,13 +91,6 @@ input[type="checkbox"] {
height: 16px; height: 16px;
float: right; float: right;
} }
form div {
padding-top: 1px;
}
.header span {
margin-left: 5px;
}
.widget-is-cached { .widget-is-cached {
display: none; display: none;
@ -132,9 +133,6 @@ span.title-block {
font-size: 11px !important; font-size: 11px !important;
} }
div.navbar { div.navbar {
-webkit-box-shadow: 0px 2px 2px #CCC;
-moz-box-shadow: 0px 2px 2px #CCC;
box-shadow: 0px 2px 2px #ccc;
z-index: 999; z-index: 999;
} }
.panel.panel-primary { .panel.panel-primary {
@ -171,10 +169,24 @@ li.widget:hover {
} }
div.widget .chart-header { div.widget .chart-header {
padding: 5px; padding-top: 8px;
background-color: #f1f1f1; background-color: #fff;
color: #333;
border-bottom: 1px solid #aaa;
margin: 0 10px;
} }
.chart-header .header-text {
font-size: 20px;
line-height: 22px;
padding-bottom: 8px;
border-bottom: 1px solid #888;
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
}
div.widget .chart-header a { div.widget .chart-header a {
margin-left: 5px; margin-left: 5px;
} }

View File

@ -24,8 +24,8 @@ div.widget .chart-controls {
} }
.slice-grid div.widget { .slice-grid div.widget {
border-radius: 0; border-radius: 0;
border: 1px solid #ccc; border: 0px;
box-shadow: 2px 1px 5px -2px #aaa; box-shadow: none;
background-color: #fff; background-color: #fff;
overflow: visible; overflow: visible;
} }
@ -39,9 +39,7 @@ div.widget .chart-controls {
margin: 5px; margin: 5px;
position: absolute; position: absolute;
} }
.dashboard .title {
text-align: center;
}
.dashboard .slice_title { .dashboard .slice_title {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
@ -69,7 +67,7 @@ div.widget .chart-controls {
} }
.slice-grid div.separator.widget { .slice-grid div.separator.widget {
border: 1px solid transparent; border: 1px solid transparent;
box-shadow: none; box-shadow: none;
z-index: 1; z-index: 1;
} }
@ -98,3 +96,15 @@ div.widget .chart-controls {
top: 0; top: 0;
bottom: 0; bottom: 0;
} }
.dashboard .title {
margin: 0 20px;
}
.dashboard .title .favstar {
font-size: 24px;
}
.chart-header .header {
font-size: 16px;
}

View File

@ -6,13 +6,36 @@
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
background-color: #fff;
} }
.header hr { .slice-name__container {
margin-top: 10px; background-color: #fff;
margin-bottom: 10px; padding: 16px 20px 20px 20px;
}
.slice-name__text {
color: #333;
font-size: 20px;
border-bottom: 1px solid #aaa;
padding-bottom: 10px;
padding-left: 42px;
font-weight: bold;
}
.edit-slice-description-icon {
float: left;
margin-top: -33px;
margin-left: 20px;
}
.slice-meta {
margin-top: -52px;
} }
.navbar { .navbar {
margin-bottom: 10px; margin-bottom: 22px;
}
.query-and-save-btns-container {
margin-bottom: 22px;
} }

View File

@ -13,10 +13,10 @@
.navbar { .navbar {
border: none; border: none;
.box-shadow(0 1px 2px rgba(0,0,0,.3));
&-brand { &-brand {
font-size: 24px; font-size: 24px;
padding: 17px 15px!important;
} }
&-inverse { &-inverse {
@ -25,16 +25,17 @@
input[type=text], input[type=text],
input[type=password] { input[type=password] {
color: #fff; color: #fff;
.box-shadow(inset 0 -1px 0 @navbar-inverse-link-color);
.placeholder(@navbar-inverse-link-color); .placeholder(@navbar-inverse-link-color);
&:focus { &:focus {
.box-shadow(inset 0 -2px 0 #fff);
} }
} }
} }
} }
} }
.navbar-inverse .navbar-nav > li > a {
color: #333;
}
// Buttons ==================================================================== // Buttons ====================================================================
@ -56,7 +57,6 @@
background-color: darken(@bg, 12%); background-color: darken(@bg, 12%);
#gradient > .radial(darken(@bg, 12%) 10%, @bg 11%); #gradient > .radial(darken(@bg, 12%) 10%, @bg 11%);
background-size: 1000%; background-size: 1000%;
.box-shadow(2px 2px 4px rgba(0,0,0,.4));
} }
} }
} }
@ -68,21 +68,21 @@
#btn(warning,@btn-warning-bg); #btn(warning,@btn-warning-bg);
#btn(danger,@btn-danger-bg); #btn(danger,@btn-danger-bg);
#btn(link,#fff); #btn(link,#fff);
.btn-group {
padding: 5px;
background-color: #fff;
}
.btn { .btn {
text-transform: uppercase; text-transform: uppercase;
border: none; border: none;
.box-shadow(1px 1px 4px rgba(0,0,0,.4));
.transition(all 0.4s); .transition(all 0.4s);
&-link { &-link {
border-radius: @btn-border-radius-base; border-radius: @btn-border-radius-base;
.box-shadow(none);
color: @btn-default-color; color: @btn-default-color;
&:hover, &:hover,
&:focus { &:focus {
.box-shadow(none);
color: @btn-default-color; color: @btn-default-color;
text-decoration: none; text-decoration: none;
} }
@ -169,11 +169,9 @@ input[type=number],
border: none; border: none;
border-radius: 0; border-radius: 0;
-webkit-appearance: none; -webkit-appearance: none;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px; font-size: 16px;
&:focus { &:focus {
.box-shadow(inset 0 -2px 0 @brand-primary);
} }
&[disabled], &[disabled],
@ -206,7 +204,6 @@ select.form-control {
background-size: 13px; background-size: 13px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right center; background-position: right center;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px; font-size: 16px;
line-height: 1.5; line-height: 1.5;
@ -332,7 +329,7 @@ input[type="checkbox"],
height: 18px; height: 18px;
margin-top: -2px; margin-top: -2px;
margin-right: 5px; margin-right: 5px;
border: 2px solid @gray; border: 1px solid #333;
border-radius: 2px; border-radius: 2px;
.transition(240ms); .transition(240ms);
} }
@ -345,15 +342,15 @@ input[type="checkbox"],
display: table; display: table;
width: 6px; width: 6px;
height: 12px; height: 12px;
border: 2px solid #fff; border: 2px solid #333;
border-top-width: 0; border-top-width: 0;
border-left-width: 0; border-left-width: 0;
.rotate(45deg); .rotate(45deg);
} }
&:checked:after { &:checked:after {
background-color: @brand-primary; background-color: #FFFFFF;
border-color: @brand-primary; border-color: #333;
} }
&:disabled:after { &:disabled:after {
@ -423,12 +420,10 @@ input[type="checkbox"],
background-color: transparent; background-color: transparent;
border: none; border: none;
color: @navbar-default-link-color; color: @navbar-default-link-color;
.box-shadow(inset 0 -1px 0 #ddd);
.transition(all 0.2s); .transition(all 0.2s);
&:hover { &:hover {
background-color: transparent; background-color: transparent;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary; color: @brand-primary;
} }
} }
@ -436,7 +431,6 @@ input[type="checkbox"],
& > li.active > a, & > li.active > a,
& > li.active > a:focus { & > li.active > a:focus {
border: none; border: none;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary; color: @brand-primary;
&:hover { &:hover {
@ -446,7 +440,6 @@ input[type="checkbox"],
} }
& > li.disabled > a { & > li.disabled > a {
.box-shadow(inset 0 -1px 0 #ddd);
} }
&.nav-justified { &.nav-justified {
@ -469,7 +462,6 @@ input[type="checkbox"],
.dropdown-menu { .dropdown-menu {
margin-top: 0; margin-top: 0;
border: none; border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
} }
// Indicators ================================================================= // Indicators =================================================================
@ -597,9 +589,8 @@ input[type="checkbox"],
.panel { .panel {
border: none; border: none;
border-radius: 2px; border-radius: 0;
.box-shadow(0 1px 4px rgba(0,0,0,.3)); box-shadow: none;
&-heading { &-heading {
border-bottom: none; border-bottom: none;
} }
@ -609,9 +600,16 @@ input[type="checkbox"],
} }
} }
.panel-default > .panel-heading {
color: #333!important;
border-bottom: 1px solid #aaa;
background-color: #fff!important;
margin: 10px;
font-weight: bold;
}
.popover { .popover {
border: none; border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
} }
.carousel { .carousel {
@ -621,4 +619,3 @@ input[type="checkbox"],
} }
} }
} }

View File

@ -22,15 +22,15 @@
@gray-base: #000; @gray-base: #000;
@gray-darker: lighten(@gray-base, 13.5%); // #222 @gray-darker: lighten(@gray-base, 13.5%); // #222
@gray-dark: #212121; @gray-dark: #212121;
@gray: #666; @gray: #333;
@gray-light: #bbb; @gray-light: #bbb;
@gray-lighter: lighten(@gray-base, 93.5%); // #eee @gray-lighter: lighten(@gray-base, 93.5%); // #eee
@brand-primary: @kazan; @brand-primary: #000;
@brand-success: darken(@lima, 25%); @brand-success: darken(@lima, 15%);
@brand-warning: darken(@beach, 10%); @brand-info: @beach;
@brand-info: darken(@babu, 10%); @brand-warning: @hackberry;
@brand-danger: darken(@rausch, 15%); @brand-danger: darken(@rausch, 5%);
@default-color: #444; @default-color: #444;
@default-bg: #fff; @default-bg: #fff;
@ -61,7 +61,7 @@
//## Settings for some of the most global styles. //## Settings for some of the most global styles.
//** Background color for `<body>`. //** Background color for `<body>`.
@body-bg: #fff; @body-bg: #EDEDED;
//** Global text color on `<body>`. //** Global text color on `<body>`.
@text-color: @gray; @text-color: @gray;
@ -83,16 +83,16 @@
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; @font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
@font-family-base: @font-family-sans-serif; @font-family-base: @font-family-sans-serif;
@font-size-base: 13px; @font-size-base: 12px;
@font-size-large: ceil((@font-size-base * 1.25)); // ~18px @font-size-large: ceil((@font-size-base * 1.25));
@font-size-small: ceil((@font-size-base * 0.85)); // ~12px @font-size-small: ceil((@font-size-base * 0.75));
@font-size-h1: 56px; @font-size-h1: 56px;
@font-size-h2: 45px; @font-size-h2: 45px;
@font-size-h3: 34px; @font-size-h3: 34px;
@font-size-h4: 24px; @font-size-h4: 24px;
@font-size-h5: 20px; @font-size-h5: 20px;
@font-size-h6: 14px; @font-size-h6: 12px;
//** Unit-less `line-height` for use in components like buttons. //** Unit-less `line-height` for use in components like buttons.
@line-height-base: 1.846; // 20/14 @line-height-base: 1.846; // 20/14
@ -101,9 +101,9 @@
//** By default, this inherits from the `<body>`. //** By default, this inherits from the `<body>`.
@headings-font-family: inherit; @headings-font-family: inherit;
@headings-font-weight: 400; @headings-font-weight: 900;
@headings-line-height: 1.1; @headings-line-height: 1.1;
@headings-color: #444; @headings-color: #333;
//== Iconography //== Iconography
@ -137,9 +137,9 @@
@line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome @line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome
@line-height-small: 1.5; @line-height-small: 1.5;
@border-radius-base: 3px; @border-radius-base: 2px;
@border-radius-large: 3px; @border-radius-large: 2px;
@border-radius-small: 3px; @border-radius-small: 2px;
//** Global color for active items (e.g., navs or dropdowns). //** Global color for active items (e.g., navs or dropdowns).
@component-active-color: #fff; @component-active-color: #fff;
@ -490,9 +490,9 @@
@pagination-hover-bg: @gray-lighter; @pagination-hover-bg: @gray-lighter;
@pagination-hover-border: #ddd; @pagination-hover-border: #ddd;
@pagination-active-color: #fff; @pagination-active-color: #333;
@pagination-active-bg: @brand-primary; @pagination-active-bg: #fff;
@pagination-active-border: @brand-primary; @pagination-active-border: #333;
@pagination-disabled-color: @gray-light; @pagination-disabled-color: @gray-light;
@pagination-disabled-bg: #fff; @pagination-disabled-bg: #fff;
@ -735,7 +735,7 @@
@panel-bg: #fff; @panel-bg: #fff;
@panel-body-padding: 15px; @panel-body-padding: 15px;
@panel-heading-padding: 10px 15px; @panel-heading-padding: 5px 15px 3px 0px;
@panel-footer-padding: @panel-heading-padding; @panel-footer-padding: @panel-heading-padding;
@panel-border-radius: @border-radius-base; @panel-border-radius: @border-radius-base;

View File

@ -19,3 +19,8 @@ input {
.panel-body { .panel-body {
overflow: auto; overflow: auto;
} }
.cal-heatmap-panel {
padding: 20px;
background-color: #fff;
}

View File

@ -9,12 +9,9 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" style="padding:7px;opacity:0.9;" href="{{appbuilder.get_url_for_index}}"> <a class="navbar-brand" href="{{appbuilder.get_url_for_index}}">
<img width="50" src="{{ appbuilder.app_icon }}"> <img width="75" src="/static/assets/images/caravel.png" style="padding-top:8px;" alt="">
</a> </a>
<span class="navbar-brand">
{{ appbuilder.app_name }}
</span>
</div> </div>
<div class="navbar-collapse collapse"> <div class="navbar-collapse collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">

View File

@ -7,75 +7,77 @@
{% block title %}[dashboard] {{ dashboard.dashboard_title }}{% endblock %} {% block title %}[dashboard] {{ dashboard.dashboard_title }}{% endblock %}
{% block body %} {% block body %}
<div class="dashboard container-fluid" data-dashboard="{{ dashboard.json_data }}" data-css="{{ dashboard.css }}" data-user="{{ user_id }}"> <div
class="dashboard container-fluid"
data-dashboard="{{ dashboard.json_data }}"
data-css="{{ dashboard.css }}"
data-user="{{ user_id }}"
>
{% include 'caravel/flash_wrapper.html' %} {% include 'caravel/flash_wrapper.html' %}
<!-- Modal --> <!-- Modal -->
<div class="modal fade" id="css_modal" tabindex="-1" role="dialog"> <div class="modal fade" id="css_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content css"> <div class="modal-content css">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Dashboard CSS</h4> <h4 class="modal-title" id="myModalLabel">Dashboard CSS</h4>
<h6><strong>Styling applies to this dashboard only</strong></h6> <h6><strong>Styling applies to this dashboard only</strong></h6>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<select id="css_template" class="select2" style="margin-bottom: 5px;"> <select id="css_template" class="select2" style="margin-bottom: 5px;">
<option value="" data-css="">CSS template</option> <option value="" data-css="">CSS template</option>
{% for t in templates %} {% for t in templates %}
<option value="{{ t.id }}" data-css="{{t.css}}"> <option value="{{ t.id }}" data-css="{{t.css}}">
{{ t.template_name }} {{ t.template_name }}
</option> </option>
{% endfor %} {% endfor %}
</select><br> </select><br>
<textarea id="dash_css" rows="30" cols="60">{{ dashboard.css }}</textarea> <textarea id="dash_css" rows="30" cols="60">{{ dashboard.css }}</textarea>
<input type="hidden" id="dashboard_id" value="{{ dashboard.id }}" /> <input type="hidden" id="dashboard_id" value="{{ dashboard.id }}" />
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"> <button type="button" class="btn btn-default" data-dismiss="modal">
Close Close
</button> </button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> <div class="modal fade" id="refresh_modal" tabindex="-1" role="dialog">
<div class="modal fade" id="refresh_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Refresh Interval</h4> <h4 class="modal-title" id="myModalLabel">Refresh Interval</h4>
<h6><strong>Choose how frequent should the dashboard refresh</strong></h6> <h6><strong>Choose how frequent should the dashboard refresh</strong></h6>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<select id="refresh_dash_interval" class="select2" style="margin-bottom: 5px;"> <select id="refresh_dash_interval" class="select2" style="margin-bottom: 5px;">
<option value="0">Don't refresh</option> <option value="0">Don't refresh</option>
<option value="10">10 seconds</option> <option value="10">10 seconds</option>
<option value="30">30 seconds</option> <option value="30">30 seconds</option>
<option value="60">1 minute</option> <option value="60">1 minute</option>
<option value="300">5 minutes</option> <option value="300">5 minutes</option>
</select><br> </select><br>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"> <button type="button" class="btn btn-default" data-dismiss="modal">
Close Close
</button> </button>
</div>
</div> </div>
</div>
</div>
<div id="add-slice-container"></div>
<div class="title">
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<h2>
<span class="favstar" class_name="Dashboard" obj_id="{{ dashboard.id }}"></span>
{{ dashboard.dashboard_title }}
</h2>
</div> </div>
<div class="col-md-3"> </div>
</div>
<div id="add-slice-container"></div>
<div class="title">
<div class="row">
<div class="col-md-8">
<span class="favstar" class_name="Dashboard" obj_id="{{ dashboard.id }}"></span>
<h2>{{ dashboard.dashboard_title }}</h2>
</div>
<div class="col-md-4">
<div class="btn-group pull-right" role="group" > <div class="btn-group pull-right" role="group" >
<button type="button" id="refresh_dash" class="btn btn-default" data-toggle="tooltip" title="Force refresh the whole dashboard"> <button type="button" id="refresh_dash" class="btn btn-default" data-toggle="tooltip" title="Force refresh the whole dashboard">
<i class="fa fa-refresh"></i> <i class="fa fa-refresh"></i>
@ -101,11 +103,10 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- gridster class used for backwards compatibility --> <!-- gridster class used for backwards compatibility -->
<div id="grid-container" class="slice-grid gridster"> <div id="grid-container" class="slice-grid gridster"></div>
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -18,7 +18,7 @@
<div> <div>
{{ field.label }} {{ field.label }}
{% if field.description %} {% if field.description %}
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right" <i class="fa fa-question-circle-o" data-toggle="tooltip" data-placement="right"
title="{{ field.description }}"></i> title="{{ field.description }}"></i>
{% endif %} {% endif %}
{{ field(class_=form.field_css_classes(field.name)) }} {{ field(class_=form.field_css_classes(field.name)) }}
@ -28,37 +28,159 @@
<div class="datasource container-fluid"> <div class="datasource container-fluid">
<form id="query" method="GET" style="display: none;"> <form id="query" method="GET" style="display: none;">
<div class="header"> <div id="form_container" class="col-left-fixed">
<span id="js-query-and-save-btns" <div
data-can-add="{{ can_add }}" id="js-query-and-save-btns"
></span> class="query-and-save-btns-container"
data-can-add="{{ can_add }}"
></div>
<span title="Data Source" data-toggle="tooltip"> <div class="panel panel-default">
<select id="datasource_id" class="select2"> <div class="panel-heading">Datasource & Chart Type</div>
{% for ds in datasources %} <div class="panel-body">
<option url="{{ ds.explore_url }}" {{ "selected" if ds.id == datasource.id }} value="{{ ds.id }}">{{ ds.full_name }}<i class="fa fa-info"></i></option> <div>
{% endfor %} <!-- DATASOURCE -->
</select> <span title="Data Source" data-toggle="tooltip">
</span> <select id="datasource_id" class="select2">
<a href="{{ datasource.url }}" class="btn btn-default-outline" data-toggle="tooltip" title="Edit/configure datasource"> {% for ds in datasources %}
<i class="fa fa-edit"></i>&nbsp; <option url="{{ ds.explore_url }}" {{ "selected" if ds.id == datasource.id }} value="{{ ds.id }}">{{ ds.full_name }}<i class="fa fa-info"></i></option>
</a> {% endfor %}
<span title="Visualization Type" data-toggle="tooltip"> </select>
{{ form.get_field("viz_type")(class_="select2-with-images") }} </span>
</span> <a href="{{ datasource.url }}" class="btn btn-default-outline" data-toggle="tooltip" title="Edit/configure datasource">
{% if slice %} <i class="fa fa-edit"></i>&nbsp;
<span class="btn btn-default notbtn" title="Slice" data-toggle="tooltip" data-placement="bottom"> </a>
<span class="favstar" class_name="Slice" obj_id="{{ slice.id }}"></span> </div>
{{ slice.slice_name }} <br/>
<a class="" href="/slicemodelview/edit/{{ slice.id }}" data-toggle="tooltip" title="Edit"> <!-- CHART TYPE -->
{% if slice.description %} <div title="Visualization Type" data-toggle="tooltip">
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="bottom" title="{{ slice.description }}"></i> {{ form.get_field("viz_type")(class_="select2-with-images") }}
</div>
</div>
</div>
{% for fieldset in form.fieldsets %}
<div class="panel panel-default">
{% if fieldset.label %}
<div class="panel-heading">
<span class="legend_label">{{ fieldset.label }}</span>
{% if fieldset.description %}
<i class="fa fa-question-circle-o" data-toggle="tooltip"
data-placement="bottom"
title="{{ fieldset.description }}"></i>
{% endif %} {% endif %}
<i class="fa fa-edit"></i> <!-- <span class="collapser"> [-]</span> -->
</a> </div>
</span> {% endif %}
<div class="panel-body">
{% for fieldname in fieldset.fields %}
{% if not fieldname %}
<hr/>
{% elif fieldname is string %}
{{ panofield(fieldname) }}
{% else %}
<div class="row">
<div class="form-group">
{% for name in fieldname %}
<div class="col-xs-{{ (12 / fieldname|length) | int }}">
{% if name %}
{{ panofield(name) }}
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
<div id="filter_panel" class="panel panel-default">
<div class="panel-heading">
<span class="legend_label">{{ _("Filters") }}</span>
<i class="fa fa-question-circle-o" data-toggle="tooltip"
data-placement="bottom"
title="{{_("Filters are defined using comma delimited strings as in 'US,FR,Other'")}}. {{_("Leave the value field empty to filter empty strings or nulls")}}"></i>
<!--<span class="collapser"> [-]</span>-->
</div>
<div class="panel-body">
<div id="flt0" style="display: none;">
<span class="">{{ form.flt_col_0(class_="form-control inc") }}</span>
<div class="row">
<span class="col col-sm-4">{{ form.flt_op_0(class_="form-control inc") }}</span>
<span class="col col-sm-6">{{ form.flt_eq_0(class_="form-control inc") }}</span>
<button type="button" class="btn btn-default btn-sm remove" aria-label="Delete filter">
<span class="fa fa-minus" aria-hidden="true"></span>
</button>
</div>
</div>
<div id="filters"></div>
<button type="button" id="plus" class="btn btn-default btn-sm" aria-label="Add a filter">
<span class="fa fa-plus" aria-hidden="true"></span>
<span>{{ _("Add filter") }}</span>
</button>
</div>
</div>
{% if form.having_col_0 %}
<div id="having_panel" class="panel panel-default">
<div class="panel-heading">
<span class="legend_label">Result Filters ("having" filters)</span>
<i class="fa fa-info-circle" data-toggle="tooltip"
data-placement="bottom"
title="{{_("The filters to apply after post-aggregation.")}} {{_("Leave the value field empty to filter empty strings or nulls")}}"></i>
<span class="collapser"> [-]</span>
</div>
<div class="panel-body">
<div id="having0" style="display: none;">
<span class="">{{ form.having_col_0(class_="form-control inc") }}</span>
<div class="row">
<span class="col col-sm-4">{{ form.having_op_0(class_="form-control inc") }}</span>
<span class="col col-sm-6">{{ form.having_eq_0(class_="form-control inc") }}</span>
<button type="button"
class="btn btn-default btn-sm remove"
aria-label="Delete filter">
<span class="fa fa-minus"
aria-hidden="true"></span>
</button>
</div>
</div>
<div id="filters"></div>
<button type="button" id="plus"
class="btn btn-default btn-sm"
aria-label="Add a filter">
<span class="fa fa-plus" aria-hidden="true"></span>
<span>Add filter</span>
</button>
</div>
</div>
{% endif %} {% endif %}
<div class="pull-right"> {{ form.slice_id() }}
{{ form.slice_name() }}
{{ form.collapsed_fieldsets() }}
<input type="hidden" name="action" id="action" value="">
<input type="hidden" name="userid" id="userid" value="{{ userid }}">
<input type="hidden" name="goto_dash" id="goto_dash" value="false">
<input type="hidden" name="datasource_name" value="{{ datasource.name }}">
<input type="hidden" name="datasource_id" value="{{ datasource.id }}">
<input type="hidden" name="datasource_type" value="{{ datasource.type }}">
<input type="hidden" name="previous_viz_type" value="{{ viz.viz_type or "table" }}">
</div>
<div class="col-offset">
{% block messages %}{% endblock %}
{% include 'appbuilder/flash.html' %}
<div class="slice-name__container">
<span class="favstar" class_name="Slice" obj_id="{{ slice.id }}"></span>
<div class="slice-name__text">{{slice.slice_name}}</div>
<a href="/slicemodelview/edit/{{ slice.id }}" data-toggle="tooltip" title="Edit Description" class="edit-slice-description-icon">
{% if slice.description %}
<i class="fa fa-question-circle-o" data-toggle="tooltip" data-placement="bottom" title="{{ slice.description }}"></i>
{% endif %}
<i class="fa fa-edit"></i>
</a>
<div class="slice-meta pull-right">
<span id="is_cached" class="label label-default" title="{{ _("Force refresh" )}}" data-toggle="tooltip"> <span id="is_cached" class="label label-default" title="{{ _("Force refresh" )}}" data-toggle="tooltip">
cached cached
</span> </span>
@ -93,132 +215,16 @@
</span> </span>
</div> </div>
</div> </div>
<hr/> </div>
<div
id="{{ viz.token }}"
class="widget viz slice {{ viz.viz_type }}"
data-slice="{{ viz.json_data }}"
style="height: 700px;">
<img src="{{ url_for("static", filename="assets/images/loading.gif") }}" class="loading" alt="loading">
<div id="{{ viz.token }}_con" class="slice_container" style="height: 100%; width: 100%"></div>
</div>
</div> </div>
<div id="form_container" class="col-left-fixed">
{% for fieldset in form.fieldsets %}
<div class="panel panel-default">
{% if fieldset.label %}
<div class="panel-heading">
<span class="legend_label">{{ fieldset.label }}</span>
{% if fieldset.description %}
<i class="fa fa-info-circle" data-toggle="tooltip"
data-placement="bottom"
title="{{ fieldset.description }}"></i>
{% endif %}
<span class="collapser"> [-]</span>
</div>
{% endif %}
<div class="panel-body">
{% for fieldname in fieldset.fields %}
{% if not fieldname %}
<hr/>
{% elif fieldname is string %}
{{ panofield(fieldname) }}
{% else %}
<div class="row">
<div class="form-group">
{% for name in fieldname %}
<div class="col-xs-{{ (12 / fieldname|length) | int }}">
{% if name %}
{{ panofield(name) }}
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
<div id="filter_panel" class="panel panel-default">
<div class="panel-heading">
<span class="legend_label">{{ _("Filters") }}</span>
<i class="fa fa-info-circle" data-toggle="tooltip"
data-placement="bottom"
title="{{_("Filters are defined using comma delimited strings as in 'US,FR,Other'")}}. {{_("Leave the value field empty to filter empty strings or nulls")}}"></i>
<span class="collapser"> [-]</span>
</div>
<div class="panel-body">
<div id="flt0" style="display: none;">
<span class="">{{ form.flt_col_0(class_="form-control inc") }}</span>
<div class="row">
<span class="col col-sm-4">{{ form.flt_op_0(class_="form-control inc") }}</span>
<span class="col col-sm-6">{{ form.flt_eq_0(class_="form-control inc") }}</span>
<button type="button" class="btn btn-default btn-sm remove" aria-label="Delete filter">
<span class="fa fa-minus" aria-hidden="true"></span>
</button>
</div>
</div>
<div id="filters"></div>
<button type="button" id="plus" class="btn btn-default btn-sm" aria-label="Add a filter">
<span class="fa fa-plus" aria-hidden="true"></span>
<span>{{ _("Add filter") }}</span>
</button>
</div>
</div>
{% if form.having_col_0 %}
<div id="having_panel" class="panel panel-default">
<div class="panel-heading">
<span class="legend_label">Result Filters ("having" filters)</span>
<i class="fa fa-info-circle" data-toggle="tooltip"
data-placement="bottom"
title="{{_("The filters to apply after post-aggregation.")}} {{_("Leave the value field empty to filter empty strings or nulls")}}"></i>
<span class="collapser"> [-]</span>
</div>
<div class="panel-body">
<div id="having0" style="display: none;">
<span class="">{{ form.having_col_0(class_="form-control inc") }}</span>
<div class="row">
<span class="col col-sm-4">{{ form.having_op_0(class_="form-control inc") }}</span>
<span class="col col-sm-6">{{ form.having_eq_0(class_="form-control inc") }}</span>
<button type="button"
class="btn btn-default btn-sm remove"
aria-label="Delete filter">
<span class="fa fa-minus"
aria-hidden="true"></span>
</button>
</div>
</div>
<div id="filters"></div>
<button type="button" id="plus"
class="btn btn-default btn-sm"
aria-label="Add a filter">
<span class="fa fa-plus" aria-hidden="true"></span>
<span>Add filter</span>
</button>
</div>
</div>
{% endif %}
{{ form.slice_id() }}
{{ form.slice_name() }}
{{ form.collapsed_fieldsets() }}
<input type="hidden" name="action" id="action" value="">
<input type="hidden" name="userid" id="userid" value="{{ userid }}">
<input type="hidden" name="goto_dash" id="goto_dash" value="false">
<input type="hidden" name="datasource_name" value="{{ datasource.name }}">
<input type="hidden" name="datasource_id" value="{{ datasource.id }}">
<input type="hidden" name="datasource_type" value="{{ datasource.type }}">
<input type="hidden" name="previous_viz_type" value="{{ viz.viz_type or "table" }}">
</div>
<div class="col-offset">
{% block messages %}{% endblock %}
{% include 'appbuilder/flash.html' %}
<div
id="{{ viz.token }}"
class="widget viz slice {{ viz.viz_type }}"
data-slice="{{ viz.json_data }}"
style="height: 700px;">
<img src="{{ url_for("static", filename="assets/images/loading.gif") }}" class="loading" alt="loading">
<div id="{{ viz.token }}_con" class="slice_container" style="height: 100%; width: 100%"></div>
</div>
<div class="credits pull-right">{{ "credits: " + viz.credits |safe if viz. credits else "" }}</div>
</div>
<div class="modal fade" id="query_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal fade" id="query_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">

View File

@ -1,15 +1,18 @@
<html> <html>
<head> <head>
<script src="/static/assets/javascripts/dist/css-theme.entry.js"></script> <title>{{viz.token}}</title>
<script src="/static/assets/javascripts/dist/standalone.entry.js"></script>
<link rel="stylesheet" type="text/css" href="/static/assets/stylesheets/caravel.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/node_modules/font-awesome/css/font-awesome.min.css" /> <link rel="stylesheet" type="text/css" href="/static/assets/node_modules/font-awesome/css/font-awesome.min.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/stylesheets/caravel.css" />
<link rel="stylesheet" type="text/css" href="/static/appbuilder/css/flags/flags16.css" />
<link rel="icon" type="image/png" href="/static/assets/images/favicon.png">
{% set CSS_THEME = appbuilder.get_app.config.get("CSS_THEME") %} {% set CSS_THEME = appbuilder.get_app.config.get("CSS_THEME") %}
{% set height = request.args.get("height", 700) %} {% set height = request.args.get("height", 700) %}
{% if CSS_THEME %} {% if CSS_THEME %}
<link rel="stylesheet" type="text/css" href="{{ CSS_THEME }}" /> <link rel="stylesheet" type="text/css" href="{{ CSS_THEME }}" />
{% endif %} {% endif %}
</head> </head>
<body> <body>
<div <div
id="{{ viz.token }}" id="{{ viz.token }}"
@ -20,4 +23,7 @@
<div id="{{ viz.token }}_con" class="slice_container" style="height: 100%; width: 100%"></div> <div id="{{ viz.token }}_con" class="slice_container" style="height: 100%; width: 100%"></div>
</div> </div>
</body> </body>
<script src="/static/assets/javascripts/dist/css-theme.entry.js"></script>
<script src="/static/assets/javascripts/dist/standalone.entry.js"></script>
</html> </html>

View File

@ -10,12 +10,9 @@
{% block body %} {% block body %}
<div class="container welcome"> <div class="container welcome">
{% include 'caravel/flash_wrapper.html' %} {% include 'caravel/flash_wrapper.html' %}
<div class="header"> <div class="cal-heatmap-panel">
<h3>{{ _("Welcome!") }}</h3> <div id="cal-heatmap"></div>
</div> </div>
<hr/>
<div id="cal-heatmap"></div>
<hr/>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="panel panel-default"> <div class="panel panel-default">

View File

@ -605,7 +605,6 @@ class SliceAsync(SliceModelView): # noqa
label_columns = { label_columns = {
'icons': ' ', 'icons': ' ',
'slice_link': _('Slice'), 'slice_link': _('Slice'),
'viz_type': _('Visualization Type'),
} }
appbuilder.add_view_no_menu(SliceAsync) appbuilder.add_view_no_menu(SliceAsync)