1
0
Fork 0

Merge branch 'devel' into HLC

This commit is contained in:
Frank Celler 2016-07-11 07:03:49 +00:00
commit 36a9b7852e
38 changed files with 801 additions and 343 deletions

View File

@ -169,7 +169,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}") message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
endif () endif ()
# -DSNAPPY -DZLIB # -DSNAPPY -DZLIB
if (SOLARIS) if (SOLARIS OR DARWIN)
set(ROCKSDB_MALLOC_USABLE_SIZE "") set(ROCKSDB_MALLOC_USABLE_SIZE "")
else() else()
set(ROCKSDB_MALLOC_USABLE_SIZE "-DROCKSDB_MALLOC_USABLE_SIZE") set(ROCKSDB_MALLOC_USABLE_SIZE "-DROCKSDB_MALLOC_USABLE_SIZE")

View File

@ -1,8 +1,6 @@
devel devel
----- -----
* fixed issue #1930
* added option `--skip-lines` for arangoimp * added option `--skip-lines` for arangoimp
this allows skipping the first few lines from the import file in case the this allows skipping the first few lines from the import file in case the
CSV or TSV import are used CSV or TSV import are used
@ -29,7 +27,13 @@ devel
v3.0.2 (XXXX-XX-XX) v3.0.2 (XXXX-XX-XX)
------------------- -------------------
* don't expose local file paths in error messages. * fixed assertion failure in case multiple remove operations were used in the same query
* fixed upsert behavior in case upsert was used in a loop with the same document example
* fixed issue #1930
* don't expose local file paths in Foxx error messages.
* fixed issue #1929 * fixed issue #1929

View File

@ -713,6 +713,10 @@ if (USE_OPENSSL_NO_SSL2)
add_definitions(-DOPENSSL_NO_SSL2) add_definitions(-DOPENSSL_NO_SSL2)
endif () endif ()
if(WIN32)
option(BUNDLE_OPENSSL "Bundle OpenSSL library" ON)
endif()
################################################################################ ################################################################################
## V8 ## V8
################################################################################ ################################################################################

View File

@ -155,11 +155,6 @@ pack-macosx-cmake:
test -d bin || mkdir bin test -d bin || mkdir bin
rm -f ./.file-list-js
cd Build && ${MAKE}
./Installation/file-copy-js.sh . Build
cd Build && ${MAKE} install DESTDIR=${PACK_DESTDIR} cd Build && ${MAKE} install DESTDIR=${PACK_DESTDIR}
################################################################################ ################################################################################
@ -186,11 +181,6 @@ pack-arm-cmake:
${MAKE} ${BUILT_SOURCES} ${MAKE} ${BUILT_SOURCES}
rm -f ./.file-list-js
cd Build && ${MAKE}
./Installation/file-copy-js.sh . Build
cd Build && cpack -G DEB cd Build && cpack -G DEB
@ -207,11 +197,8 @@ pack-deb-cmake:
${MAKE} ${BUILT_SOURCES} ${MAKE} ${BUILT_SOURCES}
rm -f ./.file-list-js
cd Build && ${MAKE} cd Build && ${MAKE}
./Installation/file-copy-js.sh . Build
cd Build && cpack -G DEB cd Build && cpack -G DEB
################################################################################ ################################################################################
@ -255,7 +242,6 @@ pack-winXX-MOREOPTS:
${MAKE} packXX BITS="$(BITS)" TARGET="$(TARGET)" BUILD_TARGET=Debug ${MAKE} packXX BITS="$(BITS)" TARGET="$(TARGET)" BUILD_TARGET=Debug
winXX-cmake: winXX-cmake:
rm -f ./.file-list-js
cd ../b && cmake \ cd ../b && cmake \
-G "$(TARGET)" \ -G "$(TARGET)" \
-D "CMAKE_BUILD_TYPE=RelWithDebInfo" \ -D "CMAKE_BUILD_TYPE=RelWithDebInfo" \
@ -269,9 +255,5 @@ winXX-build:
cd ../b && cmake --build . --config $(BUILD_TARGET) cd ../b && cmake --build . --config $(BUILD_TARGET)
packXX: packXX:
if test ! -d ../b/js; then ./Installation/file-copy-js.sh . ../b; fi cd ../b && cpack -G NSIS64 -C $(BUILD_TARGET)
cd ../b; rm -f ArangoDB-*.exe ArangoDB*.nsi
cd ../b && cpack -G NSIS -C $(BUILD_TARGET)
cd ../b && cpack -G ZIP -C $(BUILD_TARGET) cd ../b && cpack -G ZIP -C $(BUILD_TARGET)
./Installation/Windows/installer-generator.sh $(BITS) ..\\b

View File

@ -1,25 +0,0 @@
#!/bin/bash
NSIS_PATH="/cygdrive/c/Program Files (x86)/NSIS"
#shell parameter:
#1 the bits (64 or 32)
#2 the parent directory which contains the Build64 or Build32 directory
BUILD=$2
bits=$1
# Yo windows we like year backslash paths.
WD=`pwd`
SRCPATH=`cygpath -w ${WD}|sed "s;\\\\\;\\\\\\\\\\\\\;g"`
INSTALLERNAME=`grep CPACK_PACKAGE_FILE_NAME ${BUILD}/CPackConfig.cmake | grep -o '".*"' | awk -F\" '{print $2}'`
if [ ! -f ${BUILD}/$INSTALLERNAME-internal.exe ]; then
cp ${BUILD}/$INSTALLERNAME.exe ${BUILD}/$INSTALLERNAME-internal.exe
fi
cat Installation/Windows/Templates/arango-packer-template.nsi | \
sed -e "s;@BITS@;$bits;g" \
-e "s;@INSTALLERNAME@;${INSTALLERNAME};" \
-e "s;@SRCDIR@;${SRCPATH};g" > ${BUILD}/$INSTALLERNAME.nsi
"$NSIS_PATH"/makensis.exe ${BUILD}\\$INSTALLERNAME.nsi

View File

@ -77,7 +77,6 @@ build-stamp:
# not used # not used
rm -rf js/node/node_modules/js-yaml/demo rm -rf js/node/node_modules/js-yaml/demo
rm -f .file-list-js
make -j12 all make -j12 all
# --- end custom part for compiling # --- end custom part for compiling

View File

@ -1,20 +0,0 @@
#!/bin/bash
set -e
SRCDIR=$1
DSTDIR=$2
${SRCDIR}/Installation/file-list-js.sh ${SRCDIR} | while read a; do
if test -f "$DSTDIR/$a"; then
echo "$DSTDIR/$a: already exists, giving up"
exit 1
fi
FROM="${SRCDIR}/$a"
TO="${DSTDIR}/$a"
DIR=`dirname "${TO}"`
chmod a+r "${FROM}"
test -d "${DIR}" || mkdir -p "${DIR}"
cp -n "${FROM}" "${TO}"
done

View File

@ -1,35 +0,0 @@
#!/bin/bash
set -e
SRCDIR=$1
if test ! -f "$SRCDIR/.file-list-js"; then
(
cd ${SRCDIR}
find \
js/actions \
js/apps/system/_admin \
js/apps/system/_api \
js/apps/system/_system \
js/client \
js/common \
js/node \
js/server \
\
-type f -print
) \
| egrep -v "^js/common/tests/" \
| egrep -v "^js/common/test-data/" \
| egrep -v "^js/client/tests/" \
| egrep -v "^js/client/test-data/" \
| egrep -v "^js/server/tests/" \
| egrep -v "^js/server/test-data/" \
| egrep -v "^js/apps/system/_admin/.*/node_modules/" \
| egrep -v "^js/apps/system/.*/test/" \
| egrep -v "^js/apps/system/.*/test_data/" \
| egrep -v "^js/apps/system/.*/coverage/" \
| egrep -v "fileset.*tests.*fixtures.*an.*odd.*filename" > "$SRCDIR/.file-list-js"
fi
cat "$SRCDIR/.file-list-js"

