1
0
Fork 0

Bug fix 3.5/smart join and smart graph creation ui (#9910)

* added proper UI support for collections using smartGraphAttribute or smartGraphAttribute

* make key selection more clear

* added awesome ' : ' div

* fixed smart doc creation logic

* changelog
This commit is contained in:
Heiko 2019-09-09 20:39:09 +02:00 committed by KVS85
parent 068d422d59
commit e99a7eea78
4 changed files with 241 additions and 77 deletions

View File

@ -1,6 +1,9 @@
v3.5.1 (XXXX-XX-XX) v3.5.1 (XXXX-XX-XX)
------------------- -------------------
* Added UI support to create documents in a collection using smartGraphAttribute
and/or smartJoinAttribute.
* Add count of objects to latency reporting in arangoimport. * Add count of objects to latency reporting in arangoimport.
* Harden database creation against spurious "duplicate name" errors that * Harden database creation against spurious "duplicate name" errors that

View File

@ -69,16 +69,28 @@ window.ArangoDocument = Backbone.Collection.extend({
}); });
}, },
createTypeDocument: function (collectionID, key, callback, returnNew) { createTypeDocument: function (collectionID, key, callback, returnNew,
var newDocument; smartJoinAttribute, smartJoinAttributeValue,
smartGraphAttribute, smartGraphAttributeValue) {
var newDocument = {};
if (smartJoinAttribute && smartJoinAttributeValue && key) {
// case: smartJoin, bot value are needed and NOT optional
newDocument._key = smartJoinAttributeValue + ':' + key;
newDocument[smartJoinAttribute] = smartJoinAttributeValue;
} else if (smartGraphAttribute && smartGraphAttributeValue) {
// case: smartGraph with value
// other to smartJoin, we can:
// 1.) Create without smartGraphAttribute and without smartGraphAttributeValue
// 2.) Create only with smartGraphAttributeValue
if (key) { if (key) {
newDocument = JSON.stringify({ newDocument._key = smartGraphAttributeValue + ':' + key;
_key: key
});
} else {
newDocument = JSON.stringify({});
} }
newDocument[smartGraphAttribute] = smartGraphAttributeValue;
} else if (key) {
newDocument._key = key;
}
newDocument = JSON.stringify(newDocument);
var url = arangoHelper.databaseUrl('/_api/document?collection=' + encodeURIComponent(collectionID)); var url = arangoHelper.databaseUrl('/_api/document?collection=' + encodeURIComponent(collectionID));

View File

@ -13,12 +13,31 @@
MAX_SORT: 12000, MAX_SORT: 12000,
lastQuery: {}, lastQuery: {},
type: 'document',
sortAttribute: '', sortAttribute: '',
smartJoinAttribute: null,
smartGraphAttribute: null,
url: arangoHelper.databaseUrl('/_api/documents'), url: arangoHelper.databaseUrl('/_api/documents'),
model: window.arangoDocumentModel, model: window.arangoDocumentModel,
loadTotal: function (callback) { setSmartJoinAttribute: function (stringValue) {
this.smartJoinAttribute = stringValue;
},
getSmartJoinAttribute: function () {
return this.smartJoinAttribute;
},
setSmartGraphAttribute: function (stringValue) {
this.smartGraphAttribute = stringValue;
},
getSmartGraphAttribute: function () {
return this.smartGraphAttribute;
},
loadCollectionConfig: function (callback) {
var self = this; var self = this;
$.ajax({ $.ajax({
cache: false, cache: false,
@ -27,7 +46,22 @@
contentType: 'application/json', contentType: 'application/json',
processData: false, processData: false,
success: function (data) { success: function (data) {
if (data.count) {
self.setTotal(data.count); self.setTotal(data.count);
}
if (data.smartJoinAttribute) {
self.setSmartJoinAttribute(data.smartJoinAttribute);
} else {
self.setSmartJoinAttribute(null);
}
if (data.smartGraphAttribute) {
self.setSmartGraphAttribute(data.smartGraphAttribute);
} else {
self.setSmartGraphAttribute(null);
}
callback(false); callback(false);
}, },
error: function () { error: function () {
@ -49,7 +83,7 @@
} else { } else {
this.setPage(1); this.setPage(1);
} }
this.loadTotal(callback); this.loadCollectionConfig(callback);
}, },
setSort: function (key) { setSort: function (key) {

View File

@ -539,14 +539,97 @@
addDocumentModal: function (e) { addDocumentModal: function (e) {
if (!$(e.currentTarget).hasClass('disabled')) { if (!$(e.currentTarget).hasClass('disabled')) {
var collid = window.location.hash.split('/')[1]; var collid = window.location.hash.split('/')[1];
var buttons = []; var tableContent = []; var buttons = [];
var tableContent = [];
// second parameter is "true" to disable caching of collection type // second parameter is "true" to disable caching of collection type
var callback = function (error, type) { var callback = function (error, type) {
if (error) { if (error) {
arangoHelper.arangoError('Error', 'Could not fetch collection type'); arangoHelper.arangoError('Error', 'Could not fetch collection type');
} else { } else {
if (type === 'edge') { if (this.collection.getSmartJoinAttribute()) {
tableContent.push(this.createDocumentKeyInput(true));
tableContent.push(
window.modalView.createTextEntry(
'new-smart-val-attr',
'Smart Value (' + this.collection.getSmartJoinAttribute() + ')',
undefined,
'This smartJoinAttribute must be populated for all documents in the collection, and must always contain a string value.',
'',
true,
[
{
rule: Joi.string(),
msg: ''
}
]
)
);
buttons.push(
window.modalView.createSuccessButton('Create', this.addSmartAttributeDocument.bind(this))
);
window.modalView.show(
'modalTable.ejs',
'Create document',
buttons,
tableContent
);
// custom event handler, updating key label
$('#new-document-key-attr').css('width', '50%').css('float', 'right');
$('#new-document-key-attr').before(
'<input type="text" id="new-document-key-prefix-attr" value="" placeholder="<smart-prefix>" disabled style="width: 40%; float: left;">' +
'<div style="width: 2px; float: left; margin-top: 15px; margin-left: 5px; font-weight: 800;">:</div>'
);
$('new-smart-val-attr').unbind('keyup');
$('#new-smart-val-attr').on('keyup', function (element) {
$('#new-document-key-prefix-attr').val($(element.currentTarget).val());
});
} else if (this.collection.getSmartGraphAttribute()) {
tableContent.push(this.createDocumentKeyInput(false));
tableContent.push(
window.modalView.createTextEntry(
'new-smartGraph-val-attr',
'SmartGraph Value (' + this.collection.getSmartGraphAttribute() + ')',
undefined,
'This smartGraphAttribute can be populated for all documents in the collection and then contain a string value. Otherwise it will be null.',
'',
false,
[
{
rule: Joi.string().allow('').optional(),
msg: ''
}
]
)
);
buttons.push(
window.modalView.createSuccessButton('Create', this.addSmartGraphDocument.bind(this))
);
window.modalView.show(
'modalTable.ejs',
'Create document',
buttons,
tableContent
);
// custom event handler, updating key label
$('#new-document-key-attr').css('width', '50%').css('float', 'right');
$('#new-document-key-attr').before(
'<input type="text" id="new-document-key-prefix-attr" value="" placeholder="<smart-prefix>" disabled style="width: 40%; float: left;">' +
'<div style="width: 2px; float: left; margin-top: 15px; margin-left: 5px; font-weight: 800;">:</div>'
);
$('#new-smartGraph-val-attr').unbind('keyup');
$('#new-smartGraph-val-attr').on('keyup', function (element) {
$('#new-document-key-prefix-attr').val($(element.currentTarget).val());
});
} else if (type === 'edge') {
tableContent.push( tableContent.push(
window.modalView.createTextEntry( window.modalView.createTextEntry(
'new-edge-from-attr', 'new-edge-from-attr',
@ -608,23 +691,7 @@
tableContent tableContent
); );
} else { } else {
tableContent.push( tableContent.push(this.createDocumentKeyInput(false));
window.modalView.createTextEntry(
'new-document-key-attr',
'_key',
undefined,
'the documents unique key(optional attribute, leave empty for autogenerated key',
'is optional: leave empty for autogenerated key',
false,
[
{
rule: Joi.string().allow('').optional(),
msg: ''
}
]
)
);
buttons.push( buttons.push(
window.modalView.createSuccessButton('Create', this.addDocument.bind(this)) window.modalView.createSuccessButton('Create', this.addDocument.bind(this))
); );
@ -642,49 +709,99 @@
} }
}, },
createDocumentKeyInput: function (isMandatory) {
var placeholder = 'leave empty for autogenerated key';
var tooltip = 'the documents unique key';
if (isMandatory) {
placeholder = '';
} else {
tooltip += ' (optional attribute, leave empty for autogenerated key';
}
return window.modalView.createTextEntry(
'new-document-key-attr',
'_key',
undefined,
tooltip,
placeholder,
isMandatory || false,
[
{
rule: Joi.string().allow('').optional(),
msg: ''
}
]
);
},
addEdge: function () { addEdge: function () {
var collid = window.location.hash.split('/')[1]; var collid = window.location.hash.split('/')[1];
var from = $('.modal-body #new-edge-from-attr').last().val(); var from = $('.modal-body #new-edge-from-attr').last().val();
var to = $('.modal-body #new-edge-to').last().val(); var to = $('.modal-body #new-edge-to').last().val();
var key = $('.modal-body #new-edge-key-attr').last().val(); var key = $('.modal-body #new-edge-key-attr').last().val();
var url;
var callback = function (error, data, msg) {
if (error) {
arangoHelper.arangoError('Error', msg.errorMessage);
} else {
window.modalView.hide();
data = data._id.split('/');
try {
url = 'collection/' + data[0] + '/' + data[1];
decodeURI(url);
} catch (ex) {
url = 'collection/' + data[0] + '/' + encodeURIComponent(data[1]);
}
window.location.hash = url;
}
};
if (key !== '' || key !== undefined) { if (key !== '' || key !== undefined) {
this.documentStore.createTypeEdge(collid, from, to, key, callback); this.documentStore.createTypeEdge(collid, from, to, key, this.goToDocument);
} else { } else {
this.documentStore.createTypeEdge(collid, from, to, null, callback); this.documentStore.createTypeEdge(collid, from, to, null, this.goToDocument);
} }
}, },
addDocument: function () { addDocument: function () {
var collid = window.location.hash.split('/')[1]; var collid = window.location.hash.split('/')[1];
var key = $('.modal-body #new-document-key-attr').last().val(); var key = $('.modal-body #new-document-key-attr').last().val();
var url;
var callback = function (error, data, msg) { if (key !== '' || key !== undefined) {
this.documentStore.createTypeDocument(collid, key, this.goToDocument);
} else {
this.documentStore.createTypeDocument(collid, null, this.goToDocument);
}
},
addSmartAttributeDocument: function () {
var collid = window.location.hash.split('/')[1];
var key = $('.modal-body #new-document-key-attr').last().val();
var smartJoinAttributeValue = $('.modal-body #new-smart-val-attr').last().val();
if (key !== '' || key !== undefined) {
this.documentStore.createTypeDocument(collid, key, this.goToDocument, false,
this.collection.getSmartJoinAttribute(), smartJoinAttributeValue, null, null);
} else {
this.documentStore.createTypeDocument(collid, null, this.goToDocument, false,
this.collection.getSmartJoinAttribute(), smartJoinAttributeValue, null, null);
}
},
addSmartGraphDocument: function () {
var collid = window.location.hash.split('/')[1];
var key = $('.modal-body #new-document-key-attr').last().val();
var smartGraphAttributeValue = $('.modal-body #new-smartGraph-val-attr').last().val();
if (smartGraphAttributeValue === '') {
smartGraphAttributeValue = null;
}
var smartGraphAttribute = null;
if (this.collection.getSmartGraphAttribute()) {
smartGraphAttribute = this.collection.getSmartGraphAttribute();
}
if (key === '') {
key = null;
}
this.documentStore.createTypeDocument(collid, key, this.goToDocument, false, null, null,
smartGraphAttribute, smartGraphAttributeValue);
},
goToDocument: function (error, data, msg) {
if (error) { if (error) {
arangoHelper.arangoError('Error', msg.errorMessage); arangoHelper.arangoError('Error', msg.errorMessage);
} else { } else {
window.modalView.hide(); window.modalView.hide();
data = data.split('/'); data = data.split('/');
var url;
try { try {
url = 'collection/' + data[0] + '/' + data[1]; url = 'collection/' + data[0] + '/' + data[1];
decodeURI(url); decodeURI(url);
@ -694,17 +811,12 @@
window.location.hash = url; window.location.hash = url;
} }
};
if (key !== '' || key !== undefined) {
this.documentStore.createTypeDocument(collid, key, callback);
} else {
this.documentStore.createTypeDocument(collid, null, callback);
}
}, },
moveSelectedDocs: function () { moveSelectedDocs: function () {
var buttons = []; var tableContent = []; var buttons = [];
var tableContent = [];
var toDelete = this.getSelectedDocs(); var toDelete = this.getSelectedDocs();
if (toDelete.length === 0) { if (toDelete.length === 0) {
@ -771,7 +883,8 @@
}, },
deleteSelectedDocs: function () { deleteSelectedDocs: function () {
var buttons = []; var tableContent = []; var buttons = [];
var tableContent = [];
var toDelete = this.getSelectedDocs(); var toDelete = this.getSelectedDocs();
if (toDelete.length === 0) { if (toDelete.length === 0) {
@ -805,7 +918,8 @@
confirmDeleteSelectedDocs: function () { confirmDeleteSelectedDocs: function () {
var toDelete = this.getSelectedDocs(); var toDelete = this.getSelectedDocs();
var deleted = []; var self = this; var deleted = [];
var self = this;
_.each(toDelete, function (key) { _.each(toDelete, function (key) {
if (self.type === 'document') { if (self.type === 'document') {
@ -936,7 +1050,8 @@
clicked: function (event) { clicked: function (event) {
var self = event.currentTarget; var self = event.currentTarget;
var url; var doc = $(self).attr('id').substr(4); var url;
var doc = $(self).attr('id').substr(4);
try { try {
url = 'collection/' + this.collection.collectionID + '/' + doc; url = 'collection/' + this.collection.collectionID + '/' + doc;