Table viz: editor

This commit is contained in:
Levko Kravets
2017-11-30 21:52:21 +02:00
parent e7d0856831
commit 127b45a5b1
8 changed files with 49 additions and 100 deletions

View File

@@ -12,7 +12,6 @@
@import '~angular-gridster/src/angular-gridster';
@import '~pace-progress/themes/blue/pace-theme-minimal.css';
@import '~material-design-iconic-font/dist/css/material-design-iconic-font.css';
@import '~dragula/dist/dragula.css';
@import 'inc/angular';
@import 'inc/variables';

View File

@@ -18,7 +18,6 @@ import 'brace';
import 'angular-ui-ace';
import 'angular-resizable';
import ngGridster from 'angular-gridster';
import angularDragula from 'angularjs-dragula';
import { each } from 'underscore';
import '@/lib/sortable';
@@ -46,7 +45,6 @@ const requirements = [
vsRepeat,
'ui.sortable',
ngGridster.name,
angularDragula(angular),
];
const ngModule = angular.module('app', requirements);

View File

@@ -96,10 +96,13 @@
<span class="zmdi zmdi-format-indent-increase"></span> Format Query
</button>
<i class="fa fa-database"></i>
<span class="text-muted">Data Source</span>
<span class="m-l-10">
<i class="fa fa-database"></i>
<span class="text-muted">Data Source</span>
</span>
<select ng-disabled="!isQueryOwner" ng-model="query.data_source_id" ng-change="updateDataSource()"
ng-options="ds.id as ds.name for ds in dataSources"></select>
ng-options="ds.id as ds.name for ds in dataSources"
class="form-control m-l-5" style="display: inline-block; width: auto;"></select>
<div class="pull-right">
<button class="btn btn-s btn-default" ng-click="togglePublished()" ng-if="query.is_draft && query.id != undefined && (isQueryOwner || currentUser.hasPermission('admin'))">
@@ -232,11 +235,10 @@
<div class="row">
<div class="col-lg-12">
<ul class="tab-nav">
<rd-tab tab-id="table" name="Table" base-path="query.getUrl(sourceMode)"></rd-tab>
<rd-tab tab-id="{{vis.id}}" name="{{vis.name}}" ng-if="vis.type!='TABLE'" base-path="query.getUrl(sourceMode)"
ng-repeat="vis in query.visualizations">
<span class="remove" ng-click="deleteVisualization($event, vis)"
ng-show="canEdit"> &times;</span>
<rd-tab tab-id="{{vis.id}}" name="{{vis.name}}" base-path="query.getUrl(sourceMode)"
ng-repeat="vis in query.visualizations">
<span class="remove" ng-click="deleteVisualization($event, vis)"
ng-if="canEdit && !($first && (vis.type === 'TABLE'))">&times;</span>
</rd-tab>
<li class="rd-tab"><a ng-click="openVisualizationEditor()" ng-if="sourceMode && canEdit">&plus; New Visualization</a></li>
</ul>
@@ -249,10 +251,6 @@
<div class="scrollbox">
<grid-renderer query-result="queryResult" items-per-page="50"></grid-renderer>
</div>
<!-- the ng-repeat is a lame hack to find the table visualization... -->
<div class="p-15" ng-repeat="vis in query.visualizations" ng-if="vis.type == 'TABLE'">
<button class="btn btn-default" ng-if="!query.isNew()" ng-click="showEmbedDialog(query, vis)"><i class="zmdi zmdi-code"></i> Embed</button>
</div>
</div>
<div ng-if="selectedTab == vis.id" ng-repeat="vis in query.visualizations">
<visualization-renderer visualization="vis" query-result="queryResult"></visualization-renderer>

View File

