Began work on dashboard: editable flag, that actually stops users from changing anything, #1834

This commit is contained in:
Torkel Ödegaard 2015-04-23 15:26:39 +02:00
parent e9a174d1c5
commit 236c4e65f8
7 changed files with 157 additions and 109 deletions

View File

@ -28,9 +28,9 @@ type CurrentUser struct {
}
type DashboardMeta struct {
IsStarred bool `json:"isStarred"`
IsHome bool `json:"isHome"`
IsSnapshot bool `json:"isSnapshot"`
IsStarred bool `json:"isStarred,omitempty"`
IsHome bool `json:"isHome,omitempty"`
IsSnapshot bool `json:"isSnapshot,omitempty"`
Slug string `json:"slug"`
Expires time.Time `json:"expires"`
Created time.Time `json:"created"`

View File

@ -52,24 +52,20 @@ function (angular, $, kbn, _, moment) {
p._initMeta = function(meta) {
meta = meta || {};
meta.canShare = true;
meta.canSave = true;
meta.canEdit = true;
meta.canStar = true;
meta.canShare = meta.canShare === false ? false : true;
meta.canSave = meta.canSave === false ? false : true;
meta.canEdit = meta.canEdit === false ? false : true;
meta.canStar = meta.canStar === false ? false : true;
meta.canDelete = meta.canDelete === false ? false : true;
if (contextSrv.hasRole('Viewer')) {
meta.canSave = false;
}
if (meta.isSnapshot) {
meta.canSave = false;
}
if (meta.isHome) {
meta.canShare = false;
meta.canStar = false;
meta.canSave = false;
if (!this.editable) {
meta.canEdit = false;
meta.canDelete = false;
}
this.meta = meta;

View File

@ -27,19 +27,19 @@
<li ng-show="dashboardMeta.canShare">
<a class="pointer" ng-click="shareDashboard()" bs-tooltip="'Share dashboard'" data-placement="bottom"><i class="fa fa-share-square-o"></i></a>
</li>
<li ng-show="dashboardMeta.canSave">
<li ng-show="dashboardMeta.canEdit">
<a ng-click="saveDashboard()" bs-tooltip="'Save dashboard'" data-placement="bottom"><i class="fa fa-save"></i></a>
</li>
<li class="dropdown" ng-if="dashboardMeta.canEdit">
<li class="dropdown">
<a class="pointer" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
<li><a class="pointer" ng-click="openEditView('settings');">Settings</a></li>
<li><a class="pointer" ng-click="openEditView('annotations');">Annotations</a></li>
<li><a class="pointer" ng-click="openEditView('templating');">Templating</a></li>
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('settings');">Settings</a></li>
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('annotations');">Annotations</a></li>
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('templating');">Templating</a></li>
<li><a class="pointer" ng-click="exportDashboard();">Export</a></li>
<li><a class="pointer" ng-click="editJson();">View JSON</a></li>
<li ng-if="dashboardMeta.canSave"><a class="pointer" ng-click="saveDashboardAs();">Save As...</a></li>
<li ng-if="dashboardMeta.canSave"><a class="pointer" ng-click="deleteDashboard();">Delete dashboard</a></li>
<li ng-if="dashboardMeta.canDelete"><a class="pointer" ng-click="deleteDashboard();">Delete dashboard</a></li>
</ul>
</li>
</ul>

View File

@ -17,63 +17,118 @@
</div>
<div class="gf-box-body">
<div ng-if="editor.index == 0">
<div class="editor-row">
<div class="section">
<div class="editor-option">
<label class="small">Title</label><input type="text" class="input-large" ng-model='dashboard.title'></input>
</div>
<div class="editor-option">
<label class="small">Time correction</label>
<select ng-model="dashboard.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
</div>
<editor-opt-bool text="Hide controls (CTRL+H)" model="dashboard.hideControls"></editor-opt-bool>
<editor-opt-bool text="Shared Crosshair (CTRL+O)" model="dashboard.sharedCrosshair"></editor-opt-bool>
<div class="gf-box-body" style="padding-bottom: 50px;">
<div ng-if="editor.index == 0">
<div class="editor-row">
<div class="section">
<h5>Dashboard info</h5>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 90px">
Title
</li>
<li>
<input type="text" class="input-xlarge tight-form-input" ng-model='dashboard.title'></input>
</li>
<li class="tight-form-item">
Tags
<tip>Press enter to a add tag</tip>
</li>
<li>
<bootstrap-tagsinput ng-model="dashboard.tags" tagclass="label label-tag" placeholder="add tags">
</bootstrap-tagsinput>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 90px">
Timezone
</li>
<li>
<select ng-model="dashboard.timezone" class='input-small tight-form-input' ng-options="f for f in ['browser','utc']"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<div class="editor-row">
<div class="section">
<div class="editor-option">
<label class="small">Tags</label>
<bootstrap-tagsinput ng-model="dashboard.tags" tagclass="label label-tag" placeholder="add tags">
</bootstrap-tagsinput>
<tip>Press enter to a add tag</tip>
</div>
<div class="section">
<h5>Toggles</h5>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 181px">
<label class="checkbox-label" for="dashboard.editable">Editable</label>
</li>
<li>
<li class="tight-form-item last">
<input class="cr1" id="dashboard.editable" type="checkbox" ng-model="dashboard.editable" ng-checked="dashboard.editable">
<label for="dashboard.editable" class="cr1"></label>
</li>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 181px">
<label class="checkbox-label" for="dashboard.hideControls">Hide Controls (CTRL+H)</label>
</li>
<li class="tight-form-item last">
<input class="cr1" id="dashboard.hideControls" type="checkbox" ng-model="dashboard.hideControls" ng-checked="dashboard.hideControls">
<label for="dashboard.hideControls" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 181px">
<label class="checkbox-label" for="dashboard.sharedCrosshair">Shared Crosshair (CTRL+H)</label>
</li>
<li class="tight-form-item last">
<input class="cr1" id="dashboard.sharedCrosshair" type="checkbox" ng-model="dashboard.sharedCrosshair" ng-checked="dashboard.sharedCrosshair">
<label for="dashboard.sharedCrosshair" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
<div ng-if="editor.index == 1">
<div class="editor-row">
<div class="span6">
<table class="grafana-options-table">
<tr ng-repeat="row in dashboard.rows">
<td style="width: 97%">
{{row.title}}
</td>
<td><i ng-click="_.move(dashboard.rows,$index,$index-1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i></td>
<td><i ng-click="_.move(dashboard.rows,$index,$index+1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i></td>
<td>
<a ng-click="dashboard.rows = _.without(dashboard.rows,row)" class="btn btn-danger btn-small">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
</table>
</div>
</div>
</div>
<div ng-repeat="pulldown in dashboard.nav" ng-controller="SubmenuCtrl" ng-show="editor.index == 2+$index">
<ng-include ng-show="pulldown.enable" src="pulldownEditorPath(pulldown.type)"></ng-include>
<button ng-hide="pulldown.enable" class="btn" ng-click="pulldown.enable = true">Enable the {{pulldown.type}}</button>
</div>
</div>
<div class="clearfix"></div>
<div ng-if="editor.index == 1">
<div class="editor-row">
<div class="span6">
<table class="grafana-options-table">
<tr ng-repeat="row in dashboard.rows">
<td style="width: 97%">
{{row.title}}
</td>
<td><i ng-click="_.move(dashboard.rows,$index,$index-1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i></td>
<td><i ng-click="_.move(dashboard.rows,$index,$index+1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i></td>
<td>
<a ng-click="dashboard.rows = _.without(dashboard.rows,row)" class="btn btn-danger btn-small">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
</table>
</div>
<div class="clearfix"></div>
</div>
</div>
<div ng-repeat="pulldown in dashboard.nav" ng-controller="SubmenuCtrl" ng-show="editor.index == 2+$index">
<ng-include ng-show="pulldown.enable" src="pulldownEditorPath(pulldown.type)"></ng-include>
<button ng-hide="pulldown.enable" class="btn" ng-click="pulldown.enable = true">Enable the {{pulldown.type}}</button>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="gf-box-footer">

View File

@ -18,6 +18,8 @@ function (angular, _, kbn, moment, $) {
if (!$routeParams.slug) {
backendSrv.get('/api/dashboards/home').then(function(result) {
var meta = result.meta;
meta.canSave = meta.canShare = meta.canEdit = meta.canStar = false;
$scope.initDashboard(result, $scope);
},function() {
dashboardLoadFailed('Not found');
@ -38,7 +40,16 @@ function (angular, _, kbn, moment, $) {
backendSrv.get('/api/snapshots/' + $routeParams.key).then(function(result) {
$scope.initDashboard(result, $scope);
}, function() {
$scope.initDashboard({meta: {isSnapshot: true}, model: {title: 'Snapshot not found'}}, $scope);
$scope.initDashboard({
meta: {
isSnapshot: true,
canSave: false,
canEdit: false,
},
model: {
title: 'Snapshot not found'
}
}, $scope);
});
});
@ -56,7 +67,7 @@ function (angular, _, kbn, moment, $) {
meta: {},
model: {
title: "New dashboard",
rows: [{ height: '250px', panels:[] }]
rows: [{ height: '250px', panels:[] }]
},
}, $scope);
});
@ -66,10 +77,10 @@ function (angular, _, kbn, moment, $) {
var file_load = function(file) {
return $http({
url: "public/dashboards/"+file.replace(/\.(?!json)/,"/")+'?' + new Date().getTime(),
method: "GET",
transformResponse: function(response) {
return angular.fromJson(response);
}
method: "GET",
transformResponse: function(response) {
return angular.fromJson(response);
}
}).then(function(result) {
if(!result) {
return false;
@ -92,8 +103,8 @@ function (angular, _, kbn, moment, $) {
var execute_script = function(result) {
var services = {
dashboardSrv: dashboardSrv,
datasourceSrv: datasourceSrv,
$q: $q,
datasourceSrv: datasourceSrv,
$q: $q,
};
/*jshint -W054 */
@ -118,16 +129,16 @@ function (angular, _, kbn, moment, $) {
var url = 'public/dashboards/'+file.replace(/\.(?!js)/,"/") + '?' + new Date().getTime();
return $http({ url: url, method: "GET" })
.then(execute_script)
.then(null,function(err) {
console.log('Script dashboard error '+ err);
$scope.appEvent('alert-error', ["Script Error", "Please make sure it exists and returns a valid dashboard"]);
return false;
});
.then(execute_script)
.then(null,function(err) {
console.log('Script dashboard error '+ err);
$scope.appEvent('alert-error', ["Script Error", "Please make sure it exists and returns a valid dashboard"]);
return false;
});
};
script_load($routeParams.jsFile).then(function(result) {
$scope.initDashboard({meta: {fromScript: true}, model: result.data}, $scope);
$scope.initDashboard({meta: {fromScript: true, canDelete: false}, model: result.data}, $scope);
});
});

View File

@ -1,33 +1,19 @@
.bootstrap-tagsinput {
display: inline-block;
padding: 4px 6px;
margin-bottom: 10px;
color: #555;
padding: 0 0 0 6px;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
background-color: @inputBackground;
border: 1px solid @inputBorder;
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
.transition(~"border linear .2s, box-shadow linear .2s");
input {
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0;
padding-left: 5px;
margin: 0;
width: auto !important;
max-width: inherit;
&:focus {
border: none;
box-shadow: none;
}
border-right: 1px solid @grafanaTargetSegmentBorder;
margin: 0px;
border-radius: 0;
padding: 8px 6px;
height: 100%;
box-sizing: border-box;
}
.tag {
@ -49,4 +35,4 @@
}
}
}
}
}

View File

@ -500,4 +500,4 @@
$(function() {
$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
});
})(window.jQuery);
})(window.jQuery);