View File

@ -398,7 +398,9 @@ void Executor::generateCodeExpression(AstNode const* node) {
// thrown by the function // thrown by the function
_buffer->appendText(TRI_CHAR_LENGTH_PAIR(" = function(params) { try { return _AQL.fixValue(state.f")); _buffer->appendText(TRI_CHAR_LENGTH_PAIR(" = function(params) { try { return _AQL.fixValue(state.f"));
_buffer->appendInteger(it.second); _buffer->appendInteger(it.second);
_buffer->appendText(TRI_CHAR_LENGTH_PAIR(".apply(null, params)); } catch (err) { _AQL.throwFromFunction(\"")); _buffer->appendText(TRI_CHAR_LENGTH_PAIR(".apply({ name: \""));
_buffer->appendText(it.first);
_buffer->appendText(TRI_CHAR_LENGTH_PAIR("\" }, params)); } catch (err) { _AQL.throwFromFunction(\""));
_buffer->appendText(it.first); _buffer->appendText(it.first);
_buffer->appendText(TRI_CHAR_LENGTH_PAIR("\", require(\"internal\").errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, _AQL.AQL_TO_STRING(err.stack || String(err))); } }; ")); _buffer->appendText(TRI_CHAR_LENGTH_PAIR("\", require(\"internal\").errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, _AQL.AQL_TO_STRING(err.stack || String(err))); } }; "));
} }

View File

@ -72,6 +72,16 @@ ModificationBlock::~ModificationBlock() {}
/// @brief get some - this accumulates all input and calls the work() method /// @brief get some - this accumulates all input and calls the work() method
AqlItemBlock* ModificationBlock::getSome(size_t atLeast, size_t atMost) { AqlItemBlock* ModificationBlock::getSome(size_t atLeast, size_t atMost) {
// for UPSERT operations, we read and write data in the same collection
// we cannot use any batching here because if the search document is not
// found, the UPSERTs INSERT operation may create it. after that, the
// search document is present and we cannot use an already queried result
// from the initial search batch
if (getPlanNode()->getType() == ExecutionNode::NodeType::UPSERT) {
atLeast = 1;
atMost = 1;
}
std::vector<AqlItemBlock*> blocks; std::vector<AqlItemBlock*> blocks;
std::unique_ptr<AqlItemBlock> replyBlocks; std::unique_ptr<AqlItemBlock> replyBlocks;

View File

@ -1545,7 +1545,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
// subqueries that modify data must not be optimized away // subqueries that modify data must not be optimized away
continue; continue;
} }
// will remove calculation when we get here // will remove subquery when we get here
} }
auto outvars = n->getVariablesSetHere(); auto outvars = n->getVariablesSetHere();

View File

@ -31,10 +31,6 @@
#include "Random/RandomGenerator.h" #include "Random/RandomGenerator.h"
#include <ctime> #include <ctime>
//XXX #warning MOP why? use ConditionVariable
#include <condition_variable>
//XXX #warning MOP why? use Mutex
#include <mutex>
#include <velocypack/Slice.h> #include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h> #include <velocypack/velocypack-aliases.h>

View File

