// From developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys if (!Object.keys) {
Object.keys = (function () { 'use strict'; var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ], dontEnumsLength = dontEnums.length; return function (obj) { if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { throw new TypeError('Object.keys called on non-object'); } var result = [], prop, i; for (prop in obj) { if (hasOwnProperty.call(obj, prop)) { result.push(prop); } } if (hasDontEnumBug) { for (i = 0; i < dontEnumsLength; i++) { if (hasOwnProperty.call(obj, dontEnums[i])) { result.push(dontEnums[i]); } } } return result; }; }());
}
!(function(app) {
app.config([ '$routeProvider', '$locationProvider', '$rootScopeProvider', '$logProvider', '$compileProvider', function($routeProvider, $locationProvider, $rootScopeProvider, $logProvider, $compileProvider) { $routeProvider .when('/', { templateUrl: '/html/index.html', }) .when('/:keyspace', { templateUrl: '/html/keyspace.html', controller: 'keyspace', resolve: {cluster: 'cluster'} }) .when('/:keyspace/:table', { templateUrl: '/html/table.html', controller: 'table', resolve: {cluster: 'cluster'} }) .otherwise({redirect:'/'}) $locationProvider.html5Mode(true) $rootScopeProvider.digestTtl(10000) $logProvider.debugEnabled(true) $compileProvider.debugInfoEnabled(true) } ]) app.factory('cluster', [ '$http', '$rootScope', '$q', function($http, $rootScope, $q) { var cluster = { keyspaces: null, hosts: null, keyspace: null, execute: function(statement, options) { var deferred = $q.defer(); options = options || {} $http({ method: 'POST', url: '/execute', data: { statement: statement, options: options } }) .success(function(data, status, headers, config) { deferred.resolve(data) }) .error(function(data, status, headers, config) { deferred.reject(data) }) return deferred.promise } } var resolved = false var deferred = $q.defer() var events = new EventSource('/events'); events.onopen = function(e) { updateCluster(); return false; } $rootScope.$on('$destroy', function() { events.close(); }) var updateCluster = function() { $http({method: 'GET', url: '/keyspaces'}) .success(function(data, status, headers, config) { cluster.keyspaces = data events.addEventListener('keyspace_created', addKeyspace, false); events.addEventListener('keyspace_changed', updateKeyspace, false); events.addEventListener('keyspace_dropped', removeKeyspace, false); if (!resolved && cluster.keyspaces && cluster.hosts) { resolved = true deferred.resolve(cluster) } }) .error(function(data, status, headers, config) { console.log('ERROR', data); }) $http({method: 'GET', url: '/hosts'}) .success(function(data, status, headers, config) { cluster.hosts = data events.addEventListener('host_found', addHost, false); events.addEventListener('host_up', updateHost, false); events.addEventListener('host_down', updateHost, false); events.addEventListener('host_lost', removeHost, false); if (!resolved && cluster.keyspaces && cluster.hosts) { resolved = true deferred.resolve(cluster) } }) .error(function(data, status, headers, config) { console.log('ERROR', data); }) } var addHost = function(event) { var host = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('host.created', host) cluster.hosts.push(host) }) } var updateHost = function(event) { var host = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('host.updated', host) angular.forEach(cluster.hosts, function(h, index) { if (host.ip == h.ip) { angular.forEach(host, function(value, key) { cluster.hosts[index][key] = value }) } }) }) } var removeHost = function(event) { var host = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('host.removed', host) angular.forEach(cluster.hosts, function(h, index) { if (host.ip == h.ip) { cluster.hosts.splice(index, 1) } }) }) } var addKeyspace = function(event) { var keyspace = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('keyspace.created', keyspace) cluster.keyspaces.push(keyspace) }) } var updateKeyspace = function(event) { var keyspace = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('keyspace.updated', keyspace) angular.forEach(cluster.keyspaces, function(k, index) { if (keyspace.name == k.name) { angular.forEach(keyspace, function(value, key) { cluster.keyspaces[index][key] = value }) } }) }) } var removeKeyspace = function(event) { var keyspace = JSON.parse(event.data) $rootScope.$apply(function() { $rootScope.$broadcast('keyspace.removed', keyspace) angular.forEach(cluster.keyspaces, function(k, index) { if (keyspace.name == k.name) { cluster.keyspaces.splice(index, 1) } }) }) } return deferred.promise } ]) app.factory('escapeIdentifier', [ function() { var re = /[a-z][a-z0-9_]*/ return function(id) { var matches = id.match(re) if (matches.length == 1 && matches[0].length == id.length) { return id } return '"' + id + '"' } } ]) app.directive('codeHighlight',[ '$interpolate', '$compile', function ($interpolate, $compile) { return { restrict: 'E', template: '<code ng-transclude></code>', replace: true, transclude: true, link: function (scope, el, attrs) { var language = Prism.languages[attrs.language] attrs.$observe('code', function(code) { el.html(Prism.highlight(code, language)) }) } } } ]) app.controller('main', [ '$scope', 'cluster', '$routeParams', '$modal', function($scope, cluster, $routeParams, $modal) { cluster.then( function(cluster) { $scope.cluster = cluster } ) $scope.host_status_class = function(status) { if (status == 'up') { return 'success' } return 'danger' } $scope.keyspace_class = function(keyspace) { if ($routeParams.keyspace && $routeParams.keyspace == keyspace.name) { return 'active' } } $scope.show_execute_form = function(statement) { var childScope = $scope.$new() childScope.statement = {cql: statement} return $modal.open({ templateUrl: '/html/execute.html', controller: 'execute', size: 'lg', scope: childScope }) } } ]) app.controller('execute', [ '$scope', function($scope) { $scope.disabled = false $scope.options = $scope.options || { trace: false, consistency: 'one' } $scope.statement = $scope.statement || { cql: '' } $scope.consistencies = [ "any", "one", "two", "three", "quorum", "all", "local_quorum", "each_quorum", "serial", "local_serial", "local_one" ] $scope.execute = function() { $scope.disabled = true $scope.cluster.execute($scope.statement.cql, $scope.options) .then( function(result) { $scope.disabled = false $scope.result = result; }, function(error) { $scope.error = error } ) } $scope.$watch('options.consistency', function(consistency) { if ($scope.error) { $scope.disabled = false delete $scope.error } }) $scope.$watch('statement.cql', function(cql) { if ($scope.error) { $scope.disabled = false delete $scope.error } }) } ]) app.controller('keyspace', [ '$scope', 'cluster', '$routeParams', '$location', function($scope, cluster, $routeParams, $location) { cluster.keyspaces.forEach(function(keyspace) { if ($routeParams.keyspace == keyspace.name) { $scope.keyspace = keyspace } }) if (!$scope.keyspace) { $location.path('/') } $scope.$on('keyspace.removed', function(event, keyspace) { if ($routeParams.keyspace == keyspace.name) { $location.path('/') } }) } ]) app.controller('table', [ '$scope', 'cluster', '$routeParams', '$location', 'escapeIdentifier', function($scope, cluster, $routeParams, $location, escapeIdentifier) { $scope.rowLimit = { enabled: true, value: 15 }; $scope.loading = false; cluster.keyspaces.forEach(function(keyspace) { if ($routeParams.keyspace == keyspace.name) { $scope.keyspace = keyspace } }) if (!$scope.keyspace) { $location.path('/') } $scope.$on('keyspace.removed', function(event, keyspace) { if ($routeParams.keyspace == keyspace.name) { $location.path('/') } }) $scope.keyspace.tables.forEach(function(table) { if ($routeParams.table == table.name) { $scope.table = table } }) if (!$scope.table) { $location.path('/') } $scope.$on('keyspace.updated', function(keyspace) { if ($routeParams.keyspace != keyspace.name) { return } var exists = false; keyspace.tables.forEach(function(table) { exists = exists || (table.name == $scope.table.name) }) if (!exists) { $location.path('/' + $scope.keyspace.name) } }); $scope.executeStatement = function() { $scope.result = undefined; $scope.loading = true; var selectStatement = 'SELECT * FROM ' + escapeIdentifier($scope.keyspace.name) + '.' + escapeIdentifier($scope.table.name); if ($scope.rowLimit.enabled) { selectStatement = selectStatement + ' LIMIT ' + $scope.rowLimit.value; } cluster.execute(selectStatement) .then( function(result) { $scope.result = result; $scope.loading = false; }, function(error) { $scope.error = error; $scope.loading = false; } ); }; $scope.executeStatement(); } ]); app.controller('actions', [ '$scope', 'cluster', 'escapeIdentifier', function($scope, cluster, escapeIdentifier) { $scope.disabled = false $scope.drop = function(keyspaceName, tableName) { $scope.disabled = true return cluster .then( function(cluster) { return cluster .execute('DROP TABLE ' + escapeIdentifier($scope.keyspace.name) + '.' + escapeIdentifier(tableName)) } ) .then( function(result) { $scope.result = result $scope.disabled = false }, function(error) { $scope.error = error } ) } } ])
})(angular.module('cassandra', ['ngRoute', 'angular.filter', 'ui.bootstrap', 'ui.codemirror']))