mirror of
https://github.com/valitydev/redash.git
synced 2024-11-06 17:15:17 +00:00
Query snippets pages
This commit is contained in:
parent
0e5325ef1c
commit
d49e5f9d57
@ -8,3 +8,5 @@ export { default as queryLink } from './query-link';
|
||||
export { default as parameters } from './parameters';
|
||||
export { default as permissionsEditor } from './permissions-editor';
|
||||
export { default as dynamicTable } from './dynamic-table';
|
||||
export { default as paginator } from './paginator';
|
||||
export { default as settingsScreen } from './settings-screen';
|
||||
|
31
frontend/app/components/paginator.js
Normal file
31
frontend/app/components/paginator.js
Normal file
@ -0,0 +1,31 @@
|
||||
class PaginatorCtrl {
|
||||
constructor() {
|
||||
this.page = this.paginator.page;
|
||||
}
|
||||
pageChanged() {
|
||||
this.paginator.setPage(this.page);
|
||||
}
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.component('paginator', {
|
||||
template: `
|
||||
<div class="text-center">
|
||||
<ul uib-pagination total-items="$ctrl.paginator.totalCount"
|
||||
items-per-page="$ctrl.paginator.itemsPerPage"
|
||||
ng-model="$ctrl.page"
|
||||
max-size="6"
|
||||
class="pagination"
|
||||
boundary-link-numbers="true"
|
||||
rotate="false"
|
||||
next-text='>'
|
||||
previous-text='<'
|
||||
ng-change="$ctrl.pageChanged()"></ul>
|
||||
</div>
|
||||
`,
|
||||
bindings: {
|
||||
paginator: '<',
|
||||
},
|
||||
controller: PaginatorCtrl,
|
||||
});
|
||||
}
|
18
frontend/app/components/settings-screen.html
Normal file
18
frontend/app/components/settings-screen.html
Normal file
@ -0,0 +1,18 @@
|
||||
<page-header title="Settings">
|
||||
</page-header>
|
||||
|
||||
<div class="container">
|
||||
<div class="container bg-white p-5">
|
||||
<ul class="tab-nav">
|
||||
<li ng-class="{'active': dsPage }" ng-if="showDsLink"><a href="data_sources">Data Sources</a></li>
|
||||
<li ng-class="{'active': usersPage }" ng-if="showUsersLink"><a href="users">Users</a></li>
|
||||
<li ng-class="{'active': groupsPage }" ng-if="showGroupsLink"><a href="groups">Groups</a></li>
|
||||
<li ng-class="{'active': destinationsPage }" ng-if="showDestinationsLink"><a href="destinations">Alert Destinations</a></li>
|
||||
<li ng-class="{'active': snippetsPage }"><a href="query_snippets">Query Snippets</a></li>
|
||||
</ul>
|
||||
|
||||
<div ng-transclude>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
24
frontend/app/components/settings-screen.js
Normal file
24
frontend/app/components/settings-screen.js
Normal file
@ -0,0 +1,24 @@
|
||||
import startsWith from 'underscore.string/startsWith';
|
||||
import template from './settings-screen.html';
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.directive('settingsScreen', $location =>
|
||||
({
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
template,
|
||||
controller($scope, currentUser) {
|
||||
$scope.usersPage = startsWith($location.path(), '/users');
|
||||
$scope.groupsPage = startsWith($location.path(), '/groups');
|
||||
$scope.dsPage = startsWith($location.path(), '/data_sources');
|
||||
$scope.destinationsPage = startsWith($location.path(), '/destinations');
|
||||
$scope.snippetsPage = startsWith($location.path(), '/query_snippets');
|
||||
|
||||
$scope.showGroupsLink = currentUser.hasPermission('list_users');
|
||||
$scope.showUsersLink = currentUser.hasPermission('list_users');
|
||||
$scope.showDsLink = currentUser.hasPermission('admin');
|
||||
$scope.showDestinationsLink = currentUser.hasPermission('admin');
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
@ -11,6 +11,10 @@ import uiBootstrap from 'angular-ui-bootstrap';
|
||||
import uiSelect from 'ui-select';
|
||||
import toastr from 'angular-toastr';
|
||||
import 'angular-moment';
|
||||
|
||||
import 'brace';
|
||||
import 'angular-ui-ace';
|
||||
|
||||
import { ngTable } from 'ng-table';
|
||||
import { each } from 'underscore';
|
||||
|
||||
@ -25,7 +29,7 @@ import registerVisualizations from './visualizations';
|
||||
import markdownFilter from './filters/markdown';
|
||||
|
||||
const requirements = [
|
||||
ngRoute, ngResource, ngSanitize, uiBootstrap, uiSelect, ngTable.name, 'angularMoment', toastr,
|
||||
ngRoute, ngResource, ngSanitize, uiBootstrap, uiSelect, ngTable.name, 'angularMoment', toastr, 'ui.ace',
|
||||
];
|
||||
|
||||
const ngModule = angular.module('app', requirements);
|
||||
@ -88,6 +92,7 @@ function registerPages() {
|
||||
|
||||
ngModule.config(($routeProvider) => {
|
||||
each(routes, (route, path) => {
|
||||
console.log('Route: ', path);
|
||||
$routeProvider.when(path, route);
|
||||
});
|
||||
});
|
||||
|
@ -4,3 +4,4 @@ export { default as alertsList } from './alerts-list';
|
||||
export { default as alert } from './alert';
|
||||
export { default as admin } from './admin';
|
||||
export { default as dashboards } from './dashboards';
|
||||
export { default as querySnippets } from './query-snippets';
|
||||
|
29
frontend/app/pages/query-snippets/edit.html
Normal file
29
frontend/app/pages/query-snippets/edit.html
Normal file
@ -0,0 +1,29 @@
|
||||
<settings-screen>
|
||||
<div class="">
|
||||
<form name="snippetForm" class="form">
|
||||
<div class="form-group">
|
||||
<label>Trigger</label>
|
||||
<input type="string" class="form-control" ng-model="$ctrl.snippet.trigger" ng-disabled="!$ctrl.canEdit" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<input type="string" class="form-control" ng-model="$ctrl.snippet.description" ng-disabled="!$ctrl.canEdit">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Snippet</label>
|
||||
<pre ng-if="!$ctrl.canEdit">{{$ctrl.snippet.snippet}}</pre>
|
||||
<div ui-ace="$ctrl.editorOptions" ng-model="$ctrl.snippet.snippet" style="height:300px" ng-if="$ctrl.canEdit"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="$ctrl.canEdit">
|
||||
<button class="btn btn-primary" ng-disabled="!snippetForm.$valid" ng-click="$ctrl.saveChanges()">Save</button>
|
||||
<button class="btn btn-danger" ng-if="$ctrl.snippet.id" ng-click="$ctrl.delete()">Delete</button>
|
||||
</div>
|
||||
<small ng-if="$ctrl.snippet.user">
|
||||
Created by: {{$ctrl.snippet.user.name}}
|
||||
</small>
|
||||
</form>
|
||||
</div>
|
||||
</settings-screen>
|
64
frontend/app/pages/query-snippets/edit.js
Normal file
64
frontend/app/pages/query-snippets/edit.js
Normal file
@ -0,0 +1,64 @@
|
||||
import 'brace/mode/snippets';
|
||||
import template from './edit.html';
|
||||
|
||||
function SnippetCtrl($routeParams, $http, $location, toastr, currentUser, Events, QuerySnippet) {
|
||||
// $scope.$parent.pageTitle = 'Query Snippets';
|
||||
this.snippetId = $routeParams.snippetId;
|
||||
Events.record(currentUser, 'view', 'query_snippet', this.snippetId);
|
||||
|
||||
this.editorOptions = {
|
||||
mode: 'snippets',
|
||||
advanced: {
|
||||
behavioursEnabled: true,
|
||||
enableSnippets: false,
|
||||
autoScrollEditorIntoView: true,
|
||||
},
|
||||
onLoad(editor) {
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
editor.setShowPrintMargin(false);
|
||||
},
|
||||
};
|
||||
|
||||
this.saveChanges = () => {
|
||||
this.snippet.$save((snippet) => {
|
||||
toastr.success('Saved.');
|
||||
if (this.snippetId === 'new') {
|
||||
$location.path(`/query_snippets/${snippet.id}`).replace();
|
||||
}
|
||||
}, () => {
|
||||
toastr.error('Failed saving snippet.');
|
||||
});
|
||||
};
|
||||
|
||||
this.delete = () => {
|
||||
this.snippet.$delete(() => {
|
||||
$location.path('/query_snippets');
|
||||
toastr.sucess('Query snippet deleted.');
|
||||
}, () => {
|
||||
toastr.error('Failed deleting query snippet.');
|
||||
});
|
||||
};
|
||||
|
||||
if (this.snippetId === 'new') {
|
||||
this.snippet = new QuerySnippet({ description: '' });
|
||||
this.canEdit = true;
|
||||
} else {
|
||||
this.snippet = QuerySnippet.get({ id: this.snippetId }, (snippet) => {
|
||||
this.canEdit = currentUser.canEdit(snippet);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.component('snippetPage', {
|
||||
template,
|
||||
controller: SnippetCtrl,
|
||||
});
|
||||
|
||||
return {
|
||||
'/query_snippets/:snippetId': {
|
||||
template: '<snippet-page></snippet-page>',
|
||||
},
|
||||
};
|
||||
}
|
8
frontend/app/pages/query-snippets/index.js
Normal file
8
frontend/app/pages/query-snippets/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
import registerList from './list';
|
||||
import registerEdit from './edit';
|
||||
|
||||
export default function (ngModule) {
|
||||
const routes = Object.assign({}, registerList(ngModule),
|
||||
registerEdit(ngModule));
|
||||
return routes;
|
||||
}
|
41
frontend/app/pages/query-snippets/list.html
Normal file
41
frontend/app/pages/query-snippets/list.html
Normal file
@ -0,0 +1,41 @@
|
||||
<settings-screen>
|
||||
<div class="row voffset1">
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
<a href="query_snippets/new" class="btn btn-default"><i class="fa fa-plus"></i> New Snippet</a>
|
||||
</p>
|
||||
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Trigger</th>
|
||||
<th>Description</th>
|
||||
<th>Snippet</th>
|
||||
<th>Created By</th>
|
||||
<th>Updated At</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="row in $ctrl.snippets.getPageRows()">
|
||||
<td>
|
||||
<a href="query_snippets/{{row.id}}">{{row.trigger}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{row.description}}
|
||||
</td>
|
||||
<td>
|
||||
{{row.snippet}}
|
||||
</td>
|
||||
<td>
|
||||
{{row.user.name}}
|
||||
</td>
|
||||
<td>
|
||||
<span am-time-ago="row.created_at"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<paginator paginator="$ctrl.snippets"></paginator>
|
||||
</div>
|
||||
</div>
|
||||
</settings-screen>
|
25
frontend/app/pages/query-snippets/list.js
Normal file
25
frontend/app/pages/query-snippets/list.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { Paginator } from '../../utils';
|
||||
import template from './list.html';
|
||||
|
||||
function SnippetsCtrl($location, currentUser, Events, QuerySnippet) {
|
||||
Events.record(currentUser, 'view', 'page', 'query_snippets');
|
||||
// $scope.$parent.pageTitle = 'Query Snippets';
|
||||
|
||||
this.snippets = new Paginator([], { itemsPerPage: 20 });
|
||||
QuerySnippet.query((snippets) => {
|
||||
this.snippets.updateRows(snippets);
|
||||
});
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.component('snippetsListPage', {
|
||||
template,
|
||||
controller: SnippetsCtrl,
|
||||
});
|
||||
|
||||
return {
|
||||
'/query_snippets': {
|
||||
template: '<snippets-list-page></snippets-list-page>',
|
||||
},
|
||||
};
|
||||
}
|
1
frontend/app/utils/index.js
Normal file
1
frontend/app/utils/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default as Paginator } from './paginator';
|
27
frontend/app/utils/paginator.js
Normal file
27
frontend/app/utils/paginator.js
Normal file
@ -0,0 +1,27 @@
|
||||
export default class Paginator {
|
||||
constructor(rows, { page = 1, itemsPerPage = 20, totalCount = undefined } = {}) {
|
||||
this.page = page;
|
||||
this.itemsPerPage = itemsPerPage;
|
||||
this.updateRows(rows, totalCount);
|
||||
}
|
||||
|
||||
setPage(page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
getPageRows() {
|
||||
const first = this.itemsPerPage * (this.page - 1);
|
||||
const last = this.itemsPerPage * (this.page);
|
||||
|
||||
return this.rows.slice(first, last);
|
||||
}
|
||||
|
||||
updateRows(rows, totalCount = undefined) {
|
||||
this.rows = rows;
|
||||
if (this.rows) {
|
||||
this.totalCount = totalCount || rows.length;
|
||||
} else {
|
||||
this.totalCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -25,11 +25,13 @@
|
||||
"angular-route": "^1.5.8",
|
||||
"angular-sanitize": "^1.5.8",
|
||||
"angular-toastr": "^2.1.1",
|
||||
"angular-ui-ace": "^0.2.3",
|
||||
"angular-ui-bootstrap": "^2.2.0",
|
||||
"babel-core": "^6.18.0",
|
||||
"babel-loader": "^6.2.7",
|
||||
"babel-preset-es2015": "^6.18.0",
|
||||
"babel-preset-stage-2": "^6.18.0",
|
||||
"brace": "^0.9.0",
|
||||
"css-loader": "^0.25.0",
|
||||
"d3": "^3.5.17",
|
||||
"debug": "^2.2.0",
|
||||
|
Loading…
Reference in New Issue
Block a user