mirror of
https://github.com/getredash/redash.git
synced 2025-12-25 01:03:20 -05:00
Table viz: editor
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"> ×</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'))">×</span>
|
||||
</rd-tab>
|
||||
<li class="rd-tab"><a ng-click="openVisualizationEditor()" ng-if="sourceMode && canEdit">+ 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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -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
50
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user