Skip to content
Snippets Groups Projects
Commit e70bfa8f authored by Allen Gilliland's avatar Allen Gilliland
Browse files

Merge pull request #373 from metabase/finish_dat_new_query_builder

Finish new query builder
parents 6e202031 651c8ca8
No related branches found
No related tags found
No related merge requests found
Showing
with 902 additions and 1956 deletions
......@@ -4,7 +4,7 @@
JS_HINT=./node_modules/jsxhint/cli.js
JS_HINT_OPTS='--config .jshintrc'
JS_FILES=`find resources/frontend_client/app -name "*.js*" | grep -v bower_components | grep -v 'app/test/' | grep -v '\#' | grep -v 'app/dist/'`
JS_FILES=`find resources/frontend_client/app -name "*.js" | grep -v bower_components | grep -v 'app/test/' | grep -v '\#' | grep -v 'app/dist/'`
BOLD='\033[1;30m'
RED='\033[0;31m' # \e doesn't work on OS X but \033 works on either
......
......@@ -27,31 +27,6 @@
// - panKey
// - pie.dataLabels_enabled
/// WTF is this for ????
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
var DEFAULT_CARD_WIDTH = 900,
DEFAULT_CARD_HEIGHT = 500;
......@@ -611,6 +586,17 @@ var CardRenderer = {
return initialHeight - headerHeight - 5; // why the magic number :/
}
// if we can find the chart element in the DOM then max width is parent element - parent x padding
var chartElement = chartElementForId(id);
if (chartElement) {
var parent = chartElement.parentElement,
parentHeight = getComputedHeight(parent),
parentPaddingTop = getComputedSizeProperty('padding-top', parent),
parentPaddingBottom = getComputedSizeProperty('padding-bottom', parent);
return parentHeight - parentPaddingTop - parentPaddingBottom;
}
return null;
},
......@@ -892,7 +878,7 @@ var CardRenderer = {
var chartRenderer = new GeoHeatmapChartRenderer(id, card, result)
.setData(chartData, 'stateCode', 'value')
.setJson('/static/json/us-states.json', function(d) {
.setJson('/app/charts/us-states.json', function(d) {
return d.properties.name;
})
.setProjection(d3.geo.albersUsa())
......@@ -921,7 +907,7 @@ var CardRenderer = {
var chartRenderer = new GeoHeatmapChartRenderer(id, card, result)
.setData(chartData, 'code', 'value')
.setJson('/static/json/world.json', function(d) {
.setJson('/app/charts/world.json', function(d) {
return d.properties.ISO_A2; // 2-letter country code
})
.setProjection(d3.geo.mercator())
......
This diff is collapsed.
......@@ -551,19 +551,3 @@ CardDirectives.directive('cvCardFavoriteButton', ['Card', function(Card) {
link: link
};
}]);
CardDirectives.directive('queryBuilder', function() {
return {
link: function(scope, element) {
scope.$on('query:updated', function () {
renderReact();
});
function renderReact() {
React.render(new QueryBuilder({
model: scope.model
}), document.getElementById('react'));
}
}
};
});
......@@ -26,16 +26,8 @@ Card.config(['$routeProvider', function($routeProvider) {
templateUrl: '/app/card/partials/card_detail.html',
controller: 'CardDetail'
});
$routeProvider.when('/:orgSlug/card/createnew/', {
templateUrl: '/app/card/partials/card_detail_new.html',
controller: 'CardDetailNew'
});
$routeProvider.when('/:orgSlug/card/:cardId', {
templateUrl: '/app/card/partials/card_detail.html',
controller: 'CardDetail'
});
$routeProvider.when('/:orgSlug/cool_new_card/:cardId', {
templateUrl: '/app/card/partials/card_detail_new.html',
controller: 'CardDetailNew'
});
}]);
......@@ -537,4 +537,44 @@ CardServices.service('VisualizationSettings', [function() {
return defaults;
};
this.setLatitudeAndLongitude = function(settings, columnDefs) {
// latitude
var latitudeColumn,
latitudeColumnIndex;
columnDefs.forEach(function(col, index) {
if (col.special_type &&
col.special_type === "latitude" &&
latitudeColumn === undefined) {
latitudeColumn = col;
latitudeColumnIndex = index;
}
});
// longitude
var longitudeColumn,
longitudeColumnIndex;
columnDefs.forEach(function(col, index) {
if (col.special_type &&
col.special_type === "longitude" &&
longitudeColumn === undefined) {
longitudeColumn = col;
longitudeColumnIndex = index;
}
});
if (latitudeColumn && longitudeColumn) {
var settingsWithLatAndLon = angular.copy(settings);
settingsWithLatAndLon.map.latitude_source_table_field_id = latitudeColumn.id;
settingsWithLatAndLon.map.latitude_dataset_col_index = latitudeColumnIndex;
settingsWithLatAndLon.map.longitude_source_table_field_id = longitudeColumn.id;
settingsWithLatAndLon.map.longitude_dataset_col_index = longitudeColumnIndex;
return settingsWithLatAndLon;
} else {
return settings;
}
};
}]);
\ No newline at end of file
<div>
<cv-workspace>
<div class="row border-bottom py1 px2" ng-if="isCanvasEditable(card)">
<div class="Button-group float-right" ng-if="card.can_write">
<a class="Button" ng-class="{ 'Button--selected' : card.dataset_query.type == 'query' }" ng-click="toggleQueryMode('query')">GUI</a>
<a class="Button" ng-class="{ 'Button--selected' : card.dataset_query.type == 'native' }" ng-click="toggleQueryMode('native')">SQL</a>
</div>
<h3>Query</h3>
</div>
<div class="row border-bottom py1 px2" ng-if="isCanvasEditable(card)">
<h5>Database</h5>
<label class="Select block full py1">
<select ng-model="card.dataset_query.database" ng-options="db.id as db.name for db in databases" ng-disabled="!card.can_write">
</select>
</label>
<div ng-if="card.dataset_query.type == 'query'">
<h5>Table</h5>
<label class="Select block full py1">
<select ng-model="card.dataset_query.query.source_table" ng-options="tbl.id as tbl.name for tbl in tables" ng-disabled="!card.can_write">
</select>
</label>
<p ng-if="table.description">{{table.description}}</p>
</div>
</div>
<div class="row" ng-if="card.dataset_query.type == 'query'">
<form novalidate>
<aggregation-widget query="card.dataset_query.query" table="table"></aggregation-widget>
<filter-widget query="card.dataset_query.query" table="table" ng-class="{'disabled' : !card.dataset_query.database}"></filter-widget>
<sort-by-widget query="card.dataset_query.query" table="table"> </sort-by-widget>
<fields-widget query="card.dataset_query.query" table="table"></fields-widget>
<limit-widget query="card.dataset_query.query"></limit-widget>
</form>
</div>
<div class="row" ng-if="card.dataset_query.type == 'native'">
<div class="px2 py2 clearfix">
<cv-ace-sql-editor sql="card.dataset_query.native.query" database="card.dataset_query.database"></cv-ace-sql-editor>
</div>
</div>
<div class="row" ng-if="card.dataset_query.type == 'result'">
<div class="px2 py2 clearfix">
<h3>Saved Query</h3>
<p>The data for this card comes directly from a saved query. To change the data you can <a cv-org-href="/admin/query/{{card.dataset_query.result.query_id}}/modify">Modify the Query</a>.</p>
</div>
</div>
<div class="clearfix py2" ng-if="isCanvasEditable(card)">
<button class="Button Button--primary float-right" ng-click="execute(card)" ng-if="card.can_write" ng-disabled="queryExecuting">Run</button>
</div>
</cv-workspace>
<div ng-show="!cardData && !queryExecuting" class="Canvas Canvas--new offset-md-3 offset-lg-3 col col-md-9 col-lg-9">
<div class="my4 py4 text-brand text-centered">
<h1 class="text-normal text-grey-2">Start by entering a query and pressing run.</h1>
</div>
</div>
<div ng-show="queryExecuting" class="Canvas Canvas--new offset-md-3 offset-lg-3 col col-md-9 col-lg-9">
<div class="my4 py4 text-brand text-centered">
<cv-loading-spinner></cv-loading-spinner>
<h1 class="text-normal text-grey-2">Executing query and compiling data ...</h1>
</div>
</div>
<div ng-show="cardData && !queryExecuting" class="Canvas Canvas--new offset-md-3 offset-lg-3 col col-md-9 col-lg-9">
<div class="row px2 py1 border-bottom clearfix">
<div class="float-right">
<div class="mx2 inline-block">
<label class="Select">
<select class="block" ng-model="card.public_perms" ng-options="perm.id as perm.name for perm in utils.perms" ng-disabled="!card.can_write">
</select>
</label>
</div>
<a class="Button" cv-add-to-dashboard-modal card="card">Add to dashboard</a>
<a class="Button" ng-class="{'Button--primary': carddirty && queryIsValid(card.dataset_query.query)}" ng-click="save(card)" ng-if="card.can_write">Save</a>
</div>
<input class="input" type="text" size="100" ng-model="card.name" ng-if="card.can_write" />
<h3 class="text-brand inline-block" ng-if="!card.can_write">{{card.name}}</h3>
</div>
<div class="my4 py4 text-brand text-centered" ng-show="saving">
<cv-loading-spinner></cv-loading-spinner>
<h1 class="text-normal text-grey-2">Saving...</h1>
</div>
<div>
<!-- tab controls -->
<div class="clearfix py2">
<alert class="Alert alert" ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)" ng-animate=" 'animate' " cv-delayed-call="closeAlert($index)" ng-bind-html="alert.msg"></alert>
<div class="Alert alert-success" ng-if="success_message" cv-delayed-call="clearStatus()">
<span class="text-success">{{success_message}}</span>
</div>
<div class="Alert alert-error" ng-if="error_message" cv-delayed-call="clearStatus()">
<span class="text-error">{{error_message}}</span>
</div>
<div class="Button-group col col-md-6 offset-md-3 clearfix">
<div class="row">
<a class="Button col col-md-6 text-centered"
ng-click="setCanvasFocusViz()"
ng-class="{ 'Button--selected' : canvas_focus == 'viz' }">
Visualization
</a>
<a class="Button col col-md-6 text-centered"
ng-click="setCanvasFocusData()"
ng-class="{ 'Button--selected' : canvas_focus == 'data' }">Data
</a>
</div>
</div>
</div>
<!-- card visualization -->
<div ng-show="canvas_focus == 'viz'" class="row">
<div class="pl4 pr4">
<cv-card card="card" card-data="cardData.data" card-settings="cardSettings" />
</div>
<ng-include src="'/app/card/partials/_card_settings.html'"></ng-include>
</div>
<!-- results grid -->
<div ng-show="canvas_focus == 'data'">
<div class="clearfix py1">
<div class="float-right">
<a class="Button" ng-href="/api/meta/dataset/csv?query={{getEncodedQuery(card.dataset_query)}}" target="_self" ng-if="cardData">Download Data</a>
</div>
<h3>Results</h3>
</div>
<div class="my2 bordered rounded TableWrapper">
<div ng-if="cardData.error">
<pre ng-if="cardData.sql_error">{{cardData.sql_error}}</pre>
<pre ng-if="!cardData.sql_error">{{cardData.error}}</pre>
</div>
<div ng-if="!cardData.error">
<div ng-if="cardData.row_count == 0">
<pre>No Data: query completed but returned 0 rows.</pre>
</div>
<div ng-if="cardData.row_count > 0">
<table class="Table">
<tr>
<th ng-repeat="column_name in cardData.data.columns track by $index">{{column_name}}</th>
</tr>
<tr ng-repeat="row in cardData.data.rows track by $index" ng-if="$index < 50">
<td ng-repeat="cell in row track by $index">{{cell}}</td>
</tr>
<tr ng-if="cardData.row_count > 50">
<td class="text-centered" colspan="{{cardData.data.cols.length}}">
<h2 class="text-brand text-bold">Too many rows to display! Previewing 50 out of <span class="text-italic">{{cardData.row_count}}</span> total rows.</h2>
</td>
</tr>
</table>
</div><!-- end the status -->
</div><!-- end error -->
</div>
</div>
</div><!-- end ng-if card is not being saved -->
</div><!-- end canvas -->
</div><!-- end page content -->
<div class="QueryBuilder">
<div id="react_qb_header"></div>
<div id="react_qb_editor"></div>
<div class="QueryVisualization" id="react_qb_viz"></div>
</div>
<div class="QueryBuilder" query-builder>
<div id="react"></div>
</div>
This diff is collapsed.
This diff is collapsed.
:root {
--badge-border-radius: 4px;
--permissions-badge-color: #A989C5;
--headsup-badge-color: #F5A623;
}
.Badge {
border-radius: var(--badge-border-radius);
padding: 0.5em;
text-transform: uppercase;
font-weight: bold;
font-size: 0.6rem;
color: #fff;
background-color: #444;
}
.Badge.Badge--permissions {
background-color: var(--permissions-badge-color);
}
.Badge.Badge--headsUp {
background-color: var(--headsup-badge-color);
}
......@@ -103,3 +103,39 @@
border-color: var(--success-button-color);
color: #fff;
}
/* toggle button */
.Button-toggle {
color: #797979;
display: flex;
line-height: 1;
border: 1px solid #ddd;
border-radius: 40px;
width: 3rem;
transition: background .2s linear .2s, border .2s linear .2s;
}
.Button-toggleIndicator {
margin-left: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 0.25rem;
border: 1px solid #ddd;
border-radius: 99px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .02);
transition: margin .3s linear;
background-color: #fff;
}
.Button-toggle.Button--toggled .Button-toggleIndicator {
margin-left: 50%;
transition: margin .3s linear;
}
.Button-toggle.Button--toggled {
color: var(--brand-color);
background-color: var(--brand-color);
border-color: var(--brand-color);
transition: background .2s linear .2s, border .2s linear .2s;
}
......@@ -3,7 +3,7 @@
--core-nav-text-color: #8691AC;
--core-nav-selected-text-color: #4A90E2;
--core-nav-border-radius: 4px;
--core-nav-border-color: #E4E4E4;
--core-nav-border-color: #F2F2F2;
--nav-item-text-color: #8691AC;
--brand-text-color: #333;
}
......@@ -87,12 +87,29 @@
display: inline-block;
text-decoration: none;
color: var(--nav-item-text-color);
padding: 1em 0.5em;
padding: 0.5em 0.5em;
font-size: 0.9em;
text-rendering: optimizeLegibility;
position: relative;
}
/* this is jank */
.NavItem .IconWrapper svg {
width: 24px;
height: 24px;
}
@media screen and (--breakpoint-min-lg) {
.NavItem {
padding-top: 1em;
padding-bottom: 1em;
}
.NavItem .IconWrapper svg {
width: 32px;
height: 32px;
}
}
.NavItem-withIcon {
padding-left: 3.5em;
padding-right: 1em;
......@@ -107,10 +124,10 @@
content: '';
display: block;
position: absolute;
bottom: 0;
bottom: -1px;
width: 100%;
background-color: var(--core-nav-text-color);
height: 4px;
height: 1px;
left: 0;
opacity: 0;
transition: opacity .2s ease-in;
......
:root {
}
/* afaik popover needs a positioning context to be able to calculate the transform */
.PopoverContainer {
position: absolute;
z-index: 10000000000000; /* above all the things */
}
.PopoverBody {
position: relative;
min-width: 25em; /* ewwwwwwww */
border: 1px solid #ddd;
box-shadow: 0 1px 7px rgba(0, 0, 0, .18);
background-color: #fff;
border-radius: 4px;
display: flex;
flex-direction: column;
}
/* shared arrow styles */
.PopoverBody--withArrow:before,
.PopoverBody--withArrow:after {
position: absolute;
content: '';
display: block;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
}
/* create a slightly larger arrow for border purposes */
.PopoverBody--withArrow:before {
top: -20px;
border-bottom-color: #ddd;
}
/* create a smaller inset arrow */
.PopoverBody:after {
top: -18px;
border-bottom-color: #fff;
}
/* if the tether element is attached right, move our arrows right */
.tether-target-attached-right .PopoverBody--withArrow:before,
.tether-target-attached-right .PopoverBody--withArrow:after {
right: 12px;
}
:root {
--default-font-family: "Lato";
--default-font-size: 100%;
--default-font-size: 0.875em;
--large-font-size: 1em;
}
html {
text-rendering: optimizeLegibility;
height: 100%; /* ensure the entire page will fill the window */
}
body {
font-family: var(--default-font-family), "Helvetica Neue", Helvetica, sans-serif;
font-size: var(--default-font-size);
margin: 0;
box-sizing: border-box;
font-family: var(--default-font-family), "Helvetica Neue", Helvetica, sans-serif;
font-size: var(--default-font-size);
margin: 0;
box-sizing: border-box;
height: 100%; /* ensure the entire page will fill the window */
display: flex;
flex-direction: column;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: subpixel-antialiased;
}
@media screen and (--breakpoint-min-xl) {
body {
font-size: var(--large-font-size);
}
}
/*
......@@ -21,19 +33,19 @@ body {
*/
ul,
ol {
padding: 0;
margin: 0;
list-style-type: none;
padding: 0;
margin: 0;
list-style-type: none;
}
/* reset button element */
button {
font-size: 100%;
-webkit-appearance: none;
border: 0;
padding: 0;
margin: 0;
outline: none;
font-size: 100%;
-webkit-appearance: none;
border: 0;
padding: 0;
margin: 0;
outline: none;
}
.disabled {
......
......@@ -12,6 +12,7 @@ table,
fieldset,
textarea,
ul,
li {
li,
span {
box-sizing: border-box;
}
......@@ -5,6 +5,7 @@
--alt-bg-color: #F4F6F8;
--success-color: #9CC177;
--headsup-color: #F5A623;
--error-color: #EF8C8C;
}
......@@ -50,6 +51,14 @@
background-color: var(--error-color);
}
.text-headsup {
color: var(--headsup-color);
}
.bg-headsup {
background-color: var(--headsup-color);
}
/* grey */
.text-grey-1 { color: color(var(--base-grey) shade(10%)) }
......
......@@ -15,12 +15,9 @@ h5,
.h5,
h6,
.h6 {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: subpixel-antialiased;
margin-top: var(--default-header-margin);
margin-bottom: var(--default-header-margin);
color: var(--default-header-text-color);
font-weight: 100;
}
.h1 { font-size: 2em; }
......
html {
height: 100%;
:root {
--selection-color: #ccdff6;
--qb-offset-normal: 0.8rem;
--qb-offset-large: 2.05rem;
}
body {
/* @layout */
.QueryBuilder {
display: flex;
flex-direction: column;
height: 100%;
line-height: 1;
font-size: 0.85em;
}
.SearchBar:focus {
outline: none;
/* a major section of the query builder */
.QueryBuilder-section {
padding-left: var(--qb-offset-normal);
padding-right: var(--qb-offset-normal);
}
.SaveModal {
background: #fff;
border-radius: 4px;
position: absolute;
bottom: 0.5em;
right: 1.5em;
width: 400px;
@media screen and (--breakpoint-min-xl) {
.QueryBuilder-section {
padding-left: var(--qb-offset-large);
padding-right: var(--qb-offset-large);
}
}
.QueryBuilder .dc-chart {
padding: 2em;
.QueryHeader {
border-bottom: 1px solid #F0F0F0;
padding-top: var(--qb-offset-normal);
padding-bottom: var(--qb-offset-normal);
}
.QueryBuilder .dc-chart .pie-slice {
font-size: 1em;
@media screen and (--breakpoint-min-xl) {
.QueryHeader {
padding-top: var(--qb-offset-large);
padding-bottom: var(--qb-offset-large);
}
}
.QueryWrapper {
padding-left: 1.5em;
padding-right: 1.5em;
.QueryHeader-details,
.QueryHeader-actions {
display: flex;
align-items: center;
flex: 0 0 50%;
}
.SaveModal.Modal--showing {
border: 1px solid #ddd;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.24);
.QueryHeader-actions {
justify-content: flex-end;
}
.SaveModal .ModalContent {
display: none;
margin-bottom: 6em;
padding: 2em;
.Icon-download,
.Icon-addToDash {
fill: #919191;
transition: fill .3s linear;
width: 24px;
height: 24px;
}
.SaveModal input {
border: none;
font-size: 1em;
border-bottom: 1px dotted #111;
display: block;
width: 100%;
padding: 1em;
.Icon-download:hover,
.Icon-addToDash:hover {
fill: var(--brand-color);
transition: fill .3s linear;
}
.SaveModal input:focus {
outline: none;
border-bottom-color: #4A90E2;
@media screen and (--breakpoint-min-xl) {
.Icon-download,
.Icon-addToDash {
width: 32px;
height: 32px;
}
}
.SaveModal.Modal--showing .ModalContent {
display: block;
/* a section of the graphical query itself */
.Query-section {
display: flex;
align-items: center;
color: #91979E;
padding-top: 1em;
}
.SaveButton {
position: relative;
z-index: 10;
.Query-section.Query-section--right {
justify-content: flex-end;
}
.QueryBar {
display: inline-block;
margin: 0 0 1.2em 0;
.QueryVisualization {
display: flex;
flex: 1;
}
.QueryName {
font-weight: 200;
margin: 1em 0;
font-size: 1.35em;
margin-top: 0;
margin-bottom: 0;
font-size: 1.2rem;
}
.QueryBar .SelectionModule {
position: relative;
.Query-label {
min-width: 7rem;
display: inline-block;
}
.Query-filters {
display: flex;
flex-wrap: wrap;
align-items: center;
width: 100%;
}
.Query-filter {
display: flex;
align-items: center;
border: 1px solid var(--selection-color);
background-color: var(--selection-color);
margin-right: 1em;
margin-bottom: 0.5em;
}
.Query-filter .input {
padding: 0;
border-radius: 0;
padding: 0.5rem;
border-color: transparent;
}
.Query-filter .Icon-close {
margin-left: 1rem;
margin-right: 1rem;
}
.QueryTable-wrapper {
box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
margin-top: var(--qb-offset-normal);
margin-bottom: 3px; /* we need a small amount of margin here for the box shadow to show */
overflow: scroll;
border-top: 1px solid #E8E8E8;
}
@media screen and (--breakpoint-min-xl) {
.QueryTable-wrapper {
margin-top: var(--qb-offset-large);
}
}
.QueryTable-wrapper .Table {
font-family: "Lato";
font-size: 0.86em;
line-height: 0.86em;
}
.QueryTable-wrapper .Table th {
padding-top: 1.2rem;
padding-bottom: 1.2rem;
font-weight: bold;
color: #444;
border-top-color: transparent;
}
.QueryTable-wrapper .Table td {
padding: 0.5rem;
}
.QueryTable.Table tr:nth-child(even) {
background-color: #fff;
}
.QueryTable.Table tbody tr:hover {
background-color: #EAF0F7;
}
.QuerySection-addTrigger {
margin-left: 7rem;
}
/*
@selectionmodule
*/
.SelectionModule {
color: var(--brand-color);
}
.SelectionModule .SelectionItems {
.SelectionItems {
opacity: 0;
pointer-events: none;
position: absolute;
top: 2.75em;
top: 2.75rem;
border: 1px solid #ddd;
box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
border-radius: 4px;
......@@ -99,318 +192,309 @@ body {
left: 0;
right: 0;
overflow-y: scroll;
max-height: 360px;
}
.SelectionList {
max-height: 420px;
max-height: 340px;
min-width: 320px;
}
.SelectionItems.open {
opacity: 1;
transition: opacity .3s linear;
pointer-events: all;
}
.SelectionItem {
padding: 0.75em;
font-size: 0.85em;
position: relative;
background: #fff;
display: flex;
align-items: center;
cursor: pointer;
}
.SelectionItems {
min-width: 320px;
padding: 0.75rem;
background-color: #fff;
}
.SelectionItem:hover {
background-color: currentColor;
}
.SelectionItem .Icon-check {
opacity: 0;
color: #fff;
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.SelectionItem:hover .Icon-check {
opacity: 1;
}
.SelectionItem:hover .SelectionModule-display {
color: #fff;
}
.SelectionItem.SelectionItem--selected .Icon-check {
opacity: 1;
color: var(--brand-color);
}
.SelectionItem:before {
content: '';
width: 16px;
height: 16px;
border: 2px solid #ddd;
border-radius: 99px;
margin-right: 1em;
color: currentColor;
.SelectionModule.open .SelectionItems {
opacity: 1;
pointer-events: all;
}
.SelectionItem.selected {
color: #4A90E2;
.SelectionModule-display {
color: currentColor;
}
.SelectionItem.selected:before {
background-color: currentColor;
border-color: currentColor;
.SelectionTitle {
display: flex;
align-items: center;
padding: 0.25rem;
border: 1px solid var(--selection-color);
cursor: pointer;
transition: background .3s linear;
}
.QueryBar .SelectionItem:hover:before {
color: #fff;
border-color: currentColor;
transition: border .3s linear;
@media screen and (--breakpoint-min-md) {
.SelectionTitle {
padding: 0.5rem;
}
}
.QueryBar .SelectionTitle {
text-align: left;
font-size: 0.85em;
border: 1px dotted #999;
border-radius: 2px;
.SelectionModule.selected .SelectionTitle {
background-color: var(--selection-color);
transition: background .3s linear, border .3s linear;
}
.FilterSection .SelectionModule,
.FilterSection .SelectionModule a {
color: #A8C28e;
.SelectionModule.selected .SelectionTitle:hover {
background-color: var(--brand-color);
border-color: var(--brand-color);
color: #fff;
}
.FilterSection .input {
color: #A8C28e;
border-color: transparent;
.Visualization {
overflow-y: scroll;
transition: background .3s linear;
}
.FilterSection .input:focus {
border-color: transparent;
border-bottom: 1px solid #A8C28e;
.Visualization.Visualization--loading {
transition: background .3s linear;
}
.DimensionList .SelectionModule,
.DimensionList .SelectionModule a {
color: #B9A2CD;
.Visualization.Visualization--error {
justify-content: center;
}
.QueryBar .Button {
padding: 0.75em 1.25em;
border: 1px dotted #ddd;
box-shadow: none;
.Visualization--scalar {
justify-content: center;
font-size: 8rem;
font-weight: 200;
}
.SearchBar {
border: none;
border-bottom: 1px solid #ddd;
padding: 0.75em;
box-shadow: 0 2px 0 rgba(0, 0, 0, .12);
.Visualization .Card-outer {
width: 100%;
box-sizing: border-box;
}
.QueryPicker-wrapper {
padding: 0 2em;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.QueryBar .SelectionModule.open .SelectionItems {
opacity: 1;
pointer-events: all;
.VisualizationSettings {
padding-bottom: 1em;
padding-top: 1em;
background-color: #fff;
}
.SelectionModule-display {
color: currentColor;
.VisualizationSettings .Select select {
padding: 0.5rem;
}
.SelectionModule.selected .SelectionTitle {
display: inline-block;
margin: 0 0.25em;
border: 1px solid #ddd;
border-radius: 2px;
box-shadow: 0 1px 1px rgba(0, 0, 0, .08);
.Loading {
background-color: rgba(255, 255, 255, 0.82);
}
.SelectionModule.selected .SelectionTitle:hover {
box-shadow: 0 1px 1px rgba(0, 0, 0, .18);
cursor: pointer;
.QueryError {
flex-direction: column;
justify-content: center;
}
.RemoveTrigger {
display: inline-block;
.QueryError-iconWrapper {
padding: 2em;
margin-bottom: 2em;
border: 4px solid var(--error-color);
border-radius: 99px;
}
.ActionBar {
/* @save */
.SaveModal {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 1em;
z-index: 100;
}
.ActionBar .SettingsButtons {
float: right;
}
.FilterGroupWrapper {
position: relative;
display: inline-block;
bottom: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
pointer-events: none;
background-color: rgba(255, 255, 255, 0.75);
z-index: 5000;
}
.FilterGroupWrapper .FilterGroup {
margin-top: 1em;
.SaveModal.Modal--showing {
opacity: 1;
pointer-events: all;
}
.QueryPicker-group {
border-bottom: 1px solid #ddd;
.SaveModal .ModalContent {
background: #fff;
border: 1px solid #ddd;
box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
display: flex;
max-width: 32em;
flex: 1;
}
.QueryBar .Button {
font-size: 0.85em;
.SaveModal .ModalContent .Form-new {
width: 100%;
}
.QueryFilter {
background: #fff;
.GuiBuilder {
position: relative;
display: inline-block;
font-size: 0.85em;
margin-right: 1em;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 0px 3px rgba(0, 0, 0, .12);
border-bottom: 1px solid #F0F0F0;
max-height: 100%;
padding-left: var(--qb-offset-normal);
padding-right: var(--qb-offset-normal);
}
.QueryFilter .input {
padding: 1em;
border-radius: 0;
@media screen and (--breakpoint-min-xl) {
.GuiBuilder {
padding-left: var(--qb-offset-large);
padding-right: var(--qb-offset-large);
}
}
.QueryFilter .SelectionModule.selected .SelectionTitle {
box-sizing: border-box;
margin: 0;
border: none;
border-right: 1px solid #ddd;
.GuiBuilder.GuiBuilder--collapsed {
overflow: hidden;
max-height: 2rem;
min-height: 2rem;
}
.QueryFilter .SelectionModule.selected .SelectionTitle:hover {
background: #FBFCFD;
.GuiBuilder.GuiBuilder--collapsed .Query-section {
display: none;
}
.QueryFilter .RemoveTrigger {
margin: 0.75em 0.5em;
.QueryToggle {
color: #999;
position: absolute;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
right: var(--qb-offset-normal);
text-decoration: none;
font-weight: bold;
}
.FilterSection {
display: inline-block;
.QueryToggle:hover {
color: var(--brand-color);
}
.FilterSection .SelectionItems {
position: absolute;
display: none;
@media screen and (--breakpoint-min-xl) {
.QueryToggle {
right: var(--qb-offset-large);
}
}
.FilterSection .SelectionItems.open {
display: block;
/* @transitions */
.Transition-qb-section-enter {
opacity: 0.01;
transition: opacity .3s linear !important;
}
.SelectionModule.removeable .SelectionTitle {
padding-right: 3em;
.Transition-qb-section-enter-active {
opacity: 1;
transition: opacity .3s linear !important;
}
.QueryTable td,
.QueryTable th {
padding: 1em;
.Transition-qb-section-leave {
opacity: 1;
transition: opacity .3s linear !important;
}
.QueryTable {
margin-top: 1em;
box-shadow: 0 1px 3px rgba(0,0,0, .12);
.Transition-qb-section-leave-active {
opacity: 0.01;
transition: opacity .3s linear !important;
}
.Metric-sourceTable:after {
content: '•';
display: inline-block;
color: #ddd;
margin-left: 1em;
.Transition-viz-enter {
width: 100%;
opacity: 0.01;
transition: opacity .3s linear;
}
.DimensionList .RemoveTrigger {
position: absolute;
top: 12px;
right: 14px;
.Transition-viz-enter-active {
opacity: 1;
transition: opacity .3s linear;
}
/* breakpoints */
.Transition-popover-state-enter {
opacity: 0.01;
transition: opacity .3s linear;
}
@media screen and (min-width: 60em) {
.SelectionTitle {
padding: 0.75em 1.25em;
}
.Transition-popover-state-enter-active {
opacity: 1;
transition: opacity .3s linear;
}
@media screen and (min-width: 120em) {
body {
font-size: 1em;
}
.Button,
.QueryBar .Button {
padding: 1em 2em;
}
.Table-wrapper {
margin-top: 3em;
}
.SelectionItems.open {
top: 3em;
}
.DimensionList .RemoveTrigger {
top: 15px;
right: 17px;
}
.Transition-popover-state-leave {
opacity: 1;
transition: opacity .3s linear;
}
.QueryName {
margin-bottom: 1em;
}
.Transition-popover-state-leave-active {
opacity: 0.01;
transition: opacity .3s linear;
}
.ActionBar {
padding: 1em 0;
}
.QueryBar .SelectionTitle {
padding: 1em 2em;
}
.Transition-popover-enter {
opacity: 0.01;
transition: opacity .3s linear;
}
.FilterTrigger {
border-radius: 99px;
padding: 0.85em;
position: relative;
color: #fff;
background: #A8C28e;
border-color: #A8C28e;
.Transition-popover-enter-active {
opacity: 1;
transition: opacity .3s linear;
}
.FilterTrigger:hover {
color: #fff;
.Transition-popover-leave {
opacity: 1;
transition: opacity .3s linear;
}
.Transition-popover-leave-active {
opacity: 0.01;
transition: opacity .3s linear;
}
.Transition-qb-querybutton-enter {
opacity: 0.01;
transition: opacity .3s linear !important;
}
.FilterTrigger .icon {
display: flex;
.Transition-qb-querybutton-enter-active {
opacity: 1;
transition: opacity .3s linear !important;
}
.QueryHeader {
background: #fff;
.Transition-qb-querybutton-leave {
opacity: 1;
transition: opacity .3s linear !important;
}
.TypeControls {
position: fixed;
bottom: 0;
width: 100%;
z-index: 100;
left: 0;
right: 0;
text-align: center;
margin: 1em 0;
.Transition-qb-querybutton-leave-active {
opacity: 0.01;
transition: opacity .3s linear !important;
}
.TypeControls .Button {
display: inline-block;
font-size: 0.85em;
margin: 0 0.5em;
.AddToDashSuccess {
max-width: 260px;
text-align: center;
}
......@@ -132,7 +132,7 @@ ExploreServices.service('CorvusFormGenerator', [function() {
},
'IS_NOT': {
'name': "!=",
'verbose_name': "Is not",
'verbose_name': "Is Not",
'validArgumentsFilters': [equivalentArgument]
},
'IS_NULL': {
......@@ -217,6 +217,7 @@ ExploreServices.service('CorvusFormGenerator', [function() {
return {
'name': cls.name,
'verbose_name': cls.verbose_name,
'validArgumentsFilters': cls.validArgumentsFilters,
'fields': _.map(cls.validArgumentsFilters, function(validArgumentsFilter) {
return validArgumentsFilter(field, table);
})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment