Skip to content

Commit

Permalink
#1817 Update dashboard section to use query api + sorting + filtering…
Browse files Browse the repository at this point in the history
… + pagination
  • Loading branch information
nadouani committed Mar 5, 2021
1 parent a61bf21 commit 4b19689
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 42 deletions.
105 changes: 98 additions & 7 deletions frontend/app/scripts/controllers/dashboard/DashboardsCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,54 @@
return $uibModalInstance.close(dashboard);
};
})
.controller('DashboardsCtrl', function($scope, $state, $uibModal, PSearchSrv, ModalUtilsSrv, NotificationSrv, DashboardSrv, AuthenticationSrv) {
.controller('DashboardsCtrl', function($scope, $state, $uibModal, PaginatedQuerySrv, FilteringSrv, ModalUtilsSrv, NotificationSrv, DashboardSrv, AuthenticationSrv) {
this.dashboards = [];
var self = this;

this.$onInit = function() {
self.filtering = new FilteringSrv('dashboard', 'dashboard.list', {
version: 'v0',
defaults: {
showFilters: true,
showStats: false,
pageSize: 15,
sort: ['+title']
},
defaultFilter: []
});

self.filtering.initContext('list')
.then(function() {
self.load();

$scope.$watch('$vm.list.pageSize', function (newValue) {
self.filtering.setPageSize(newValue);
});
});
}

this.load = function() {
DashboardSrv.list().then(function(response) {
self.dashboards = response.data;
}, function(err){
NotificationSrv.error('DashboardsCtrl', err.data, err.status);

self.list = new PaginatedQuerySrv({
name: 'dashboard-list',
version: 'v0',
skipStream: true,
sort: self.filtering.context.sort,
loadAll: false,
pageSize: self.filtering.context.pageSize,
filter: this.filtering.buildQuery(),
operations: [
{'_name': 'listDashboard'}
],
onFailure: function(err) {
if(err && err.status === 400) {
self.filtering.resetContext();
self.load();
}
}
});
};

this.load();

this.openDashboardModal = function(dashboard) {
return $uibModal.open({
templateUrl: 'views/partials/dashboard/create.dialog.html',
Expand Down Expand Up @@ -186,5 +220,62 @@
}
});
}

// Filtering
this.toggleFilters = function () {
this.filtering.toggleFilters();
};

this.filter = function () {
self.filtering.filter().then(this.applyFilters);
};

this.clearFilters = function () {
this.filtering.clearFilters()
.then(self.search);
};

this.removeFilter = function (index) {
self.filtering.removeFilter(index)
.then(self.search);
};

this.search = function () {
self.load();
self.filtering.storeContext();
};
this.addFilterValue = function (field, value) {
this.filtering.addFilterValue(field, value);
this.search();
};

this.filterBy = function(field, value) {
self.filtering.clearFilters()
.then(function(){
self.addFilterValue(field, value);
});
};

this.sortBy = function(sort) {
self.list.sort = sort;
self.list.update();
self.filtering.setSort(sort);
};

this.sortByField = function(field) {
var context = this.filtering.context;
var currentSort = Array.isArray(context.sort) ? context.sort[0] : context.sort;
var sort = null;

if(currentSort.substr(1) !== field) {
sort = ['+' + field];
} else {
sort = [(currentSort === '+' + field) ? '-'+field : '+'+field];
}

self.list.sort = sort;
self.list.update();
self.filtering.setSort(sort);
};
});
})();
2 changes: 1 addition & 1 deletion frontend/app/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ body {
}

.container-main {
padding-top: 60px;
padding-top: 80px;
}

.marked>table, .markdown>table {
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/views/partials/case/case.list.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ <h3 class="box-title">List of cases ({{$vm.list.total || 0}} of {{$vm.caseCount}
</th>
<th style="width: 150px;">Details</th>
<th style="width: 90px;">
<a href class="text-default ml-xxxs" ng-click="$vm.sortByField('assignee')" uib-tooltip="Sort by occur start date">
<a href class="text-default ml-xxxs" ng-click="$vm.sortByField('assignee')" uib-tooltip="Sort by assignee">
Assignee
<i ng-show="$vm.filtering.context.sort.indexOf('+assignee') === -1 && $vm.filtering.context.sort.indexOf('-assignee') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+assignee') !== -1" class="fa fa-caret-up"></i>
Expand Down
152 changes: 119 additions & 33 deletions frontend/app/views/partials/dashboard/list.html
Original file line number Diff line number Diff line change
@@ -1,42 +1,128 @@
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Dashboards ({{$vm.dashboards.length}})</h3>
</div>
<div class="box-body">
<button class="btn btn-primary" type="button" ng-click="$vm.addDashboard()">Create new Dashboard</button>
<button class="btn btn-default" type="button" ng-click="$vm.importDashboard()">Import Dashboard</button>

<div class="row mv-s" ng-if="$vm.dashboards.length === 0">
<div class="col-md-12">
<div class="empty-message">No dashboards defined.</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">
Dashboard List ({{$vm.list.values.length || 0}} of {{$vm.list.total}})
</h3>
</div>
</div>
<div class="box-body">
<div ng-include="'views/partials/dashboard/list/toolbar.html'"></div>

<div class="row mv-s" ng-if="$vm.dashboards.length > 0">
<div class="col-sm-12 dashboards-list">
<div class="dashboard-item media" ng-repeat="db in $vm.dashboards track by db.id">
<div class="media-left">
<span class="label label-default">{{db.status}}</span>
</div>
<div class="media-body">
<h4 class="media-heading">
<a href ui-sref="app.dashboards-view({id: db.id})">{{db.title}}</a>
</h4>
<span class="text-muted">{{db.description}}</span>
</div>
<div class="media-right ph-xs text-center" ng-if="(db.createdBy === currentUser.login)">
<a href ng-click="$vm.editDashboard(db)"><i class="fa fa-pencil"></i>Edit</a>
</div>
<div class="media-right ph-xs text-center" ng-if="(db.createdBy === currentUser.login)">
<a href class="text-danger" ng-click="$vm.deleteDashboard(db.id)"><i class="fa fa-trash"></i>Delete</a>
<div class="mt-xs filter-panel" ng-include="'views/partials/dashboard/list/filters.html'" ng-show="$vm.filtering.context.showFilters"></div>

<!-- Filters preview -->
<div class="row mt-xs">
<div class="col-md-12 clearfix">
<filters-preview filters="$vm.filtering.context.filters"
on-clear-item="$vm.removeFilter(field)"
on-clear-all="$vm.clearFilters()"></filters-preview>
</div>
<div class="media-right ph-xs text-center">
<a href ng-click="$vm.duplicateDashboard(db)"><i class="fa fa-copy"></i>Duplicate</a>
</div>

<!-- Datalist -->
<div class="row mt-xs">
<div class="col-md-12 mv-s" ng-show="$vm.list.total === 0">
<div class="empty-message">No records</div>
</div>
<div class="media-right ph-xs text-center">
<a href ng-click="$vm.exportDashboard(db)"><i class="fa fa-download"></i> Export</a>

<div class="col-md-12" ng-show="$vm.list.total > 0">
<psearch control="$vm.list"></psearch>

<table class="table table-striped case-list">
<thead>
<tr>
<th width="150px">
<a href class="text-default" ng-click="$vm.sortByField('status')">
Status
<i ng-show="$vm.filtering.context.sort.indexOf('+status') === -1 && $vm.filtering.context.sort.indexOf('-status') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+status') !== -1" class="fa fa-caret-up"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('-status') !== -1" class="fa fa-caret-down"></i>
</a>
</th>
<th>
<a href class="text-default" ng-click="$vm.sortByField('title')">
Title
<i ng-show="$vm.filtering.context.sort.indexOf('+title') === -1 && $vm.filtering.context.sort.indexOf('-title') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+title') !== -1" class="fa fa-caret-up"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('-title') !== -1" class="fa fa-caret-down"></i>
</a>
</th>
<th style="width: 250px;">
<a href class="text-default ml-xxxs" ng-click="$vm.sortByField('createdBy')" uib-tooltip="Sort by owner">
By
<i ng-show="$vm.filtering.context.sort.indexOf('+createdBy') === -1 && $vm.filtering.context.sort.indexOf('-createdBy') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+createdBy') !== -1" class="fa fa-caret-up"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('-createdBy') !== -1" class="fa fa-caret-down"></i>
</a>
</th>
<th style="width: 150px">
Dates
<a href class="text-default ml-xxxs" ng-click="$vm.sortByField('createdAt')" uib-tooltip="Sort by creation date">
C.
<i ng-show="$vm.filtering.context.sort.indexOf('+createdAt') === -1 && $vm.filtering.context.sort.indexOf('-createdAt') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+createdAt') !== -1" class="fa fa-caret-up"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('-createdAt') !== -1" class="fa fa-caret-down"></i>
</a>
<a href class="text-default ml-xxxs" ng-click="$vm.sortByField('updatedAt')" uib-tooltip="Sort by last update date">
U.
<i ng-show="$vm.filtering.context.sort.indexOf('+updatedAt') === -1 && $vm.filtering.context.sort.indexOf('-updatedAt') === -1" class="fa fa-sort"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('+updatedAt') !== -1" class="fa fa-caret-up"></i>
<i ng-show="$vm.filtering.context.sort.indexOf('-updatedAt') !== -1" class="fa fa-caret-down"></i>
</a>
</th>
<th style="width: 160px"></th>
</tr>
</thead>

<tbody>
<tr ng-repeat="item in $vm.list.values">

<td class="wrap">
<span class="label label-default clickable" ng-click="$vm.addFilterValue('status', item.status)">{{item.status}}</span>
</td>

<td class="wrap">
<div>
<a href ui-sref="app.dashboards-view({id: item._id})">{{item.title}}</a>
</div>
<span class="text-muted">{{item.description}}</span>
</td>
<td class="nowrap">
<user user-id="item.createdBy" icon-size="m"></user>
</td>
<td>
<div ng-class="{'text-bold': $vm.filtering.context.sort.indexOf('+createdAt') !== -1 || $vm.filtering.context.sort.indexOf('-createdAt') !== -1}">
C. <a href ng-click="$vm.addFilterValue('createdAt', item.createdAt)">{{item.createdAt | shortDate}}</a>
</div>
<div ng-if="item.updatedAt > 0" ng-class="{'text-bold': $vm.filtering.context.sort.indexOf('+updatedAt') !== -1 || $vm.filtering.context.sort.indexOf('-updatedAt') !== -1}">
U. <a href ng-click="$vm.addFilterValue('updatedAt', item.updatedAt)">{{item.updatedAt | shortDate}}</a>
</div>
</td>
<td>
<div class="media-right ph-xs text-center" ng-if="(item.createdBy === currentUser.login)">
<a href ng-click="$vm.editDashboard(item)"><i class="fa fa-pencil"></i>Edit</a>
</div>
<div class="media-right ph-xs text-center" ng-if="(item.createdBy === currentUser.login)">
<a href class="text-danger" ng-click="$vm.deleteDashboard(item._id)"><i class="fa fa-trash"></i>Delete</a>
</div>
<div class="media-right ph-xs text-center">
<a href ng-click="$vm.duplicateDashboard(item)"><i class="fa fa-copy"></i>Duplicate</a>
</div>
<div class="media-right ph-xs text-center">
<a href ng-click="$vm.exportDashboard(item)"><i class="fa fa-download"></i> Export</a>
</div>
</td>
</tr>
</tbody>
</table>

<psearch control="$vm.list"></psearch>
</div>
</div>



</div>
</div>
</div>
Expand Down
39 changes: 39 additions & 0 deletions frontend/app/views/partials/dashboard/list/filters.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<div class="row">
<div class="col-md-12 active-filters">
<h4>Filters</h4>

<form ng-submit="$vm.search()">
<div class="row mb-xxxs" ng-repeat="filter in $vm.filtering.context.filters track by $index">
<div class="col-sm-4 col-md-4 col-lg-2">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="$vm.removeFilter($index)">
<i class="fa fa-times text-danger"></i>
</button>
</span>
<select class="form-control" ng-model="filter.field"
ng-options="item for item in $vm.filtering.attributeKeys"
ng-change="$vm.filtering.setFilterField(filter, config.entity)"></select>
</div>
</div>
<div class="col-sm-8 col-md-8 col-lg-6">
<filter-editor metadata="$vm.filtering.metadata" filter="filter" entity="$vm.filtering.entity"></filter-editor>
</div>
</div>
<div class="mv-xs row">
<div class="col-sm-12 col-md-12 col-lg-8">
<a href class="btn btn-sm btn-link btn-clear" ng-click="$vm.filtering.addFilter()">
<i class="fa fa-plus"></i> Add a filter
</a>
<a href class="btn btn-sm btn-danger" ng-click="$vm.clearFilters()" ng-if="$vm.filtering.context.filters.length > 0">
<i class="fa fa-times"></i> Clear
</a>
<button href class="btn btn-sm btn-primary pull-right" type="submit" ng-if="$vm.filtering.context.filters.length > 0">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
</form>

</div>
</div>
20 changes: 20 additions & 0 deletions frontend/app/views/partials/dashboard/list/toolbar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="row">
<div class="col-md-12">
<div class="btn-toolbar" role="toolbar">

<button class="btn btn-sm btn-primary" type="button" ng-click="$vm.addDashboard()">Create new Dashboard</button>

<button class="btn btn-sm btn-default" type="button" ng-click="$vm.importDashboard()">Import Dashboard</button>

<div class="btn-group pull-right" role="group">
<page-sizer collection="$vm.list" sizes="[10, 15, 30, 100]"></page-sizer>
</div>

<div class="btn-group pull-right" role="group">
<button class="btn btn-sm" ng-class="{true: 'btn-primary', false:'btn-default'}[$vm.filtering.context.showFilters]" type="button" ng-click="$vm.toggleFilters()">
<i class="fa fa-search"></i> Filters
</button>
</div>
</div>
</div>
</div>

0 comments on commit 4b19689

Please sign in to comment.