@ -156,18 +156,18 @@ void LogfileManager::collectOptions(std::shared_ptr<ProgramOptions> options) {
options->addOption("--wal.directory", "logfile directory", options->addOption("--wal.directory", "logfile directory",
new StringParameter(&_directory)); new StringParameter(&_directory));
options->addHiddenOption( options->addOption(
"--wal.historic-logfiles", "--wal.historic-logfiles",
"maximum number of historic logfiles to keep after collection", "maximum number of historic logfiles to keep after collection",
new UInt32Parameter(&_historicLogfiles)); new UInt32Parameter(&_historicLogfiles));
options->addHiddenOption( options->addOption(
"--wal.ignore-logfile-errors", "--wal.ignore-logfile-errors",
"ignore logfile errors. this will read recoverable data from corrupted " "ignore logfile errors. this will read recoverable data from corrupted "
"logfiles but ignore any unrecoverable data", "logfiles but ignore any unrecoverable data",
new BooleanParameter(&_ignoreLogfileErrors)); new BooleanParameter(&_ignoreLogfileErrors));
options->addHiddenOption( options->addOption(
"--wal.ignore-recovery-errors", "--wal.ignore-recovery-errors",
"continue recovery even if re-applying operations fails", "continue recovery even if re-applying operations fails",
new BooleanParameter(&_ignoreRecoveryErrors)); new BooleanParameter(&_ignoreRecoveryErrors));

View File

@ -469,13 +469,13 @@ ConsoleFeature::Prompt ConsoleFeature::buildPrompt(ClientFeature* client) {
if (c == 'E') { if (c == 'E') {
// replace protocol // replace protocol
if (ep.find("tcp://") == 0) { if (ep.compare(0, strlen("tcp://"), "tcp://") == 0) {
ep = ep.substr(strlen("tcp://")); ep = ep.substr(strlen("tcp://"));
} else if (ep.find("http+tcp://") == 0) { } else if (ep.compare(0, strlen("http+tcp://"), "http+tcp://") == 0) {
ep = ep.substr(strlen("http+tcp://")); ep = ep.substr(strlen("http+tcp://"));
} else if (ep.find("ssl://") == 0) { } else if (ep.compare(0, strlen("ssl://"), "ssl://") == 0) {
ep = ep.substr(strlen("ssl://")); ep = ep.substr(strlen("ssl://"));
} else if (ep.find("unix://") == 0) { } else if (ep.compare(0, strlen("unix://"), "unix://") == 0) {
ep = ep.substr(strlen("unix://")); ep = ep.substr(strlen("unix://"));
} }
} }

View File

@ -12,7 +12,9 @@ if (MSVC)
INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} DESTINATION bin COMPONENT Libraries) INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} DESTINATION bin COMPONENT Libraries)
endif() endif()
STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ETCDIR_ESCAPED "${CMAKE_INSTALL_FULL_SYSCONFDIR}") file(TO_NATIVE_PATH "${CMAKE_INSTALL_FULL_SYSCONFDIR}" ETCDIR_NATIVE)
STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ETCDIR_ESCAPED "${ETCDIR_NATIVE}")
add_definitions("-D_SYSCONFDIR_=\"${ETCDIR_ESCAPED}\"") add_definitions("-D_SYSCONFDIR_=\"${ETCDIR_ESCAPED}\"")
# database directory # database directory
@ -406,3 +408,15 @@ install(
install( install(
DIRECTORY ${PROJECT_BINARY_DIR}/var/lib/arangodb3-apps DIRECTORY ${PROJECT_BINARY_DIR}/var/lib/arangodb3-apps
DESTINATION ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib) DESTINATION ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib)
if (BUNDLE_OPENSSL)
if (NOT LIB_EAY_RELEASE_DLL OR NOT SSL_EAY_RELEASE_DLL)
message(FATAL_ERROR, "BUNDLE_OPENSSL set but couldn't locate SSL DLLs. Please set LIB_EAY_RELEASE_DLL and SSL_EAY_RELEASE_DLL")
endif()
install (FILES "${LIB_EAY_RELEASE_DLL}"
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin"
COMPONENT Libraries)
install (FILES "${SSL_EAY_RELEASE_DLL}"
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin"
COMPONENT Libraries)
endif()

View File

@ -64,13 +64,16 @@
"frontend/js/lib/sigma.layout.noverlap.js", "frontend/js/lib/sigma.layout.noverlap.js",
"frontend/js/lib/sigma.plugins.fullScreen.js", "frontend/js/lib/sigma.plugins.fullScreen.js",
"frontend/js/lib/sigma.layout.fruchtermanReingold.js", "frontend/js/lib/sigma.layout.fruchtermanReingold.js",
"frontend/js/lib/sigma.exporters.svg.js",
"frontend/js/lib/worker.js", "frontend/js/lib/worker.js",
"frontend/js/lib/supervisor.js", "frontend/js/lib/supervisor.js",
// END SIGMA LIBRARIES // END SIGMA LIBRARIES
// START NEW
"frontend/js/lib/wheelnav.slicePath.js", "frontend/js/lib/wheelnav.slicePath.js",
"frontend/js/lib/wheelnav.min.js", "frontend/js/lib/wheelnav.min.js",
"frontend/js/lib/raphael.min.js", "frontend/js/lib/raphael.min.js",
"frontend/js/lib/raphael.icons.min.js", "frontend/js/lib/raphael.icons.min.js",
// END NEW LIBRARIES
"frontend/js/lib/jsoneditor-min.js", "frontend/js/lib/jsoneditor-min.js",
"frontend/js/lib/strftime-min.js", "frontend/js/lib/strftime-min.js",
"frontend/js/lib/d3.fisheye.min.js", "frontend/js/lib/d3.fisheye.min.js",

View File

@ -1,28 +1,31 @@
/* global AQL_EXECUTE */
'use strict'; 'use strict';
//////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER // DISCLAIMER
/// //
/// Copyright 2010-2013 triAGENS GmbH, Cologne, Germany // Copyright 2010-2013 triAGENS GmbH, Cologne, Germany
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany // Copyright 2016 ArangoDB GmbH, Cologne, Germany
/// //
/// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at // You may obtain a copy of the License at
/// //
/// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
/// //
/// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
/// limitations under the License. // limitations under the License.
/// //
/// Copyright holder is ArangoDB GmbH, Cologne, Germany // Copyright holder is ArangoDB GmbH, Cologne, Germany
/// //
/// @author Michael Hackstein // @author Michael Hackstein
/// @author Alan Plum // @author Heiko Kernbach
//////////////////////////////////////////////////////////////////////////////// // @author Alan Plum
// //////////////////////////////////////////////////////////////////////////////
const joi = require('joi'); const joi = require('joi');
const dd = require('dedent'); const dd = require('dedent');
@ -42,7 +45,7 @@ API_DOCS.basePath = `/_db/${encodeURIComponent(db._name())}`;
const router = createRouter(); const router = createRouter();
module.exports = router; module.exports = router;
router.get('/config.js', function(req, res) { router.get('/config.js', function (req, res) {
const scriptName = req.get('x-script-name'); const scriptName = req.get('x-script-name');
const basePath = req.trustProxy && scriptName || ''; const basePath = req.trustProxy && scriptName || '';
res.send( res.send(
@ -56,7 +59,7 @@ router.get('/config.js', function(req, res) {
}) })
.response(['text/javascript']); .response(['text/javascript']);
router.get('/whoAmI', function(req, res) { router.get('/whoAmI', function (req, res) {
res.json({user: req.arangoUser || null}); res.json({user: req.arangoUser || null});
}) })
.summary('Return the current user') .summary('Return the current user')
@ -65,7 +68,6 @@ router.get('/whoAmI', function(req, res) {
Returns "false" if authentication is disabled. Returns "false" if authentication is disabled.
`); `);
const authRouter = createRouter(); const authRouter = createRouter();
router.use(authRouter); router.use(authRouter);
@ -78,9 +80,8 @@ authRouter.use((req, res, next) => {
next(); next();
}); });
router.get('/api/*', module.context.apiDocumentation({ router.get('/api/*', module.context.apiDocumentation({
swaggerJson(req, res) { swaggerJson (req, res) {
res.json(API_DOCS); res.json(API_DOCS);
} }
})) }))
@ -89,8 +90,7 @@ router.get('/api/*', module.context.apiDocumentation({
Mounts the system API documentation. Mounts the system API documentation.
`); `);
authRouter.get('shouldCheckVersion', function (req, res) {
authRouter.get('shouldCheckVersion', function(req, res) {
const versions = notifications.versions(); const versions = notifications.versions();
res.json(Boolean(versions && versions.enableVersionNotification)); res.json(Boolean(versions && versions.enableVersionNotification));
}) })
@ -99,8 +99,7 @@ authRouter.get('shouldCheckVersion', function(req, res) {
Check if version check is allowed. Check if version check is allowed.
`); `);
authRouter.post('disableVersionCheck', function (req, res) {
authRouter.post('disableVersionCheck', function(req, res) {
notifications.setVersions({enableVersionNotification: false}); notifications.setVersions({enableVersionNotification: false});
res.json('ok'); res.json('ok');
}) })
@ -109,8 +108,7 @@ authRouter.post('disableVersionCheck', function(req, res) {
Disable the version check in web interface Disable the version check in web interface
`); `);
authRouter.post('/query/explain', function (req, res) {
authRouter.post('/query/explain', function(req, res) {
const bindVars = req.body.bindVars; const bindVars = req.body.bindVars;
const query = req.body.query; const query = req.body.query;
const id = req.body.id; const id = req.body.id;
@ -145,8 +143,7 @@ authRouter.post('/query/explain', function(req, res) {
Explains a query in a more user-friendly way than the query_api/explain Explains a query in a more user-friendly way than the query_api/explain
`); `);
authRouter.post('/query/upload/:user', function (req, res) {
authRouter.post('/query/upload/:user', function(req, res) {
let user = req.pathParams.user; let user = req.pathParams.user;
try { try {
@ -187,8 +184,7 @@ authRouter.post('/query/upload/:user', function(req, res) {
This function uploads all given user queries. This function uploads all given user queries.
`); `);
authRouter.get('/query/download/:user', function (req, res) {
authRouter.get('/query/download/:user', function(req, res) {
let user = req.pathParams.user; let user = req.pathParams.user;
try { try {
@ -210,14 +206,12 @@ authRouter.get('/query/download/:user', function(req, res) {
Download and export all queries from the given username. Download and export all queries from the given username.
`); `);
authRouter.get('/query/result/download/:query', function (req, res) {
authRouter.get('/query/result/download/:query', function(req, res) {
let query; let query;
try { try {
query = internal.base64Decode(req.pathParams.query); query = internal.base64Decode(req.pathParams.query);
query = JSON.parse(query); query = JSON.parse(query);
} } catch (e) {
catch (e) {
res.throw('bad request', e.message, {cause: e}); res.throw('bad request', e.message, {cause: e});
} }
@ -232,8 +226,7 @@ authRouter.get('/query/result/download/:query', function(req, res) {
This function downloads the result of a user query. This function downloads the result of a user query.
`); `);
authRouter.post('/graph-examples/create/:name', function (req, res) {
authRouter.post('/graph-examples/create/:name', function(req, res) {
const name = req.pathParams.name; const name = req.pathParams.name;
if (['knows_graph', 'social', 'routeplanner'].indexOf(name) === -1) { if (['knows_graph', 'social', 'routeplanner'].indexOf(name) === -1) {
@ -249,8 +242,7 @@ authRouter.post('/graph-examples/create/:name', function(req, res) {
Create one of the given example graphs. Create one of the given example graphs.
`); `);
authRouter.post('/job', function (req, res) {
authRouter.post('/job', function(req, res) {
db._frontend.save(Object.assign(req.body, {model: 'job'})); db._frontend.save(Object.assign(req.body, {model: 'job'}));
res.json(true); res.json(true);
}) })
@ -265,8 +257,7 @@ authRouter.post('/job', function(req, res) {
Create a new job id entry in a specific system database with a given id. Create a new job id entry in a specific system database with a given id.
`); `);
authRouter.delete('/job', function (req, res) {
authRouter.delete('/job', function(req, res) {
db._frontend.removeByExample({model: 'job'}, false); db._frontend.removeByExample({model: 'job'}, false);
res.json(true); res.json(true);
}) })
@ -275,8 +266,7 @@ authRouter.delete('/job', function(req, res) {
Delete all jobs in a specific system database with a given id. Delete all jobs in a specific system database with a given id.
`); `);
authRouter.delete('/job/:id', function (req, res) {
authRouter.delete('/job/:id', function(req, res) {
db._frontend.removeByExample({id: req.pathParams.id}, false); db._frontend.removeByExample({id: req.pathParams.id}, false);
res.json(true); res.json(true);
}) })
@ -285,8 +275,7 @@ authRouter.delete('/job/:id', function(req, res) {
Delete an existing job id entry in a specific system database with a given id. Delete an existing job id entry in a specific system database with a given id.
`); `);
authRouter.get('/job', function (req, res) {
authRouter.get('/job', function(req, res) {
const result = db._frontend.all().toArray(); const result = db._frontend.all().toArray();
res.json(result); res.json(result);
}) })
@ -295,12 +284,11 @@ authRouter.get('/job', function(req, res) {
This function returns the job ids of all currently running jobs. This function returns the job ids of all currently running jobs.
`); `);
authRouter.get('/graph/:name', function (req, res) {
authRouter.get('/graph/:name', function(req, res) { var _ = require('lodash');
var _ = require("lodash");
var name = req.pathParams.name; var name = req.pathParams.name;
var gm = require("@arangodb/general-graph"); var gm = require('@arangodb/general-graph');
//var traversal = require("@arangodb/graph/traversal"); // var traversal = require("@arangodb/graph/traversal");
var graph = gm._graph(name); var graph = gm._graph(name);
var vertexName = graph._vertexCollections()[0].name(); var vertexName = graph._vertexCollections()[0].name();
@ -313,10 +301,13 @@ authRouter.get('/graph/:name', function(req, res) {
var cursor = AQL_EXECUTE(aqlQuery); var cursor = AQL_EXECUTE(aqlQuery);
var nodesObj = {}, nodesArr = [], edgesObj = {}, edgesArr = []; var nodesObj = {};
var nodesArr = [];
var edgesObj = {};
var edgesArr = [];
_.each(cursor.json, function(obj) { _.each(cursor.json, function (obj) {
_.each(obj.edges, function(edge) { _.each(obj.edges, function (edge) {
if (edge._to && edge._from) { if (edge._to && edge._from) {
edgesObj[edge._from + edge._to] = { edgesObj[edge._from + edge._to] = {
id: edge._id, id: edge._id,
@ -327,11 +318,10 @@ authRouter.get('/graph/:name', function(req, res) {
} }
}); });
var label; var label;
_.each(obj.vertices, function(node) { _.each(obj.vertices, function (node) {
if (node.label) { if (node.label) {
label = node.label; label = node.label;
} } else {
else {
label = node._id; label = node._id;
} }
@ -346,11 +336,11 @@ authRouter.get('/graph/:name', function(req, res) {
}); });
}); });
//array format for sigma.js // array format for sigma.js
_.each(edgesObj, function(node) { _.each(edgesObj, function (node) {
edgesArr.push(node); edgesArr.push(node);
}); });
_.each(nodesObj, function(node) { _.each(nodesObj, function (node) {
nodesArr.push(node); nodesArr.push(node);
}); });
@ -358,7 +348,6 @@ authRouter.get('/graph/:name', function(req, res) {
nodes: nodesArr, nodes: nodesArr,
edges: edgesArr edges: edgesArr
}); });
}) })
.summary('Return vertices and edges of a graph.') .summary('Return vertices and edges of a graph.')
.description(dd` .description(dd`

File diff suppressed because one or more lines are too long

View File

@ -1041,8 +1041,10 @@ if (list.length > 0) {
</div> </div>
</div> </div>
<div class="pure-g pure-table pure-table-body"> <% _.each(specific, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div> <div class="pure-g pure-table pure-table-body"> <% _.each(specific, function(val, key) { %> <div class="<%= genClass %> left"><%=val.name%></div>
<div class="<%= genClass %> left"><%=val%></div> <% }); %> </div> <div class="<%= genClass %> left"> <% var VALUE; %> <% if (val.value) { %> <% VALUE = val.value %> <% } else { %> <% VALUE = val.default %> <% } %> <% if (val.type === 'string') { %> <input type="text" value="<%=VALUE%>" placeholder=""></input> <% } %> <% if (val.type === 'color') { %> <input type='color' name='color' value="<%=VALUE%>"/> <% } %> <% if (val.type === 'select') { %> <div class="<%= genClass %> left">
<select> <% _.each(val, function(option, optKey) { %> <% if (option.name) { %> <option> <%=option.name%> </option> <% } %> <% }); %> </select>
</div> <% } %> </div> <% }); %> </div>
</div> </div>
@ -1063,22 +1065,37 @@ if (list.length > 0) {
</div> </div>
</div> </div>
<div class="pure-g pure-table pure-table-body"> <% _.each(general, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div> <div class="pure-g pure-table pure-table-body"> <% _.each(general, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div> <% if (val.type === 'select') { %> <div class="<%= genClass %> left">
<div class="<%= genClass %> left"><%=val%></div> <% }); %> </div> <select> <% _.each(val, function(option, optKey) { %> <% if (option.name) { %> <option> <%=option.name%> </option> <% } %> <% }); %> </select>
</div> <% } %> <% if (val.type === 'numeric') { %> <input type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input> <% } %> <% }); %> </div>
</div> </div>
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button> <button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button>
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Restore defaults</button>
</div></script><script id="graphViewer2.ejs" type="text/template"><div class="graphContent" id="graphContainer"> </div></script><script id="graphViewer2.ejs" type="text/template"><div class="graphContent" id="graphContainer">
<div class="headerBar"> <div class="headerBar">
<div class="headerButtonBar" style="margin: 0;"> <div class="headerButtonBar" style="margin: 0;">
<ul class="headerButtonList"> <ul class="headerButtonList">
<li class="enabled"> <li class="enabled">
<a id="addDocument" class="headerButton"> <a id="graph-fullscreen-btn" class="headerButton">
<span title="Add new document"> <span title="Switch to fullscreen mode">
<i class="fa fa-file fa-stack-1x"></i> <i class="fa fa-television"></i>
<i class="fa fa-plus fa-stack-1x fa-top"></i> </span>
</a>
</li>
<li class="enabled">
<a id="downloadPNG" class="headerButton">
<span title="Download visible graph as png image">
<i class="fa fa-camera fa-stack-1x"></i>
</span>
</a>
</li>
<li class="enabled">
<a id="selectNodes" class="headerButton">
<span title="Download visible graph as png image">
<i class="fa fa-pencil fa-stack-1x"></i>
</span> </span>
</a> </a>
</li> </li>
@ -1086,7 +1103,7 @@ if (list.length > 0) {
</div> </div>
</div> </div>
<div id="graph-fullscreen-btn"><i class="fa fa-television"></i></div> <!--<div id="graph-fullscreen-btn"><i class="fa fa-desktop"></i></div>-->
<div id="graph-container" oncontextmenu="return false;"></div> <div id="graph-container" oncontextmenu="return false;"></div>
</div></script><script id="graphViewGroupByEntry.ejs" type="text/template"><div class="control-group"> </div></script><script id="graphViewGroupByEntry.ejs" type="text/template"><div class="control-group">
<label for="<%=type %>_<%=id%>" class="control-label">Attribute <%=id%></label> <label for="<%=type %>_<%=id%>" class="control-label">Attribute <%=id%></label>
@ -2706,4 +2723,4 @@ var cutByResolution = function (str) {
</div> </div>
<div id="workMonitorContent" class="innerContent"> <div id="workMonitorContent" class="innerContent">
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1467885481708"></script><script src="app.js?version=1467885481708"></script></body></html> </div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1467901818158"></script><script src="app.js?version=1467901818158"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
/* jshint strict: false, unused: false */ /* jshint strict: false, unused: false */
/* global Backbone, window, arangoDocumentModel, $, arangoHelper */ /* global Backbone, window, arangoDocumentModel, $, arangoHelper */
window.arangoDocument = Backbone.Collection.extend({ window.ArangoDocument = Backbone.Collection.extend({
url: '/_api/document/', url: '/_api/document/',
model: arangoDocumentModel, model: arangoDocumentModel,
collectionInfo: {}, collectionInfo: {},

View File

@ -0,0 +1,248 @@
;(function(undefined) {
'use strict';
/**
* Sigma SVG Exporter
* ===================
*
* This plugin is designed to export a graph to a svg file that can be
* downloaded or just used elsewhere.
*
* Author: Guillaume Plique (Yomguithereal)
* Version: 0.0.1
*/
// Terminating if sigma were not to be found
if (typeof sigma === 'undefined')
throw 'sigma.renderers.snapshot: sigma not in scope.';
/**
* Polyfills
*/
var URL = this.URL || this.webkitURL || this;
/**
* Utilities
*/
function createBlob(data) {
return new Blob(
[data],
{type: 'image/svg+xml;charset=utf-8'}
);
}
function download(string, filename) {
if (typeof safari !== 'undefined') {
var msg = "File download does not work in Safari. Please use a modern web browser such as Firefox, Chrome, or Internet Explorer 11.";
alert(msg);
throw new Error(msg);
}
// Blob
var blob = createBlob(string),
objectUrl = window.URL.createObjectURL(blob);
if (navigator.msSaveBlob) { // IE11+ : (has Blob, but not a[download])
navigator.msSaveBlob(blob, filename);
} else if (navigator.msSaveOrOpenBlob) { // IE10+ : (has Blob, but not a[download])
navigator.msSaveOrOpenBlob(blob, filename);
} else {
// A-download
var anchor = document.createElement('a');
anchor.setAttribute('href', objectUrl);
anchor.setAttribute('download', filename);
// Firefox requires the link to be added to the DOM before it can be clicked.
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
setTimeout(function() { // Firefox needs a timeout
window.URL.revokeObjectURL(objectUrl);
}, 0);
}
/**
* Defaults
*/
var DEFAULTS = {
size: '1000',
width: '1000',
height: '1000',
margin: 0.05,
classes: true,
labels: true,
data: false,
download: false,
filename: 'graph.svg'
};
var XMLNS = 'http://www.w3.org/2000/svg';
/**
* Subprocesses
*/
function optimize(svg, prefix, params) {
var nodeColorIndex = {},
edgeColorIndex = {},
count = 0,
color,
style,
styleText = '',
f,
i,
l;
// Creating style tag if needed
if (params.classes) {
style = document.createElementNS(XMLNS, 'style');
svg.insertBefore(style, svg.firstChild);
}
// Iterating over nodes
var nodes = svg.querySelectorAll('[id="' + prefix + '-group-nodes"] > [class="' + prefix + '-node"]');
for (i = 0, l = nodes.length, f = true; i < l; i++) {
color = nodes[i].getAttribute('fill');
if (!params.data)
nodes[i].removeAttribute('data-node-id');
if (params.classes) {
if (!(color in nodeColorIndex)) {
nodeColorIndex[color] = (f ? prefix + '-node' : 'c-' + (count++));
styleText += '.' + nodeColorIndex[color] + '{fill: ' + color + '}';
}
if (nodeColorIndex[color] !== prefix + '-node')
nodes[i].setAttribute('class', nodes[i].getAttribute('class') + ' ' + nodeColorIndex[color]);
nodes[i].removeAttribute('fill');
}
f = false;
}
// Iterating over edges
var edges = svg.querySelectorAll('[id="' + prefix + '-group-edges"] > [class="' + prefix + '-edge"]');
for (i = 0, l = edges.length, f = true; i < l; i++) {
color = edges[i].getAttribute('stroke');
if (!params.data)
edges[i].removeAttribute('data-edge-id');
if (params.classes) {
if (!(color in edgeColorIndex)) {
edgeColorIndex[color] = (f ? prefix + '-edge' : 'c-' + (count++));
styleText += '.' + edgeColorIndex[color] + '{stroke: ' + color + '}';
}
if (edgeColorIndex[color] !== prefix + '-edge')
edges[i].setAttribute('class', edges[i].getAttribute('class') + ' ' + edgeColorIndex[color]);
edges[i].removeAttribute('stroke');
}
f = false;
}
if (params.classes)
style.appendChild(document.createTextNode(styleText));
}
/**
* Extending prototype
*/
sigma.prototype.toSVG = function(params) {
params = params || {};
var prefix = this.settings('classPrefix'),
w = params.size || params.width || DEFAULTS.size,
h = params.size || params.height || DEFAULTS.size,
margin = params.margin || DEFAULTS.margin;
// Creating a dummy container
var container = document.createElement('div');
container.setAttribute('width', w);
container.setAttribute('height', h);
container.setAttribute('style', 'position:absolute; top: 0px; left:0px; width: ' + w + 'px; height: ' + h + 'px;');
// Add margin to deal with curved edges
var sideMargin = this.settings('sideMargin');
this.settings('sideMargin', margin);
// Fit graph to viewport
var autoRescale = this.settings('autoRescale');
this.settings('autoRescale', true);
// Creating a camera
var camera = this.addCamera();
// Creating a svg renderer
var renderer = this.addRenderer({
camera: camera,
container: container,
type: 'svg',
forceLabels: !!params.labels
});
// Refreshing
renderer.resize(w, h);
this.refresh();
// Dropping camera and renderers before something nasty happens
this.killRenderer(renderer);
this.killCamera(camera);
// reset setting
this.settings('sideMargin', sideMargin);
this.settings('autoRescale', autoRescale);
// Retrieving svg
var svg = container.querySelector('svg');
svg.removeAttribute('style');
svg.setAttribute('width', w + 'px');
svg.setAttribute('height', h + 'px');
svg.setAttribute('x', '0px');
svg.setAttribute('y', '0px');
// svg.setAttribute('viewBox', '0 0 1000 1000');
// Dropping labels
if (!params.labels) {
var labelGroup = svg.querySelector('[id="' + prefix + '-group-labels"]');
svg.removeChild(labelGroup);
}
// Dropping hovers
var hoverGroup = svg.querySelector('[id="' + prefix + '-group-hovers"]');
svg.removeChild(hoverGroup);
// Optims?
params.classes = (params.classes !== false);
if (!params.data || params.classes)
optimize(svg, prefix, params);
// Retrieving svg string
var svgString = svg.outerHTML;
// Paranoid cleanup
container = null;
// Output string
var output = '<?xml version="1.0" encoding="utf-8"?>\n';
output += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
output += svgString;
if (params.download)
download(output, params.filename || DEFAULTS.filename);
return output;
};
}).call(this);

View File

@ -857,6 +857,9 @@
if (this.queryView) { if (this.queryView) {
this.queryView.resize(); this.queryView.resize();
} }
if (this.graphViewer2) {
this.graphViewer2.resize();
}
if (this.documentsView) { if (this.documentsView) {
this.documentsView.resize(); this.documentsView.resize();
} }

View File

@ -30,8 +30,38 @@
<div class="pure-g pure-table pure-table-body"> <div class="pure-g pure-table pure-table-body">
<% _.each(specific, function(val, key) { %> <% _.each(specific, function(val, key) { %>
<div class="<%= genClass %> left"><%=key%></div> <div class="<%= genClass %> left"><%=val.name%></div>
<div class="<%= genClass %> left"><%=val%></div> <div class="<%= genClass %> left">
<% var VALUE; %>
<% if (val.value) { %>
<% VALUE = val.value %>
<% } else { %>
<% VALUE = val.default %>
<% } %>
<% if (val.type === 'string') { %>
<input type="text" value="<%=VALUE%>" placeholder=""></input>
<% } %>
<% if (val.type === 'color') { %>
<input type='color' name='color' value="<%=VALUE%>"/>
<% } %>
<% if (val.type === 'select') { %>
<div class="<%= genClass %> left">
<select>
<% _.each(val, function(option, optKey) { %>
<% if (option.name) { %>
<option> <%=option.name%> </option>
<% } %>
<% }); %>
</select>
</div>
<% } %>
</div>
<% }); %> <% }); %>
</div> </div>
@ -55,15 +85,33 @@
</div> </div>
<div class="pure-g pure-table pure-table-body"> <div class="pure-g pure-table pure-table-body">
<% _.each(general, function(val, key) { %> <% _.each(general, function(val, key) { %>
<div class="<%= genClass %> left"><%=key%></div> <div class="<%= genClass %> left"><%=key%></div>
<div class="<%= genClass %> left"><%=val%></div>
<% if (val.type === 'select') { %>
<div class="<%= genClass %> left">
<select>
<% _.each(val, function(option, optKey) { %>
<% if (option.name) { %>
<option> <%=option.name%> </option>
<% } %>
<% }); %>
</select>
</div>
<% } %>
<% if (val.type === 'numeric') { %>
<input type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input>
<% } %>
<% }); %> <% }); %>
</div> </div>
</div> </div>
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button> <button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button>
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Restore defaults</button>
</div> </div>
</script> </script>

View File

@ -5,10 +5,23 @@
<div class="headerButtonBar" style="margin: 0;"> <div class="headerButtonBar" style="margin: 0;">
<ul class="headerButtonList"> <ul class="headerButtonList">
<li class="enabled"> <li class="enabled">
<a id="addDocument" class="headerButton"> <a id="graph-fullscreen-btn" class="headerButton">
<span title="Add new document"> <span title="Switch to fullscreen mode">
<i class="fa fa-file fa-stack-1x"></i> <i class="fa fa-television"></i>
<i class="fa fa-plus fa-stack-1x fa-top"></i> </span>
</a>
</li>
<li class="enabled">
<a id="downloadPNG" class="headerButton">
<span title="Download visible graph as png image">
<i class="fa fa-camera fa-stack-1x"></i>
</span>
</a>
</li>
<li class="enabled">
<a id="selectNodes" class="headerButton">
<span title="Download visible graph as png image">
<i class="fa fa-pencil fa-stack-1x"></i>
</span> </span>
</a> </a>
</li> </li>
@ -16,7 +29,7 @@
</div> </div>
</div> </div>
<div id="graph-fullscreen-btn"><i class="fa fa-television"></i></div> <!--<div id="graph-fullscreen-btn"><i class="fa fa-desktop"></i></div>-->
<div id="graph-container" oncontextmenu="return false;"></div> <div id="graph-container" oncontextmenu="return false;"></div>
</div> </div>
</script> </script>

View File

@ -8,14 +8,81 @@
el: '#content', el: '#content',
general: { general: {
'layout': undefined, 'Layout': {
'depth': undefined type: 'select',
noverlap: {
name: 'No overlap (fast)'
},
force: {
name: 'Force (slow)'
},
fruchtermann: {
name: 'Fruchtermann (very slow)'
}
},
'Renderer': {
type: 'select',
canvas: {
name: 'Canvas (editable)'
},
webgl: {
name: 'WebGL (only display)'
}
},
'depth': {
type: 'numeric',
value: 2
}
}, },
specific: { specific: {
'node_label': undefined, 'nodeLabel': {
'node_color': undefined, type: 'string',
'node_size': undefined name: 'Node label',
desc: 'Default node color. RGB or HEX value.',
default: '_key'
},
'nodeColor': {
type: 'color',
name: 'Node color',
desc: 'Default node color. RGB or HEX value.',
default: '#2ecc71'
},
'nodeSize': {
type: 'string',
name: 'Node size',
desc: 'Default node size. Numeric value > 0.',
value: undefined
},
'edgeLabel': {
type: 'string',
name: 'Edge label',
desc: 'Default edge label.',
value: undefined
},
'edgeColor': {
type: 'color',
name: 'Edge color',
desc: 'Default edge color. RGB or HEX value.',
default: '#cccccc'
},
'edgeSize': {
type: 'string',
name: 'Edge thickness',
desc: 'Default edge thickness. Numeric value > 0.',
value: undefined
},
'edgeType': {
type: 'select',
name: 'Edge type',
desc: 'The type of the edge',
canvas: {
name: 'Straight'
},
webgl: {
name: 'Curved'
}
}
}, },
template: templateEngine.createTemplate('graphSettingsView.ejs'), template: templateEngine.createTemplate('graphSettingsView.ejs'),
@ -24,6 +91,14 @@
this.name = options.name; this.name = options.name;
}, },
loadGraphSettings: function () {
},
saveGraphSettings: function () {
},
events: { events: {
}, },
@ -33,6 +108,9 @@
specific: this.specific specific: this.specific
})); }));
arangoHelper.buildGraphSubNav(this.name, 'Settings'); arangoHelper.buildGraphSubNav(this.name, 'Settings');
// load graph settings from local storage
// apply those values to view then
} }
}); });

View File

@ -14,6 +14,10 @@
this.initSigma(); this.initSigma();
}, },
events: {
'click #downloadPNG': 'downloadSVG'
},
initSigma: function () { initSigma: function () {
// init sigma // init sigma
try { try {
@ -30,19 +34,40 @@
} catch (ignore) {} } catch (ignore) {}
}, },
downloadSVG: function () {
var self = this;
this.currentGraph.toSVG({
download: true,
filename: self.name + '.svg',
size: 1000
});
},
resize: function () {
// adjust container widht + height
$('#graph-container').width($('.centralContent').width());
$('#graph-container').height($('.centralRow').height() - 150);
},
render: function () { render: function () {
this.$el.html(this.template.render({})); this.$el.html(this.template.render({}));
arangoHelper.buildGraphSubNav(this.name, 'Content'); arangoHelper.buildGraphSubNav(this.name, 'Content');
// adjust container widht + height this.resize();
$('#graph-container').width($('.centralContent').width());
$('#graph-container').height($('.centralRow').height() - 150);
this.fetchGraph(); this.fetchGraph();
}, },
fetchGraph: function () { fetchGraph: function () {
var self = this; var self = this;
$('#content').append(
'<div id="calculatingGraph" style="position: absolute; left: 25px; top: 130px;">' +
'<i class="fa fa-circle-o-notch fa-spin" style="margin-right: 10px;"></i>' +
'Calculating layout. Please wait ... </div>'
);
// TODO LOAD GRAPH SETTINGS
// var settings = this.loadGraphSettings();
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
@ -50,6 +75,9 @@
contentType: 'application/json', contentType: 'application/json',
success: function (data) { success: function (data) {
self.renderGraph(data); self.renderGraph(data);
},
error: function () {
$('#calculatingGraph').html('Failed to fetch graph information.');
} }
}); });
}, },
@ -117,6 +145,12 @@
generateMenu(e, nodeId); generateMenu(e, nodeId);
}, },
loadGraphSettings: function () {
var settings;
return settings;
},
editNode: function (id) { editNode: function (id) {
var callback = function () {}; var callback = function () {};
@ -132,35 +166,50 @@
this.Sigma = sigma; this.Sigma = sigma;
var algorithm = 'force';
var renderer = 'webgl';
var settings = {
doubleClickEnabled: false,
minEdgeSize: 0.5,
maxEdgeSize: 4,
enableEdgeHovering: true,
// edgeHoverColor: 'edge',
// defaultEdgeHoverColor: '#000',
// defaultEdgeType: 'curve',
edgeHoverSizeRatio: 1,
edgeHoverExtremities: true
};
// adjust display settings for big graphs
if (graph.nodes.length > 500) {
// show node label if size is 20
settings.labelThreshold = 20;
}
// adjust display settings for webgl renderer
if (renderer === 'webgl') {
settings.enableEdgeHovering = false;
}
// create sigma graph // create sigma graph
var s = new this.Sigma({ var s = new this.Sigma({
graph: graph, graph: graph,
container: 'graph-container', container: 'graph-container',
renderer: { renderer: {
container: document.getElementById('graph-container'), container: document.getElementById('graph-container'),
type: 'canvas' type: renderer
}, },
settings: { settings: settings
doubleClickEnabled: false,
minEdgeSize: 0.5,
maxEdgeSize: 4,
enableEdgeHovering: true,
// edgeHoverColor: 'edge',
// defaultEdgeHoverColor: '#000',
// defaultEdgeType: 'curve',
edgeHoverSizeRatio: 1,
edgeHoverExtremities: true
}
}); });
this.currentGraph = s;
sigma.plugins.fullScreen({ sigma.plugins.fullScreen({
container: 'graph-container', container: 'graph-container',
btnId: 'graph-fullscreen-btn' btnId: 'graph-fullscreen-btn'
}); });
var renderer = 'fruchtermann'; if (algorithm === 'noverlap') {
if (renderer === 'noverlap') {
var noverlapListener = s.configNoverlap({ var noverlapListener = s.configNoverlap({
nodeMargin: 0.1, nodeMargin: 0.1,
scaleNodes: 1.05, scaleNodes: 1.05,
@ -175,7 +224,7 @@
if (e.type === 'interpolate') { if (e.type === 'interpolate') {
} }
}); });
} else if (renderer === 'fruchtermann') { } else if (algorithm === 'fruchtermann') {
var frListener = sigma.layouts.fruchtermanReingold.configure(s, { var frListener = sigma.layouts.fruchtermanReingold.configure(s, {
iterations: 500, iterations: 500,
easing: 'quadraticInOut', easing: 'quadraticInOut',
@ -192,70 +241,60 @@
e.originalColor = e.color; e.originalColor = e.color;
}); });
if (document.addEventListener) { if (renderer !== 'webgl') {
document.addEventListener('contextmenu', function (e) { s.bind('rightClickNode', function (e) {
// my custom functionality on right click var nodeId = e.data.node.id;
e.preventDefault(); self.createNodeContextMenu(nodeId, e);
}, false); });
} else {
document.attachEvent('oncontextmenu', function () { s.bind('doubleClickNode', function (e) {
// my custom functionality on right click var nodeId = e.data.node.id;
window.event.returnValue = false; var toKeep = s.graph.neighbors(nodeId);
toKeep[nodeId] = e.data.node;
s.graph.nodes().forEach(function (n) {
if (toKeep[n.id]) {
n.color = n.originalColor;
} else {
n.color = '#eee';
}
});
s.graph.edges().forEach(function (e) {
if (toKeep[e.source] && toKeep[e.target]) {
e.color = 'rgb(64, 74, 83)';
} else {
e.color = '#eee';
}
});
s.refresh();
});
s.bind('doubleClickStage', function () {
s.graph.nodes().forEach(function (n) {
n.color = n.originalColor;
});
s.graph.edges().forEach(function (e) {
e.color = e.originalColor;
});
s.refresh();
});
s.bind('clickStage', function () {
self.clearOldContextMenu();
}); });
} }
s.bind('rightClickNode', function (e) {
var nodeId = e.data.node.id;
self.createNodeContextMenu(nodeId, e);
});
s.bind('doubleClickNode', function (e) {
var nodeId = e.data.node.id;
var toKeep = s.graph.neighbors(nodeId);
toKeep[nodeId] = e.data.node;
s.graph.nodes().forEach(function (n) {
if (toKeep[n.id]) {
n.color = n.originalColor;
} else {
n.color = '#eee';
}
});
s.graph.edges().forEach(function (e) {
if (toKeep[e.source] && toKeep[e.target]) {
e.color = 'rgb(64, 74, 83)';
} else {
e.color = '#eee';
}
});
s.refresh();
});
s.bind('doubleClickStage', function () {
s.graph.nodes().forEach(function (n) {
n.color = n.originalColor;
});
s.graph.edges().forEach(function (e) {
e.color = e.originalColor;
});
s.refresh();
});
s.bind('clickStage', function () {
self.clearOldContextMenu();
});
var dragListener; var dragListener;
// Initialize the dragNodes plugin: // Initialize the dragNodes plugin:
if (renderer === 'noverlap') { if (algorithm === 'noverlap') {
s.startNoverlap(); s.startNoverlap();
// allow draggin nodes // allow draggin nodes
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]); dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
} else if (renderer === 'force') { } else if (algorithm === 'force') {
s.startForceAtlas2({worker: true, barnesHutOptimize: false}); s.startForceAtlas2({worker: true, barnesHutOptimize: false});
window.setTimeout(function () { window.setTimeout(function () {
@ -263,7 +302,7 @@
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]); dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
console.log('stopped force'); console.log('stopped force');
}, 3000); }, 3000);
} else if (renderer === 'fruchtermann') { } else if (algorithm === 'fruchtermann') {
// Start the Fruchterman-Reingold algorithm: // Start the Fruchterman-Reingold algorithm:
sigma.layouts.fruchtermanReingold.start(s); sigma.layouts.fruchtermanReingold.start(s);
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]); dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
@ -271,6 +310,8 @@
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]); dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
} }
console.log(dragListener); console.log(dragListener);
$('#calculatingGraph').remove();
} }
}); });

View File

@ -840,7 +840,7 @@ function FCALL_USER (name, parameters) {
} }
try { try {
return FIX_VALUE(UserFunctions[prefix][name].func.apply(null, parameters)); return FIX_VALUE(UserFunctions[prefix][name].func.apply({ name: name }, parameters));
} catch (err) { } catch (err) {
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err.stack || String(err))); WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err.stack || String(err)));
return null; return null;
@ -888,7 +888,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
if (applyDirect) { if (applyDirect) {
try { try {
return FIX_VALUE(toCall.apply(null, args)); return FIX_VALUE(toCall.apply({ name: name }, args));
} catch (err) { } catch (err) {
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err)); WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err));
return null; return null;
@ -902,7 +902,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
for (i in values) { for (i in values) {
if (values.hasOwnProperty(i)) { if (values.hasOwnProperty(i)) {
args[0] = values[i]; args[0] = values[i];
result[i] = FIX_VALUE(toCall.apply(null, args)); result[i] = FIX_VALUE(toCall.apply({ name: name }, args));
} }
} }
return result; return result;
@ -910,7 +910,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
result = []; result = [];
for (i = 0; i < values.length; ++i) { for (i = 0; i < values.length; ++i) {
args[0] = values[i]; args[0] = values[i];
result[i] = FIX_VALUE(toCall.apply(null, args)); result[i] = FIX_VALUE(toCall.apply({ name: name }, args));
} }
return result; return result;
} }

View File

@ -320,6 +320,23 @@ function ahuacatlCallUserDefinedTestSuite () {
testThrows : function () { testThrows : function () {
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN CALL('UNITTESTS::FUNC::THROWING')"); assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN CALL('UNITTESTS::FUNC::THROWING')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN APPLY('UNITTESTS::FUNC::THROWING', [ ])"); assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN APPLY('UNITTESTS::FUNC::THROWING', [ ])");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test function name passed from the outside
////////////////////////////////////////////////////////////////////////////////
testFunctionName : function () {
aqlfunctions.register("UnitTests::func::call", function () { return this.name; });
var actual = getQueryResults("RETURN UnitTests::func::call()");
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
actual = getQueryResults("RETURN CALL('UNITTESTS::FUNC::CALL', [])");
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
actual = getQueryResults("RETURN CALL('unittests::func::call', [])");
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
} }
}; };

View File

@ -744,6 +744,78 @@ function ahuacatlModifySuite () {
queries.forEach(function(query) { queries.forEach(function(query) {
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, query, { "@cn": cn1 }, query); assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, query, { "@cn": cn1 }, query);
}); });
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test upsert on same document
////////////////////////////////////////////////////////////////////////////////
testUpsertDocumentInitiallyPresent : function () {
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
var expected = { writesExecuted: 1, writesIgnored: 0 };
var actual = AQL_EXECUTE("UPSERT { value1: 0 } INSERT { value1: 0, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
assertEqual(2001, c1.count());
assertEqual(expected, sanitizeStats(actual.stats));
assertEqual([ ], actual.json);
assertEqual(0, c1.document("test0").value1);
assertEqual(1, c1.document("test0").value2);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test upsert on same document
////////////////////////////////////////////////////////////////////////////////
testUpsertDocumentInitiallyNotPresent : function () {
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
var expected = { writesExecuted: 1, writesIgnored: 0 };
var actual = AQL_EXECUTE("UPSERT { value1: 999999 } INSERT { _key: 'test999999', value1: 999999, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
assertEqual(2002, c1.count());
assertEqual(expected, sanitizeStats(actual.stats));
assertEqual([ ], actual.json);
assertEqual(999999, c1.document("test999999").value1);
assertEqual(0, c1.document("test999999").value2);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test upsert on same document
////////////////////////////////////////////////////////////////////////////////
testUpsertDocumentRepeatedInitiallyPresent : function () {
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
var expected = { writesExecuted: 2000, writesIgnored: 0 };
var actual = AQL_EXECUTE("FOR i IN 1..2000 UPSERT { value1: 0 } INSERT { value1: 0, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
assertEqual(2001, c1.count());
assertEqual(expected, sanitizeStats(actual.stats));
assertEqual([ ], actual.json);
assertEqual(0, c1.document("test0").value1);
assertEqual(1, c1.document("test0").value2);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test upsert on same document
////////////////////////////////////////////////////////////////////////////////
testUpsertDocumentRepeatedInitiallyNotPresent : function () {
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
var expected = { writesExecuted: 2000, writesIgnored: 0 };
var actual = AQL_EXECUTE("FOR i IN 1..2000 UPSERT { value1: 999999 } INSERT { _key: 'test999999', value1: 999999, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
assertEqual(2002, c1.count());
assertEqual(expected, sanitizeStats(actual.stats));
assertEqual([ ], actual.json);
assertEqual(999999, c1.document("test999999").value1);
assertEqual(1, c1.document("test999999").value2);
} }
}; };

View File

@ -546,7 +546,7 @@ void SimpleHttpClient::setRequest(
for (; i != _pathToBasicAuth.end(); ++i) { for (; i != _pathToBasicAuth.end(); ++i) {
std::string& f = i->first; std::string& f = i->first;
if (l->find(f) == 0) { if (l->compare(0, f.size(), f) == 0) {
// f is prefix of l // f is prefix of l
if (f.length() > foundPrefix.length()) { if (f.length() > foundPrefix.length()) {
foundPrefix = f; foundPrefix = f;

View File

@ -78,36 +78,34 @@ static v8::Handle<v8::Value> ObjectVPackObject(v8::Isolate* isolate,
} else { } else {
// optimized code path for translated system attributes // optimized code path for translated system attributes
VPackSlice v = VPackSlice(k.begin() + 1); VPackSlice v = VPackSlice(k.begin() + 1);
v8::Local<v8::Value> sub;
if (v.isString()) {
char const* p = v.getString(l);
sub = TRI_V8_ASCII_PAIR_STRING(p, l);
} else {
sub = TRI_VPackToV8(isolate, v, options, &slice);
}
uint8_t which = static_cast<uint8_t>(k.getUInt()) + VelocyPackHelper::AttributeBase; uint8_t which = static_cast<uint8_t>(k.getUInt()) + VelocyPackHelper::AttributeBase;
switch (which) { switch (which) {
case VelocyPackHelper::KeyAttribute: { case VelocyPackHelper::KeyAttribute: {
char const* p = v.getString(l); object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_KeyKey), sub);
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_KeyKey), TRI_V8_ASCII_PAIR_STRING(p, l));
break; break;
} }
case VelocyPackHelper::RevAttribute: { case VelocyPackHelper::RevAttribute: {
char const* p = v.getString(l); object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_RevKey), sub);
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_RevKey), TRI_V8_ASCII_PAIR_STRING(p, l));
break; break;
} }
case VelocyPackHelper::IdAttribute: { case VelocyPackHelper::IdAttribute: {
if (v.isString()) { object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), sub);
char const* p = v.getString(l);
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), TRI_V8_ASCII_PAIR_STRING(p, l));
} else {
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), TRI_VPackToV8(isolate, v, options, &slice));
}
break; break;
} }
case VelocyPackHelper::FromAttribute: { case VelocyPackHelper::FromAttribute: {
char const* p = v.getString(l); object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_FromKey), sub);
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_FromKey), TRI_V8_ASCII_PAIR_STRING(p, l));
break; break;
} }
case VelocyPackHelper::ToAttribute: { case VelocyPackHelper::ToAttribute: {
char const* p = v.getString(l); object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_ToKey), sub);
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_ToKey), TRI_V8_ASCII_PAIR_STRING(p, l));
break; break;
} }
} }