mirror of
https://github.com/valitydev/redash.git
synced 2024-11-08 09:53:59 +00:00
Working version of the dashboard page
This commit is contained in:
parent
00bd38771d
commit
b249b9a444
@ -679,3 +679,14 @@ div.table-name:hover {
|
||||
stroke-opacity: .2;
|
||||
}
|
||||
|
||||
/*Dashboard list view */
|
||||
.no-margin{
|
||||
margin:0px;
|
||||
}
|
||||
.two-px-margin{
|
||||
margin:2px;
|
||||
}
|
||||
|
||||
.taglist{
|
||||
margin-top:20px;
|
||||
}
|
@ -13,7 +13,7 @@ function controller($scope, $location, currentUser, Dashboard) {
|
||||
this.currentUser = currentUser;
|
||||
|
||||
this.reloadDashboards = () => {
|
||||
Dashboard.query((dashboards) => {
|
||||
Dashboard.recent((dashboards) => {
|
||||
this.dashboards = sortBy(dashboards, 'name');
|
||||
this.allDashboards = groupBy(this.dashboards, (d) => {
|
||||
const parts = d.name.split(':');
|
||||
|
30
frontend/app/pages/dashboards/dashboard-list.html
Normal file
30
frontend/app/pages/dashboards/dashboard-list.html
Normal file
@ -0,0 +1,30 @@
|
||||
<div class='container row'>
|
||||
<page-header title="Dashboards"></page-header>
|
||||
<div class="col-lg-3">
|
||||
<input type='text' class='form-control' placeholder="Search Dashboards..."
|
||||
ng-change="$ctrl.tableParams.reload()" ng-model="searchText"/>
|
||||
<div class='list-group taglist'>
|
||||
<h3 class='list-group-item no-margin'>Tags</h3>
|
||||
<a ng-repeat='tag in $ctrl.allTags' ng-class='{"active": $ctrl.tagIsSelected(tag)}'
|
||||
class='list-group-item' ng-click='$ctrl.toggleTag(tag)'>
|
||||
{{ tag }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<tab-nav tabs="$ctrl.tabs"></tab-nav>
|
||||
<div class="bg-white">
|
||||
<table class="table table-condensed table-hover" ng-table="$ctrl.tableParams" show-filters='true'>
|
||||
<tr ng-repeat="dashboard in $data">
|
||||
<td data-title="'Name'" sortable="'untagged_name'">
|
||||
<a href="dashboard/{{ dashboard.slug }}">
|
||||
{{ dashboard.untagged_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td data-title="'Tags'"><span class="label label-primary two-px-margin" ng-bind="tag" ng-repeat="tag in dashboard.tags"></span></td>
|
||||
<td data-title="'Created At'">{{ dashboard.created_at | dateTime }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
96
frontend/app/pages/dashboards/dashboard-list.js
Normal file
96
frontend/app/pages/dashboards/dashboard-list.js
Normal file
@ -0,0 +1,96 @@
|
||||
import template from './dashboard-list.html';
|
||||
import {_} from 'underscore';
|
||||
|
||||
function DashboardListCtrl($scope, Dashboard, $location, currentUser, clientConfig, NgTableParams) {
|
||||
const self = this;
|
||||
|
||||
self.logoUrl = clientConfig.logoUrl;
|
||||
const page = parseInt($location.search().page || 1, 10);
|
||||
const count = 25;
|
||||
|
||||
this.defaultOptions = {};
|
||||
self.dashboards = Dashboard.query({}); // shared promise
|
||||
|
||||
$scope.selectedTags = []; // in scope because it needs to be accessed inside a table refresh
|
||||
$scope.searchText = "";
|
||||
|
||||
$scope.$watch(function(){
|
||||
return $scope.searchText;
|
||||
}, function(){this.defaultOptions.reload()})
|
||||
|
||||
this.tagIsSelected = (tag) => {
|
||||
return $scope.selectedTags.indexOf(tag) > -1;
|
||||
}
|
||||
|
||||
this.toggleTag = (tag) => {
|
||||
if(this.tagIsSelected(tag)){
|
||||
$scope.selectedTags = $scope.selectedTags.filter((e) => e!=tag);
|
||||
}else{
|
||||
$scope.selectedTags.push(tag);
|
||||
}
|
||||
this.tableParams.reload();
|
||||
}
|
||||
|
||||
this.allTags = [];
|
||||
self.dashboards.$promise.then((data) => {
|
||||
const out = data.results.map((dashboard) => {
|
||||
return dashboard.name.match(/(^\w+):|(#\w+)/ig);
|
||||
});
|
||||
this.allTags = _.unique(_.flatten(out)).filter((e) => e);
|
||||
});
|
||||
|
||||
this.tableParams = new NgTableParams({ page, count }, {
|
||||
getData(params) {
|
||||
const options = params.url();
|
||||
$location.search('page', options.page);
|
||||
|
||||
const request = {};
|
||||
|
||||
return self.dashboards.$promise.then((data) => {
|
||||
params.total(data.count);
|
||||
return data.results.map((dashboard) => {
|
||||
dashboard.tags = dashboard.name.match(/(^\w+):|(#\w+)/ig);
|
||||
dashboard.untagged_name = dashboard.name.replace(/(\w+):|(#\w+)/ig, '').trim();
|
||||
return dashboard;
|
||||
}).filter((value) => {
|
||||
if($scope.selectedTags.length){
|
||||
const value_tags = new Set(value.tags);
|
||||
const tag_match = $scope.selectedTags;
|
||||
const filtered_match = tag_match.filter(x => value_tags.has(x));
|
||||
if(tag_match.length != filtered_match.length){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($scope.searchText && $scope.searchText.length){
|
||||
if(!value.untagged_name.toLowerCase().includes($scope.searchText)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.tabs = [
|
||||
{ name: 'All Dashboards', path: 'dashboards' },
|
||||
];
|
||||
|
||||
self.currentUser = currentUser;
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.component('pageDashboardList', {
|
||||
template,
|
||||
controller: DashboardListCtrl,
|
||||
});
|
||||
|
||||
const route = {
|
||||
template: '<page-dashboard-list></page-dashboard-list>',
|
||||
reloadOnSearch: false,
|
||||
};
|
||||
|
||||
return {
|
||||
'/dashboards': route,
|
||||
};
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import dashboardPage from './dashboard';
|
||||
import dashboardList from './dashboard-list';
|
||||
import widgetComponent from './widget';
|
||||
import addWidgetDialog from './add-widget-dialog';
|
||||
import registerEditDashboardDialog from './edit-dashboard-dialog';
|
||||
@ -7,5 +8,5 @@ export default function (ngModule) {
|
||||
addWidgetDialog(ngModule);
|
||||
widgetComponent(ngModule);
|
||||
registerEditDashboardDialog(ngModule);
|
||||
return dashboardPage(ngModule);
|
||||
return Object.assign({}, dashboardPage(ngModule), dashboardList(ngModule));
|
||||
}
|
@ -18,14 +18,17 @@ function Dashboard($resource, $http, currentUser, Widget) {
|
||||
const resource = $resource('api/dashboards/:slug', { slug: '@slug' }, {
|
||||
get: { method: 'GET', transformResponse: transform },
|
||||
save: { method: 'POST', transformResponse: transform },
|
||||
query: { method: 'GET', isArray: true, transformResponse: transform },
|
||||
query: { method: 'GET', isArray: false, transformResponse: transform },
|
||||
recent: {
|
||||
method: 'get',
|
||||
isArray: true,
|
||||
url: 'api/dashboards/recent',
|
||||
transformResponse: transform,
|
||||
} });
|
||||
|
||||
},
|
||||
dashboards: {
|
||||
isArray: false,
|
||||
}
|
||||
});
|
||||
resource.prototype.canEdit = () => currentUser.canEdit(this) || this.can_edit;
|
||||
|
||||
return resource;
|
||||
|
@ -7,7 +7,7 @@ from itertools import chain
|
||||
from redash import models
|
||||
from redash.models import ConflictDetectedError
|
||||
from redash.permissions import require_permission, require_admin_or_owner, require_object_modify_permission, can_modify
|
||||
from redash.handlers.base import BaseResource, get_object_or_404
|
||||
from redash.handlers.base import BaseResource, get_object_or_404, paginate
|
||||
|
||||
|
||||
class RecentDashboardsResource(BaseResource):
|
||||
@ -25,8 +25,11 @@ class RecentDashboardsResource(BaseResource):
|
||||
class DashboardListResource(BaseResource):
|
||||
@require_permission('list_dashboards')
|
||||
def get(self):
|
||||
dashboards = [d.to_dict() for d in models.Dashboard.all(self.current_org, self.current_user.groups, self.current_user)]
|
||||
return dashboards
|
||||
results = models.Dashboard.all(self.current_org, self.current_user.groups, self.current_user)
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 25, type=int)
|
||||
dashboards = models.Dashboard.all(self.current_org, self.current_user.groups, self.current_user)
|
||||
return paginate(results, page, page_size, lambda q: q.to_dict())
|
||||
|
||||
@require_permission('create_dashboard')
|
||||
def post(self):
|
||||
|
Loading…
Reference in New Issue
Block a user