1
0
Fork 0

use of job api for patching and removing views (#7354)

* use of job api for patching and removing views

* fixed check of async call of in progress

* finalizing views ui

* link docu change
This commit is contained in:
Heiko 2018-11-22 14:53:37 +01:00 committed by Michael Hackstein
parent a905b2ca35
commit 9a7bd2d360
8 changed files with 359 additions and 66 deletions

View File

@ -789,7 +789,7 @@
}); });
}, },
syncAndReturnUninishedAardvarkJobs: function (type, callback) { syncAndReturnUnfinishedAardvarkJobs: function (type, callback) {
var callbackInner = function (error, AaJobs) { var callbackInner = function (error, AaJobs) {
if (error) { if (error) {
callback(true); callback(true);

View File

@ -0,0 +1,22 @@
/* jshint browser: true */
/* jshint unused: false */
/* global Backbone, window, arangoViewModel, arangoHelper */
(function () {
'use strict';
window.ArangoViews = Backbone.Collection.extend({
url: arangoHelper.databaseUrl('/_api/view'),
model: arangoViewModel,
parse: function (response) {
return response.result;
}
/*
newIndex: function (object, callback) {
}
*/
});
}());

View File

@ -0,0 +1,111 @@
/* global window, Backbone, $, arangoHelper */
(function () {
'use strict';
window.arangoViewModel = Backbone.Model.extend({
idAttribute: 'name',
urlRoot: arangoHelper.databaseUrl('/_api/view'),
defaults: {
id: '',
name: '',
type: '',
globallyUniqueId: ''
},
getProperties: function (callback) {
$.ajax({
type: 'GET',
cache: false,
url: arangoHelper.databaseUrl('/_api/view/' + encodeURIComponent(this.get('name')) + '/properties'),
contentType: 'application/json',
processData: false,
success: function (data) {
callback(false, data);
},
error: function (data) {
callback(true, data);
}
});
},
patchProperties: function (reqData, callback) {
var self = this;
$.ajax({
type: 'PUT',
cache: false,
data: JSON.stringify(reqData),
url: arangoHelper.databaseUrl('/_api/view/' + encodeURIComponent(this.get('name')) + '/properties'),
headers: {
'x-arango-async': 'store'
},
contentType: 'application/json',
processData: false,
success: function (data, textStatus, xhr) {
if (xhr.getResponseHeader('x-arango-async-id')) {
window.arangoHelper.addAardvarkJob({
id: xhr.getResponseHeader('x-arango-async-id'),
type: 'view',
desc: 'Patching View',
collection: self.get('name')
});
callback(false, data, true);
} else {
callback(true, data);
}
callback(false, data, false);
}
});
},
deleteView: function (callback) {
var self = this;
$.ajax({
cache: false,
type: 'DELETE',
url: arangoHelper.databaseUrl('/_api/view/' + self.get('name')),
headers: {
'x-arango-async': 'store'
},
success: function (data, textStatus, xhr) {
if (xhr.getResponseHeader('x-arango-async-id')) {
window.arangoHelper.addAardvarkJob({
id: xhr.getResponseHeader('x-arango-async-id'),
type: 'view',
desc: 'Removing View',
collection: self.get('name')
});
callback(false, data);
} else {
callback(true, data);
}
},
error: function (data) {
callback(true, data);
}
});
},
renameView: function (name, callback) {
var self = this;
$.ajax({
cache: false,
type: 'PUT',
url: arangoHelper.databaseUrl('/_api/view/' + self.get('name') + '/rename'),
data: JSON.stringify({ name: name }),
contentType: 'application/json',
processData: false,
success: function () {
self.set('name', name);
callback(false);
},
error: function (data) {
callback(true, data);
}
});
}
});
}());

View File

@ -269,6 +269,7 @@
this.arangoCollectionsStore = new window.ArangoCollections(); this.arangoCollectionsStore = new window.ArangoCollections();
this.arangoDocumentStore = new window.ArangoDocument(); this.arangoDocumentStore = new window.ArangoDocument();
this.arangoViewsStore = new window.ArangoViews();
// Cluster // Cluster
this.coordinatorCollection = new window.ClusterCoordinators(); this.coordinatorCollection = new window.ClusterCoordinators();
@ -279,10 +280,6 @@
cache: false cache: false
}); });
window.spotlightView = new window.SpotlightView({
collection: this.arangoCollectionsStore
});
this.footerView = new window.FooterView({ this.footerView = new window.FooterView({
collection: self.coordinatorCollection collection: self.coordinatorCollection
}); });
@ -1180,6 +1177,7 @@
}, },
view: function (name, initialized) { view: function (name, initialized) {
var self = this;
this.checkUser(); this.checkUser();
if (!initialized) { if (!initialized) {
this.waitForInit(this.view.bind(this), name); this.waitForInit(this.view.bind(this), name);
@ -1189,10 +1187,15 @@
this.viewView.remove(); this.viewView.remove();
} }
this.viewView = new window.ViewView({ this.arangoViewsStore.fetch({
name: name success: function () {
self.viewView = new window.ViewView({
model: self.arangoViewsStore.get(name),
name: name
});
self.viewView.render();
}
}); });
this.viewView.render();
}, },
views: function (initialized) { views: function (initialized) {
@ -1205,7 +1208,9 @@
this.viewsView.remove(); this.viewsView.remove();
} }
this.viewsView = new window.ViewsView({}); this.viewsView = new window.ViewsView({
collection: this.arangoViewsStore
});
this.viewsView.render(); this.viewsView.render();
}, },