@@ -1,4 +1,4 @@
import { pick, any, some, find } from 'underscore';
import { pick, any, some, find, values } from 'underscore';
import template from './query.html';
function QueryViewCtrl(
@@ -8,6 +8,12 @@ function QueryViewCtrl(
) {
const DEFAULT_TAB = 'table';
$scope.$watch('query', (query) => {
if (query) {
query.visualizations = values(query.visualizations).reverse();
}
});
function getQueryResult(maxAge) {
if (maxAge === undefined) {
maxAge = $location.search().maxAge;

View File

@@ -43,21 +43,36 @@ function getColumnContentAlignment(type) {
return ['integer', 'float', 'boolean', 'date', 'datetime'].indexOf(type) >= 0 ? 'right' : 'left';
}
function getColumnsOptions(columns, $filter, clientConfig) {
function getDefaultColumnsOptions(columns) {
return _.map(columns, (col, index) => ({
name: col.name,
type: col.type,
visible: true,
order: 100000 + index,
title: getColumnCleanName(col.name),
formatFunction: _.partial(formatValue, $filter, clientConfig, _, col.type),
allowHTML: true,
allowHTML: false,
alignContent: getColumnContentAlignment(col.type),
}));
}
function columnOptionsAsMap(options) {
return _.object(_.map(options, column => [column.name, column]));
function getColumnsOptions(columns, visualizationColumns) {
const options = getDefaultColumnsOptions(columns);
visualizationColumns = _.object(_.map(
visualizationColumns,
(col, index) => [col.name, _.extend({}, col, { order: index })],
));
_.each(options, col => _.extend(col, visualizationColumns[col.name]));
return _.sortBy(options, 'order');
}
function getColumnsToDisplay(columns, options, $filter, clientConfig) {
columns = _.object(_.map(columns, col => [col.name, col]));
const result = _.map(options, col => _.extend({}, col, columns[col.name], {
formatFunction: _.partial(formatValue, $filter, clientConfig, _, col.type),
}));
return _.sortBy(_.filter(result, 'visible'), 'order');
}
function GridRenderer(clientConfig) {
@@ -82,32 +97,18 @@ function GridRenderer(clientConfig) {
$scope.gridRows = $scope.queryResult.getData();
const columns = $scope.queryResult.getColumns();
const columnsOptions = columnOptionsAsMap(getColumnsOptions(columns, $filter, clientConfig));
const visualizationOptions = columnOptionsAsMap(_.map(
const columnsOptions = getColumnsOptions(
columns,
_.extend({}, $scope.options).columns,
(col, index) => {
col.order = index;
return col;
},
));
$scope.gridColumns = _.map(columns, col => _.extend(
{},
columnsOptions[col.name],
visualizationOptions[col.name],
col,
));
$scope.gridColumns = _.sortBy(
_.filter($scope.gridColumns, 'visible'),
'order',
);
$scope.gridColumns = getColumnsToDisplay(columns, columnsOptions, $filter, clientConfig);
}
}
$scope.$watch('queryResult && queryResult.getData()', (queryResult) => {
if (!queryResult) {
return;
if (queryResult) {
update();
}
update();
});
$scope.$watch('options', (newValue, oldValue) => {
@@ -119,7 +120,7 @@ function GridRenderer(clientConfig) {
};
}
function GridEditor($filter, clientConfig) {
function GridEditor() {
return {
restrict: 'E',
template: editorTemplate,
@@ -132,14 +133,13 @@ function GridEditor($filter, clientConfig) {
return;
}
if ($scope.queryResult.getData() == null) {
$scope.visualization.options.columns = {};
$scope.visualization.options.columns = [];
} else {
const columns = $scope.queryResult.getColumns();
const columnsOptions = getColumnsOptions(columns, $filter, clientConfig);
_.each(columnsOptions, (column) => {
column.allowHTML = false;
});
$scope.visualization.options.columns = columnsOptions;
$scope.visualization.options.columns = getColumnsOptions(
columns,
$scope.visualization.options.columns,
);
}
});
},

View File

@@ -8,7 +8,7 @@
</div>
</div>
<div dragula="'table-editor-columns'" dragula-model="visualization.options.columns">
<div ui-sortable ng-model="visualization.options.columns">
<div ng-repeat="column in visualization.options.columns">
<h5>{{ column.title }}</h5>
<div class="row">

50
package-lock.json generated
View File

@@ -250,15 +250,6 @@
"resolved": "https://registry.npmjs.org/angular-vs-repeat/-/angular-vs-repeat-1.1.7.tgz",
"integrity": "sha1-7kD97lsYqC/NEoKhrPuzlCyM0Hc="
},
"angularjs-dragula": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/angularjs-dragula/-/angularjs-dragula-2.0.0.tgz",
"integrity": "sha512-TkBnvt130FTRj5+g8ly6H6BlvZoBS7lnVRD+92WL5uKqR7PmX+UYWaiMOtO5kEMcQfRCeDZ/62xOvbekvGetMA==",
"requires": {
"atoa": "1.0.0",
"dragula": "3.7.2"
}
},
"ansi-escapes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
@@ -455,11 +446,6 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"atoa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz",
"integrity": "sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk="
},
"atob-lite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-1.0.0.tgz",
@@ -2372,15 +2358,6 @@
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"dev": true
},
"contra": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/contra/-/contra-1.9.4.tgz",
"integrity": "sha1-9TveQtfltZhcrk2ZqNYQUm3o8o0=",
"requires": {
"atoa": "1.0.0",
"ticky": "1.0.1"
}
},
"convert-source-map": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz",
@@ -2472,14 +2449,6 @@
"which": "1.3.0"
}
},
"crossvent": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.4.tgz",
"integrity": "sha1-2ixPj0DJR4JRe/K+7BBEFIGUq5I=",
"requires": {
"custom-event": "1.0.0"
}
},
"cryptiles": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
@@ -2669,11 +2638,6 @@
"array-find-index": "1.0.2"
}
},
"custom-event": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.0.tgz",
"integrity": "sha1-LkYovhncSyFLXAJjDFlx6BFhgGI="
},
"cwise": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz",
@@ -3021,15 +2985,6 @@
"resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
"integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
},
"dragula": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/dragula/-/dragula-3.7.2.tgz",
"integrity": "sha1-SjXJ05gf+sGpScKcpyhQWOhzk84=",
"requires": {
"contra": "1.9.4",
"crossvent": "1.5.4"
}
},
"dup": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz",
@@ -11230,11 +11185,6 @@
"integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=",
"dev": true
},
"ticky": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.1.tgz",
"integrity": "sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0="
},
"time-stamp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz",

View File

@@ -37,7 +37,6 @@
"angular-ui-ace": "^0.2.3",
"angular-ui-bootstrap": "^2.5.0",
"angular-vs-repeat": "^1.1.7",
"angularjs-dragula": "^2.0.0",
"bootstrap": "^3.3.7",
"brace": "^0.10.0",
"core-js": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
@@ -45,7 +44,6 @@
"d3": "^3.5.17",
"d3-cloud": "^1.2.4",
"debug": "^3.1.0",
"dragula": "^3.7.2",
"font-awesome": "^4.7.0",
"jquery": "^3.2.1",
"jquery-ui": "^1.12.1",