1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
Jan Steemann 2016-02-22 09:41:44 +01:00
commit 4277f7a131
68 changed files with 4521 additions and 113438 deletions

View File

@ -29,7 +29,7 @@ if (GO_FOUND)
CONFIGURE_COMMAND ""
BUILD_IN_SOURCE TRUE
BUILD_COMMAND "${ETCD_BUILD_COMMAND}"
INSTALL_COMMAND ""
INSTALL_COMMAND "cp" ${CMAKE_CURRENT_SOURCE_DIR}/etcd/bin/etcd ${CMAKE_BINARY_DIR}/bin/etcd-arango
)
endif ()

View File

@ -1130,6 +1130,31 @@ AstNode* Ast::createNodeCalculatedObjectElement(AstNode const* attributeName,
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST with collections node
////////////////////////////////////////////////////////////////////////////////
AstNode* Ast::createNodeWithCollections (AstNode const* collections) {
AstNode* node = createNode(NODE_TYPE_COLLECTION_LIST);
TRI_ASSERT(collections->type == NODE_TYPE_ARRAY);
for (size_t i = 0; i < collections->numMembers(); ++i) {
auto c = collections->getMember(i);
if (c->isStringValue()) {
_query->collections()->add(c->getStringValue(), TRI_TRANSACTION_READ);
}// else bindParameter use default for collection bindVar
// We do not need to propagate these members
node->addMember(c);
}
AstNode* with = createNode(NODE_TYPE_WITH);
with->addMember(node);
return with;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collection list node

View File

@ -506,6 +506,12 @@ class Ast {
//////////////////////////////////////////////////////////////////////////////
AstNode* createNodeCollectionPair(AstNode const*, AstNode const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief create an AST with collections node
//////////////////////////////////////////////////////////////////////////////
AstNode* createNodeWithCollections (AstNode const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collection list node

View File

@ -169,6 +169,7 @@ std::unordered_map<int, std::string const> const AstNode::TypeNames{
{static_cast<int>(NODE_TYPE_OPERATOR_NARY_AND), "n-ary and"},
{static_cast<int>(NODE_TYPE_OPERATOR_NARY_OR), "n-ary or"},
{static_cast<int>(NODE_TYPE_AGGREGATIONS), "aggregations array"},
{static_cast<int>(NODE_TYPE_WITH), "with collections"},
{static_cast<int>(NODE_TYPE_OPERATOR_BINARY_ARRAY_EQ), "array compare =="},
{static_cast<int>(NODE_TYPE_OPERATOR_BINARY_ARRAY_NE), "array compare !="},
{static_cast<int>(NODE_TYPE_OPERATOR_BINARY_ARRAY_LT), "array compare <"},
@ -639,6 +640,7 @@ AstNode::AstNode(Ast* ast, arangodb::basics::Json const& json)
case NODE_TYPE_COLLECTION_LIST:
case NODE_TYPE_OPERATOR_NARY_AND:
case NODE_TYPE_OPERATOR_NARY_OR:
case NODE_TYPE_WITH:
break;
}
@ -762,7 +764,8 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
case NODE_TYPE_TRAVERSAL:
case NODE_TYPE_DIRECTION:
case NODE_TYPE_COLLECTION_LIST:
case NODE_TYPE_PASSTHRU: {
case NODE_TYPE_PASSTHRU:
case NODE_TYPE_WITH: {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"Unsupported node type");
}
@ -2720,6 +2723,7 @@ void AstNode::findVariableAccess(
case NODE_TYPE_TRAVERSAL:
case NODE_TYPE_COLLECTION_LIST:
case NODE_TYPE_DIRECTION:
case NODE_TYPE_WITH:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_EQ:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_NE:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_LT:
@ -2872,6 +2876,7 @@ AstNode const* AstNode::findReference(AstNode const* findme) const {
case NODE_TYPE_DIRECTION:
case NODE_TYPE_OPERATOR_NARY_AND:
case NODE_TYPE_OPERATOR_NARY_OR:
case NODE_TYPE_WITH:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_EQ:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_NE:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_LT:

View File

@ -201,7 +201,8 @@ enum AstNodeType : uint32_t {
NODE_TYPE_OPERATOR_BINARY_ARRAY_GE = 70,
NODE_TYPE_OPERATOR_BINARY_ARRAY_IN = 71,
NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN = 72,
NODE_TYPE_QUANTIFIER = 73
NODE_TYPE_QUANTIFIER = 73,
NODE_TYPE_WITH = 74
};
static_assert(NODE_TYPE_VALUE < NODE_TYPE_ARRAY, "incorrect node types order");

View File

@ -1447,6 +1447,11 @@ ExecutionNode* ExecutionPlan::fromNode(AstNode const* node) {
}
switch (member->type) {
case NODE_TYPE_WITH: {
// the using declaration...
break;
}
case NODE_TYPE_FOR: {
en = fromNodeFor(en, member);
break;

File diff suppressed because it is too large Load Diff

View File

@ -275,6 +275,7 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
%type <node> T_INTEGER
%type <node> T_DOUBLE
%type <strval> T_PARAMETER;
%type <node> with_collection;
%type <node> sort_list;
%type <node> sort_element;
%type <node> sort_direction;
@ -326,10 +327,57 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
/* define start token of language */
%start query
%start queryStart
%%
with_collection:
T_STRING {
$$ = parser->ast()->createNodeValueString($1.value, $1.length);
}
| bind_parameter {
char const* p = $1->getStringValue();
size_t const len = $1->getStringLength();
if (len < 1 || *p != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), p, yylloc.first_line, yylloc.first_column);
}
$$ = $1;
}
;
with_collection_list:
with_collection {
auto node = static_cast<AstNode*>(parser->peekStack());
node->addMember($1);
}
| with_collection_list T_COMMA with_collection {
auto node = static_cast<AstNode*>(parser->peekStack());
node->addMember($3);
}
| with_collection_list with_collection {
auto node = static_cast<AstNode*>(parser->peekStack());
node->addMember($2);
}
;
optional_with:
/* empty */ {
}
| T_WITH {
auto node = parser->ast()->createNodeArray();
parser->pushStack(node);
} with_collection_list {
auto node = static_cast<AstNode*>(parser->popStack());
auto withNode = parser->ast()->createNodeWithCollections(node);
parser->ast()->addOperation(withNode);
}
;
queryStart:
optional_with query {
}
;
query:
optional_statement_block_statements final_statement {
}

View File

@ -69,7 +69,6 @@ Syncer::Syncer(TRI_vocbase_t* vocbase,
_barrierId(0),
_barrierUpdateTime(0),
_barrierTtl(600) {
if (configuration->_database.empty()) {
// use name of current database
_databaseName = std::string(vocbase->_name);
@ -121,8 +120,7 @@ Syncer::Syncer(TRI_vocbase_t* vocbase,
Syncer::~Syncer() {
try {
sendRemoveBarrier();
}
catch (...) {
} catch (...) {
}
// shutdown everything properly
@ -147,7 +145,7 @@ std::string Syncer::rewriteLocation(void* data, std::string const& location) {
if (location[0] == '/') {
return "/_db/" + s->_databaseName + location;
}
}
return "/_db/" + s->_databaseName + "/" + location;
}
@ -170,16 +168,16 @@ int Syncer::sendCreateBarrier(std::string& errorMsg, TRI_voc_tick_t minTick) {
_barrierId = 0;
std::string const url = BaseUrl + "/barrier";
std::string const body = "{\"ttl\":" + StringUtils::itoa(_barrierTtl) + ",\"tick\":\"" + StringUtils::itoa(minTick) + "\"}";
std::string const body = "{\"ttl\":" + StringUtils::itoa(_barrierTtl) +
",\"tick\":\"" + StringUtils::itoa(minTick) + "\"}";
// send request
std::unique_ptr<SimpleHttpResult> response(_client->retryRequest(
HttpRequest::HTTP_REQUEST_POST, url, body.c_str(), body.size()));
if (response == nullptr || !response->isComplete()) {
errorMsg = "could not connect to master at " +
_masterInfo._endpoint + ": " +
_client->getErrorMessage();
errorMsg = "could not connect to master at " + _masterInfo._endpoint +
": " + _client->getErrorMessage();
return TRI_ERROR_REPLICATION_NO_RESPONSE;
}
@ -191,10 +189,9 @@ int Syncer::sendCreateBarrier(std::string& errorMsg, TRI_voc_tick_t minTick) {
if (response->wasHttpError()) {
res = TRI_ERROR_REPLICATION_MASTER_ERROR;
errorMsg = "got invalid response from master at " +
_masterInfo._endpoint + ": HTTP " +
StringUtils::itoa(response->getHttpReturnCode()) + ": " +
response->getHttpReturnMessage();
errorMsg = "got invalid response from master at " + _masterInfo._endpoint +
": HTTP " + StringUtils::itoa(response->getHttpReturnCode()) +
": " + response->getHttpReturnMessage();
} else {
std::unique_ptr<TRI_json_t> json(
TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, response->getBody().c_str()));
@ -209,7 +206,8 @@ int Syncer::sendCreateBarrier(std::string& errorMsg, TRI_voc_tick_t minTick) {
} else {
_barrierId = StringUtils::uint64(id);
_barrierUpdateTime = TRI_microtime();
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "created WAL logfile barrier " << _barrierId;
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "created WAL logfile barrier "
<< _barrierId;
}
}
}
@ -234,7 +232,8 @@ int Syncer::sendExtendBarrier(TRI_voc_tick_t tick) {
}
std::string const url = BaseUrl + "/barrier/" + StringUtils::itoa(_barrierId);
std::string const body = "{\"ttl\":" + StringUtils::itoa(_barrierTtl) + ",\"tick\"" + StringUtils::itoa(tick) + "\"}";
std::string const body = "{\"ttl\":" + StringUtils::itoa(_barrierTtl) +
",\"tick\"" + StringUtils::itoa(tick) + "\"}";
// send request
std::unique_ptr<SimpleHttpResult> response(_client->request(
@ -267,7 +266,8 @@ int Syncer::sendRemoveBarrier() {
}
try {
std::string const url = BaseUrl + "/barrier/" + StringUtils::itoa(_barrierId);
std::string const url =
BaseUrl + "/barrier/" + StringUtils::itoa(_barrierId);
// send request
std::unique_ptr<SimpleHttpResult> response(_client->retryRequest(
@ -518,7 +518,6 @@ int Syncer::createCollection(TRI_json_t const* json, TRI_vocbase_col_t** dst) {
return TRI_ERROR_NO_ERROR;
}
std::shared_ptr<VPackBuilder> builder =
arangodb::basics::JsonHelper::toVelocyPack(json);
@ -528,7 +527,8 @@ int Syncer::createCollection(TRI_json_t const* json, TRI_vocbase_col_t** dst) {
s.add("isSystem", VPackValue(true));
s.close();
VPackBuilder merged = VPackCollection::merge(s.slice(), builder->slice(), true);
VPackBuilder merged =
VPackCollection::merge(s.slice(), builder->slice(), true);
VocbaseCollectionInfo params(_vocbase, name.c_str(), merged.slice());
@ -710,9 +710,8 @@ int Syncer::getMasterState(std::string& errorMsg) {
_client->_retryWaitTime = retryWaitTime;
if (response == nullptr || !response->isComplete()) {
errorMsg = "could not connect to master at " +
_masterInfo._endpoint + ": " +
_client->getErrorMessage();
errorMsg = "could not connect to master at " + _masterInfo._endpoint +
": " + _client->getErrorMessage();
return TRI_ERROR_REPLICATION_NO_RESPONSE;
}
@ -722,10 +721,9 @@ int Syncer::getMasterState(std::string& errorMsg) {
if (response->wasHttpError()) {
res = TRI_ERROR_REPLICATION_MASTER_ERROR;
errorMsg = "got invalid response from master at " +
_masterInfo._endpoint + ": HTTP " +
StringUtils::itoa(response->getHttpReturnCode()) + ": " +
response->getHttpReturnMessage();
errorMsg = "got invalid response from master at " + _masterInfo._endpoint +
": HTTP " + StringUtils::itoa(response->getHttpReturnCode()) +
": " + response->getHttpReturnMessage();
} else {
std::unique_ptr<TRI_json_t> json(
TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, response->getBody().c_str()));
@ -835,8 +833,8 @@ int Syncer::handleStateResponse(TRI_json_t const* json, std::string& errorMsg) {
return TRI_ERROR_REPLICATION_MASTER_INCOMPATIBLE;
}
if (major < 2 || major > 2 || (major == 2 && minor < 2)) {
// we can connect to 1.4, 2.0 and higher only
if (major != 3) {
// we can connect to 3.x onyl
errorMsg = "got incompatible master version" + endpointString + ": '" +
versionString + "'";
@ -849,7 +847,11 @@ int Syncer::handleStateResponse(TRI_json_t const* json, std::string& errorMsg) {
_masterInfo._lastLogTick = lastLogTick;
_masterInfo._active = running;
LOG_TOPIC(INFO, Logger::REPLICATION) << "connected to master at " << _masterInfo._endpoint << ", id " << _masterInfo._serverId << ", version " << _masterInfo._majorVersion << "." << _masterInfo._minorVersion << ", last log tick " << _masterInfo._lastLogTick;
LOG_TOPIC(INFO, Logger::REPLICATION)
<< "connected to master at " << _masterInfo._endpoint << ", id "
<< _masterInfo._serverId << ", version " << _masterInfo._majorVersion
<< "." << _masterInfo._minorVersion << ", last log tick "
<< _masterInfo._lastLogTick;
return TRI_ERROR_NO_ERROR;
}

View File

@ -1004,6 +1004,7 @@ static bool CompactifyDocumentCollection(TRI_document_collection_t* document) {
bool doCompact = false;
uint64_t totalSize = 0;
char const* reason = nullptr;
char const* firstReason = nullptr;
for (size_t i = start; i < n; ++i) {
TRI_datafile_t* df =
@ -1060,23 +1061,36 @@ static bool CompactifyDocumentCollection(TRI_document_collection_t* document) {
numAlive += static_cast<int64_t>(dfi.numberAlive);
continue;
}
TRI_ASSERT(doCompact);
if (firstReason == nullptr) {
firstReason = reason;
}
// remember for next compaction
start = i + 1;
if (!toCompact.empty() &&
totalSize + (uint64_t)df->_maximalSize >= maxSize &&
(toCompact.size() != 1 || reason != ReasonDatafileSmall)) {
// found enough files to compact (in terms of cumulated size)
// there's one exception to this: if we're merging multiple datafiles,
// then we don't stop at the first one even if the merge of file #1 and #2
// would be too big. if we wouldn't stop in this case, then file #1 would
// be selected for compaction over and over
// normally this case won't happen at all, it can occur however if one
// decreases the journalSize configuration for the collection afterwards, and
// there are already datafiles which are more than 3 times bigger than the
// new (smaller) journalSize value
break;
// if we got only deletions then it's safe to continue compaction, regardless of
// the size of the resulting file. this is because deletions will reduce the
// size of the resulting file
if (reason != ReasonOnlyDeletions) {
if (!toCompact.empty() &&
totalSize + (uint64_t)df->_maximalSize >= maxSize &&
(toCompact.size() != 1 || reason != ReasonDatafileSmall)) {
// found enough files to compact (in terms of cumulated size)
// there's one exception to this: if we're merging multiple datafiles,
// then we don't stop at the first one even if the merge of file #1 and #2
// would be too big. if we wouldn't stop in this case, then file #1 would
// be selected for compaction over and over
// normally this case won't happen at all, it can occur however if one
// decreases the journalSize configuration for the collection afterwards, and
// there are already datafiles which are more than 3 times bigger than the
// new (smaller) journalSize value
break;
}
}
TRI_ASSERT(reason != nullptr);

View File

@ -1,5 +1,5 @@
/*jshint unused: false */
/*global window, $, document, _ */
/*global window, $, document, arangoHelper, _ */
(function() {
"use strict";
@ -443,16 +443,28 @@
this.arangoDocumentStore = a;
},
collectionApiType: function (identifier, refresh) {
collectionApiType: function (identifier, refresh, toRun) {
// set "refresh" to disable caching collection type
if (refresh || this.CollectionTypes[identifier] === undefined) {
this.CollectionTypes[identifier] = this.arangoDocumentStore
.getCollectionInfo(identifier).type;
var callback = function(error, data, toRun) {
if (error) {
arangoHelper.arangoError("Error", "Could not detect collection type");
}
else {
this.CollectionTypes[identifier] = data.type;
if (this.CollectionTypes[identifier] === 3) {
toRun(false, "edge");
}
else {
toRun(false, "document");
}
}
}.bind(this);
this.arangoDocumentStore.getCollectionInfo(identifier, callback, toRun);
}
if (this.CollectionTypes[identifier] === 3) {
return "edge";
else {
toRun(false, this.CollectionTypes[identifier]);
}
return "document";
},
collectionType: function (val) {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
<script src="sharedLibs.js?version=1455882035132"></script>
<script src="libs.js?version=1455882035132"></script>
<script src="app.js?version=1455882035132"></script>
<script src="sharedLibs.js?version=1455929599138"></script>
<script src="libs.js?version=1455929599138"></script>
<script src="app.js?version=1455929599138"></script>

View File

@ -1630,9 +1630,8 @@ if (list.length > 0) {
<button id="modal-abort-delete" class="button-neutral pull-right">No</button>
</div>
</div></script><script id="modalCollectionInfo.ejs" type="text/template"><%
var figuresData = content.getFigures();
var revision = content.getRevision();
var index = content.getIndex();
var figuresData = content.figures;
var revision = content.revision;
%>
<ul id="infoTab" class="nav nav-tabs">
@ -1680,7 +1679,7 @@ if (list.length > 0) {
<th class="collectionInfoTh2">ID:</th>
<th class="collectionInfoTh">
<div id="show-collection-id" class="modal-text">
<%=content.get("id")%>
<%=content.model.get("id")%>
</div>
<th>
</tr>
@ -1697,14 +1696,14 @@ if (list.length > 0) {
<tr>
<th class="collectionInfoTh2">Type:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("type")%></div>
<div class="modal-text"><%=content.model.get("type")%></div>
</th>
</tr>
<tr>
<th class="collectionInfoTh2">Status:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("status")%></div>
<div class="modal-text"><%=content.model.get("status")%></div>
</th>
</tr>
@ -2249,7 +2248,7 @@ if (list.length > 0) {
<li id="dbSelect" class="dropdown databases-menu"></li>
<li class="collections-menu"><a id="collections" class="tab" href="#collections">Collections</a></li>
<li class="demo-menu"><a id="demo" class="tab" href="#demo">Demo</a></li>
<li class="graphviewer-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="graph-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="applications-menu">
<a id="applications" class="tab" href="#applications">Services</a>
</li>
@ -2739,4 +2738,4 @@ var cutByResolution = function (str) {
</div>
<div id="workMonitorContent" class="innerContent">
</div></script></head><body><nav class="navbar"><div class="resizecontainer"><div class="navlogo"><a class="logo" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a></div><div id="progressPlaceholderIcon"></div><div class="statmenu" id="statisticBar"></div><div class="usermenu" id="userBar" style="float:right"></div><div class="notificationmenu" id="notificationBar" style="float:right"></div><div class="navmenu" id="navigationBar"></div></div></nav><div class="centralRow resizecontainer"><div id="content" class="centralContent"></div></div><div id="modalPlaceholder"></div><div id="progressPlaceholder" style="display:none"></div><footer class="footer"><div class="resizecontainer" id="footerBar"></div></footer><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="sharedLibs.js?version=1455882035132"></script><script src="libs.js?version=1455882035132"></script><script src="app.js?version=1455882035132"></script></body></html>
</div></script></head><body><nav class="navbar"><div class="resizecontainer"><div class="navlogo"><a class="logo" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a></div><div id="progressPlaceholderIcon"></div><div class="statmenu" id="statisticBar"></div><div class="usermenu" id="userBar" style="float:right"></div><div class="notificationmenu" id="notificationBar" style="float:right"></div><div class="navmenu" id="navigationBar"></div></div></nav><div class="centralRow resizecontainer"><div id="content" class="centralContent"></div></div><div id="modalPlaceholder"></div><div id="progressPlaceholder" style="display:none"></div><footer class="footer"><div class="resizecontainer" id="footerBar"></div></footer><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="sharedLibs.js?version=1455929599138"></script><script src="libs.js?version=1455929599138"></script><script src="app.js?version=1455929599138"></script></body></html>

View File

@ -1760,9 +1760,8 @@ if (list.length > 0) {
<script id="modalCollectionInfo.ejs" type="text/template">
<%
var figuresData = content.getFigures();
var revision = content.getRevision();
var index = content.getIndex();
var figuresData = content.figures;
var revision = content.revision;
%>
<ul id="infoTab" class="nav nav-tabs">
@ -1810,7 +1809,7 @@ if (list.length > 0) {
<th class="collectionInfoTh2">ID:</th>
<th class="collectionInfoTh">
<div id="show-collection-id" class="modal-text">
<%=content.get("id")%>
<%=content.model.get("id")%>
</div>
<th>
</tr>
@ -1827,14 +1826,14 @@ if (list.length > 0) {
<tr>
<th class="collectionInfoTh2">Type:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("type")%></div>
<div class="modal-text"><%=content.model.get("type")%></div>
</th>
</tr>
<tr>
<th class="collectionInfoTh2">Status:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("status")%></div>
<div class="modal-text"><%=content.model.get("status")%></div>
</th>
</tr>
@ -2410,7 +2409,7 @@ if (list.length > 0) {
<li id="dbSelect" class="dropdown databases-menu"></li>
<li class="collections-menu"><a id="collections" class="tab" href="#collections">Collections</a></li>
<li class="demo-menu"><a id="demo" class="tab" href="#demo">Demo</a></li>
<li class="graphviewer-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="graph-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="applications-menu">
<a id="applications" class="tab" href="#applications">Services</a>
</li>
@ -3003,9 +3002,9 @@ var cutByResolution = function (str) {
</div>
</div>
<script src="sharedLibs.js?version=1455882035132"></script>
<script src="libs.js?version=1455882035132"></script>
<script src="app.js?version=1455882035132"></script>
<script src="sharedLibs.js?version=1455929599138"></script>
<script src="libs.js?version=1455929599138"></script>
<script src="app.js?version=1455929599138"></script>
</body>
</html>

View File

@ -1,5 +1,5 @@
/*jshint unused: false */
/*global window, $, document, _ */
/*global window, $, document, arangoHelper, _ */
(function() {
"use strict";
@ -443,16 +443,28 @@
this.arangoDocumentStore = a;
},
collectionApiType: function (identifier, refresh) {
collectionApiType: function (identifier, refresh, toRun) {
// set "refresh" to disable caching collection type
if (refresh || this.CollectionTypes[identifier] === undefined) {
this.CollectionTypes[identifier] = this.arangoDocumentStore
.getCollectionInfo(identifier).type;
var callback = function(error, data, toRun) {
if (error) {
arangoHelper.arangoError("Error", "Could not detect collection type");
}
else {
this.CollectionTypes[identifier] = data.type;
if (this.CollectionTypes[identifier] === 3) {
toRun(false, "edge");
}
else {
toRun(false, "document");
}
}
}.bind(this);
this.arangoDocumentStore.getCollectionInfo(identifier, callback, toRun);
}
if (this.CollectionTypes[identifier] === 3) {
return "edge";
else {
toRun(false, this.CollectionTypes[identifier]);
}
return "document";
},
collectionType: function (val) {

View File

@ -6,56 +6,40 @@ window.arangoDocument = Backbone.Collection.extend({
url: '/_api/document/',
model: arangoDocumentModel,
collectionInfo: {},
deleteEdge: function (colid, docid) {
var returnval = false;
try {
$.ajax({
cache: false,
type: 'DELETE',
async: false,
contentType: "application/json",
url: "/_api/edge/" + colid + "/" + docid,
success: function () {
returnval = true;
},
error: function () {
returnval = false;
}
});
}
catch (e) {
returnval = false;
}
return returnval;
deleteEdge: function (colid, docid, callback) {
$.ajax({
cache: false,
type: 'DELETE',
contentType: "application/json",
url: "/_api/edge/" + colid + "/" + docid,
success: function () {
callback(false);
},
error: function () {
callback(true);
}
});
},
deleteDocument: function (colid, docid){
var returnval = false;
try {
$.ajax({
cache: false,
type: 'DELETE',
async: false,
contentType: "application/json",
url: "/_api/document/" + colid + "/" + docid,
success: function () {
returnval = true;
},
error: function () {
returnval = false;
}
});
}
catch (e) {
returnval = false;
}
return returnval;
deleteDocument: function (colid, docid, callback) {
$.ajax({
cache: false,
type: 'DELETE',
contentType: "application/json",
url: "/_api/document/" + colid + "/" + docid,
success: function () {
callback(false);
},
error: function () {
callback(true);
}
});
},
addDocument: function (collectionID, key) {
var self = this;
self.createTypeDocument(collectionID, key);
},
createTypeEdge: function (collectionID, from, to, key) {
var result = false, newEdge;
createTypeEdge: function (collectionID, from, to, key, callback) {
var newEdge;
if (key) {
newEdge = JSON.stringify({
@ -69,22 +53,20 @@ window.arangoDocument = Backbone.Collection.extend({
$.ajax({
cache: false,
type: "POST",
async: false,
url: "/_api/edge?collection=" + collectionID + "&from=" + from + "&to=" + to,
data: newEdge,
contentType: "application/json",
processData: false,
success: function(data) {
result = data._id;
callback(false, data);
},
error: function(data) {
result = false;
callback(true, data);
}
});
return result;
},
createTypeDocument: function (collectionID, key) {
var result = false, newDocument;
createTypeDocument: function (collectionID, key, callback) {
var newDocument;
if (key) {
newDocument = JSON.stringify({
@ -98,21 +80,19 @@ window.arangoDocument = Backbone.Collection.extend({
$.ajax({
cache: false,
type: "POST",
async: false,
url: "/_api/document?collection=" + encodeURIComponent(collectionID),
data: newDocument,
contentType: "application/json",
processData: false,
success: function(data) {
result = data._id;
callback(false, data._id);
},
error: function(data) {
result = false;
callback(true, data._id);
}
});
return result;
},
getCollectionInfo: function (identifier) {
getCollectionInfo: function (identifier, callback, toRun) {
var self = this;
$.ajax({
@ -121,94 +101,82 @@ window.arangoDocument = Backbone.Collection.extend({
url: "/_api/collection/" + identifier + "?" + arangoHelper.getRandomToken(),
contentType: "application/json",
processData: false,
async: false,
success: function(data) {
self.collectionInfo = data;
callback(false, data, toRun);
},
error: function(data) {
callback(true, data, toRun);
}
});
return self.collectionInfo;
},
getEdge: function (colid, docid){
var result = false, self = this;
getEdge: function (colid, docid, callback){
var self = this;
this.clearDocument();
$.ajax({
cache: false,
type: "GET",
async: false,
url: "/_api/edge/" + colid +"/"+ docid,
contentType: "application/json",
processData: false,
success: function(data) {
self.add(data);
result = true;
callback(false, data, 'edge');
},
error: function(data) {
result = false;
callback(true, data);
}
});
return result;
},
getDocument: function (colid, docid) {
var result = false, self = this;
getDocument: function (colid, docid, callback) {
var self = this;
this.clearDocument();
$.ajax({
cache: false,
type: "GET",
async: false,
url: "/_api/document/" + colid +"/"+ docid,
contentType: "application/json",
processData: false,
success: function(data) {
self.add(data);
result = true;
callback(false, data, 'document');
},
error: function(data) {
result = false;
self.add(true, data);
}
});
return result;
},
saveEdge: function (colid, docid, model) {
var result = false;
saveEdge: function (colid, docid, model, callback) {
$.ajax({
cache: false,
type: "PUT",
async: false,
url: "/_api/edge/" + colid + "/" + docid,
data: model,
contentType: "application/json",
processData: false,
success: function(data) {
result = true;
callback(false, data);
},
error: function(data) {
result = false;
callback(true, data);
}
});
return result;
},
saveDocument: function (colid, docid, model) {
var result = false;
saveDocument: function (colid, docid, model, callback) {
$.ajax({
cache: false,
type: "PUT",
async: false,
url: "/_api/document/" + colid + "/" + docid,
data: model,
contentType: "application/json",
processData: false,
success: function(data) {
result = true;
callback(false, data);
},
error: function(data) {
result = false;
callback(true, data);
}
});
return result;
},
updateLocalDocument: function (data) {

View File

@ -44,12 +44,11 @@
return toReturn;
},
saveCollectionQueries: function() {
saveCollectionQueries: function(callback) {
if (this.activeUser === 0) {
return false;
}
var returnValue = false;
var queries = [];
this.each(function(query) {
@ -64,7 +63,6 @@
$.ajax({
cache: false,
type: "PATCH",
async: false,
url: "/_api/user/" + encodeURIComponent(this.activeUser),
data: JSON.stringify({
extra: {
@ -73,15 +71,13 @@
}),
contentType: "application/json",
processData: false,
success: function() {
returnValue = true;
success: function(data) {
callback(false, data);
},
error: function() {
returnValue = false;
callback(true);
}
});
return returnValue;
},
saveImportQueries: function(file, callback) {
@ -94,7 +90,6 @@
$.ajax({
cache: false,
type: "POST",
async: false,
url: "query/upload/" + encodeURIComponent(this.activeUser),
data: file,
contentType: "application/json",

View File

@ -31,23 +31,27 @@ window.ArangoUsers = Backbone.Collection.extend({
return a > b ? 1 : a < b ? -1 : 0;
},
login: function (username, password) {
var result = null;
login: function (username, password, callback) {
var self = this;
$.ajax("login", {
async: false,
method: "POST",
data: JSON.stringify({
username: username,
password: password
}),
dataType: "json"
}).done(
}).success(
function (data) {
result = data.user;
self.activeUser = data.user;
callback(false, self.activeUser);
}
).error(
function () {
self.activeUser = null;
callback(true, null);
}
);
this.activeUser = result;
return this.activeUser;
},
setSortingDesc: function(yesno) {
@ -55,7 +59,7 @@ window.ArangoUsers = Backbone.Collection.extend({
},
logout: function () {
$.ajax("logout", {async:false,method:"POST"});
$.ajax("logout", {method:"POST"});
this.activeUser = null;
this.reset();
window.App.navigate("");
@ -108,18 +112,21 @@ window.ArangoUsers = Backbone.Collection.extend({
return result;
},
whoAmI: function() {
whoAmI: function(callback) {
if (this.activeUser) {
return this.activeUser;
callback(false, this.activeUser);
return;
}
var result;
$.ajax("whoAmI?_=" + Date.now(), {async:false}).done(
$.ajax("whoAmI?_=" + Date.now())
.success(
function(data) {
result = data.user;
callback(false, data.user);
}
).error(
function(data) {
callback(true, null);
}
);
this.activeUser = result;
return this.activeUser;
}

View File

@ -19,22 +19,11 @@
url: "/_api/gharial/" + encodeURIComponent(name) + "?dropCollections=true",
contentType: "application/json",
processData: true,
async: false,
success: function() {
arangoHelper.arangoNotification("Graph deleted.");
callback(true);
return true;
},
error: function(data) {
try {
var errorMsg = JSON.parse(data.responseText).errorMessage;
arangoHelper.arangoError("Graph", errorMsg);
}
catch (e) {
arangoHelper.arangoError("Graph", "Could not delete Graph.");
}
error: function() {
callback(false);
return false;
}
});
},

View File

@ -17,59 +17,50 @@
desc: undefined
},
getProperties: function () {
var data2;
getProperties: function (callback) {
$.ajax({
type: "GET",
cache: false,
url: "/_api/collection/" + encodeURIComponent(this.get("id")) + "/properties",
contentType: "application/json",
processData: false,
async: false,
success: function(data) {
data2 = data;
callback(false, data);
},
error: function(data) {
data2 = data;
callback(true, data);
}
});
return data2;
},
getFigures: function () {
var data2;
getFigures: function (callback) {
$.ajax({
type: "GET",
cache: false,
url: "/_api/collection/" + this.get("id") + "/figures",
contentType: "application/json",
processData: false,
async: false,
success: function(data) {
data2 = data;
callback(false, data);
},
error: function(data) {
data2 = data;
error: function() {
callback(true);
}
});
return data2;
},
getRevision: function () {
var data2;
getRevision: function (callback, figures) {
$.ajax({
type: "GET",
cache: false,
url: "/_api/collection/" + this.get("id") + "/revision",
contentType: "application/json",
processData: false,
async: false,
success: function(data) {
data2 = data;
callback(false, data, figures);
},
error: function(data) {
data2 = data;
error: function() {
callback(true);
}
});
return data2;
},
getIndex: function (callback) {

View File

@ -28,29 +28,27 @@ window.Users = Backbone.Model.extend({
return "/_api/user";
},
checkPassword: function(passwd) {
var result = false;
checkPassword: function(passwd, callback) {
$.ajax({
cache: false,
type: "POST",
async: false, // sequential calls!
url: "/_api/user/" + this.get("user"),
data: JSON.stringify({ passwd: passwd }),
contentType: "application/json",
processData: false,
success: function(data) {
result = data.result;
callback(false, data);
},
error: function(data) {
callback(true, data);
}
});
return result;
},
setPassword: function(passwd) {
$.ajax({
cache: false,
type: "PATCH",
async: false, // sequential calls!
url: "/_api/user/" + this.get("user"),
data: JSON.stringify({ passwd: passwd }),
contentType: "application/json",
@ -58,15 +56,20 @@ window.Users = Backbone.Model.extend({
});
},
setExtras: function(name, img) {
setExtras: function(name, img, callback) {
$.ajax({
cache: false,
type: "PATCH",
async: false, // sequential calls!
url: "/_api/user/" + this.get("user"),
data: JSON.stringify({"extra": {"name":name, "img":img}}),
contentType: "application/json",
processData: false
processData: false,
success: function() {
callback(false);
},
error: function() {
callback(true);
}
});
}

View File

@ -29,6 +29,47 @@
"test": "test"
},
checkUser: function () {
var callback = function(error) {
if (error) {
this.navigate("login", {trigger: true});
}
else {
this.initOnce();
}
}.bind(this);
this.userCollection.whoAmI(callback);
},
waitForInit: function(origin, param1, param2) {
if (!this.initFinished) {
setTimeout(function() {
if (!param1) {
origin(false);
}
if (param1 && !param2) {
origin(param1, false);
}
if (param1 && param2) {
origin(param1, param2, false);
}
}, 100);
} else {
if (!param1) {
origin(true);
}
if (param1 && !param2) {
origin(param1, true);
}
if (param1 && param2) {
origin(param1, param2, true);
}
}
},
initFinished: false,
initialize: function () {
// This should be the only global object
window.modalView = new window.ModalView();
@ -44,31 +85,34 @@
this.initOnce = function () {
this.initOnce = function() {};
this.initFinished = true;
this.arangoDatabase = new window.ArangoDatabase();
this.currentDB = new window.CurrentDatabase();
this.currentDB.fetch({
async: false
});
this.arangoCollectionsStore = new window.arangoCollections();
this.arangoDocumentStore = new window.arangoDocument();
arangoHelper.setDocumentStore(this.arangoDocumentStore);
this.arangoCollectionsStore.fetch({async: false});
this.arangoCollectionsStore.fetch();
this.footerView = new window.FooterView();
this.notificationList = new window.NotificationCollection();
this.naviView = new window.NavigationView({
database: this.arangoDatabase,
currentDB: this.currentDB,
notificationCollection: self.notificationList,
userCollection: this.userCollection
this.currentDB.fetch({
success: function() {
self.naviView = new window.NavigationView({
database: self.arangoDatabase,
currentDB: self.currentDB,
notificationCollection: self.notificationList,
userCollection: self.userCollection
});
self.naviView.render();
}
});
this.queryCollection = new window.ArangoQueries();
this.footerView.render();
this.naviView.render();
window.checkVersion();
}.bind(this);
@ -80,17 +124,10 @@
},
checkUser: function () {
if (this.userCollection.whoAmI() === null) {
this.navigate("login", {trigger: true});
return false;
}
this.initOnce();
return true;
},
logs: function () {
if (!this.checkUser()) {
logs: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.logs.bind(this));
return;
}
if (!this.logsView) {
@ -118,46 +155,61 @@
});
}
this.logsView.render();
this.naviView.selectMenuItem('tools-menu');
},
applicationDetail: function (mount) {
if (!this.checkUser()) {
applicationDetail: function (mount, initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.applicationDetail.bind(this), mount);
return;
}
this.naviView.selectMenuItem('applications-menu');
var callback = function() {
if (!this.hasOwnProperty('applicationDetailView')) {
this.applicationDetailView = new window.ApplicationDetailView({
model: this.foxxList.get(decodeURIComponent(mount))
});
}
this.applicationDetailView.model = this.foxxList.get(decodeURIComponent(mount));
this.applicationDetailView.render('swagger');
}.bind(this);
if (this.foxxList.length === 0) {
this.foxxList.fetch({ async: false });
}
if (!this.hasOwnProperty('applicationDetailView')) {
this.applicationDetailView = new window.ApplicationDetailView({
model: this.foxxList.get(decodeURIComponent(mount))
this.foxxList.fetch({
success: function() {
callback();
}
});
}
this.applicationDetailView.model = this.foxxList.get(decodeURIComponent(mount));
this.applicationDetailView.render('swagger');
else {
callback();
}
},
login: function () {
if (this.userCollection.whoAmI() !== null) {
this.navigate("", {trigger: true});
return false;
}
if (!this.loginView) {
this.loginView = new window.loginView({
collection: this.userCollection
});
}
this.loginView.render();
login: function (initialized) {
var callback = function(error) {
if (error) {
if (!this.loginView) {
this.loginView = new window.loginView({
collection: this.userCollection
});
}
this.loginView.render();
}
else {
this.navigate("", {trigger: true});
}
}.bind(this);
this.userCollection.whoAmI(callback);
},
collections: function () {
if (!this.checkUser()) {
collections: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.collections.bind(this));
return;
}
var naviView = this.naviView, self = this;
var self = this;
if (!this.collectionsView) {
this.collectionsView = new window.CollectionsView({
collection: this.arangoCollectionsStore
@ -166,13 +218,14 @@
this.arangoCollectionsStore.fetch({
success: function () {
self.collectionsView.render();
naviView.selectMenuItem('collections-menu');
}
});
},
documents: function (colid, pageid) {
if (!this.checkUser()) {
documents: function (colid, pageid, initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.documents.bind(this), colid, pageid);
return;
}
if (!this.documentsView) {
@ -187,8 +240,10 @@
},
document: function (colid, docid) {
if (!this.checkUser()) {
document: function (colid, docid, initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.document.bind(this), colid, docid);
return;
}
if (!this.documentView) {
@ -199,23 +254,35 @@
this.documentView.colid = colid;
this.documentView.docid = docid;
this.documentView.render();
var type = arangoHelper.collectionApiType(colid);
this.documentView.setType(type);
var callback = function(error, type) {
if (!error) {
this.documentView.setType(type);
}
else {
console.log("Error", "Could not fetch collection type");
}
}.bind(this);
arangoHelper.collectionApiType(colid, null, callback);
},
shell: function () {
if (!this.checkUser()) {
shell: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.shell.bind(this));
return;
}
if (!this.shellView) {
this.shellView = new window.shellView();
}
this.shellView.render();
this.naviView.selectMenuItem('tools-menu');
},
query: function () {
if (!this.checkUser()) {
query: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.query.bind(this));
return;
}
if (!this.queryView) {
@ -224,11 +291,12 @@
});
}
this.queryView.render();
this.naviView.selectMenuItem('query-menu');
},
test: function () {
if (!this.checkUser()) {
test: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.test.bind(this));
return;
}
if (!this.testView) {
@ -238,8 +306,10 @@
this.testView.render();
},
workMonitor: function () {
if (!this.checkUser()) {
workMonitor: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.workMonitor.bind(this));
return;
}
if (!this.workMonitorCollection) {
@ -251,11 +321,12 @@
});
}
this.workMonitorView.render();
this.naviView.selectMenuItem('tools-menu');
},
queryManagement: function () {
if (!this.checkUser()) {
queryManagement: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.queryManagement.bind(this));
return;
}
if (!this.queryManagementView) {
@ -264,11 +335,12 @@
});
}
this.queryManagementView.render();
this.naviView.selectMenuItem('tools-menu');
},
databases: function () {
if (!this.checkUser()) {
databases: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.databases.bind(this));
return;
}
if (arangoHelper.databaseAllowed() === true) {
@ -279,20 +351,21 @@
});
}
this.databaseView.render();
this.naviView.selectMenuItem('databases-menu');
} else {
this.navigate("#", {trigger: true});
this.naviView.selectMenuItem('dashboard-menu');
$('#databaseNavi').css('display', 'none');
$('#databaseNaviSelect').css('display', 'none');
}
},
dashboard: function () {
if (!this.checkUser()) {
dashboard: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.dashboard.bind(this));
return;
}
this.naviView.selectMenuItem('dashboard-menu');
if (this.dashboardView === undefined) {
this.dashboardView = new window.DashboardView({
dygraphConfig: window.dygraphConfig,
@ -302,8 +375,10 @@
this.dashboardView.render();
},
graphManagement: function () {
if (!this.checkUser()) {
graphManagement: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.graphManagement.bind(this));
return;
}
if (!this.graphManagementView) {
@ -316,11 +391,12 @@
);
}
this.graphManagementView.render();
this.naviView.selectMenuItem('graphviewer-menu');
},
showGraph: function (name) {
if (!this.checkUser()) {
showGraph: function (name, initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.showGraph.bind(this), name);
return;
}
if (!this.graphManagementView) {
@ -334,11 +410,12 @@
}
this.graphManagementView.render();
this.graphManagementView.loadGraphViewer(name);
this.naviView.selectMenuItem('graphviewer-menu');
},
applications: function () {
if (!this.checkUser()) {
applications: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.applications.bind(this));
return;
}
if (this.applicationsView === undefined) {
@ -347,11 +424,12 @@
});
}
this.applicationsView.reload();
this.naviView.selectMenuItem('applications-menu');
},
handleSelectDatabase: function () {
if (!this.checkUser()) {
handleSelectDatabase: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.handleSelectDatabase.bind(this));
return;
}
this.naviView.handleSelectDatabase();
@ -369,8 +447,10 @@
}
},
userManagement: function () {
if (!this.checkUser()) {
userManagement: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.userManagement.bind(this));
return;
}
if (!this.userManagementView) {
@ -379,11 +459,12 @@
});
}
this.userManagementView.render();
this.naviView.selectMenuItem('tools-menu');
},
userProfile: function () {
if (!this.checkUser()) {
userProfile: function (initialized) {
this.checkUser();
if (!initialized) {
this.waitForInit(this.userProfile.bind(this));
return;
}
if (!this.userManagementView) {
@ -392,7 +473,6 @@
});
}
this.userManagementView.render(true);
this.naviView.selectMenuItem('tools-menu');
}
});

View File

@ -1,8 +1,7 @@
<script id="modalCollectionInfo.ejs" type="text/template">
<%
var figuresData = content.getFigures();
var revision = content.getRevision();
var index = content.getIndex();
var figuresData = content.figures;
var revision = content.revision;
%>
<ul id="infoTab" class="nav nav-tabs">
@ -50,7 +49,7 @@
<th class="collectionInfoTh2">ID:</th>
<th class="collectionInfoTh">
<div id="show-collection-id" class="modal-text">
<%=content.get("id")%>
<%=content.model.get("id")%>
</div>
<th>
</tr>
@ -67,14 +66,14 @@
<tr>
<th class="collectionInfoTh2">Type:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("type")%></div>
<div class="modal-text"><%=content.model.get("type")%></div>
</th>
</tr>
<tr>
<th class="collectionInfoTh2">Status:</th>
<th class="collectionInfoTh">
<div class="modal-text"><%=content.get("status")%></div>
<div class="modal-text"><%=content.model.get("status")%></div>
</th>
</tr>

View File

@ -3,7 +3,7 @@
<li id="dbSelect" class="dropdown databases-menu"></li>
<li class="collections-menu"><a id="collections" class="tab" href="#collections">Collections</a></li>
<li class="demo-menu"><a id="demo" class="tab" href="#demo">Demo</a></li>
<li class="graphviewer-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="graph-menu"><a id="graph" class="tab" href="#graph">Graphs</a></li>
<li class="applications-menu">
<a id="applications" class="tab" href="#applications">Services</a>
</li>

View File

@ -270,319 +270,350 @@
}
if (collectionIsLoaded) {
// needs to be refactored. move getProperties into model
var journalSize = this.model.getProperties().journalSize;
journalSize = journalSize/(1024*1024);
tableContent.push(
window.modalView.createTextEntry(
"change-collection-size",
"Journal size",
journalSize,
"The maximal size of a journal or datafile (in MB). Must be at least 1.",
"",
true,
[
{
rule: Joi.string().allow('').optional().regex(/^[0-9]*$/),
msg: "Must be a number."
}
]
)
);
var indexBuckets = this.model.getProperties().indexBuckets;
tableContent.push(
window.modalView.createTextEntry(
"change-index-buckets",
"Index buckets",
indexBuckets,
"The number of index buckets for this collection. Must be at least 1 and a power of 2.",
"",
true,
[
{
rule: Joi.string().allow('').optional().regex(/^[1-9][0-9]*$/),
msg: "Must be a number greater than 1 and a power of 2."
}
]
)
);
// prevent "unexpected sync method error"
var wfs = this.model.getProperties().waitForSync;
tableContent.push(
window.modalView.createSelectEntry(
"change-collection-sync",
"Wait for sync",
wfs,
"Synchronize to disk before returning from a create or update of a document.",
[{value: false, label: "No"}, {value: true, label: "Yes"}] )
);
}
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-id", "ID", this.model.get('id'), ""
)
);
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-type", "Type", this.model.get('type'), ""
)
);
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-status", "Status", this.model.get('status'), ""
)
);
buttons.push(
window.modalView.createDeleteButton(
"Delete",
this.deleteCollection.bind(this)
)
);
buttons.push(
window.modalView.createDeleteButton(
"Truncate",
this.truncateCollection.bind(this)
)
);
if (collectionIsLoaded) {
buttons.push(
window.modalView.createNotificationButton(
"Unload",
this.unloadCollection.bind(this)
)
);
} else {
buttons.push(
window.modalView.createNotificationButton(
"Load",
this.loadCollection.bind(this)
)
);
}
buttons.push(
window.modalView.createSuccessButton(
"Save",
this.saveModifiedCollection.bind(this)
)
);
var tabBar = ["General", "Indices"],
templates = ["modalTable.ejs", "indicesView.ejs"];
window.modalView.show(
templates,
"Modify Collection",
buttons,
tableContent, null, null,
this.events, null,
tabBar
);
if (this.model.get("status") === 'loaded') {
this.getIndex();
}
else {
$($('#infoTab').children()[1]).remove();
}
},
bindIndexEvents: function() {
this.unbindIndexEvents();
var self = this;
$('#indexEditView #addIndex').bind('click', function() {
self.toggleNewIndexView();
$('#cancelIndex').unbind('click');
$('#cancelIndex').bind('click', function() {
self.toggleNewIndexView();
});
$('#createIndex').unbind('click');
$('#createIndex').bind('click', function() {
self.createIndex();
});
});
$('#newIndexType').bind('change', function() {
self.selectIndexType();
});
$('.deleteIndex').bind('click', function(e) {
console.log("asdasd");
self.prepDeleteIndex(e);
});
$('#infoTab a').bind('click', function(e) {
$('#indexDeleteModal').remove();
if ($(e.currentTarget).html() === 'Indices' && !$(e.currentTarget).parent().hasClass('active')) {
$('#newIndexView').hide();
$('#indexEditView').show();
$('#modal-dialog .modal-footer .button-danger').hide();
$('#modal-dialog .modal-footer .button-success').hide();
$('#modal-dialog .modal-footer .button-notification').hide();
//$('#addIndex').detach().appendTo('#modal-dialog .modal-footer');
}
if ($(e.currentTarget).html() === 'General' && !$(e.currentTarget).parent().hasClass('active')) {
$('#modal-dialog .modal-footer .button-danger').show();
$('#modal-dialog .modal-footer .button-success').show();
$('#modal-dialog .modal-footer .button-notification').show();
var elem = $('.index-button-bar')[0];
var elem2 = $('.index-button-bar2')[0];
//$('#addIndex').detach().appendTo(elem);
if ($('#cancelIndex').is(':visible')) {
$('#cancelIndex').detach().appendTo(elem2);
$('#createIndex').detach().appendTo(elem2);
}
}
});
},
unbindIndexEvents: function() {
$('#indexEditView #addIndex').unbind('click');
$('#newIndexType').unbind('change');
$('#infoTab a').unbind('click');
$('.deleteIndex').unbind('click');
/*
//$('#documentsToolbar ul').unbind('click');
this.markFilterToggle();
this.changeEditMode(false);
0Ads0asd0sd0f0asdf0sa0f
"click #documentsToolbar ul" : "resetIndexForms"
*/
},
createInfoModal: function() {
var buttons = [],
tableContent = this.model;
window.modalView.show(
"modalCollectionInfo.ejs",
"Collection: " + this.model.get('name'),
buttons,
tableContent
);
},
//index functions
resetIndexForms: function () {
$('#indexHeader input').val('').prop("checked", false);
$('#newIndexType').val('Cap').prop('selected',true);
this.selectIndexType();
},
createIndex: function () {
//e.preventDefault();
var self = this;
var indexType = $('#newIndexType').val();
var result;
var postParameter = {};
var fields;
var unique;
var sparse;
switch (indexType) {
case 'Cap':
var size = parseInt($('#newCapSize').val(), 10) || 0;
var byteSize = parseInt($('#newCapByteSize').val(), 10) || 0;
postParameter = {
type: 'cap',
size: size,
byteSize: byteSize
};
break;
case 'Geo':
//HANDLE ARRAY building
fields = $('#newGeoFields').val();
var geoJson = self.checkboxToValue('#newGeoJson');
var constraint = self.checkboxToValue('#newGeoConstraint');
var ignoreNull = self.checkboxToValue('#newGeoIgnoreNull');
postParameter = {
type: 'geo',
fields: self.stringToArray(fields),
geoJson: geoJson,
constraint: constraint,
ignoreNull: ignoreNull
};
break;
case 'Hash':
fields = $('#newHashFields').val();
unique = self.checkboxToValue('#newHashUnique');
sparse = self.checkboxToValue('#newHashSparse');
postParameter = {
type: 'hash',
fields: self.stringToArray(fields),
unique: unique,
sparse: sparse
};
break;
case 'Fulltext':
fields = ($('#newFulltextFields').val());
var minLength = parseInt($('#newFulltextMinLength').val(), 10) || 0;
postParameter = {
type: 'fulltext',
fields: self.stringToArray(fields),
minLength: minLength
};
break;
case 'Skiplist':
fields = $('#newSkiplistFields').val();
unique = self.checkboxToValue('#newSkiplistUnique');
sparse = self.checkboxToValue('#newSkiplistSparse');
postParameter = {
type: 'skiplist',
fields: self.stringToArray(fields),
unique: unique,
sparse: sparse
};
break;
}
var callback = function(error, msg){
if (error) {
if (msg) {
var message = JSON.parse(msg.responseText);
arangoHelper.arangoError("Document error", message.errorMessage);
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError("Collection", "Could not fetch properties");
}
else {
arangoHelper.arangoError("Document error", "Could not create index.");
var journalSize = data.journalSize/(1024*1024);
var indexBuckets = data.indexBuckets;
var wfs = data.waitForSync;
tableContent.push(
window.modalView.createTextEntry(
"change-collection-size",
"Journal size",
journalSize,
"The maximal size of a journal or datafile (in MB). Must be at least 1.",
"",
true,
[
{
rule: Joi.string().allow('').optional().regex(/^[0-9]*$/),
msg: "Must be a number."
}
]
)
);
tableContent.push(
window.modalView.createTextEntry(
"change-index-buckets",
"Index buckets",
indexBuckets,
"The number of index buckets for this collection. Must be at least 1 and a power of 2.",
"",
true,
[
{
rule: Joi.string().allow('').optional().regex(/^[1-9][0-9]*$/),
msg: "Must be a number greater than 1 and a power of 2."
}
]
)
);
// prevent "unexpected sync method error"
tableContent.push(
window.modalView.createSelectEntry(
"change-collection-sync",
"Wait for sync",
wfs,
"Synchronize to disk before returning from a create or update of a document.",
[{value: false, label: "No"}, {value: true, label: "Yes"}] )
);
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-id", "ID", this.model.get('id'), ""
)
);
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-type", "Type", this.model.get('type'), ""
)
);
tableContent.push(
window.modalView.createReadOnlyEntry(
"change-collection-status", "Status", this.model.get('status'), ""
)
);
buttons.push(
window.modalView.createDeleteButton(
"Delete",
this.deleteCollection.bind(this)
)
);
buttons.push(
window.modalView.createDeleteButton(
"Truncate",
this.truncateCollection.bind(this)
)
);
if (collectionIsLoaded) {
buttons.push(
window.modalView.createNotificationButton(
"Unload",
this.unloadCollection.bind(this)
)
);
} else {
buttons.push(
window.modalView.createNotificationButton(
"Load",
this.loadCollection.bind(this)
)
);
}
buttons.push(
window.modalView.createSuccessButton(
"Save",
this.saveModifiedCollection.bind(this)
)
);
var tabBar = ["General", "Indices"],
templates = ["modalTable.ejs", "indicesView.ejs"];
window.modalView.show(
templates,
"Modify Collection",
buttons,
tableContent, null, null,
this.events, null,
tabBar
);
if (this.model.get("status") === 'loaded') {
this.getIndex();
}
else {
$($('#infoTab').children()[1]).remove();
}
}
self.refreshCollectionsView();
}.bind(this);
this.model.getProperties(callback);
}
},
bindIndexEvents: function() {
this.unbindIndexEvents();
var self = this;
$('#indexEditView #addIndex').bind('click', function() {
self.toggleNewIndexView();
$('#cancelIndex').unbind('click');
$('#cancelIndex').bind('click', function() {
self.toggleNewIndexView();
});
$('#createIndex').unbind('click');
$('#createIndex').bind('click', function() {
self.createIndex();
});
});
$('#newIndexType').bind('change', function() {
self.selectIndexType();
});
$('.deleteIndex').bind('click', function(e) {
console.log("asdasd");
self.prepDeleteIndex(e);
});
$('#infoTab a').bind('click', function(e) {
$('#indexDeleteModal').remove();
if ($(e.currentTarget).html() === 'Indices' && !$(e.currentTarget).parent().hasClass('active')) {
$('#newIndexView').hide();
$('#indexEditView').show();
$('#modal-dialog .modal-footer .button-danger').hide();
$('#modal-dialog .modal-footer .button-success').hide();
$('#modal-dialog .modal-footer .button-notification').hide();
//$('#addIndex').detach().appendTo('#modal-dialog .modal-footer');
}
if ($(e.currentTarget).html() === 'General' && !$(e.currentTarget).parent().hasClass('active')) {
$('#modal-dialog .modal-footer .button-danger').show();
$('#modal-dialog .modal-footer .button-success').show();
$('#modal-dialog .modal-footer .button-notification').show();
var elem = $('.index-button-bar')[0];
var elem2 = $('.index-button-bar2')[0];
//$('#addIndex').detach().appendTo(elem);
if ($('#cancelIndex').is(':visible')) {
$('#cancelIndex').detach().appendTo(elem2);
$('#createIndex').detach().appendTo(elem2);
}
}
});
},
unbindIndexEvents: function() {
$('#indexEditView #addIndex').unbind('click');
$('#newIndexType').unbind('change');
$('#infoTab a').unbind('click');
$('.deleteIndex').unbind('click');
/*
//$('#documentsToolbar ul').unbind('click');
this.markFilterToggle();
this.changeEditMode(false);
0Ads0asd0sd0f0asdf0sa0f
"click #documentsToolbar ul" : "resetIndexForms"
*/
},
createInfoModal: function() {
var callbackRev = function(error, revision, figures) {
if (error) {
arangoHelper.arangoError("Figures", "Could not get revision.");
}
else {
var buttons = [];
var tableContent = {
figures: figures,
revision: revision,
model: this.model
};
window.modalView.show(
"modalCollectionInfo.ejs",
"Collection: " + this.model.get('name'),
buttons,
tableContent
);
}
}.bind(this);
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError("Figures", "Could not get figures.");
}
else {
var figures = data;
this.model.getRevision(callbackRev, figures);
}
}.bind(this);
this.model.getFigures(callback);
},
//index functions
resetIndexForms: function () {
$('#indexHeader input').val('').prop("checked", false);
$('#newIndexType').val('Cap').prop('selected',true);
this.selectIndexType();
},
createIndex: function () {
//e.preventDefault();
var self = this;
var indexType = $('#newIndexType').val();
var postParameter = {};
var fields;
var unique;
var sparse;
switch (indexType) {
case 'Cap':
var size = parseInt($('#newCapSize').val(), 10) || 0;
var byteSize = parseInt($('#newCapByteSize').val(), 10) || 0;
postParameter = {
type: 'cap',
size: size,
byteSize: byteSize
};
break;
case 'Geo':
//HANDLE ARRAY building
fields = $('#newGeoFields').val();
var geoJson = self.checkboxToValue('#newGeoJson');
var constraint = self.checkboxToValue('#newGeoConstraint');
var ignoreNull = self.checkboxToValue('#newGeoIgnoreNull');
postParameter = {
type: 'geo',
fields: self.stringToArray(fields),
geoJson: geoJson,
constraint: constraint,
ignoreNull: ignoreNull
};
break;
case 'Hash':
fields = $('#newHashFields').val();
unique = self.checkboxToValue('#newHashUnique');
sparse = self.checkboxToValue('#newHashSparse');
postParameter = {
type: 'hash',
fields: self.stringToArray(fields),
unique: unique,
sparse: sparse
};
break;
case 'Fulltext':
fields = ($('#newFulltextFields').val());
var minLength = parseInt($('#newFulltextMinLength').val(), 10) || 0;
postParameter = {
type: 'fulltext',
fields: self.stringToArray(fields),
minLength: minLength
};
break;
case 'Skiplist':
fields = $('#newSkiplistFields').val();
unique = self.checkboxToValue('#newSkiplistUnique');
sparse = self.checkboxToValue('#newSkiplistSparse');
postParameter = {
type: 'skiplist',
fields: self.stringToArray(fields),
unique: unique,
sparse: sparse
};
break;
}
var callback = function(error, msg){
if (error) {
if (msg) {
var message = JSON.parse(msg.responseText);
arangoHelper.arangoError("Document error", message.errorMessage);
}
else {
arangoHelper.arangoError("Document error", "Could not create index.");
}
}
self.refreshCollectionsView();
};
window.modalView.hide();
//$($('#infoTab').children()[1]).find('a').click();
self.model.createIndex(postParameter, callback);
},
window.modalView.hide();
//$($('#infoTab').children()[1]).find('a').click();
self.model.createIndex(postParameter, callback);
},
lastTarget: null,
lastTarget: null,
prepDeleteIndex: function (e) {
var self = this;
this.lastTarget = e;
prepDeleteIndex: function (e) {
var self = this;
this.lastTarget = e;
this.lastId = $(this.lastTarget.currentTarget).
parent().
parent().
first().
children().
first().
text();
//window.modalView.hide();
this.lastId = $(this.lastTarget.currentTarget).
parent().
parent().
first().
children().
first().
text();
//window.modalView.hide();
//delete modal
$("#modal-dialog .modal-footer").after(
'<div id="indexDeleteModal" style="display:block;" class="alert alert-error modal-delete-confirmation">' +
'<strong>Really delete?</strong>' +
'<button id="indexConfirmDelete" class="button-danger pull-right modal-confirm-delete">Yes</button>' +
'<button id="indexAbortDelete" class="button-neutral pull-right">No</button>' +
//delete modal
$("#modal-dialog .modal-footer").after(
'<div id="indexDeleteModal" style="display:block;" class="alert alert-error modal-delete-confirmation">' +
'<strong>Really delete?</strong>' +
'<button id="indexConfirmDelete" class="button-danger pull-right modal-confirm-delete">Yes</button>' +
'<button id="indexAbortDelete" class="button-neutral pull-right">No</button>' +
'</div>');
$('#indexConfirmDelete').unbind('click');
$('#indexConfirmDelete').bind('click', function() {
@ -596,98 +627,98 @@
});
},
},
refreshCollectionsView: function() {
window.App.arangoCollectionsStore.fetch({
success: function () {
window.App.collectionsView.render();
}
});
},
refreshCollectionsView: function() {
window.App.arangoCollectionsStore.fetch({
success: function () {
window.App.collectionsView.render();
}
});
},
deleteIndex: function () {
var callback = function(error) {
if (error) {
arangoHelper.arangoError("Could not delete index");
$("tr th:contains('"+ this.lastId+"')").parent().children().last().html(
'<span class="deleteIndex icon_arangodb_roundminus"' +
deleteIndex: function () {
var callback = function(error) {
if (error) {
arangoHelper.arangoError("Could not delete index");
$("tr th:contains('"+ this.lastId+"')").parent().children().last().html(
'<span class="deleteIndex icon_arangodb_roundminus"' +
' data-original-title="Delete index" title="Delete index"></span>'
);
this.model.set("locked", false);
this.refreshCollectionsView();
}
else if (!error && error !== undefined) {
$("tr th:contains('"+ this.lastId+"')").parent().remove();
this.model.set("locked", false);
this.refreshCollectionsView();
}
);
this.model.set("locked", false);
this.refreshCollectionsView();
}.bind(this);
}
else if (!error && error !== undefined) {
$("tr th:contains('"+ this.lastId+"')").parent().remove();
this.model.set("locked", false);
this.refreshCollectionsView();
}
this.refreshCollectionsView();
}.bind(this);
this.model.set("locked", true);
this.model.deleteIndex(this.lastId, callback);
this.model.set("locked", true);
this.model.deleteIndex(this.lastId, callback);
$("tr th:contains('"+ this.lastId+"')").parent().children().last().html(
'<i class="fa fa-circle-o-notch fa-spin"></i>'
);
},
$("tr th:contains('"+ this.lastId+"')").parent().children().last().html(
'<i class="fa fa-circle-o-notch fa-spin"></i>'
);
},
selectIndexType: function () {
$('.newIndexClass').hide();
var type = $('#newIndexType').val();
$('#newIndexType'+type).show();
},
selectIndexType: function () {
$('.newIndexClass').hide();
var type = $('#newIndexType').val();
$('#newIndexType'+type).show();
},
getIndex: function () {
getIndex: function () {
var callback = function(error, data) {
if (error) {
window.arangoHelper.arangoError('Index', data.errorMessage);
var callback = function(error, data) {
if (error) {
window.arangoHelper.arangoError('Index', data.errorMessage);
}
else {
this.renderIndex(data);
}
}.bind(this);
this.model.getIndex(callback);
},
renderIndex: function(data) {
this.index = data;
var cssClass = 'collectionInfoTh modal-text';
if (this.index) {
var fieldString = '';
var actionString = '';
_.each(this.index.indexes, function(v) {
if (v.type === 'primary' || v.type === 'edge') {
actionString = '<span class="icon_arangodb_locked" ' +
'data-original-title="No action"></span>';
}
else {
this.renderIndex(data);
actionString = '<span class="deleteIndex icon_arangodb_roundminus" ' +
'data-original-title="Delete index" title="Delete index"></span>';
}
}.bind(this);
this.model.getIndex(callback);
},
if (v.fields !== undefined) {
fieldString = v.fields.join(", ");
}
renderIndex: function(data) {
this.index = data;
var cssClass = 'collectionInfoTh modal-text';
if (this.index) {
var fieldString = '';
var actionString = '';
_.each(this.index.indexes, function(v) {
if (v.type === 'primary' || v.type === 'edge') {
actionString = '<span class="icon_arangodb_locked" ' +
'data-original-title="No action"></span>';
}
else {
actionString = '<span class="deleteIndex icon_arangodb_roundminus" ' +
'data-original-title="Delete index" title="Delete index"></span>';
}
if (v.fields !== undefined) {
fieldString = v.fields.join(", ");
}
//cut index id
var position = v.id.indexOf('/');
var indexId = v.id.substr(position + 1, v.id.length);
var selectivity = (
v.hasOwnProperty("selectivityEstimate") ?
//cut index id
var position = v.id.indexOf('/');
var indexId = v.id.substr(position + 1, v.id.length);
var selectivity = (
v.hasOwnProperty("selectivityEstimate") ?
(v.selectivityEstimate * 100).toFixed(2) + "%" :
"n/a"
);
var sparse = (v.hasOwnProperty("sparse") ? v.sparse : "n/a");
);
var sparse = (v.hasOwnProperty("sparse") ? v.sparse : "n/a");
$('#collectionEditIndexTable').append(
'<tr>' +
$('#collectionEditIndexTable').append(
'<tr>' +
'<th class=' + JSON.stringify(cssClass) + '>' + indexId + '</th>' +
'<th class=' + JSON.stringify(cssClass) + '>' + v.type + '</th>' +
'<th class=' + JSON.stringify(cssClass) + '>' + v.unique + '</th>' +
@ -696,49 +727,49 @@
'<th class=' + JSON.stringify(cssClass) + '>' + fieldString + '</th>' +
'<th class=' + JSON.stringify(cssClass) + '>' + actionString + '</th>' +
'</tr>'
);
});
}
this.bindIndexEvents();
},
toggleNewIndexView: function () {
var elem = $('.index-button-bar2')[0];
var elem2 = $('.index-button-bar')[0];
if ($('#indexEditView').is(':visible')) {
$('#indexEditView').hide();
$('#newIndexView').show();
//$('#addIndex').detach().appendTo(elem2);
$('#cancelIndex').detach().appendTo('#modal-dialog .modal-footer');
$('#createIndex').detach().appendTo('#modal-dialog .modal-footer');
}
else {
$('#indexEditView').show();
$('#newIndexView').hide();
//$('#addIndex').detach().appendTo('#modal-dialog .modal-footer');
$('#cancelIndex').detach().appendTo(elem);
$('#createIndex').detach().appendTo(elem);
}
arangoHelper.fixTooltips(".icon_arangodb, .arangoicon", "right");
this.resetIndexForms();
},
stringToArray: function (fieldString) {
var fields = [];
fieldString.split(',').forEach(function(field){
field = field.replace(/(^\s+|\s+$)/g,'');
if (field !== '') {
fields.push(field);
}
);
});
return fields;
},
checkboxToValue: function (id) {
return $(id).prop('checked');
}
this.bindIndexEvents();
},
toggleNewIndexView: function () {
var elem = $('.index-button-bar2')[0];
var elem2 = $('.index-button-bar')[0];
if ($('#indexEditView').is(':visible')) {
$('#indexEditView').hide();
$('#newIndexView').show();
//$('#addIndex').detach().appendTo(elem2);
$('#cancelIndex').detach().appendTo('#modal-dialog .modal-footer');
$('#createIndex').detach().appendTo('#modal-dialog .modal-footer');
}
else {
$('#indexEditView').show();
$('#newIndexView').hide();
//$('#addIndex').detach().appendTo('#modal-dialog .modal-footer');
$('#cancelIndex').detach().appendTo(elem);
$('#createIndex').detach().appendTo(elem);
}
arangoHelper.fixTooltips(".icon_arangodb, .arangoicon", "right");
this.resetIndexForms();
},
stringToArray: function (fieldString) {
var fields = [];
fieldString.split(',').forEach(function(field){
field = field.replace(/(^\s+|\s+$)/g,'');
if (field !== '') {
fields.push(field);
}
});
return fields;
},
checkboxToValue: function (id) {
return $(id).prop('checked');
}
});
}());

View File

@ -53,20 +53,31 @@
editor: 0,
setType: function (type) {
var result, type2;
if (type === 2) {
type = 'document';
}
else {
type = 'edge';
}
var callback = function(error, data, type) {
if (error) {
console.log(data);
arangoHelper.arangoError("Error", "Could not fetch data.");
}
else {
var type2 = type + ': ';
this.type = type;
this.fillInfo(type2);
this.fillEditor();
}
}.bind(this);
if (type === 'edge') {
result = this.collection.getEdge(this.colid, this.docid);
type2 = "Edge: ";
this.collection.getEdge(this.colid, this.docid, callback);
}
else if (type === 'document') {
result = this.collection.getDocument(this.colid, this.docid);
type2 = "Document: ";
}
if (result === true) {
this.type = type;
this.fillInfo(type2);
this.fillEditor();
return true;
this.collection.getDocument(this.colid, this.docid, callback);
}
},
@ -91,23 +102,7 @@
deleteDocument: function() {
var result;
if (this.type === 'document') {
result = this.collection.deleteDocument(this.colid, this.docid);
if (result === false) {
arangoHelper.arangoError('Document error:','Could not delete');
return;
}
}
else if (this.type === 'edge') {
result = this.collection.deleteEdge(this.colid, this.docid);
if (result === false) {
arangoHelper.arangoError('Edge error:', 'Could not delete');
return;
}
}
if (result === true) {
var successFunction = function() {
if (this.customView) {
this.customDeleteFunction();
}
@ -116,6 +111,29 @@
window.modalView.hide();
window.App.navigate(navigateTo, {trigger: true});
}
}.bind(this);
if (this.type === 'document') {
var callbackDoc = function(error) {
if (error) {
arangoHelper.arangoError('Error', 'Could not delete document');
}
else {
successFunction();
}
}.bind(this);
this.collection.deleteDocument(this.colid, this.docid, callbackDoc);
}
else if (this.type === 'edge') {
var callbackEdge = function(error) {
if (error) {
arangoHelper.arangoError('Edge error', 'Could not delete edge');
}
else {
successFunction();
}
}.bind(this);
this.collection.deleteEdge(this.colid, this.docid, callbackEdge);
}
},
@ -218,7 +236,7 @@
window.modalView.hide();
var model, result;
var model;
try {
model = this.editor.get();
@ -232,23 +250,30 @@
model = JSON.stringify(model);
if (this.type === 'document') {
result = this.collection.saveDocument(this.colid, this.docid, model);
if (result === false) {
arangoHelper.arangoError('Document error:','Could not save');
return;
}
var callback = function(error) {
if (error) {
arangoHelper.arangoError('Error', 'Could not save document.');
}
else {
this.successConfirmation();
this.disableSaveButton();
}
}.bind(this);
this.collection.saveDocument(this.colid, this.docid, model, callback);
}
else if (this.type === 'edge') {
result = this.collection.saveEdge(this.colid, this.docid, model);
if (result === false) {
arangoHelper.arangoError('Edge error:', 'Could not save');
return;
}
}
var callbackE = function(error) {
if (error) {
arangoHelper.arangoError('Error', 'Could not save edge.');
}
else {
this.successConfirmation();
this.disableSaveButton();
}
}.bind(this);
if (result === true) {
this.successConfirmation();
this.disableSaveButton();
this.collection.saveEdge(this.colid, this.docid, model, callbackE);
}
},

View File

@ -46,12 +46,20 @@
setCollectionId : function (colid, page) {
this.collection.setCollection(colid);
this.collection.setPage(page);
var type = arangoHelper.collectionApiType(colid);
this.page = page;
this.type = type;
this.collection.getDocuments(this.getDocsCallback.bind(this));
this.collectionModel = this.collectionsStore.get(colid);
var callback = function(error, type) {
if (error) {
arangoHelper.arangoError("Error", "Could not get collection properties.");
}
else {
this.type = type;
this.collection.getDocuments(this.getDocsCallback.bind(this));
this.collectionModel = this.collectionsStore.get(colid);
}
}.bind(this);
arangoHelper.collectionApiType(colid, null, callback);
},
getDocsCallback: function(error) {
@ -459,102 +467,109 @@
addDocumentModal: function () {
var collid = window.location.hash.split("/")[1],
buttons = [], tableContent = [],
buttons = [], tableContent = [];
// second parameter is "true" to disable caching of collection type
doctype = arangoHelper.collectionApiType(collid, true);
if (doctype === 'edge') {
tableContent.push(
window.modalView.createTextEntry(
'new-edge-from-attr',
'_from',
'',
"document _id: document handle of the linked vertex (incoming relation)",
undefined,
false,
[
{
rule: Joi.string().required(),
msg: "No _from attribute given."
}
]
)
);
var callback = function(error, type) {
if (error) {
arangoHelper.arangoError("Error", "Could not fetch collection type");
}
else {
if (type === 'edge') {
tableContent.push(
window.modalView.createTextEntry(
'new-edge-to',
'_to',
'',
"document _id: document handle of the linked vertex (outgoing relation)",
undefined,
false,
[
{
rule: Joi.string().required(),
msg: "No _to attribute given."
}
]
)
);
tableContent.push(
window.modalView.createTextEntry(
'new-edge-from-attr',
'_from',
'',
"document _id: document handle of the linked vertex (incoming relation)",
undefined,
false,
[
{
rule: Joi.string().required(),
msg: "No _from attribute given."
}
]
)
);
tableContent.push(
window.modalView.createTextEntry(
'new-edge-key-attr',
'_key',
undefined,
"the edges unique key(optional attribute, leave empty for autogenerated key",
'is optional: leave empty for autogenerated key',
false,
[
{
rule: Joi.string().allow('').optional(),
msg: ""
}
]
)
);
tableContent.push(
window.modalView.createTextEntry(
'new-edge-to',
'_to',
'',
"document _id: document handle of the linked vertex (outgoing relation)",
undefined,
false,
[
{
rule: Joi.string().required(),
msg: "No _to attribute given."
}
]
)
);
buttons.push(
window.modalView.createSuccessButton('Create', this.addEdge.bind(this))
);
tableContent.push(
window.modalView.createTextEntry(
'new-edge-key-attr',
'_key',
undefined,
"the edges 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(
window.modalView.createSuccessButton('Create', this.addEdge.bind(this))
);
window.modalView.show(
'modalTable.ejs',
'Create edge',
buttons,
tableContent
);
}
else {
tableContent.push(
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: ""
}
]
)
);
window.modalView.show(
'modalTable.ejs',
'Create edge',
buttons,
tableContent
);
}
else {
tableContent.push(
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(
window.modalView.createSuccessButton('Create', this.addDocument.bind(this))
);
buttons.push(
window.modalView.createSuccessButton('Create', this.addDocument.bind(this))
);
window.modalView.show(
'modalTable.ejs',
'Create document',
buttons,
tableContent
);
}
window.modalView.show(
'modalTable.ejs',
'Create document',
buttons,
tableContent
);
}
}
}.bind(this);
arangoHelper.collectionApiType(collid, true, callback);
},
addEdge: function () {
@ -563,42 +578,44 @@
var to = $('.modal-body #new-edge-to').last().val();
var key = $('.modal-body #new-edge-key-attr').last().val();
var result;
if (key !== '' || key !== undefined) {
result = this.documentStore.createTypeEdge(collid, from, to, key);
}
else {
result = this.documentStore.createTypeEdge(collid, from, to);
}
if (result !== false) {
//$('#edgeCreateModal').modal('hide');
window.modalView.hide();
window.location.hash = "collection/"+result;
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError('Error', 'Could not create edge');
}
else {
window.modalView.hide();
window.location.hash = "collection/" + data;
}
}.bind(this);
if (key !== '' || key !== undefined) {
this.documentStore.createTypeEdge(collid, from, to, key, callback);
}
//Error
else {
arangoHelper.arangoError('Edge error', 'Creation failed.');
this.documentStore.createTypeEdge(collid, from, to, null, callback);
}
},
addDocument: function() {
var collid = window.location.hash.split("/")[1];
var key = $('.modal-body #new-document-key-attr').last().val();
var result;
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError('Error', 'Could not create document');
}
else {
window.modalView.hide();
window.location.hash = "collection/" + data;
}
}.bind(this);
if (key !== '' || key !== undefined) {
result = this.documentStore.createTypeDocument(collid, key);
this.documentStore.createTypeDocument(collid, key, callback);
}
else {
result = this.documentStore.createTypeDocument(collid);
}
//Success
if (result !== false) {
window.modalView.hide();
window.location.hash = "collection/" + result;
}
else {
arangoHelper.arangoError('Document error', 'Creation failed.');
this.documentStore.createTypeDocument(collid, null, callback);
}
},
@ -700,37 +717,42 @@
var deleted = [], self = this;
_.each(toDelete, function(key) {
var result = false;
if (self.type === 'document') {
result = self.documentStore.deleteDocument(
self.collection.collectionID, key
);
if (result) {
//on success
deleted.push(true);
self.collection.setTotalMinusOne();
}
else {
deleted.push(false);
arangoHelper.arangoError('Document error', 'Could not delete document.');
}
var callback = function(error) {
if (error) {
deleted.push(false);
arangoHelper.arangoError('Document error', 'Could not delete document.');
}
else {
deleted.push(true);
self.collection.setTotalMinusOne();
self.collection.getDocuments(this.getDocsCallback.bind(this));
$('#markDocuments').click();
window.modalView.hide();
}
}.bind(self);
self.documentStore.deleteDocument(self.collection.collectionID, key, callback);
}
else if (self.type === 'edge') {
result = self.documentStore.deleteEdge(self.collection.collectionID, key);
if (result === true) {
//on success
self.collection.setTotalMinusOne();
deleted.push(true);
}
else {
deleted.push(false);
arangoHelper.arangoError('Edge error', 'Could not delete edge');
}
var callback2 = function(error) {
if (error) {
deleted.push(false);
arangoHelper.arangoError('Edge error', 'Could not delete edge');
}
else {
self.collection.setTotalMinusOne();
deleted.push(true);
self.collection.getDocuments(this.getDocsCallback.bind(this));
$('#markDocuments').click();
window.modalView.hide();
}
}.bind(self);
self.documentStore.deleteEdge(self.collection.collectionID, key, callback2);
}
});
this.collection.getDocuments(this.getDocsCallback.bind(this));
$('#markDocuments').click();
window.modalView.hide();
},
getSelectedDocs: function() {
@ -760,36 +782,35 @@
},
reallyDelete: function () {
var deleted = false;
var result;
if (this.type === 'document') {
result = this.documentStore.deleteDocument(
this.collection.collectionID, this.docid
);
if (result) {
//on success
this.collection.setTotalMinusOne();
deleted = true;
}
else {
arangoHelper.arangoError('Doc error');
}
var callback = function(error) {
if (error) {
arangoHelper.arangoError('Error', 'Could not delete document');
}
else {
this.collection.setTotalMinusOne();
this.collection.getDocuments(this.getDocsCallback.bind(this));
$('#docDeleteModal').modal('hide');
}
}.bind(this);
this.documentStore.deleteDocument(this.collection.collectionID, this.docid, callback);
}
else if (this.type === 'edge') {
result = this.documentStore.deleteEdge(this.collection.collectionID, this.docid);
if (result === true) {
//on success
this.collection.setTotalMinusOne();
deleted = true;
}
else {
arangoHelper.arangoError('Edge error');
}
}
if (deleted === true) {
this.collection.getDocuments(this.getDocsCallback.bind(this));
$('#docDeleteModal').modal('hide');
var callback2 = function(error) {
if (error) {
arangoHelper.arangoError('Edge error', "Could not delete edge");
}
else {
this.collection.setTotalMinusOne();
this.collection.getDocuments(this.getDocsCallback.bind(this));
$('#docDeleteModal').modal('hide');
}
}.bind(this);
this.documentStore.deleteEdge(this.collection.collectionID, this.docid, callback2);
}
},

View File

@ -11,10 +11,16 @@
};
var installCallback = function(result) {
var self = this;
if (result.error === false) {
this.collection.fetch({ async: false });
window.modalView.hide();
this.reload();
this.collection.fetch({
success: function() {
window.modalView.hide();
self.reload();
}
});
} else {
var res = result;
if (result.hasOwnProperty("responseJSON")) {

View File

@ -105,8 +105,9 @@
}
else {
window.modalView.hide();
arangoHelper.arangoError("Graph", "Could not delete Graph.");
}
};
}.bind(this);
this.collection.dropAndDeleteGraph(name, callback);
}
@ -187,39 +188,42 @@
},
render: function() {
var self = this;
this.collection.fetch({
async: false
});
this.collection.sort();
success: function() {
self.collection.sort();
$(this.el).html(this.template.render({
graphs: this.collection,
searchString : ''
}));
$(self.el).html(self.template.render({
graphs: self.collection,
searchString : ''
}));
if (this.dropdownVisible === true) {
$('#graphManagementDropdown2').show();
$('#graphSortDesc').attr('checked', this.collection.sortOptions.desc);
$('#graphManagementToggle').toggleClass('activated');
$('#graphManagementDropdown').show();
}
this.events["click .tableRow"] = this.showHideDefinition.bind(this);
this.events['change tr[id*="newEdgeDefinitions"]'] = this.setFromAndTo.bind(this);
this.events["click .graphViewer-icon-button"] = this.addRemoveDefinition.bind(this);
this.events["click #graphTab a"] = this.toggleTab.bind(this);
this.events["click .createExampleGraphs"] = this.createExampleGraphs.bind(this);
this.events["focusout .select2-search-field input"] = function(e){
if ($('.select2-drop').is(':visible')) {
if (!$('#select2-search-field input').is(':focus')) {
window.setTimeout(function() {
$(e.currentTarget).parent().parent().parent().select2('close');
}, 80);
if (self.dropdownVisible === true) {
$('#graphManagementDropdown2').show();
$('#graphSortDesc').attr('checked', self.collection.sortOptions.desc);
$('#graphManagementToggle').toggleClass('activated');
$('#graphManagementDropdown').show();
}
}
}.bind(this);
arangoHelper.setCheckboxStatus("#graphManagementDropdown");
self.events["click .tableRow"] = self.showHideDefinition.bind(self);
self.events['change tr[id*="newEdgeDefinitions"]'] = self.setFromAndTo.bind(self);
self.events["click .graphViewer-icon-button"] = self.addRemoveDefinition.bind(self);
self.events["click #graphTab a"] = self.toggleTab.bind(self);
self.events["click .createExampleGraphs"] = self.createExampleGraphs.bind(self);
self.events["focusout .select2-search-field input"] = function(e){
if ($('.select2-drop').is(':visible')) {
if (!$('#select2-search-field input').is(':focus')) {
window.setTimeout(function() {
$(e.currentTarget).parent().parent().parent().select2('close');
}, 80);
}
}
}.bind(self);
arangoHelper.setCheckboxStatus("#graphManagementDropdown");
}
});
return this;
},

View File

@ -41,19 +41,23 @@
//Heiko: Form-Validator - please fill out all req. fields
return;
}
username = this.collection.login(username, password);
if (username) {
$(this.el2).show();
$(this.el3).show();
window.location.reload();
$('#currentUser').text(username);
this.collection.loadUserSettings();
}
else {
$('#loginForm input').addClass("form-error");
$('.wrong-credentials').show();
}
var callback = function(error, username) {
if (error) {
$('#loginForm input').addClass("form-error");
$('.wrong-credentials').show();
}
else {
$(this.el2).show();
$(this.el3).show();
window.location.reload();
$('#currentUser').text(username);
this.collection.loadUserSettings();
}
}.bind(this);
this.collection.login(username, password, callback);
}
});

View File

@ -9,11 +9,16 @@
events: {
"change #arangoCollectionSelect": "navigateBySelect",
"click .tab": "navigateByTab",
"click li": "switchTab",
"click .arangodbLogo": "selectMenuItem",
"mouseenter .dropdown > *": "showDropdown",
"mouseleave .dropdown": "hideDropdown"
},
renderFirst: true,
initialize: function () {
this.userCollection = this.options.userCollection;
this.currentDB = this.options.currentDB;
this.dbSelectionView = new window.DBSelectionView({
@ -39,20 +44,39 @@
template: templateEngine.createTemplate("navigationView.ejs"),
render: function () {
var self = this;
$(this.el).html(this.template.render({
currentDB: this.currentDB
}));
this.dbSelectionView.render($("#dbSelect"));
this.notificationView.render($("#notificationBar"));
if (this.userCollection.whoAmI()) {
this.userBarView.render();
}
var callback = function(error) {
if (!error) {
this.userBarView.render();
}
}.bind(this);
this.userCollection.whoAmI(callback);
this.statisticBarView.render($("#statisticBar"));
// if demo content not available, do not show demo menu tab
if (!window.App.arangoCollectionsStore.findWhere({"name": "arangodbflightsdemo"})) {
$('.demo-menu').css("display","none");
}
if (this.renderFirst) {
this.renderFirst = false;
var select = ((window.location.hash).substr(1, (window.location.hash).length) + '-menu');
if (select.indexOf('/') < -1) {
this.selectMenuItem(select);
}
$('.arangodbLogo').on('click', function() {
self.selectMenuItem();
});
}
return this;
},
@ -104,10 +128,20 @@
});
},
switchTab: function(e) {
var id = $(e.currentTarget).children().first().attr('id');
if (id) {
this.selectMenuItem(id + '-menu');
}
},
selectMenuItem: function (menuItem) {
$('.navlist li').removeClass('active');
if (menuItem) {
$('.' + menuItem).addClass('active');
if (typeof menuItem === 'string') {
if (menuItem) {
$('.' + menuItem).addClass('active');
}
}
},

View File

@ -365,17 +365,23 @@
if (this.allowUpload === true) {
var callback = function() {
this.collection.fetch({async: false});
this.updateLocalQueries();
this.renderSelectboxes();
this.updateTable();
self.allowUpload = false;
$('#customs-switch').click();
};
this.collection.fetch({
success: function() {
self.updateLocalQueries();
self.renderSelectboxes();
self.updateTable();
self.allowUpload = false;
$('#customs-switch').click();
$('#confirmQueryImport').addClass('disabled');
$('#queryImportDialog').modal('hide');
},
error: function(data) {
arangoHelper.arangoError("Custom Queries", data.responseText);
}
});
}.bind(this);
self.collection.saveImportQueries(self.file, callback.bind(this));
$('#confirmQueryImport').addClass('disabled');
$('#queryImportDialog').modal('hide');
}
},
@ -401,17 +407,16 @@
}
};
$.ajax("whoAmI?_=" + Date.now(), {async:false}).done(
$.ajax("whoAmI?_=" + Date.now()).success(
function(data) {
name = data.user;
if (name === null || name === false) {
name = "root";
}
window.open("query/download/" + encodeURIComponent(name));
});
window.open("query/download/" + encodeURIComponent(name));
},
deselect: function (editor) {
@ -446,45 +451,63 @@
this.checkSaveName();
},
getAQL: function () {
getAQL: function (originCallback) {
var self = this, result;
this.collection.fetch({
async: false
});
success: function() {
//old storage method
var item = localStorage.getItem("customQueries");
if (item) {
var queries = JSON.parse(item);
//save queries in user collections extra attribute
_.each(queries, function(oldQuery) {
self.collection.add({
value: oldQuery.value,
name: oldQuery.name
});
});
//old storage method
var item = localStorage.getItem("customQueries");
if (item) {
var queries = JSON.parse(item);
//save queries in user collections extra attribute
_.each(queries, function(oldQuery) {
self.collection.add({
value: oldQuery.value,
name: oldQuery.name
});
});
result = self.collection.saveCollectionQueries();
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError(
"Custom Queries",
"Could not import old local storage queries"
);
}
else {
localStorage.removeItem("customQueries");
}
}.bind(self);
self.collection.saveCollectionQueries(callback);
}
self.updateLocalQueries();
if (result === true) {
//and delete them from localStorage
localStorage.removeItem("customQueries");
if (originCallback) {
originCallback();
}
}
}
this.updateLocalQueries();
});
},
deleteAQL: function (e) {
var callbackSave = function(error) {
if (error) {
arangoHelper.arangoError("Query", "Could not delete query.");
}
else {
this.updateLocalQueries();
this.renderSelectboxes();
this.updateTable();
}
}.bind(this);
var deleteName = $(e.target).parent().parent().parent().children().first().text();
var toDelete = this.collection.findWhere({name: deleteName});
this.collection.remove(toDelete);
this.collection.saveCollectionQueries();
this.updateLocalQueries();
this.renderSelectboxes();
this.updateTable();
this.collection.remove(toDelete);
this.collection.saveCollectionQueries(callbackSave);
},
updateLocalQueries: function () {
@ -556,16 +579,26 @@
});
}
this.collection.saveCollectionQueries();
var callback = function(error) {
if (error) {
arangoHelper.arangoError("Query", "Could not save query");
}
else {
var self = this;
this.collection.fetch({
success: function() {
self.updateLocalQueries();
self.renderSelectboxes();
$('#querySelect').val(saveName);
}
});
}
}.bind(this);
this.collection.saveCollectionQueries(callback);
window.modalView.hide();
this.updateLocalQueries();
this.renderSelectboxes();
$('#querySelect').val(saveName);
},
getSystemQueries: function () {
getSystemQueries: function (callback) {
var self = this;
$.ajax({
type: "GET",
@ -573,11 +606,16 @@
url: "js/arango/aqltemplates.json",
contentType: "application/json",
processData: false,
async: false,
success: function (data) {
if (callback) {
callback(false);
}
self.queries = data;
},
error: function () {
if (callback) {
callback(true);
}
arangoHelper.arangoNotification("Query", "Error while loading system templates");
}
});
@ -592,15 +630,28 @@
},
refreshAQL: function(select) {
this.getAQL();
this.getSystemQueries();
this.updateLocalQueries();
if (select) {
var previous = $("#querySelect" ).val();
this.renderSelectboxes();
$("#querySelect" ).val(previous);
}
var self = this;
var callback = function(error) {
if (error) {
arangoHelper.arangoError('Query', 'Could not reload Queries');
}
else {
self.updateLocalQueries();
if (select) {
var previous = $("#querySelect").val();
self.renderSelectboxes();
$("#querySelect").val(previous);
}
}
}.bind(self);
var originCallback = function() {
self.getSystemQueries(callback);
}.bind(self);
this.getAQL(originCallback);
},
importSelected: function (e) {

View File

@ -1,6 +1,6 @@
/*jshint browser: true */
/*jshint unused: false */
/*global Backbone, templateEngine, $, window*/
/*global arangoHelper, Backbone, templateEngine, $, window*/
(function () {
"use strict";
@ -49,43 +49,60 @@
},
render: function () {
var username = this.userCollection.whoAmI(),
img = null,
name = null,
active = false,
currentUser = null;
if (username) {
currentUser = this.userCollection.findWhere({user: username});
currentUser.set({loggedIn : true});
name = currentUser.get("extra").name;
img = currentUser.get("extra").img;
active = currentUser.get("active");
}
if (! img) {
img = "img/default_user.png";
}
else {
img = "https://s.gravatar.com/avatar/" + img + "?s=24";
}
if (! name) {
name = "";
}
this.$el = $("#userBar");
this.$el.html(this.template.render({
img : img,
name : name,
username : username,
active : active
}));
var callback = function(error, username) {
if (error) {
arangoHelper.arangoErro("User", "Could not fetch user.");
}
else {
var img = null,
name = null,
active = false,
currentUser = null;
if (username) {
currentUser = this.userCollection.findWhere({user: username});
currentUser.set({loggedIn : true});
name = currentUser.get("extra").name;
img = currentUser.get("extra").img;
active = currentUser.get("active");
}
if (! img) {
img = "img/default_user.png";
}
else {
img = "https://s.gravatar.com/avatar/" + img + "?s=24";
}
if (! name) {
name = "";
}
this.delegateEvents();
return this.$el;
this.$el = $("#userBar");
this.$el.html(this.template.render({
img : img,
name : name,
username : username,
active : active
}));
this.delegateEvents();
return this.$el;
}
}.bind(this);
this.userCollection.whoAmI(callback);
},
userLogout : function() {
this.userCollection.whoAmI();
this.userCollection.logout();
var userCallback = function(error) {
if (error) {
arangoHelper.arangoError("User", "Logout error");
}
else {
this.userCollection.logout();
}
}.bind(this);
this.userCollection.whoAmI(userCallback);
}
});
}());

View File

@ -339,49 +339,54 @@
$('#newCurrentPassword').closest("th").css("backgroundColor", "white");
$('#confirmCurrentPassword').closest("th").css("backgroundColor", "white");
//check
var hasError = false;
//Check old password
if (!this.validateCurrentPassword(oldPasswd)) {
$('#oldCurrentPassword').closest("th").css("backgroundColor", "red");
hasError = true;
}
//check confirmation
if (newPasswd !== confirmPasswd) {
$('#confirmCurrentPassword').closest("th").css("backgroundColor", "red");
hasError = true;
}
//check new password
if (!this.validatePassword(newPasswd)) {
$('#newCurrentPassword').closest("th").css("backgroundColor", "red");
hasError = true;
}
if (hasError) {
return;
}
this.currentUser.setPassword(newPasswd);
window.modalView.hide();
var callback = function(error, data) {
if (error) {
arangoHelper.arangoError("User", "Could not verify old password");
}
else {
if (data) {
//check confirmation
if (newPasswd !== confirmPasswd) {
arangoHelper.arangoError("User", "New passwords do not match");
hasError = true;
}
//check new password
/*if (!this.validatePassword(newPasswd)) {
$('#newCurrentPassword').closest("th").css("backgroundColor", "red");
hasError = true;
}*/
if (!hasError) {
this.currentUser.setPassword(newPasswd);
arangoHelper.arangoNotification("User", "Password changed");
window.modalView.hide();
}
}
}
}.bind(this);
this.currentUser.checkPassword(oldPasswd, callback);
},
validateCurrentPassword : function (pwd) {
return this.currentUser.checkPassword(pwd);
},
submitEditCurrentUserProfile: function() {
var name = $('#editCurrentName').val();
var img = $('#editCurrentUserProfileImg').val();
img = this.parseImgString(img);
/* if (!this.validateName(name)) {
$('#editName').closest("th").css("backgroundColor", "red");
return;
}*/
this.currentUser.setExtras(name, img);
this.updateUserProfile();
var callback = function(error) {
if (error) {
arangoHelper.arangoError("User", "Could not edit user settings");
}
else {
arangoHelper.arangoNotification("User", "Changes confirmed.");
this.updateUserProfile();
}
}.bind(this);
this.currentUser.setExtras(name, img, callback);
window.modalView.hide();
},

View File

@ -84,7 +84,7 @@ table.arangoDataTable tr.odd {
}
#documentsTableID_wrapper {
min-height: 420px !important;
min-height: 467px !important;
padding-bottom: 0 !important;
.fg-toolbar {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -6,7 +6,7 @@
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"repository": {

View File

@ -91,21 +91,25 @@ const optionsDocumentation = [
' - `cluster`: if set to true the tests are run with the coordinator',
' of a small local cluster',
' - `clusterNodes`: number of DB-Servers to use',
' - valgrindHosts - configure which clustercomponents to run using valgrind',
' Coordinator - flag to run Coordinator with valgrind',
' DBServer - flag to run DBServers with valgrind',
' - `test`: path to single test to execute for "single" test target',
' - `cleanup`: if set to true (the default), the cluster data files',
' and logs are removed after termination of the test.',
'',
' - benchargs : additional commandline arguments to arangob',
'',
'',
' - `sanitizer`: if set the programs are run with enabled sanitizer',
' and need longer tomeouts',
'',
' - `valgrind`: if set the programs are run with the valgrind',
' memory checker; should point to the valgrind executable',
' - `valgrindXmlFileBase`: string to prepend to the xml report name',
' - `valgrindArgs`: list of commandline parameters to add to valgrind',
' - valgrindHosts - configure which clustercomponents to run using valgrind',
' Coordinator - flag to run Coordinator with valgrind',
' DBServer - flag to run DBServers with valgrind',
'',
' - `extraargs`: list of extra commandline arguments to add to arangod',
' - `extraArgs`: list of extra commandline arguments to add to arangod',
' - `extremeVerbosity`: if set to true, then there will be more test run',
' output, especially for cluster tests.',
''
@ -118,7 +122,7 @@ const optionsDefaults = {
"concurrency": 3,
"coreDirectory": "/var/tmp",
"duration": 10,
"extraargs": [],
"extraArgs": [],
"extremeVerbosity": false,
"force": true,
"jsonReply": false,
@ -128,6 +132,7 @@ const optionsDefaults = {
"onlyNightly": false,
"password": "",
"replication": false,
"sanitizer": false,
"skipAql": false,
"skipArangoB": false,
"skipArangoBNonConnKeepAlive": true,
@ -182,13 +187,13 @@ const TOP_DIR = (function findTopDir() {
return topDir;
}());
const BIN_DIR = (fs.exists("build") && fs.exists(fs.join("build", "bin")))
? fs.join(TOP_DIR, "build", "bin")
: fs.join(TOP_DIR, "bin");
const BIN_DIR = (fs.exists("build") && fs.exists(fs.join("build", "bin"))) ?
fs.join(TOP_DIR, "build", "bin") :
fs.join(TOP_DIR, "bin");
const CONFIG_DIR = (fs.exists("build") && fs.exists(fs.join("build", "etc")))
? fs.join(TOP_DIR, "build", "etc", "arangodb")
: fs.join(TOP_DIR, "etc", "arangodb");
const CONFIG_DIR = (fs.exists("build") && fs.exists(fs.join("build", "etc"))) ?
fs.join(TOP_DIR, "build", "etc", "arangodb") :
fs.join(TOP_DIR, "etc", "arangodb");
const ARANGOB_BIN = fs.join(BIN_DIR, "arangob");
const ARANGODUMP_BIN = fs.join(BIN_DIR, "arangodump");
@ -1147,8 +1152,15 @@ function shutdownInstance(instanceInfo, options) {
let count = 0;
let bar = "[";
let timeout = 600;
if (options.sanitizer) {
timeout *= 2;
}
while (true) {
instanceInfo.exitStatus = statusExternal(instanceInfo.pid, false);
if (instanceInfo.exitStatus.status === "RUNNING") {
++count;
@ -1163,7 +1175,7 @@ function shutdownInstance(instanceInfo, options) {
if (count > 600) {
print("forcefully terminating " + yaml.safeDump(instanceInfo.pid) +
" after 600 s grace period; marking crashy.");
" after " + timeout + "s grace period; marking crashy.");
serverCrashed = true;
killExternal(instanceInfo.pid);
break;
@ -1261,14 +1273,14 @@ function startDispatcher(instanceInfo) {
/// protocol must be one of ["tcp", "ssl", "unix"]
////////////////////////////////////////////////////////////////////////////////
function startInstanceCluster(instanceInfo, protocol, options, optionsExtraArgs,
function startInstanceCluster(instanceInfo, protocol, options,
addArgs, testname, appDir, tmpDataDir) {
startDispatcher(instanceInfo, options);
const clusterNodes = options.clusterNodes;
let extraArgs = makeArgsArangod(options, appDir);
extraArgs = _.extend(extraArgs, optionsExtraArgs);
extraArgs = _.extend(extraArgs, options.extraArgs);
if (addArgs !== undefined) {
extraArgs = _.extend(extraArgs, addArgs);
@ -1385,7 +1397,7 @@ function valgrindArgsSingleServer(options, testname, run) {
return toArgv(valgrindOpts, true).concat([run]);
}
function startInstanceSingleServer(instanceInfo, protocol, options, optionsExtraArgs,
function startInstanceSingleServer(instanceInfo, protocol, options,
addArgs, testname, appDir, tmpDataDir) {
const port = findFreePort();
instanceInfo.port = port;
@ -1405,7 +1417,7 @@ function startInstanceSingleServer(instanceInfo, protocol, options, optionsExtra
args["server.keyfile"] = fs.join("UnitTests", "server.pem");
}
args = _.extend(args, optionsExtraArgs);
args = _.extend(args, options.extraArgs);
if (addArgs !== undefined) {
args = _.extend(args, addArgs);
@ -1438,24 +1450,17 @@ function startInstance(protocol, options, addArgs, testname, tmpDir) {
fs.makeDirectoryRecursive(tmpDataDir);
instanceInfo.tmpDataDir = tmpDataDir;
// build extra / valgrind arguments
let optionsExtraArgs = {};
if (typeof(options.extraArgs) === 'object') {
optionsExtraArgs = options.extraArgs;
}
// startup in cluster mode
let res = false;
if (options.cluster) {
res = startInstanceCluster(instanceInfo, protocol, options, optionsExtraArgs,
res = startInstanceCluster(instanceInfo, protocol, options,
addArgs, testname, appDir, tmpDataDir);
}
// single instance mode
else {
res = startInstanceSingleServer(instanceInfo, protocol, options, optionsExtraArgs,
res = startInstanceSingleServer(instanceInfo, protocol, options,
addArgs, testname, appDir, tmpDataDir);
}

View File

@ -2,7 +2,7 @@
"name": "broken-controller-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "broken-controller.js"

View File

@ -2,7 +2,7 @@
"name": "broken-exports-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"exports": {
"broken": "broken-exports.js"

View File

@ -2,7 +2,7 @@
"name": "broken-if-unconfigured",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "needs-config.js"

View File

@ -2,7 +2,7 @@
"name": "minimal-working-manifest",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "controller.js"

View File

@ -2,7 +2,7 @@
"name": "itzpapalotl",
"version": "0.0.6",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"author": "jsteemann",
"description": "random aztec god service",

View File

@ -2,7 +2,7 @@
"name": "malformed-controller-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "broken-controller.js"

View File

@ -2,9 +2,9 @@
"name": "malformed-controller-name",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"?": "controller.js"
}
}
}

View File

@ -2,9 +2,9 @@
"name": "malformed-controller-path",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "/illegal/file/name/"
}
}
}

View File

@ -2,7 +2,7 @@
"name": "malformed-exports-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"exports": {
"broken": "broken-exports.js"

View File

@ -2,9 +2,9 @@
"name": "malformed-exports-path",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"exports": {
"broken": "/illegal/file/name/"
}
}
}

View File

@ -2,7 +2,7 @@
"name": "minimal-working-manifest",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"scripts": {
"setup": "setup.js",

View File

@ -2,7 +2,7 @@
"name": "missing-controller-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"controllers": {
"/": "does-not-exist.js"

View File

@ -2,7 +2,7 @@
"name": "missing-exports-file",
"version": "0.0.0",
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0"
},
"exports": {
"nope": "no-such-file.js"

View File

@ -0,0 +1,348 @@
/*jshint globalstrict:false, strict:false, maxlen: 500 */
/*global assertEqual, AQL_PARSE, AQL_EXECUTE */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for with collections
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var internal = require("internal");
var db = require("org/arangodb").db;
var helper = require("org/arangodb/aql-helper");
var assertQueryError = helper.assertQueryError;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function queryWithCollectionsTestSuite () {
var c1, c2;
var errors = internal.errors;
return {
setUp : function () {
db._drop("UnitTestsCollection1");
db._drop("UnitTestsCollection2");
c1 = db._create("UnitTestsCollection1");
c2 = db._create("UnitTestsCollection2");
},
tearDown : function () {
db._drop("UnitTestsCollection2");
db._drop("UnitTestsCollection1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with at invalid position
////////////////////////////////////////////////////////////////////////////////
testWithInvalidPos1 : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "LET a = 1 WITH UnitTestsCollection1 RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with at invalid position
////////////////////////////////////////////////////////////////////////////////
testWithInvalidPos2 : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "FOR i IN 1..10 RETURN i WITH UnitTestsCollection1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with at invalid position
////////////////////////////////////////////////////////////////////////////////
testWithInvalidPos3 : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "FOR i IN 1..10 WITH UnitTestsCollection1 RETURN i");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with only
////////////////////////////////////////////////////////////////////////////////
testWithOnlySingle : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH UnitTestsCollection1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with only
////////////////////////////////////////////////////////////////////////////////
testWithOnlyMulti : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH UnitTestsCollection1, UnitTestsCollection2");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with only
////////////////////////////////////////////////////////////////////////////////
testWithOnlyMultiSpace : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH UnitTestsCollection1 UnitTestsCollection2");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with invalid value
////////////////////////////////////////////////////////////////////////////////
testWithString : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH 'UnitTestsCollection1' RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with invalid value
////////////////////////////////////////////////////////////////////////////////
testWithNumber : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH 1 RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with invalid value
////////////////////////////////////////////////////////////////////////////////
testWithArray : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH [ 'UnitTestsCollection1' ] RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with invalid value
////////////////////////////////////////////////////////////////////////////////
testWithObject : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH { name : 'UnitTestsCollection1' } RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with invalid value
////////////////////////////////////////////////////////////////////////////////
testWithKeyword : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "WITH OUTBOUND RETURN 1");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with one collection
////////////////////////////////////////////////////////////////////////////////
testWithSingle : function () {
var query = "WITH UnitTestsCollection1 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1" ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with one collection
////////////////////////////////////////////////////////////////////////////////
testWithSingleBind : function () {
var query = "WITH @@col FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query, { "@col" : "UnitTestsCollection1" }).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with one collection
////////////////////////////////////////////////////////////////////////////////
testWithSingleBindWrongType : function () {
var query = "WITH @col FOR i IN 1..10 RETURN i";
assertQueryError(errors.ERROR_QUERY_BIND_PARAMETER_TYPE.code, query);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMulti : function () {
var query = "WITH UnitTestsCollection1, UnitTestsCollection2 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1", "UnitTestsCollection2" ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiSpace : function () {
var query = "WITH UnitTestsCollection1 UnitTestsCollection2 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1", "UnitTestsCollection2" ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithReturn : function () {
var query = "WITH `return` RETURN 1";
var collections = AQL_PARSE(query).collections;
assertEqual([ "return" ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiReserved : function () {
var query = "WITH `for` `with` `replace` `insert` `outbound` RETURN 1";
var collections = AQL_PARSE(query).collections;
assertEqual([ "for", "insert", "outbound", "replace", "with" ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiBind : function () {
var query = "WITH @@col1, @@col2 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query, { "@col1" : "UnitTestsCollection1", "@col2" : "UnitTestsCollection2" }).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiBindSpace : function () {
var query = "WITH @@col1 @@col2 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query, { "@col1" : "UnitTestsCollection1", "@col2" : "UnitTestsCollection2" }).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiMixed : function () {
var query = "WITH UnitTestsCollection1, UnitTestsCollection2 FOR i IN _users RETURN i";
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1", "UnitTestsCollection2", "_users" ], collections.sort());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiRedundant : function () {
var query = "WITH UnitTestsCollection1, UnitTestsCollection1 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1" ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiRedundantBind : function () {
var query = "WITH @@col1, @@col1 FOR i IN 1..10 RETURN i";
var result = AQL_EXECUTE(query, { "@col1" : "UnitTestsCollection1" }).json;
assertEqual(10, result.length);
var collections = AQL_PARSE(query).collections;
assertEqual([ ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiRedundantMixed : function () {
var query = "WITH UnitTestsCollection1, UnitTestsCollection1 FOR i IN _users RETURN i";
var collections = AQL_PARSE(query).collections;
assertEqual([ "UnitTestsCollection1", "_users" ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiRedundantMixedBind : function () {
var query = "WITH @@col1, @@col2 FOR i IN @@col2 RETURN i";
var collections = AQL_PARSE(query).collections;
assertEqual([ ], collections);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test with multiple collections
////////////////////////////////////////////////////////////////////////////////
testWithMultiRedundantMixedBind2 : function () {
var query = "WITH @@col1, _users FOR i IN @@col2 RETURN i";
var collections = AQL_PARSE(query).collections;
assertEqual([ "_users" ], collections);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(queryWithCollectionsTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -41,10 +41,20 @@ JAVASCRIPT_JSLINT="\
FILELIST=""
for file in ${JAVASCRIPT_JSLINT}; do
FILELIST="${FILELIST} --jslint ${file}";
FILELIST="${FILELIST} --jslint ${file}";
done
exec ./build/bin/arangosh \
if [ -z "${ARANGOSH}" ]; then
if [ -x build/bin/arangosh ]; then
ARANGOSH=build/bin/arangosh
elif [ -x bin/arangosh ]; then
ARANGOSH=bin/arangosh
else
echo "$0: cannot locate arangosh"
fi
fi
exec $ARANGOSH \
-c none \
--log.level error \
--server.password "" \

View File

@ -16,12 +16,14 @@ export PORT=`expr 1024 + $RANDOM`
export ETCD_NONO_WAL_SYNC=1
if [ -x build/bin/arangosh ]; then
ARANGOSH=build/bin/arangosh
elif [ -x bin/arangosh ]; then
ARANGOSH=bin/arangosh
else
echo "$0: cannot locate arangosh"
if [ -z "${ARANGOSH}" ]; then
if [ -x build/bin/arangosh ]; then
ARANGOSH=build/bin/arangosh
elif [ -x bin/arangosh ]; then
ARANGOSH=bin/arangosh
else
echo "$0: cannot locate arangosh"
fi
fi
exec $ARANGOSH \