View File

@ -1,14 +1,22 @@
<script id="viewView.ejs" type="text/template"> <script id="viewView.ejs" type="text/template">
<div class="innerContent"> <div class="innerContent">
<div id="propertiesEditor" class="document-editor"></div> <div id="viewDocumentation" class="infoBox" style="margin-top: 10px; margin-bottom: 30px;">
<h4>Info</h4>
<p>To learn how to configure Views, please read <a style="color: #5bc0de" href="https://docs.arangodb.com/3.4/Manual/Views/ArangoSearch/" target="_blank"><b>our documentation</b></a>.</p>
</div>
<div id="viewProcessing"class="infoBox" style="margin-top: 10px; margin-bottom: 30px; display: none">
<h4>Processing <i class="fa fa-spinner fa-spin"></i></h4>
<p>The view is currently in processing. No editing possible right now.</p>
</div>
<div id="propertiesEditor" class="document-editor" style="border-top: 1px solid rgba(140,138,137,.25)"></div>
<div class="bottomButtonBar"> <div class="bottomButtonBar">
<span class="buttonBarInfo">To learn how to configure Views, please read <a href="https://docs.arangodb.com/3.4/Manual/Views/" target="_blank"><b>our documentation</b>.</a></span>
<button id="savePropertiesButton" class="button-close pull-right" disabled>Save</button> <button id="savePropertiesButton" class="button-close pull-right" disabled>Save</button>
<% if (!window.frontendConfig.isCluster) { %> <% if (!window.frontendConfig.isCluster) { %>
<button id="renameViewButton" class="button-warning pull-right">Rename</button> <button id="renameViewButton" class="button-warning pull-right">Rename</button>
<% } %> <% } %>
<button id="deleteViewButton" class="button-danger pull-right">Delete</button> <button id="deleteViewButton" class="button-danger pull-right">Delete</button>
<span class="buttonBarInfo pull-right"></span>
</div> </div>
</div> </div>

View File

@ -84,7 +84,7 @@
}.bind(this); }.bind(this);
if (!frontendConfig.ldapEnabled) { if (!frontendConfig.ldapEnabled) {
window.arangoHelper.syncAndReturnUninishedAardvarkJobs('index', callback); window.arangoHelper.syncAndReturnUnfinishedAardvarkJobs('index', callback);
} }
}, },

View File

@ -1,19 +1,36 @@
/* jshint browser: true */ /* jshint browser: true */
/* jshint unused: false */ /* jshint unused: false */
/* global $, arangoHelper, JSONEditor, Backbone, templateEngine, window */ /* global $, arangoHelper, frontendConfig, JSONEditor, Backbone, templateEngine, window, _, localStorage */
(function () { (function () {
'use strict'; 'use strict';
window.ViewView = Backbone.View.extend({ window.ViewView = Backbone.View.extend({
el: '#content', el: '#content',
readOnly: false, readOnly: false,
refreshRate: 5000,
template: templateEngine.createTemplate('viewView.ejs'), template: templateEngine.createTemplate('viewView.ejs'),
initialize: function (options) { initialize: function (options) {
var mode = localStorage.getItem('JSONViewEditorMode');
if (mode) {
this.defaultMode = mode;
}
this.name = options.name; this.name = options.name;
}, },
defaultMode: 'tree',
storeMode: function (mode) {
var self = this;
if (mode !== 'view') {
localStorage.setItem('JSONViewEditorMode', mode);
self.defaultMode = mode;
self.editor.setMode(this.defaultMode);
}
},
remove: function () { remove: function () {
this.$el.empty().off(); /* off to unbind the events */ this.$el.empty().off(); /* off to unbind the events */
this.stopListening(); this.stopListening();
@ -28,25 +45,87 @@
'click #deleteViewButton': 'deleteView' 'click #deleteViewButton': 'deleteView'
}, },
setReadOnly: function () { checkIfInProgress: function () {
if (window.location.hash.search('view/') > -1 && $('.breadcrumb').text().search(this.model.get('name')) > -1) {
var self = this;
var callback = function (error, lockedViews) {
if (error) {
console.log('Could not check locked views');
} else {
var found = false;
_.each(lockedViews, function (foundView) {
if (self.model.get('name') === foundView.collection) {
found = true;
}
});
if (found) {
self.getViewProperties(true);
self.setInProgress(true);
window.setTimeout(function () {
self.checkIfInProgress();
}, self.refreshRate);
} else {
self.setInProgress(false);
}
}
};
if (!frontendConfig.ldapEnabled) {
window.arangoHelper.syncAndReturnUnfinishedAardvarkJobs('view', callback);
}
}
},
setReadOnlyPermissions: function () {
this.readOnly = true; this.readOnly = true;
$('.bottomButtonBar button').attr('disabled', true); $('.bottomButtonBar button').attr('disabled', true);
console.log('need to disable');
}, },
render: function () { render: function () {
this.breadcrumb(); this.breadcrumb();
this.$el.html(this.template.render({})); this.$el.html(this.template.render({}));
$('#propertiesEditor').height($('.centralRow').height() - 300 + 70); $('#propertiesEditor').height($('.centralRow').height() - 300 + 70 - $('.infoBox').innerHeight() - 10);
this.initAce(); this.initAce();
this.getView(); this.getViewProperties();
arangoHelper.checkDatabasePermissions(this.setReadOnly.bind(this)); arangoHelper.checkDatabasePermissions(this.setReadOnlyPermissions.bind(this));
this.checkIfInProgress();
}, },
jsonContentChanged: function () { jsonContentChanged: function () {
this.enableSaveButton(); this.enableSaveButton();
}, },
buttons: [
'#renameViewButton',
'#deleteViewButton'
],
disableAllButtons: function () {
var self = this;
_.each(this.buttons, function (id) {
self.disableButton(id);
});
this.disableSaveButton();
},
enableAllButtons: function () {
var self = this;
_.each(this.buttons, function (id) {
self.enableButton(id);
});
this.enableSaveButton();
},
enableButton: function (id) {
$(id).prop('disabled', false);
},
disableButton: function (id) {
$(id).prop('disabled', true);
},
enableSaveButton: function () { enableSaveButton: function () {
if (!this.readOnly) { if (!this.readOnly) {
$('#savePropertiesButton').prop('disabled', false); $('#savePropertiesButton').prop('disabled', false);
@ -68,6 +147,9 @@
onChange: function () { onChange: function () {
self.jsonContentChanged(); self.jsonContentChanged();
}, },
onModeChange: function (newMode) {
self.storeMode(newMode);
},
search: true, search: true,
mode: 'code', mode: 'code',
modes: ['tree', 'code'], modes: ['tree', 'code'],
@ -80,25 +162,24 @@
} }
}, },
getView: function () { getViewProperties: function (expand) {
var self = this; var self = this;
$.ajax({ var callback = function (error, data) {
type: 'GET', if (error) {
cache: false, arangoHelper.arangoError('View', 'Could not fetch properties for view:' + self.model.get('name'));
url: arangoHelper.databaseUrl('/_api/view/' + encodeURIComponent(self.name) + '/properties'), } else {
contentType: 'application/json',
processData: false,
success: function (data) {
delete data.name; delete data.name;
delete data.code; delete data.code;
delete data.error; delete data.error;
self.editor.set(data); self.editor.set(data);
}, if (expand) {
error: function (error) { self.editor.expandAll();
arangoHelper.arangoError('View', error.errorMessage); }
} }
}); };
this.model.getProperties(callback);
}, },
patchView: function () { patchView: function () {
@ -115,22 +196,48 @@
return; return;
} }
$.ajax({ var callback = function (error, data, done) {
type: 'PUT', if (error) {
cache: false, arangoHelper.arangoError('View', 'Could not update view properties.');
url: arangoHelper.databaseUrl('/_api/view/' + encodeURIComponent(self.name) + '/properties'), } else {
contentType: 'application/json', if (data) {
processData: false, self.editor.set(data);
data: JSON.stringify(self.editor.get()), }
success: function (properties) { if (done) {
self.disableSaveButton(); // arangoHelper.arangoNotification('View', 'Saved view properties of: ' + self.model.get('name'));
self.editor.set(properties); self.setInProgress(false);
arangoHelper.arangoNotification('View', 'Saved properties.'); } else {
}, arangoHelper.arangoNotification('View', 'Saving properties of view: ' + self.model.get('name') + ' in progress.');
error: function (error) { window.setTimeout(function () {
arangoHelper.arangoError('View', error.responseJSON.errorMessage); self.checkIfInProgress();
}, self.refreshRate);
self.setInProgress(true);
}
} }
}); };
this.model.patchProperties(self.editor.get(), callback);
},
setInProgress: function (inProgress) {
if (inProgress) {
this.disableAllButtons();
this.editor.setMode('view');
$('#viewProcessing').show();
$('#viewDocumentation').hide();
$('.jsoneditor').attr('style', 'background-color: rgba(0, 0, 0, 0.05) !important');
$('.jsoneditor-menu button').css('visibility', 'hidden');
$('.jsoneditor-modes').css('visibility', 'hidden');
} else {
this.enableAllButtons();
this.editor.setMode(this.defaultMode);
$('.buttonBarInfo').html('');
$('#viewProcessing').hide();
$('#viewDocumentation').show();
$('.jsoneditor').attr('style', 'background-color: rgba(255,255, 255, 1) !important');
$('.jsoneditor-menu button').css('visibility', 'inline');
$('.jsoneditor-modes').css('visibility', 'inline');
}
}, },
deleteView: function () { deleteView: function () {
@ -154,21 +261,16 @@
deleteViewTrue: function () { deleteViewTrue: function () {
var self = this; var self = this;
$.ajax({
type: 'DELETE', var callback = function (error, data) {
cache: false, if (error) {
url: arangoHelper.databaseUrl('/_api/view/' + encodeURIComponent(self.name)), arangoHelper.arangoError('View', 'Could not delete the view.');
contentType: 'application/json', } else {
processData: false,
success: function () {
window.modalView.hide(); window.modalView.hide();
window.App.navigate('#views', {trigger: true}); window.App.navigate('#views', {trigger: true});
},
error: function (error) {
window.modalView.hide();
arangoHelper.arangoError('View', error.responseJSON.errorMessage);
} }
}); };
self.model.deleteView(callback);
}, },
renameView: function () { renameView: function () {
@ -219,8 +321,14 @@
if (window.App.naviView) { if (window.App.naviView) {
$('#subNavigationBar .breadcrumb').html( $('#subNavigationBar .breadcrumb').html(
'View: ' + this.name 'View: ' + self.name
); );
window.setTimeout(function () {
$('#subNavigationBar .breadcrumb').html(
'View: ' + self.name
);
self.checkIfInProgress();
}, 100);
} else { } else {
window.setTimeout(function () { window.setTimeout(function () {
self.breadcrumb(); self.breadcrumb();

View File

@ -1,6 +1,6 @@
/* jshint browser: true */ /* jshint browser: true */
/* jshint unused: false */ /* jshint unused: false */
/* global $, Joi, arangoHelper, _, Backbone, templateEngine, window */ /* global $, Joi, frontendConfig, arangoHelper, _, Backbone, templateEngine, window */
(function () { (function () {
'use strict'; 'use strict';
@ -13,6 +13,8 @@
initialize: function () { initialize: function () {
}, },
refreshRate: 10000,
sortOptions: { sortOptions: {
desc: false desc: false
}, },
@ -45,6 +47,41 @@
arangoHelper.setCheckboxStatus('#viewsDropdown'); arangoHelper.setCheckboxStatus('#viewsDropdown');
}, },
checkIfInProgress: function () {
if (window.location.hash.search('views') > -1) {
var self = this;
var callback = function (error, lockedViews) {
if (error) {
console.log('Could not check locked views');
} else {
if (lockedViews.length > 0) {
_.each(lockedViews, function (foundView) {
if ($('#' + foundView.collection)) {
// found view html container
$('#' + foundView.collection + ' .collection-type-icon').removeClass('fa-clone');
$('#' + foundView.collection + ' .collection-type-icon').addClass('fa-spinner').addClass('fa-spin');
} else {
$('#' + foundView.collection + ' .collection-type-icon').addClass('fa-clone');
$('#' + foundView.collection + ' .collection-type-icon').removeClass('fa-spinner').removeClass('fa-spin');
}
});
} else {
// if no view found at all, just reset all to default
$('.tile .collection-type-icon').addClass('fa-clone').removeClass('fa-spinner').removeClass('fa-spin');
}
window.setTimeout(function () {
self.checkIfInProgress();
}, self.refreshRate);
}
};
if (!frontendConfig.ldapEnabled) {
window.arangoHelper.syncAndReturnUnfinishedAardvarkJobs('view', callback);
}
}
},
sorting: function () { sorting: function () {
if ($('#viewsSortDesc').is(':checked')) { if ($('#viewsSortDesc').is(':checked')) {
this.setSortingDesc(true); this.setSortingDesc(true);
@ -159,14 +196,16 @@
getViews: function () { getViews: function () {
var self = this; var self = this;
$.ajax({ this.collection.fetch({
type: 'GET',
cache: false,
url: arangoHelper.databaseUrl('/_api/view'),
contentType: 'application/json',
processData: false,
success: function (data) { success: function (data) {
self.render(data); var res = {
result: []
};
self.collection.each(function (view) {
res.result.push(view.toJSON());
});
self.render(res);
self.checkIfInProgress();
}, },
error: function (error) { error: function (error) {
console.log(error); console.log(error);