fix: semi

This commit is contained in:
1ambda 2017-04-15 08:48:54 +09:00
parent d4a8082639
commit cc874d26cd
79 changed files with 3968 additions and 3965 deletions

View file

@ -31,7 +31,6 @@
"process": false
},
"rules": {
"semi": 0,
"array-bracket-spacing": 0,
"space-before-function-paren": 0,
"no-unneeded-ternary": 0,

View file

@ -12,48 +12,48 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('MainCtrl', MainCtrl);
angular.module('zeppelinWebApp').controller('MainCtrl', MainCtrl)
function MainCtrl ($scope, $rootScope, $window, arrayOrderingSrv) {
'ngInject';
'ngInject'
$scope.looknfeel = 'default';
$scope.looknfeel = 'default'
let init = function () {
$scope.asIframe = (($window.location.href.indexOf('asIframe') > -1) ? true : false);
};
$scope.asIframe = (($window.location.href.indexOf('asIframe') > -1) ? true : false)
}
init();
init()
$rootScope.$on('setIframe', function (event, data) {
if (!event.defaultPrevented) {
$scope.asIframe = data;
event.preventDefault();
$scope.asIframe = data
event.preventDefault()
}
});
})
$rootScope.$on('setLookAndFeel', function (event, data) {
if (!event.defaultPrevented && data && data !== '' && data !== $scope.looknfeel) {
$scope.looknfeel = data;
event.preventDefault();
$scope.looknfeel = data
event.preventDefault()
}
});
})
// Set The lookAndFeel to default on every page
$rootScope.$on('$routeChangeStart', function (event, next, current) {
$rootScope.$broadcast('setLookAndFeel', 'default');
});
$rootScope.$broadcast('setLookAndFeel', 'default')
})
$rootScope.noteName = function (note) {
if (!_.isEmpty(note)) {
return arrayOrderingSrv.getNoteName(note);
return arrayOrderingSrv.getNoteName(note)
}
};
}
BootstrapDialog.defaultOptions.onshown = function () {
angular.element('#' + this.id).find('.btn:last').focus();
};
angular.element('#' + this.id).find('.btn:last').focus()
}
// Remove BootstrapDialog animation
BootstrapDialog.configDefaultOptions({animate: false});
BootstrapDialog.configDefaultOptions({animate: false})
}

View file

@ -1,28 +1,28 @@
describe('Controller: MainCtrl', function () {
beforeEach(angular.mock.module('zeppelinWebApp'));
beforeEach(angular.mock.module('zeppelinWebApp'))
let scope;
let rootScope;
let scope
let rootScope
beforeEach(inject(function ($controller, $rootScope) {
rootScope = $rootScope;
scope = $rootScope.$new();
rootScope = $rootScope
scope = $rootScope.$new()
$controller('MainCtrl', {
$scope: scope
});
}));
})
}))
it('should attach "asIframe" to the scope and the default value should be false', function () {
expect(scope.asIframe).toBeDefined();
expect(scope.asIframe).toEqual(false);
});
expect(scope.asIframe).toBeDefined()
expect(scope.asIframe).toEqual(false)
})
it('should set the default value of "looknfeel to "default"', function () {
expect(scope.looknfeel).toEqual('default');
});
expect(scope.looknfeel).toEqual('default')
})
it('should set "asIframe" flag to true when a controller broadcasts setIframe event', function () {
rootScope.$broadcast('setIframe', true);
expect(scope.asIframe).toEqual(true);
});
});
rootScope.$broadcast('setIframe', true)
expect(scope.asIframe).toEqual(true)
})
})

View file

@ -39,19 +39,19 @@ let zeppelinWebApp = angular.module('zeppelinWebApp', [
return function (text) {
// eslint-disable-next-line no-extra-boolean-cast
if (!!text) {
return text.replace(/\n/g, '<br />');
return text.replace(/\n/g, '<br />')
}
};
}
})
.config(function ($httpProvider, $routeProvider, ngToastProvider) {
// withCredentials when running locally via grunt
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.withCredentials = true
let visBundleLoad = {
load: ['heliumService', function (heliumService) {
return heliumService.load;
return heliumService.load
}]
};
}
$routeProvider
.when('/', {
@ -108,14 +108,14 @@ let zeppelinWebApp = angular.module('zeppelinWebApp', [
})
.otherwise({
redirectTo: '/'
});
})
ngToastProvider.configure({
dismissButton: true,
dismissOnClick: false,
combineDuplications: true,
timeout: 6000
});
})
})
// handel logout on API failure
@ -124,51 +124,51 @@ let zeppelinWebApp = angular.module('zeppelinWebApp', [
return {
'responseError': function (rejection) {
if (rejection.status === 405) {
let data = {};
data.info = '';
$rootScope.$broadcast('session_logout', data);
let data = {}
data.info = ''
$rootScope.$broadcast('session_logout', data)
}
$rootScope.$broadcast('httpResponseError', rejection);
return $q.reject(rejection);
$rootScope.$broadcast('httpResponseError', rejection)
return $q.reject(rejection)
}
};
});
$httpProvider.interceptors.push('httpInterceptor');
}
})
$httpProvider.interceptors.push('httpInterceptor')
})
.constant('TRASH_FOLDER_ID', '~Trash');
.constant('TRASH_FOLDER_ID', '~Trash')
function auth () {
let $http = angular.injector(['ng']).get('$http');
let baseUrlSrv = angular.injector(['zeppelinWebApp']).get('baseUrlSrv');
let $http = angular.injector(['ng']).get('$http')
let baseUrlSrv = angular.injector(['zeppelinWebApp']).get('baseUrlSrv')
// withCredentials when running locally via grunt
$http.defaults.withCredentials = true;
$http.defaults.withCredentials = true
jQuery.ajaxSetup({
dataType: 'json',
xhrFields: {
withCredentials: true
},
crossDomain: true
});
})
return $http.get(baseUrlSrv.getRestApiBase() + '/security/ticket').then(function (response) {
zeppelinWebApp.run(function ($rootScope) {
$rootScope.ticket = angular.fromJson(response.data).body;
});
$rootScope.ticket = angular.fromJson(response.data).body
})
}, function (errorResponse) {
// Handle error case
});
})
}
function bootstrapApplication () {
zeppelinWebApp.run(function ($rootScope, $location) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
if (!$rootScope.ticket && next.$$route && !next.$$route.publicAccess) {
$location.path('/');
$location.path('/')
}
});
});
angular.bootstrap(document, ['zeppelinWebApp']);
})
})
angular.bootstrap(document, ['zeppelinWebApp'])
}
angular.element(document).ready(function () {
auth().then(bootstrapApplication);
});
auth().then(bootstrapApplication)
})

View file

@ -12,19 +12,19 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('ConfigurationCtrl', ConfigurationCtrl);
angular.module('zeppelinWebApp').controller('ConfigurationCtrl', ConfigurationCtrl)
function ConfigurationCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
'ngInject';
'ngInject'
$scope.configrations = [];
$scope._ = _;
ngToast.dismiss();
$scope.configrations = []
$scope._ = _
ngToast.dismiss()
let getConfigurations = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/configurations/all')
.success(function (data, status, headers, config) {
$scope.configurations = data.body;
$scope.configurations = data.body
})
.error(function (data, status, headers, config) {
if (status === 401) {
@ -32,18 +32,18 @@ function ConfigurationCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
content: 'You don\'t have permission on this page',
verticalPosition: 'bottom',
timeout: '3000'
});
})
setTimeout(function () {
window.location.replace('/');
}, 3000);
window.location.replace('/')
}, 3000)
}
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
let init = function () {
getConfigurations();
};
getConfigurations()
}
init();
init()
}

View file

@ -12,25 +12,25 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('CredentialCtrl', CredentialCtrl);
angular.module('zeppelinWebApp').controller('CredentialCtrl', CredentialCtrl)
function CredentialCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
'ngInject';
'ngInject'
$scope._ = _;
ngToast.dismiss();
$scope._ = _
ngToast.dismiss()
$scope.credentialInfo = [];
$scope.showAddNewCredentialInfo = false;
$scope.availableInterpreters = [];
$scope.credentialInfo = []
$scope.showAddNewCredentialInfo = false
$scope.availableInterpreters = []
let getCredentialInfo = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/credential')
.success(function (data, status, headers, config) {
$scope.credentialInfo = _.map(data.body.userCredentials, function (value, prop) {
return {entity: prop, password: value.password, username: value.username};
});
console.log('Success %o %o', status, $scope.credentialInfo);
return {entity: prop, password: value.password, username: value.username}
})
console.log('Success %o %o', status, $scope.credentialInfo)
})
.error(function (data, status, headers, config) {
if (status === 401) {
@ -38,14 +38,14 @@ function CredentialCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
content: 'You don\'t have permission on this page',
verticalPosition: 'bottom',
timeout: '3000'
});
})
setTimeout(function () {
window.location.replace('/');
}, 3000);
window.location.replace('/')
}, 3000)
}
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
$scope.addNewCredentialInfo = function () {
if ($scope.entity && _.isEmpty($scope.entity.trim()) &&
@ -54,15 +54,15 @@ function CredentialCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
content: 'Username \\ Entity can not be empty.',
verticalPosition: 'bottom',
timeout: '3000'
});
return;
})
return
}
let newCredential = {
'entity': $scope.entity,
'username': $scope.username,
'password': $scope.password
};
}
$http.put(baseUrlSrv.getRestApiBase() + '/credential', newCredential)
.success(function (data, status, headers, config) {
@ -70,92 +70,92 @@ function CredentialCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
content: 'Successfully saved credentials.',
verticalPosition: 'bottom',
timeout: '3000'
});
$scope.credentialInfo.push(newCredential);
resetCredentialInfo();
$scope.showAddNewCredentialInfo = false;
console.log('Success %o %o', status, data.message);
})
$scope.credentialInfo.push(newCredential)
resetCredentialInfo()
$scope.showAddNewCredentialInfo = false
console.log('Success %o %o', status, data.message)
})
.error(function (data, status, headers, config) {
ngToast.danger({
content: 'Error saving credentials',
verticalPosition: 'bottom',
timeout: '3000'
});
console.log('Error %o %o', status, data.message);
});
};
})
console.log('Error %o %o', status, data.message)
})
}
let getAvailableInterpreters = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/setting')
.success(function (data, status, headers, config) {
for (let setting = 0; setting < data.body.length; setting++) {
$scope.availableInterpreters.push(
data.body[setting].group + '.' + data.body[setting].name);
data.body[setting].group + '.' + data.body[setting].name)
}
angular.element('#entityname').autocomplete({
source: $scope.availableInterpreters,
select: function (event, selected) {
$scope.entity = selected.item.value;
return false;
$scope.entity = selected.item.value
return false
}
});
})
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
$scope.toggleAddNewCredentialInfo = function () {
if ($scope.showAddNewCredentialInfo) {
$scope.showAddNewCredentialInfo = false;
$scope.showAddNewCredentialInfo = false
} else {
$scope.showAddNewCredentialInfo = true;
$scope.showAddNewCredentialInfo = true
}
};
}
$scope.cancelCredentialInfo = function () {
$scope.showAddNewCredentialInfo = false;
resetCredentialInfo();
};
$scope.showAddNewCredentialInfo = false
resetCredentialInfo()
}
const resetCredentialInfo = function () {
$scope.entity = '';
$scope.username = '';
$scope.password = '';
};
$scope.entity = ''
$scope.username = ''
$scope.password = ''
}
$scope.copyOriginCredentialsInfo = function () {
ngToast.info({
content: 'Since entity is a unique key, you can edit only username & password',
verticalPosition: 'bottom',
timeout: '3000'
});
};
})
}
$scope.updateCredentialInfo = function (form, data, entity) {
let request = {
entity: entity,
username: data.username,
password: data.password
};
}
$http.put(baseUrlSrv.getRestApiBase() + '/credential/', request)
.success(function (data, status, headers, config) {
let index = _.findIndex($scope.credentialInfo, {'entity': entity});
$scope.credentialInfo[index] = request;
return true;
let index = _.findIndex($scope.credentialInfo, {'entity': entity})
$scope.credentialInfo[index] = request
return true
})
.error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
console.log('Error %o %o', status, data.message)
ngToast.danger({
content: 'We couldn\'t save the credential',
verticalPosition: 'bottom',
timeout: '3000'
});
form.$show();
});
return false;
};
})
form.$show()
})
return false
}
$scope.removeCredentialInfo = function (entity) {
BootstrapDialog.confirm({
@ -168,22 +168,22 @@ function CredentialCtrl ($scope, $rootScope, $http, baseUrlSrv, ngToast) {
if (result) {
$http.delete(baseUrlSrv.getRestApiBase() + '/credential/' + entity)
.success(function (data, status, headers, config) {
let index = _.findIndex($scope.credentialInfo, {'entity': entity});
$scope.credentialInfo.splice(index, 1);
console.log('Success %o %o', status, data.message);
let index = _.findIndex($scope.credentialInfo, {'entity': entity})
$scope.credentialInfo.splice(index, 1)
console.log('Success %o %o', status, data.message)
})
.error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
console.log('Error %o %o', status, data.message)
})
}
}
});
};
})
}
let init = function () {
getAvailableInterpreters();
getCredentialInfo();
};
getAvailableInterpreters()
getCredentialInfo()
}
init();
init()
}

View file

@ -17,14 +17,14 @@
*/
export default class HandsonHelper {
constructor (columns, rows, comment) {
this.columns = columns || [];
this.rows = rows || [];
this.comment = comment || '';
this._numericValidator = this._numericValidator.bind(this);
this.columns = columns || []
this.rows = rows || []
this.comment = comment || ''
this._numericValidator = this._numericValidator.bind(this)
}
getHandsonTableConfig (columns, columnNames, resultRows) {
let self = this;
let self = this
return {
colHeaders: columnNames,
data: resultRows,
@ -42,32 +42,32 @@ export default class HandsonHelper {
fragmentSelection: true,
disableVisualSelection: true,
cells: function (ro, co, pro) {
let cellProperties = {};
let colType = columns[co].type;
let cellProperties = {}
let colType = columns[co].type
cellProperties.renderer = function (instance, td, row, col, prop, value, cellProperties) {
self._cellRenderer(instance, td, row, col, prop, value, cellProperties, colType);
};
return cellProperties;
self._cellRenderer(instance, td, row, col, prop, value, cellProperties, colType)
}
return cellProperties
},
afterGetColHeader: function (col, TH) {
let instance = this;
let menu = self._buildDropDownMenu(columns[col].type);
let button = self._buildTypeSwitchButton();
let instance = this
let menu = self._buildDropDownMenu(columns[col].type)
let button = self._buildTypeSwitchButton()
self._addButtonMenuEvent(button, menu);
self._addButtonMenuEvent(button, menu)
Handsontable.Dom.addEvent(menu, 'click', function (event) {
if (event.target.nodeName === 'LI') {
self._setColumnType(columns, event.target.data.colType, instance, col);
self._setColumnType(columns, event.target.data.colType, instance, col)
}
});
})
if (TH.firstChild.lastChild.nodeName === 'BUTTON') {
TH.firstChild.removeChild(TH.firstChild.lastChild);
TH.firstChild.removeChild(TH.firstChild.lastChild)
}
TH.firstChild.appendChild(button);
TH.style['white-space'] = 'normal';
TH.firstChild.appendChild(button)
TH.style['white-space'] = 'normal'
}
};
}
}
/*
@ -76,126 +76,126 @@ export default class HandsonHelper {
_addButtonMenuEvent (button, menu) {
Handsontable.Dom.addEvent(button, 'click', function (event) {
let changeTypeMenu;
let position;
let removeMenu;
let changeTypeMenu
let position
let removeMenu
document.body.appendChild(menu);
document.body.appendChild(menu)
event.preventDefault();
event.stopImmediatePropagation();
event.preventDefault()
event.stopImmediatePropagation()
changeTypeMenu = document.querySelectorAll('.changeTypeMenu');
changeTypeMenu = document.querySelectorAll('.changeTypeMenu')
for (let i = 0, len = changeTypeMenu.length; i < len; i++) {
changeTypeMenu[i].style.display = 'none';
changeTypeMenu[i].style.display = 'none'
}
menu.style.display = 'block';
position = button.getBoundingClientRect();
menu.style.display = 'block'
position = button.getBoundingClientRect()
menu.style.top = (position.top + (window.scrollY || window.pageYOffset)) + 2 + 'px';
menu.style.left = (position.left) + 'px';
menu.style.top = (position.top + (window.scrollY || window.pageYOffset)) + 2 + 'px'
menu.style.left = (position.left) + 'px'
removeMenu = function (event) {
if (menu.parentNode) {
menu.parentNode.removeChild(menu);
menu.parentNode.removeChild(menu)
}
};
Handsontable.Dom.removeEvent(document, 'click', removeMenu);
Handsontable.Dom.addEvent(document, 'click', removeMenu);
});
}
Handsontable.Dom.removeEvent(document, 'click', removeMenu)
Handsontable.Dom.addEvent(document, 'click', removeMenu)
})
}
_buildDropDownMenu (activeCellType) {
let menu = document.createElement('UL');
let types = ['text', 'numeric', 'date'];
let item;
let menu = document.createElement('UL')
let types = ['text', 'numeric', 'date']
let item
menu.className = 'changeTypeMenu';
menu.className = 'changeTypeMenu'
for (let i = 0, len = types.length; i < len; i++) {
item = document.createElement('LI');
item = document.createElement('LI')
if ('innerText' in item) {
item.innerText = types[i];
item.innerText = types[i]
} else {
item.textContent = types[i];
item.textContent = types[i]
}
item.data = {'colType': types[i]};
item.data = {'colType': types[i]}
if (activeCellType === types[i]) {
item.className = 'active';
item.className = 'active'
}
menu.appendChild(item);
menu.appendChild(item)
}
return menu;
return menu
}
_buildTypeSwitchButton () {
let button = document.createElement('BUTTON');
let button = document.createElement('BUTTON')
button.innerHTML = '\u25BC';
button.className = 'changeType';
button.innerHTML = '\u25BC'
button.className = 'changeType'
return button;
return button
}
_isNumeric (value) {
if (!isNaN(value)) {
if (value.length !== 0) {
if (Number(value) <= Number.MAX_SAFE_INTEGER && Number(value) >= Number.MIN_SAFE_INTEGER) {
return true;
return true
}
}
}
return false;
return false
}
_cellRenderer (instance, td, row, col, prop, value, cellProperties, colType) {
if (colType === 'numeric' && this._isNumeric(value)) {
cellProperties.format = '0,0.[00000]';
td.style.textAlign = 'left';
cellProperties.format = '0,0.[00000]'
td.style.textAlign = 'left'
// eslint-disable-next-line prefer-rest-params
Handsontable.renderers.NumericRenderer.apply(this, arguments);
Handsontable.renderers.NumericRenderer.apply(this, arguments)
} else if (value.length > '%html'.length && value.substring(0, '%html '.length) === '%html ') {
td.innerHTML = value.substring('%html'.length);
td.innerHTML = value.substring('%html'.length)
} else {
// eslint-disable-next-line prefer-rest-params
Handsontable.renderers.TextRenderer.apply(this, arguments);
Handsontable.renderers.TextRenderer.apply(this, arguments)
}
}
_dateValidator (value, callback) {
let d = moment(value);
return callback(d.isValid());
let d = moment(value)
return callback(d.isValid())
}
_numericValidator (value, callback) {
return callback(this._isNumeric(value));
return callback(this._isNumeric(value))
}
_setColumnType (columns, type, instance, col) {
columns[col].type = type;
this._setColumnValidator(columns, col);
instance.updateSettings({columns: columns});
instance.validateCells(null);
columns[col].type = type
this._setColumnValidator(columns, col)
instance.updateSettings({columns: columns})
instance.validateCells(null)
if (this._isColumnSorted(instance, col)) {
instance.sort(col, instance.sortOrder);
instance.sort(col, instance.sortOrder)
}
}
_isColumnSorted (instance, col) {
return instance.sortingEnabled && instance.sortColumn === col;
return instance.sortingEnabled && instance.sortColumn === col
}
_setColumnValidator (columns, col) {
if (columns[col].type === 'numeric') {
columns[col].validator = this._numericValidator;
columns[col].validator = this._numericValidator
} else if (columns[col].type === 'date') {
columns[col].validator = this._dateValidator;
columns[col].validator = this._dateValidator
} else {
columns[col].validator = null;
columns[col].validator = null
}
}
}

View file

@ -16,73 +16,73 @@ export const HeliumConfFieldType = {
NUMBER: 'number',
JSON: 'json',
STRING: 'string',
};
}
/**
* @param persisted <Object> including `type`, `description`, `defaultValue` for each conf key
* @param spec <Object> including `value` for each conf key
*/
export function mergePersistedConfWithSpec (persisted, spec) {
const confs = [];
const confs = []
for (let name in spec) {
const specField = spec[name];
const persistedValue = persisted[name];
const specField = spec[name]
const persistedValue = persisted[name]
const value = (persistedValue) ? persistedValue : specField.defaultValue;
const value = (persistedValue) ? persistedValue : specField.defaultValue
const merged = {
name: name,
type: specField.type,
description: specField.description,
value: value,
defaultValue: specField.defaultValue,
};
}
confs.push(merged);
confs.push(merged)
}
return confs;
return confs
}
export function createPackageConf (defaultPackages, persistedPackacgeConfs) {
let packageConfs = {};
let packageConfs = {}
for (let name in defaultPackages) {
const pkgInfo = defaultPackages[name];
const pkgInfo = defaultPackages[name]
const configSpec = pkgInfo.pkg.config;
if (!configSpec) { continue; }
const configSpec = pkgInfo.pkg.config
if (!configSpec) { continue }
const version = pkgInfo.pkg.version;
if (!version) { continue; }
const version = pkgInfo.pkg.version
if (!version) { continue }
let config = {};
let config = {}
if (persistedPackacgeConfs[name] && persistedPackacgeConfs[name][version]) {
config = persistedPackacgeConfs[name][version];
config = persistedPackacgeConfs[name][version]
}
const confs = mergePersistedConfWithSpec(config, configSpec);
packageConfs[name] = confs;
const confs = mergePersistedConfWithSpec(config, configSpec)
packageConfs[name] = confs
}
return packageConfs;
return packageConfs
}
export function parseConfigValue (type, stringified) {
let value = stringified;
let value = stringified
try {
if (HeliumConfFieldType.NUMBER === type) {
value = parseFloat(stringified);
value = parseFloat(stringified)
} else if (HeliumConfFieldType.JSON === type) {
value = JSON.parse(stringified);
value = JSON.parse(stringified)
}
} catch (error) {
// return just the stringified one
console.error(`Failed to parse conf type ${type}, value ${value}`);
console.error(`Failed to parse conf type ${type}, value ${value}`)
}
return value;
return value
}
/**
@ -92,10 +92,10 @@ export function createPersistableConfig (currentConf) {
// persist key-value only
// since other info (e.g type, desc) can be provided by default config
const filtered = currentConf.reduce((acc, c) => {
let value = parseConfigValue(c.type, c.value);
acc[c.name] = value;
return acc;
}, {});
let value = parseConfigValue(c.type, c.value)
acc[c.name] = value
return acc
}, {})
return filtered;
return filtered
}

View file

@ -12,17 +12,17 @@
* limitations under the License.
*/
import { HeliumType, } from '../../components/helium/helium-type';
import { HeliumType, } from '../../components/helium/helium-type'
export default function HeliumCtrl ($scope, $rootScope, $sce,
baseUrlSrv, ngToast, heliumService) {
'ngInject';
'ngInject'
$scope.pkgSearchResults = {};
$scope.defaultPackages = {};
$scope.showVersions = {};
$scope.bundleOrder = [];
$scope.bundleOrderChanged = false;
$scope.pkgSearchResults = {}
$scope.defaultPackages = {}
$scope.showVersions = {}
$scope.bundleOrder = []
$scope.bundleOrderChanged = false
$scope.vizTypePkg = {}
$scope.spellTypePkg = {}
$scope.intpTypePkg = {}
@ -30,34 +30,34 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
$scope.numberOfEachPackageByType = {}
$scope.allPackageTypes = [HeliumType][0]
$scope.pkgListByType = 'VISUALIZATION'
$scope.defaultPackageConfigs = {}; // { pkgName, [{name, type, desc, value, defaultValue}] }
$scope.intpDefaultIcon = $sce.trustAsHtml('<img src="../assets/images/maven_default_icon.png" style="width: 12px"/>');
$scope.defaultPackageConfigs = {} // { pkgName, [{name, type, desc, value, defaultValue}] }
$scope.intpDefaultIcon = $sce.trustAsHtml('<img src="../assets/images/maven_default_icon.png" style="width: 12px"/>')
function init () {
// get all package info and set config
heliumService.getAllPackageInfoAndDefaultPackages()
.then(({ pkgSearchResults, defaultPackages }) => {
// pagination
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$scope.maxSize = 5;
$scope.itemsPerPage = 10
$scope.currentPage = 1
$scope.maxSize = 5
$scope.pkgSearchResults = pkgSearchResults;
$scope.defaultPackages = defaultPackages;
classifyPkgType($scope.defaultPackages);
$scope.pkgSearchResults = pkgSearchResults
$scope.defaultPackages = defaultPackages
classifyPkgType($scope.defaultPackages)
return heliumService.getAllPackageConfigs()
})
.then(defaultPackageConfigs => {
$scope.defaultPackageConfigs = defaultPackageConfigs;
});
$scope.defaultPackageConfigs = defaultPackageConfigs
})
// 2. get vis package order
heliumService.getVisualizationPackageOrder()
.then(visPackageOrder => {
$scope.bundleOrder = visPackageOrder;
$scope.bundleOrderChanged = false;
});
$scope.bundleOrder = visPackageOrder
$scope.bundleOrderChanged = false
})
}
let orderPackageByPubDate = function (a, b) {
@ -66,36 +66,36 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
a.pkg.published = new Date().getTime()
}
return new Date(a.pkg.published).getTime() - new Date(b.pkg.published).getTime();
};
return new Date(a.pkg.published).getTime() - new Date(b.pkg.published).getTime()
}
const classifyPkgType = function (packageInfo) {
let allTypesOfPkg = {};
let vizTypePkg = [];
let spellTypePkg = [];
let intpTypePkg = [];
let appTypePkg = [];
let allTypesOfPkg = {}
let vizTypePkg = []
let spellTypePkg = []
let intpTypePkg = []
let appTypePkg = []
let packageInfoArr = Object.keys(packageInfo).map(key => packageInfo[key])
packageInfoArr = packageInfoArr.sort(orderPackageByPubDate).reverse();
packageInfoArr = packageInfoArr.sort(orderPackageByPubDate).reverse()
for (let name in packageInfoArr) {
let pkgs = packageInfoArr[name];
let pkgType = pkgs.pkg.type;
let pkgs = packageInfoArr[name]
let pkgType = pkgs.pkg.type
switch (pkgType) {
case HeliumType.VISUALIZATION:
vizTypePkg.push(pkgs);
break;
vizTypePkg.push(pkgs)
break
case HeliumType.SPELL:
spellTypePkg.push(pkgs);
break;
spellTypePkg.push(pkgs)
break
case HeliumType.INTERPRETER:
intpTypePkg.push(pkgs);
break;
intpTypePkg.push(pkgs)
break
case HeliumType.APPLICATION:
appTypePkg.push(pkgs);
break;
appTypePkg.push(pkgs)
break
}
}
@ -106,19 +106,19 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
appTypePkg
]
for (let idx in _.keys(HeliumType)) {
allTypesOfPkg[_.keys(HeliumType)[idx]] = pkgsArr[idx];
allTypesOfPkg[_.keys(HeliumType)[idx]] = pkgsArr[idx]
}
$scope.allTypesOfPkg = allTypesOfPkg;
};
$scope.allTypesOfPkg = allTypesOfPkg
}
$scope.bundleOrderListeners = {
accept: function (sourceItemHandleScope, destSortableScope) { return true; },
accept: function (sourceItemHandleScope, destSortableScope) { return true },
itemMoved: function (event) {},
orderChanged: function (event) {
$scope.bundleOrderChanged = true;
$scope.bundleOrderChanged = true
}
};
}
$scope.saveBundleOrder = function () {
const confirm = BootstrapDialog.confirm({
@ -129,67 +129,67 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
message: 'Save changes?',
callback: function (result) {
if (result) {
confirm.$modalFooter.find('button').addClass('disabled');
confirm.$modalFooter.find('button').addClass('disabled')
confirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling');
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling')
heliumService.setVisualizationPackageOrder($scope.bundleOrder)
.success(function (data, status) {
init();
confirm.close();
init()
confirm.close()
})
.error(function (data, status) {
confirm.close();
console.log('Failed to save order');
confirm.close()
console.log('Failed to save order')
BootstrapDialog.show({
title: 'Error on saving order ',
message: data.message
});
});
return false;
})
})
return false
}
}
});
};
})
}
let getLicense = function (name, artifact) {
let filteredPkgSearchResults = _.filter($scope.defaultPackages[name], function (p) {
return p.artifact === artifact;
});
return p.artifact === artifact
})
let license;
let license
if (filteredPkgSearchResults.length === 0) {
filteredPkgSearchResults = _.filter($scope.pkgSearchResults[name], function (p) {
return p.pkg.artifact === artifact;
});
return p.pkg.artifact === artifact
})
if (filteredPkgSearchResults.length > 0) {
license = filteredPkgSearchResults[0].pkg.license;
license = filteredPkgSearchResults[0].pkg.license
}
} else {
license = filteredPkgSearchResults[0].license;
license = filteredPkgSearchResults[0].license
}
if (!license) {
license = 'Unknown';
license = 'Unknown'
}
return license;
return license
}
const getHeliumTypeText = function (type) {
if (type === HeliumType.VISUALIZATION) {
return `<a target="_blank" href="https://zeppelin.apache.org/docs/${$rootScope.zeppelinVersion}/development/writingzeppelinvisualization.html">${type}</a>`; // eslint-disable-line max-len
return `<a target="_blank" href="https://zeppelin.apache.org/docs/${$rootScope.zeppelinVersion}/development/writingzeppelinvisualization.html">${type}</a>` // eslint-disable-line max-len
} else if (type === HeliumType.SPELL) {
return `<a target="_blank" href="https://zeppelin.apache.org/docs/${$rootScope.zeppelinVersion}/development/writingzeppelinspell.html">${type}</a>`; // eslint-disable-line max-len
return `<a target="_blank" href="https://zeppelin.apache.org/docs/${$rootScope.zeppelinVersion}/development/writingzeppelinspell.html">${type}</a>` // eslint-disable-line max-len
} else {
return type;
return type
}
}
$scope.enable = function (name, artifact, type, groupId, description) {
let license = getLicense(name, artifact);
let mavenArtifactInfoToHTML = groupId + ':' + artifact.split('@')[0] + ':' + artifact.split('@')[1];
let zeppelinVersion = $rootScope.zeppelinVersion;
let url = 'https://zeppelin.apache.org/docs/' + zeppelinVersion + '/manual/interpreterinstallation.html';
let license = getLicense(name, artifact)
let mavenArtifactInfoToHTML = groupId + ':' + artifact.split('@')[0] + ':' + artifact.split('@')[1]
let zeppelinVersion = $rootScope.zeppelinVersion
let url = 'https://zeppelin.apache.org/docs/' + zeppelinVersion + '/manual/interpreterinstallation.html'
let confirm = ''
if (type === HeliumType.INTERPRETER) {
@ -205,7 +205,7 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
'<p>After restart Zeppelin, create interpreter setting and bind it with your note. ' +
'For more detailed information, see <a target="_blank" href=' +
url + '>Interpreter Installation.</a></p>'
});
})
} else {
confirm = BootstrapDialog.confirm({
closable: false,
@ -226,26 +226,26 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
`<div style="color:gray">${license}</div>`,
callback: function (result) {
if (result) {
confirm.$modalFooter.find('button').addClass('disabled');
confirm.$modalFooter.find('button').addClass('disabled')
confirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling');
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling')
heliumService.enable(name, artifact, type).success(function (data, status) {
init();
confirm.close();
init()
confirm.close()
}).error(function (data, status) {
confirm.close();
console.log('Failed to enable package %o %o. %o', name, artifact, data);
confirm.close()
console.log('Failed to enable package %o %o. %o', name, artifact, data)
BootstrapDialog.show({
title: 'Error on enabling ' + name,
message: data.message
});
});
return false;
})
})
return false
}
}
});
})
}
};
}
$scope.disable = function (name, artifact) {
const confirm = BootstrapDialog.confirm({
@ -256,52 +256,52 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
message: artifact,
callback: function (result) {
if (result) {
confirm.$modalFooter.find('button').addClass('disabled');
confirm.$modalFooter.find('button').addClass('disabled')
confirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Disabling');
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Disabling')
heliumService.disable(name)
.success(function (data, status) {
init();
confirm.close();
init()
confirm.close()
})
.error(function (data, status) {
confirm.close();
console.log('Failed to disable package %o. %o', name, data);
confirm.close()
console.log('Failed to disable package %o. %o', name, data)
BootstrapDialog.show({
title: 'Error on disabling ' + name,
message: data.message
});
});
return false;
})
})
return false
}
}
});
};
})
}
$scope.toggleVersions = function (pkgName) {
if ($scope.showVersions[pkgName]) {
$scope.showVersions[pkgName] = false;
$scope.showVersions[pkgName] = false
} else {
$scope.showVersions[pkgName] = true;
$scope.showVersions[pkgName] = true
}
};
}
$scope.isLocalPackage = function (pkgSearchResult) {
const pkg = pkgSearchResult.pkg;
return pkg.artifact && !pkg.artifact.includes('@');
};
const pkg = pkgSearchResult.pkg
return pkg.artifact && !pkg.artifact.includes('@')
}
$scope.hasNpmLink = function (pkgSearchResult) {
const pkg = pkgSearchResult.pkg;
const pkg = pkgSearchResult.pkg
return (pkg.type === HeliumType.SPELL || pkg.type === HeliumType.VISUALIZATION) &&
!$scope.isLocalPackage(pkgSearchResult);
};
!$scope.isLocalPackage(pkgSearchResult)
}
$scope.hasMavenLink = function (pkgSearchResult) {
const pkg = pkgSearchResult.pkg;
const pkg = pkgSearchResult.pkg
return (pkg.type === HeliumType.APPLICATION || pkg.type === HeliumType.INTERPRETER) &&
!$scope.isLocalPackage(pkgSearchResult);
};
!$scope.isLocalPackage(pkgSearchResult)
}
$scope.getPackageSize = function (pkgSearchResult, targetPkgType) {
let result = []
@ -313,49 +313,49 @@ export default function HeliumCtrl ($scope, $rootScope, $sce,
$scope.configExists = function (pkgSearchResult) {
// helium package config is persisted per version
return pkgSearchResult.pkg.config && pkgSearchResult.pkg.artifact;
};
return pkgSearchResult.pkg.config && pkgSearchResult.pkg.artifact
}
$scope.configOpened = function (pkgSearchResult) {
return pkgSearchResult.configOpened && !pkgSearchResult.configFetching;
};
return pkgSearchResult.configOpened && !pkgSearchResult.configFetching
}
$scope.getConfigButtonClass = function (pkgSearchResult) {
return (pkgSearchResult.configOpened && pkgSearchResult.configFetching)
? 'disabled' : '';
? 'disabled' : ''
}
$scope.toggleConfigButton = function (pkgSearchResult) {
if (pkgSearchResult.configOpened) {
pkgSearchResult.configOpened = false;
return;
pkgSearchResult.configOpened = false
return
}
const pkg = pkgSearchResult.pkg;
const pkgName = pkg.name;
pkgSearchResult.configFetching = true;
pkgSearchResult.configOpened = true;
const pkg = pkgSearchResult.pkg
const pkgName = pkg.name
pkgSearchResult.configFetching = true
pkgSearchResult.configOpened = true
heliumService.getSinglePackageConfigs(pkg)
.then(confs => {
$scope.defaultPackageConfigs[pkgName] = confs;
pkgSearchResult.configFetching = false;
});
};
$scope.defaultPackageConfigs[pkgName] = confs
pkgSearchResult.configFetching = false
})
}
$scope.saveConfig = function (pkgSearchResult) {
const pkgName = pkgSearchResult.pkg.name;
const currentConf = $scope.defaultPackageConfigs[pkgName];
const pkgName = pkgSearchResult.pkg.name
const currentConf = $scope.defaultPackageConfigs[pkgName]
heliumService.saveConfig(pkgSearchResult.pkg, currentConf, () => {
// close after config is saved
pkgSearchResult.configOpened = false;
});
};
pkgSearchResult.configOpened = false
})
}
$scope.getDescriptionText = function (pkgSearchResult) {
return $sce.trustAsHtml(pkgSearchResult.pkg.description);
};
return $sce.trustAsHtml(pkgSearchResult.pkg.description)
}
init();
init()
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
import HeliumController from './helium.controller';
import HeliumController from './helium.controller'
angular.module('zeppelinWebApp')
.controller('HeliumCtrl', HeliumController);
.controller('HeliumCtrl', HeliumController)

View file

@ -12,135 +12,135 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('HomeCtrl', HomeCtrl);
angular.module('zeppelinWebApp').controller('HomeCtrl', HomeCtrl)
function HomeCtrl ($scope, noteListDataFactory, websocketMsgSrv, $rootScope, arrayOrderingSrv,
ngToast, noteActionSrv, TRASH_FOLDER_ID) {
'ngInject';
'ngInject'
ngToast.dismiss();
let vm = this;
vm.notes = noteListDataFactory;
vm.websocketMsgSrv = websocketMsgSrv;
vm.arrayOrderingSrv = arrayOrderingSrv;
ngToast.dismiss()
let vm = this
vm.notes = noteListDataFactory
vm.websocketMsgSrv = websocketMsgSrv
vm.arrayOrderingSrv = arrayOrderingSrv
vm.notebookHome = false;
vm.noteCustomHome = true;
vm.notebookHome = false
vm.noteCustomHome = true
if ($rootScope.ticket !== undefined) {
vm.staticHome = false;
vm.staticHome = false
} else {
vm.staticHome = true;
vm.staticHome = true
}
$scope.isReloading = false;
$scope.TRASH_FOLDER_ID = TRASH_FOLDER_ID;
$scope.query = {q: ''};
$scope.isReloading = false
$scope.TRASH_FOLDER_ID = TRASH_FOLDER_ID
$scope.query = {q: ''}
$scope.initHome = function () {
websocketMsgSrv.getHomeNote();
vm.noteCustomHome = false;
};
websocketMsgSrv.getHomeNote()
vm.noteCustomHome = false
}
$scope.reloadNoteList = function () {
websocketMsgSrv.reloadAllNotesFromRepo();
$scope.isReloadingNotes = true;
};
websocketMsgSrv.reloadAllNotesFromRepo()
$scope.isReloadingNotes = true
}
$scope.toggleFolderNode = function (node) {
node.hidden = !node.hidden;
};
node.hidden = !node.hidden
}
angular.element('#loginModal').on('hidden.bs.modal', function (e) {
$rootScope.$broadcast('initLoginValues');
});
$rootScope.$broadcast('initLoginValues')
})
/*
** $scope.$on functions below
*/
$scope.$on('setNoteMenu', function (event, notes) {
$scope.isReloadingNotes = false;
});
$scope.isReloadingNotes = false
})
$scope.$on('setNoteContent', function (event, note) {
if (vm.noteCustomHome) {
return;
return
}
if (note) {
vm.note = note;
vm.note = note
// initialize look And Feel
$rootScope.$broadcast('setLookAndFeel', 'home');
$rootScope.$broadcast('setLookAndFeel', 'home')
// make it read only
vm.viewOnly = true;
vm.viewOnly = true
vm.notebookHome = true;
vm.staticHome = false;
vm.notebookHome = true
vm.staticHome = false
} else {
vm.staticHome = true;
vm.notebookHome = false;
vm.staticHome = true
vm.notebookHome = false
}
});
})
$scope.renameNote = function (nodeId, nodePath) {
noteActionSrv.renameNote(nodeId, nodePath);
};
noteActionSrv.renameNote(nodeId, nodePath)
}
$scope.moveNoteToTrash = function (noteId) {
noteActionSrv.moveNoteToTrash(noteId, false);
};
noteActionSrv.moveNoteToTrash(noteId, false)
}
$scope.moveFolderToTrash = function (folderId) {
noteActionSrv.moveFolderToTrash(folderId);
};
noteActionSrv.moveFolderToTrash(folderId)
}
$scope.restoreNote = function (noteId) {
websocketMsgSrv.restoreNote(noteId);
};
websocketMsgSrv.restoreNote(noteId)
}
$scope.restoreFolder = function (folderId) {
websocketMsgSrv.restoreFolder(folderId);
};
websocketMsgSrv.restoreFolder(folderId)
}
$scope.restoreAll = function () {
noteActionSrv.restoreAll();
};
noteActionSrv.restoreAll()
}
$scope.renameFolder = function (node) {
noteActionSrv.renameFolder(node.id);
};
noteActionSrv.renameFolder(node.id)
}
$scope.removeNote = function (noteId) {
noteActionSrv.removeNote(noteId, false);
};
noteActionSrv.removeNote(noteId, false)
}
$scope.removeFolder = function (folderId) {
noteActionSrv.removeFolder(folderId);
};
noteActionSrv.removeFolder(folderId)
}
$scope.emptyTrash = function () {
noteActionSrv.emptyTrash();
};
noteActionSrv.emptyTrash()
}
$scope.clearAllParagraphOutput = function (noteId) {
noteActionSrv.clearAllParagraphOutput(noteId);
};
noteActionSrv.clearAllParagraphOutput(noteId)
}
$scope.isFilterNote = function (note) {
if (!$scope.query.q) {
return true;
return true
}
let noteName = note.name;
let noteName = note.name
if (noteName.toLowerCase().indexOf($scope.query.q.toLowerCase()) > -1) {
return true;
return true
}
return false;
};
return false
}
$scope.getNoteName = function (note) {
return arrayOrderingSrv.getNoteName(note);
};
return arrayOrderingSrv.getNoteName(note)
}
}

View file

@ -12,29 +12,29 @@
* limitations under the License.
*/
import { ParagraphStatus, } from '../notebook/paragraph/paragraph.status';
import { ParagraphStatus, } from '../notebook/paragraph/paragraph.status'
angular.module('zeppelinWebApp').controller('InterpreterCtrl', InterpreterCtrl);
angular.module('zeppelinWebApp').controller('InterpreterCtrl', InterpreterCtrl)
function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeout, $route) {
'ngInject';
'ngInject'
let interpreterSettingsTmp = [];
$scope.interpreterSettings = [];
$scope.availableInterpreters = {};
$scope.showAddNewSetting = false;
$scope.showRepositoryInfo = false;
$scope.searchInterpreter = '';
$scope._ = _;
ngToast.dismiss();
let interpreterSettingsTmp = []
$scope.interpreterSettings = []
$scope.availableInterpreters = {}
$scope.showAddNewSetting = false
$scope.showRepositoryInfo = false
$scope.searchInterpreter = ''
$scope._ = _
ngToast.dismiss()
$scope.openPermissions = function () {
$scope.showInterpreterAuth = true;
};
$scope.showInterpreterAuth = true
}
$scope.closePermissions = function () {
$scope.showInterpreterAuth = false;
};
$scope.showInterpreterAuth = false
}
let getSelectJson = function () {
let selectJson = {
@ -45,19 +45,19 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
ajax: {
url: function (params) {
if (!params.term) {
return false;
return false
}
return baseUrlSrv.getRestApiBase() + '/security/userlist/' + params.term;
return baseUrlSrv.getRestApiBase() + '/security/userlist/' + params.term
},
delay: 250,
processResults: function (data, params) {
let users = [];
let users = []
if (data.body.users.length !== 0) {
for (let i = 0; i < data.body.users.length; i++) {
users.push({
'id': data.body.users[i],
'text': data.body.users[i]
});
})
}
}
return {
@ -65,55 +65,55 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
pagination: {
more: false
}
};
}
},
cache: false
}
};
return selectJson;
};
}
return selectJson
}
$scope.togglePermissions = function (intpName) {
angular.element('#' + intpName + 'Users').select2(getSelectJson());
angular.element('#' + intpName + 'Users').select2(getSelectJson())
if ($scope.showInterpreterAuth) {
$scope.closePermissions();
$scope.closePermissions()
} else {
$scope.openPermissions();
$scope.openPermissions()
}
};
}
$scope.$on('ngRenderFinished', function (event, data) {
for (let setting = 0; setting < $scope.interpreterSettings.length; setting++) {
angular.element('#' + $scope.interpreterSettings[setting].name + 'Users').select2(getSelectJson());
angular.element('#' + $scope.interpreterSettings[setting].name + 'Users').select2(getSelectJson())
}
});
})
let getInterpreterSettings = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/setting')
.success(function (data, status, headers, config) {
$scope.interpreterSettings = data.body;
checkDownloadingDependencies();
$scope.interpreterSettings = data.body
checkDownloadingDependencies()
}).error(function (data, status, headers, config) {
if (status === 401) {
ngToast.danger({
content: 'You don\'t have permission on this page',
verticalPosition: 'bottom',
timeout: '3000'
});
})
setTimeout(function () {
window.location.replace('/');
}, 3000);
window.location.replace('/')
}, 3000)
}
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
const checkDownloadingDependencies = function () {
let isDownloading = false;
let isDownloading = false
for (let index = 0; index < $scope.interpreterSettings.length; index++) {
let setting = $scope.interpreterSettings[index];
let setting = $scope.interpreterSettings[index]
if (setting.status === 'DOWNLOADING_DEPENDENCIES') {
isDownloading = true;
isDownloading = true
}
if (setting.status === ParagraphStatus.ERROR || setting.errorReason) {
@ -121,186 +121,186 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
setting.group + '.' + setting.name + '\': ' + setting.errorReason,
verticalPosition: 'top',
dismissOnTimeout: false
});
})
}
}
if (isDownloading) {
$timeout(function () {
if ($route.current.$$route.originalPath === '/interpreter') {
getInterpreterSettings();
getInterpreterSettings()
}
}, 2000);
}, 2000)
}
};
}
let getAvailableInterpreters = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter').success(function (data, status, headers, config) {
$scope.availableInterpreters = data.body;
$scope.availableInterpreters = data.body
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
let emptyNewProperty = function (object) {
angular.extend(object, {propertyValue: '', propertyKey: ''});
};
angular.extend(object, {propertyValue: '', propertyKey: ''})
}
let emptyNewDependency = function (object) {
angular.extend(object, {depArtifact: '', depExclude: ''});
};
angular.extend(object, {depArtifact: '', depExclude: ''})
}
let removeTMPSettings = function (index) {
interpreterSettingsTmp.splice(index, 1);
};
interpreterSettingsTmp.splice(index, 1)
}
$scope.copyOriginInterpreterSettingProperties = function (settingId) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
interpreterSettingsTmp[index] = angular.copy($scope.interpreterSettings[index]);
};
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
interpreterSettingsTmp[index] = angular.copy($scope.interpreterSettings[index])
}
$scope.setPerNoteOption = function (settingId, sessionOption) {
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
if (sessionOption === 'isolated') {
option.perNote = sessionOption;
option.session = false;
option.process = true;
option.perNote = sessionOption
option.session = false
option.process = true
} else if (sessionOption === 'scoped') {
option.perNote = sessionOption;
option.session = true;
option.process = false;
option.perNote = sessionOption
option.session = true
option.process = false
} else {
option.perNote = 'shared';
option.session = false;
option.process = false;
option.perNote = 'shared'
option.session = false
option.process = false
}
};
}
$scope.setPerUserOption = function (settingId, sessionOption) {
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
if (sessionOption === 'isolated') {
option.perUser = sessionOption;
option.session = false;
option.process = true;
option.perUser = sessionOption
option.session = false
option.process = true
} else if (sessionOption === 'scoped') {
option.perUser = sessionOption;
option.session = true;
option.process = false;
option.perUser = sessionOption
option.session = true
option.process = false
} else {
option.perUser = 'shared';
option.session = false;
option.process = false;
option.perUser = 'shared'
option.session = false
option.process = false
}
};
}
$scope.getPerNoteOption = function (settingId) {
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
if (option.perNote === 'scoped') {
return 'scoped';
return 'scoped'
} else if (option.perNote === 'isolated') {
return 'isolated';
return 'isolated'
} else {
return 'shared';
return 'shared'
}
};
}
$scope.getPerUserOption = function (settingId) {
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
if (option.perUser === 'scoped') {
return 'scoped';
return 'scoped'
} else if (option.perUser === 'isolated') {
return 'isolated';
return 'isolated'
} else {
return 'shared';
return 'shared'
}
};
}
$scope.getInterpreterRunningOption = function (settingId) {
let sharedModeName = 'shared';
let sharedModeName = 'shared'
let globallyModeName = 'Globally';
let perNoteModeName = 'Per Note';
let perUserModeName = 'Per User';
let globallyModeName = 'Globally'
let perNoteModeName = 'Per Note'
let perUserModeName = 'Per User'
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
let perNote = option.perNote;
let perUser = option.perUser;
let perNote = option.perNote
let perUser = option.perUser
// Globally == shared_perNote + shared_perUser
if (perNote === sharedModeName && perUser === sharedModeName) {
return globallyModeName;
return globallyModeName
}
if ($rootScope.ticket.ticket === 'anonymous' && $rootScope.ticket.roles === '[]') {
if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') {
return perNoteModeName;
return perNoteModeName
}
} else if ($rootScope.ticket.ticket !== 'anonymous') {
if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') {
if (perUser !== undefined && typeof perUser === 'string' && perUser !== '') {
return perUserModeName;
return perUserModeName
}
return perNoteModeName;
return perNoteModeName
}
}
option.perNote = sharedModeName;
option.perUser = sharedModeName;
return globallyModeName;
};
option.perNote = sharedModeName
option.perUser = sharedModeName
return globallyModeName
}
$scope.setInterpreterRunningOption = function (settingId, isPerNoteMode, isPerUserMode) {
let option;
let option
if (settingId === undefined) {
option = $scope.newInterpreterSetting.option;
option = $scope.newInterpreterSetting.option
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
option = setting.option;
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
option = setting.option
}
option.perNote = isPerNoteMode;
option.perUser = isPerUserMode;
};
option.perNote = isPerNoteMode
option.perUser = isPerUserMode
}
$scope.updateInterpreterSetting = function (form, settingId) {
const thisConfirm = BootstrapDialog.confirm({
@ -311,75 +311,75 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
message: 'Do you want to update this interpreter and restart with new settings?',
callback: function (result) {
if (result) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
if (setting.propertyKey !== '' || setting.propertyKey) {
$scope.addNewInterpreterProperty(settingId);
$scope.addNewInterpreterProperty(settingId)
}
if (setting.depArtifact !== '' || setting.depArtifact) {
$scope.addNewInterpreterDependency(settingId);
$scope.addNewInterpreterDependency(settingId)
}
// add missing field of option
if (!setting.option) {
setting.option = {};
setting.option = {}
}
if (setting.option.isExistingProcess === undefined) {
setting.option.isExistingProcess = false;
setting.option.isExistingProcess = false
}
if (setting.option.setPermission === undefined) {
setting.option.setPermission = false;
setting.option.setPermission = false
}
if (setting.option.isUserImpersonate === undefined) {
setting.option.isUserImpersonate = false;
setting.option.isUserImpersonate = false
}
if (!($scope.getInterpreterRunningOption(settingId) === 'Per User' &&
$scope.getPerUserOption(settingId) === 'isolated')) {
setting.option.isUserImpersonate = false;
setting.option.isUserImpersonate = false
}
if (setting.option.remote === undefined) {
// remote always true for now
setting.option.remote = true;
setting.option.remote = true
}
setting.option.users = angular.element('#' + setting.name + 'Users').val();
setting.option.users = angular.element('#' + setting.name + 'Users').val()
let request = {
option: angular.copy(setting.option),
properties: angular.copy(setting.properties),
dependencies: angular.copy(setting.dependencies)
};
}
thisConfirm.$modalFooter.find('button').addClass('disabled');
thisConfirm.$modalFooter.find('button').addClass('disabled')
thisConfirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Saving Setting');
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Saving Setting')
$http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/' + settingId, request)
.success(function (data, status, headers, config) {
$scope.interpreterSettings[index] = data.body;
removeTMPSettings(index);
checkDownloadingDependencies();
thisConfirm.close();
$scope.interpreterSettings[index] = data.body
removeTMPSettings(index)
checkDownloadingDependencies()
thisConfirm.close()
})
.error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
ngToast.danger({content: data.message, verticalPosition: 'bottom'});
form.$show();
thisConfirm.close();
});
return false;
console.log('Error %o %o', status, data.message)
ngToast.danger({content: data.message, verticalPosition: 'bottom'})
form.$show()
thisConfirm.close()
})
return false
} else {
form.$show();
form.$show()
}
}
});
};
})
}
$scope.resetInterpreterSetting = function (settingId) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
// Set the old settings back
$scope.interpreterSettings[index] = angular.copy(interpreterSettingsTmp[index]);
removeTMPSettings(index);
};
$scope.interpreterSettings[index] = angular.copy(interpreterSettingsTmp[index])
removeTMPSettings(index)
}
$scope.removeInterpreterSetting = function (settingId) {
BootstrapDialog.confirm({
@ -390,31 +390,31 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
if (result) {
$http.delete(baseUrlSrv.getRestApiBase() + '/interpreter/setting/' + settingId)
.success(function (data, status, headers, config) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
$scope.interpreterSettings.splice(index, 1);
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
$scope.interpreterSettings.splice(index, 1)
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
console.log('Error %o %o', status, data.message)
})
}
}
});
};
})
}
$scope.newInterpreterGroupChange = function () {
let el = _.pluck(_.filter($scope.availableInterpreters, {'name': $scope.newInterpreterSetting.group}),
'properties');
let properties = {};
'properties')
let properties = {}
for (let i = 0; i < el.length; i++) {
let intpInfo = el[i];
let intpInfo = el[i]
for (let key in intpInfo) {
properties[key] = {
value: intpInfo[key].defaultValue,
description: intpInfo[key].description
};
}
}
}
$scope.newInterpreterSetting.properties = properties;
};
$scope.newInterpreterSetting.properties = properties
}
$scope.restartInterpreterSetting = function (settingId) {
BootstrapDialog.confirm({
@ -425,18 +425,18 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
if (result) {
$http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/restart/' + settingId)
.success(function (data, status, headers, config) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
$scope.interpreterSettings[index] = data.body;
ngToast.info('Interpreter stopped. Will be lazily started on next run.');
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
$scope.interpreterSettings[index] = data.body
ngToast.info('Interpreter stopped. Will be lazily started on next run.')
}).error(function (data, status, headers, config) {
let errorMsg = (data !== null) ? data.message : 'Could not connect to server.';
console.log('Error %o %o', status, errorMsg);
ngToast.danger(errorMsg);
});
let errorMsg = (data !== null) ? data.message : 'Could not connect to server.'
console.log('Error %o %o', status, errorMsg)
ngToast.danger(errorMsg)
})
}
}
});
};
})
}
$scope.addNewInterpreterSetting = function () {
// user input validation on interpreter creation
@ -446,8 +446,8 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
closable: true,
title: 'Add interpreter',
message: 'Please fill in interpreter name and choose a group'
});
return;
})
return
}
if ($scope.newInterpreterSetting.name.indexOf('.') >= 0) {
@ -455,8 +455,8 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
closable: true,
title: 'Add interpreter',
message: '\'.\' is invalid for interpreter name'
});
return;
})
return
}
if (_.findIndex($scope.interpreterSettings, {'name': $scope.newInterpreterSetting.name}) >= 0) {
@ -464,47 +464,47 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
closable: true,
title: 'Add interpreter',
message: 'Name ' + $scope.newInterpreterSetting.name + ' already exists'
});
return;
})
return
}
let newSetting = $scope.newInterpreterSetting;
let newSetting = $scope.newInterpreterSetting
if (newSetting.propertyKey !== '' || newSetting.propertyKey) {
$scope.addNewInterpreterProperty();
$scope.addNewInterpreterProperty()
}
if (newSetting.depArtifact !== '' || newSetting.depArtifact) {
$scope.addNewInterpreterDependency();
$scope.addNewInterpreterDependency()
}
if (newSetting.option.setPermission === undefined) {
newSetting.option.setPermission = false;
newSetting.option.setPermission = false
}
newSetting.option.users = angular.element('#newInterpreterUsers').val();
newSetting.option.users = angular.element('#newInterpreterUsers').val()
let request = angular.copy($scope.newInterpreterSetting);
let request = angular.copy($scope.newInterpreterSetting)
// Change properties to proper request format
let newProperties = {};
let newProperties = {}
for (let p in newSetting.properties) {
newProperties[p] = newSetting.properties[p].value;
newProperties[p] = newSetting.properties[p].value
}
request.properties = newProperties;
request.properties = newProperties
$http.post(baseUrlSrv.getRestApiBase() + '/interpreter/setting', request)
.success(function (data, status, headers, config) {
$scope.resetNewInterpreterSetting();
getInterpreterSettings();
$scope.showAddNewSetting = false;
checkDownloadingDependencies();
$scope.resetNewInterpreterSetting()
getInterpreterSettings()
$scope.showAddNewSetting = false
checkDownloadingDependencies()
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
ngToast.danger({content: data.message, verticalPosition: 'bottom'});
});
};
console.log('Error %o %o', status, data.message)
ngToast.danger({content: data.message, verticalPosition: 'bottom'})
})
}
$scope.cancelInterpreterSetting = function () {
$scope.showAddNewSetting = false;
$scope.resetNewInterpreterSetting();
};
$scope.showAddNewSetting = false
$scope.resetNewInterpreterSetting()
}
$scope.resetNewInterpreterSetting = function () {
$scope.newInterpreterSetting = {
@ -520,88 +520,88 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
process: false
}
};
emptyNewProperty($scope.newInterpreterSetting);
};
}
emptyNewProperty($scope.newInterpreterSetting)
}
$scope.removeInterpreterProperty = function (key, settingId) {
if (settingId === undefined) {
delete $scope.newInterpreterSetting.properties[key];
delete $scope.newInterpreterSetting.properties[key]
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
delete $scope.interpreterSettings[index].properties[key];
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
delete $scope.interpreterSettings[index].properties[key]
}
};
}
$scope.removeInterpreterDependency = function (artifact, settingId) {
if (settingId === undefined) {
$scope.newInterpreterSetting.dependencies = _.reject($scope.newInterpreterSetting.dependencies,
function (el) {
return el.groupArtifactVersion === artifact;
});
return el.groupArtifactVersion === artifact
})
} else {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
$scope.interpreterSettings[index].dependencies = _.reject($scope.interpreterSettings[index].dependencies,
function (el) {
return el.groupArtifactVersion === artifact;
});
return el.groupArtifactVersion === artifact
})
}
};
}
$scope.addNewInterpreterProperty = function (settingId) {
if (settingId === undefined) {
// Add new property from create form
if (!$scope.newInterpreterSetting.propertyKey || $scope.newInterpreterSetting.propertyKey === '') {
return;
return
}
$scope.newInterpreterSetting.properties[$scope.newInterpreterSetting.propertyKey] = {
value: $scope.newInterpreterSetting.propertyValue
};
emptyNewProperty($scope.newInterpreterSetting);
}
emptyNewProperty($scope.newInterpreterSetting)
} else {
// Add new property from edit form
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
if (!setting.propertyKey || setting.propertyKey === '') {
return;
return
}
setting.properties[setting.propertyKey] = setting.propertyValue;
emptyNewProperty(setting);
setting.properties[setting.propertyKey] = setting.propertyValue
emptyNewProperty(setting)
}
};
}
$scope.addNewInterpreterDependency = function (settingId) {
if (settingId === undefined) {
// Add new dependency from create form
if (!$scope.newInterpreterSetting.depArtifact || $scope.newInterpreterSetting.depArtifact === '') {
return;
return
}
// overwrite if artifact already exists
let newSetting = $scope.newInterpreterSetting;
let newSetting = $scope.newInterpreterSetting
for (let d in newSetting.dependencies) {
if (newSetting.dependencies[d].groupArtifactVersion === newSetting.depArtifact) {
newSetting.dependencies[d] = {
'groupArtifactVersion': newSetting.depArtifact,
'exclusions': newSetting.depExclude
};
newSetting.dependencies.splice(d, 1);
}
newSetting.dependencies.splice(d, 1)
}
}
newSetting.dependencies.push({
'groupArtifactVersion': newSetting.depArtifact,
'exclusions': (newSetting.depExclude === '') ? [] : newSetting.depExclude
});
emptyNewDependency(newSetting);
})
emptyNewDependency(newSetting)
} else {
// Add new dependency from edit form
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
let setting = $scope.interpreterSettings[index];
let index = _.findIndex($scope.interpreterSettings, {'id': settingId})
let setting = $scope.interpreterSettings[index]
if (!setting.depArtifact || setting.depArtifact === '') {
return;
return
}
// overwrite if artifact already exists
@ -610,18 +610,18 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
setting.dependencies[dep] = {
'groupArtifactVersion': setting.depArtifact,
'exclusions': setting.depExclude
};
setting.dependencies.splice(dep, 1);
}
setting.dependencies.splice(dep, 1)
}
}
setting.dependencies.push({
'groupArtifactVersion': setting.depArtifact,
'exclusions': (setting.depExclude === '') ? [] : setting.depExclude
});
emptyNewDependency(setting);
})
emptyNewDependency(setting)
}
};
}
$scope.resetNewRepositorySetting = function () {
$scope.newRepoSetting = {
@ -635,30 +635,30 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
proxyPort: null,
proxyLogin: '',
proxyPassword: ''
};
};
}
}
let getRepositories = function () {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/repository')
.success(function (data, status, headers, config) {
$scope.repositories = data.body;
$scope.repositories = data.body
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
$scope.addNewRepository = function () {
let request = angular.copy($scope.newRepoSetting);
let request = angular.copy($scope.newRepoSetting)
$http.post(baseUrlSrv.getRestApiBase() + '/interpreter/repository', request)
.success(function (data, status, headers, config) {
getRepositories();
$scope.resetNewRepositorySetting();
angular.element('#repoModal').modal('hide');
getRepositories()
$scope.resetNewRepositorySetting()
angular.element('#repoModal').modal('hide')
}).error(function (data, status, headers, config) {
console.log('Error %o %o', headers, config);
});
};
console.log('Error %o %o', headers, config)
})
}
$scope.removeRepository = function (repoId) {
BootstrapDialog.confirm({
@ -669,55 +669,55 @@ function InterpreterCtrl ($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeo
if (result) {
$http.delete(baseUrlSrv.getRestApiBase() + '/interpreter/repository/' + repoId)
.success(function (data, status, headers, config) {
let index = _.findIndex($scope.repositories, {'id': repoId});
$scope.repositories.splice(index, 1);
let index = _.findIndex($scope.repositories, {'id': repoId})
$scope.repositories.splice(index, 1)
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
console.log('Error %o %o', status, data.message)
})
}
}
});
};
})
}
$scope.isDefaultRepository = function (repoId) {
if (repoId === 'central' || repoId === 'local') {
return true;
return true
} else {
return false;
return false
}
};
}
$scope.showErrorMessage = function (setting) {
BootstrapDialog.show({
title: 'Error downloading dependencies',
message: setting.errorReason
});
};
})
}
let init = function () {
$scope.resetNewInterpreterSetting();
$scope.resetNewRepositorySetting();
$scope.resetNewInterpreterSetting()
$scope.resetNewRepositorySetting()
getInterpreterSettings();
getAvailableInterpreters();
getRepositories();
};
getInterpreterSettings()
getAvailableInterpreters()
getRepositories()
}
$scope.showSparkUI = function (settingId) {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/getmetainfos/' + settingId + '?propName=url')
.success(function (data, status, headers, config) {
let url = data.body.url;
let url = data.body.url
if (!url) {
BootstrapDialog.alert({
message: 'No spark application running'
});
return;
})
return
}
window.open(url, '_blank');
window.open(url, '_blank')
}).error(function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
};
console.log('Error %o %o', status, data.message)
})
}
init();
init()
}

View file

@ -12,11 +12,11 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').filter('sortByKey', sortByKey);
angular.module('zeppelinWebApp').filter('sortByKey', sortByKey)
function sortByKey () {
return function (properties) {
let sortedKeys = properties ? Object.keys(properties) : [];
return sortedKeys.sort();
};
let sortedKeys = properties ? Object.keys(properties) : []
return sortedKeys.sort()
}
}

View file

@ -13,169 +13,169 @@
*/
angular.module('zeppelinWebApp')
.controller('JobmanagerCtrl', JobmanagerCtrl);
.controller('JobmanagerCtrl', JobmanagerCtrl)
function JobmanagerCtrl ($scope, websocketMsgSrv, $interval, ngToast, $q, $timeout, jobManagerFilter) {
'ngInject';
'ngInject'
ngToast.dismiss();
ngToast.dismiss()
let asyncNotebookJobFilter = function (jobInfomations, filterConfig) {
return $q(function (resolve, reject) {
$scope.JobInfomationsByFilter = $scope.jobTypeFilter(jobInfomations, filterConfig);
resolve($scope.JobInfomationsByFilter);
});
};
$scope.JobInfomationsByFilter = $scope.jobTypeFilter(jobInfomations, filterConfig)
resolve($scope.JobInfomationsByFilter)
})
}
$scope.doFiltering = function (jobInfomations, filterConfig) {
asyncNotebookJobFilter(jobInfomations, filterConfig).then(
function () {
// success
$scope.isLoadingFilter = false;
$scope.isLoadingFilter = false
},
function () {
// failed
});
};
})
}
$scope.filterValueToName = function (filterValue, maxStringLength) {
if ($scope.activeInterpreters === undefined) {
return;
return
}
let index = _.findIndex($scope.activeInterpreters, {value: filterValue});
let index = _.findIndex($scope.activeInterpreters, {value: filterValue})
if ($scope.activeInterpreters[index].name !== undefined) {
if (maxStringLength !== undefined && maxStringLength > $scope.activeInterpreters[index].name) {
return $scope.activeInterpreters[index].name.substr(0, maxStringLength - 3) + '...';
return $scope.activeInterpreters[index].name.substr(0, maxStringLength - 3) + '...'
}
return $scope.activeInterpreters[index].name;
return $scope.activeInterpreters[index].name
} else {
return 'Interpreter is not set';
return 'Interpreter is not set'
}
};
}
$scope.setFilterValue = function (filterValue) {
$scope.filterConfig.filterValueInterpreter = filterValue;
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig);
};
$scope.filterConfig.filterValueInterpreter = filterValue
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig)
}
$scope.onChangeRunJobToAlwaysTopToggle = function () {
$scope.filterConfig.isRunningAlwaysTop = !$scope.filterConfig.isRunningAlwaysTop;
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig);
};
$scope.filterConfig.isRunningAlwaysTop = !$scope.filterConfig.isRunningAlwaysTop
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig)
}
$scope.onChangeSortAsc = function () {
$scope.filterConfig.isSortByAsc = !$scope.filterConfig.isSortByAsc;
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig);
};
$scope.filterConfig.isSortByAsc = !$scope.filterConfig.isSortByAsc
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig)
}
$scope.doFilterInputTyping = function (keyEvent, jobInfomations, filterConfig) {
let RETURN_KEY_CODE = 13;
$timeout.cancel($scope.dofilterTimeoutObject);
$scope.isActiveSearchTimer = true;
let RETURN_KEY_CODE = 13
$timeout.cancel($scope.dofilterTimeoutObject)
$scope.isActiveSearchTimer = true
$scope.dofilterTimeoutObject = $timeout(function () {
$scope.doFiltering(jobInfomations, filterConfig);
$scope.isActiveSearchTimer = false;
}, 10000);
$scope.doFiltering(jobInfomations, filterConfig)
$scope.isActiveSearchTimer = false
}, 10000)
if (keyEvent.which === RETURN_KEY_CODE) {
$timeout.cancel($scope.dofilterTimeoutObject);
$scope.doFiltering(jobInfomations, filterConfig);
$scope.isActiveSearchTimer = false;
$timeout.cancel($scope.dofilterTimeoutObject)
$scope.doFiltering(jobInfomations, filterConfig)
$scope.isActiveSearchTimer = false
}
};
}
$scope.doForceFilterInputTyping = function (keyEvent, jobInfomations, filterConfig) {
$timeout.cancel($scope.dofilterTimeoutObject);
$scope.doFiltering(jobInfomations, filterConfig);
$scope.isActiveSearchTimer = false;
};
$timeout.cancel($scope.dofilterTimeoutObject)
$scope.doFiltering(jobInfomations, filterConfig)
$scope.isActiveSearchTimer = false
}
$scope.init = function () {
$scope.isLoadingFilter = true;
$scope.jobInfomations = [];
$scope.JobInfomationsByFilter = $scope.jobInfomations;
$scope.isLoadingFilter = true
$scope.jobInfomations = []
$scope.JobInfomationsByFilter = $scope.jobInfomations
$scope.filterConfig = {
isRunningAlwaysTop: true,
filterValueNotebookName: '',
filterValueInterpreter: '*',
isSortByAsc: true
};
$scope.sortTooltipMsg = 'Switch to sort by desc';
$scope.jobTypeFilter = jobManagerFilter;
}
$scope.sortTooltipMsg = 'Switch to sort by desc'
$scope.jobTypeFilter = jobManagerFilter
websocketMsgSrv.getNoteJobsList();
websocketMsgSrv.getNoteJobsList()
$scope.$watch('filterConfig.isSortByAsc', function (value) {
if (value) {
$scope.sortTooltipMsg = 'Switch to sort by desc';
$scope.sortTooltipMsg = 'Switch to sort by desc'
} else {
$scope.sortTooltipMsg = 'Switch to sort by asc';
$scope.sortTooltipMsg = 'Switch to sort by asc'
}
});
})
$scope.$on('$destroy', function () {
websocketMsgSrv.unsubscribeJobManager();
});
};
websocketMsgSrv.unsubscribeJobManager()
})
}
/*
** $scope.$on functions below
*/
$scope.$on('setNoteJobs', function (event, responseData) {
$scope.lastJobServerUnixTime = responseData.lastResponseUnixTime;
$scope.jobInfomations = responseData.jobs;
$scope.jobInfomationsIndexs = $scope.jobInfomations ? _.indexBy($scope.jobInfomations, 'noteId') : {};
$scope.jobTypeFilter($scope.jobInfomations, $scope.filterConfig);
$scope.lastJobServerUnixTime = responseData.lastResponseUnixTime
$scope.jobInfomations = responseData.jobs
$scope.jobInfomationsIndexs = $scope.jobInfomations ? _.indexBy($scope.jobInfomations, 'noteId') : {}
$scope.jobTypeFilter($scope.jobInfomations, $scope.filterConfig)
$scope.activeInterpreters = [
{
name: 'ALL',
value: '*'
}
];
let interpreterLists = _.uniq(_.pluck($scope.jobInfomations, 'interpreter'), false);
]
let interpreterLists = _.uniq(_.pluck($scope.jobInfomations, 'interpreter'), false)
for (let index = 0, length = interpreterLists.length; index < length; index++) {
$scope.activeInterpreters.push({
name: interpreterLists[index],
value: interpreterLists[index]
});
})
}
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig);
});
$scope.doFiltering($scope.jobInfomations, $scope.filterConfig)
})
$scope.$on('setUpdateNoteJobs', function (event, responseData) {
let jobInfomations = $scope.jobInfomations;
let indexStore = $scope.jobInfomationsIndexs;
$scope.lastJobServerUnixTime = responseData.lastResponseUnixTime;
let notes = responseData.jobs;
let jobInfomations = $scope.jobInfomations
let indexStore = $scope.jobInfomationsIndexs
$scope.lastJobServerUnixTime = responseData.lastResponseUnixTime
let notes = responseData.jobs
notes.map(function (changedItem) {
if (indexStore[changedItem.noteId] === undefined) {
let newItem = angular.copy(changedItem);
jobInfomations.push(newItem);
indexStore[changedItem.noteId] = newItem;
let newItem = angular.copy(changedItem)
jobInfomations.push(newItem)
indexStore[changedItem.noteId] = newItem
} else {
let changeOriginTarget = indexStore[changedItem.noteId];
let changeOriginTarget = indexStore[changedItem.noteId]
if (changedItem.isRemoved !== undefined && changedItem.isRemoved === true) {
// remove Item.
let removeIndex = _.findIndex(indexStore, changedItem.noteId);
let removeIndex = _.findIndex(indexStore, changedItem.noteId)
if (removeIndex > -1) {
indexStore.splice(removeIndex, 1);
indexStore.splice(removeIndex, 1)
}
removeIndex = _.findIndex(jobInfomations, {'noteId': changedItem.noteId});
removeIndex = _.findIndex(jobInfomations, {'noteId': changedItem.noteId})
if (removeIndex) {
jobInfomations.splice(removeIndex, 1);
jobInfomations.splice(removeIndex, 1)
}
} else {
// change value for item.
changeOriginTarget.isRunningJob = changedItem.isRunningJob;
changeOriginTarget.noteName = changedItem.noteName;
changeOriginTarget.noteType = changedItem.noteType;
changeOriginTarget.interpreter = changedItem.interpreter;
changeOriginTarget.unixTimeLastRun = changedItem.unixTimeLastRun;
changeOriginTarget.paragraphs = changedItem.paragraphs;
changeOriginTarget.isRunningJob = changedItem.isRunningJob
changeOriginTarget.noteName = changedItem.noteName
changeOriginTarget.noteType = changedItem.noteType
changeOriginTarget.interpreter = changedItem.interpreter
changeOriginTarget.unixTimeLastRun = changedItem.unixTimeLastRun
changeOriginTarget.paragraphs = changedItem.paragraphs
}
}
});
$scope.doFiltering(jobInfomations, $scope.filterConfig);
});
})
$scope.doFiltering(jobInfomations, $scope.filterConfig)
})
}

View file

@ -12,36 +12,36 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').filter('jobManager', jobManagerFilter);
angular.module('zeppelinWebApp').filter('jobManager', jobManagerFilter)
function jobManagerFilter () {
function filterContext (jobItems, filterConfig) {
let filterValueInterpreter = filterConfig.filterValueInterpreter;
let filterValueNotebookName = filterConfig.filterValueNotebookName;
let isSortByAsc = filterConfig.isSortByAsc;
let filterItems = jobItems;
let filterValueInterpreter = filterConfig.filterValueInterpreter
let filterValueNotebookName = filterConfig.filterValueNotebookName
let isSortByAsc = filterConfig.isSortByAsc
let filterItems = jobItems
if (filterValueInterpreter === undefined) {
filterItems = _.filter(filterItems, function (jobItem) {
return jobItem.interpreter === undefined ? true : false;
});
return jobItem.interpreter === undefined ? true : false
})
} else if (filterValueInterpreter !== '*') {
filterItems = _.where(filterItems, {interpreter: filterValueInterpreter});
filterItems = _.where(filterItems, {interpreter: filterValueInterpreter})
}
if (filterValueNotebookName !== '') {
filterItems = _.filter(filterItems, function (jobItem) {
let lowerFilterValue = filterValueNotebookName.toLocaleLowerCase();
let lowerNotebookName = jobItem.noteName.toLocaleLowerCase();
return lowerNotebookName.match(new RegExp('.*' + lowerFilterValue + '.*'));
});
let lowerFilterValue = filterValueNotebookName.toLocaleLowerCase()
let lowerNotebookName = jobItem.noteName.toLocaleLowerCase()
return lowerNotebookName.match(new RegExp('.*' + lowerFilterValue + '.*'))
})
}
filterItems = _.sortBy(filterItems, function (sortItem) {
return sortItem.noteName.toLowerCase();
});
return sortItem.noteName.toLowerCase()
})
return isSortByAsc ? filterItems : filterItems.reverse();
return isSortByAsc ? filterItems : filterItems.reverse()
}
return filterContext;
return filterContext
}

View file

@ -12,31 +12,31 @@
* limitations under the License.
*/
import { ParagraphStatus, } from '../../notebook/paragraph/paragraph.status';
import { ParagraphStatus, } from '../../notebook/paragraph/paragraph.status'
angular.module('zeppelinWebApp').controller('JobCtrl', JobCtrl);
angular.module('zeppelinWebApp').controller('JobCtrl', JobCtrl)
function JobCtrl ($scope, $http, baseUrlSrv) {
'ngInject';
'ngInject'
$scope.init = function (jobInformation) {
$scope.progressValue = 0;
};
$scope.progressValue = 0
}
$scope.getProgress = function () {
let statusList = _.pluck($scope.notebookJob.paragraphs, 'status');
let statusList = _.pluck($scope.notebookJob.paragraphs, 'status')
let runningJob = _.countBy(statusList, function (status) {
if (status === ParagraphStatus.RUNNING || status === ParagraphStatus.FINISHED) {
return 'matchCount';
return 'matchCount'
} else {
return 'none';
return 'none'
}
});
let totalCount = statusList.length;
let runningJobCount = runningJob.matchCount;
let result = Math.ceil(runningJobCount / totalCount * 100);
return isNaN(result) ? 0 : result;
};
})
let totalCount = statusList.length
let runningJobCount = runningJob.matchCount
let result = Math.ceil(runningJobCount / totalCount * 100)
return isNaN(result) ? 0 : result
}
$scope.runNotebookJob = function (notebookId) {
BootstrapDialog.confirm({
@ -54,21 +54,21 @@ function JobCtrl ($scope, $http, baseUrlSrv) {
}).then(function successCallback (response) {
// success
}, function errorCallback (errorResponse) {
let errorText = 'SERVER ERROR';
let errorText = 'SERVER ERROR'
// eslint-disable-next-line no-extra-boolean-cast
if (!!errorResponse.data.message) {
errorText = errorResponse.data.message;
errorText = errorResponse.data.message
}
BootstrapDialog.alert({
closable: true,
title: 'Execution Failure',
message: errorText
});
});
})
})
}
}
});
};
})
}
$scope.stopNotebookJob = function (notebookId) {
BootstrapDialog.confirm({
@ -86,23 +86,23 @@ function JobCtrl ($scope, $http, baseUrlSrv) {
}).then(function successCallback (response) {
// success
}, function errorCallback (errorResponse) {
let errorText = 'SERVER ERROR';
let errorText = 'SERVER ERROR'
// eslint-disable-next-line no-extra-boolean-cast
if (!!errorResponse.data.message) {
errorText = errorResponse.data.message;
errorText = errorResponse.data.message
}
BootstrapDialog.alert({
closable: true,
title: 'Stop Failure',
message: errorText
});
});
})
})
}
}
});
};
})
}
$scope.lastExecuteTime = function (unixtime) {
return moment.unix(unixtime / 1000).fromNow();
};
return moment.unix(unixtime / 1000).fromNow()
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
describe('Controller: NotebookCtrl', function () {
beforeEach(angular.mock.module('zeppelinWebApp'));
beforeEach(angular.mock.module('zeppelinWebApp'))
let scope;
let scope
let websocketMsgSrvMock = {
getNote: function () {},
@ -9,131 +9,131 @@ describe('Controller: NotebookCtrl', function () {
getInterpreterBindings: function () {},
updateNote: function () {},
renameNote: function () {}
};
}
let baseUrlSrvMock = {
getRestApiBase: function () {
return 'http://localhost:8080';
return 'http://localhost:8080'
}
};
}
let noteMock = {
id: 1,
name: 'my note',
config: {},
};
}
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
scope = $rootScope.$new()
$controller('NotebookCtrl', {
$scope: scope,
websocketMsgSrv: websocketMsgSrvMock,
baseUrlSrv: baseUrlSrvMock
});
}));
})
}))
beforeEach(function () {
scope.note = noteMock;
});
scope.note = noteMock
})
let functions = ['getCronOptionNameFromValue', 'removeNote', 'runAllParagraphs', 'saveNote', 'toggleAllEditor',
'showAllEditor', 'hideAllEditor', 'toggleAllTable', 'hideAllTable', 'showAllTable', 'isNoteRunning',
'killSaveTimer', 'startSaveTimer', 'setLookAndFeel', 'setCronScheduler', 'setConfig', 'updateNoteName',
'openSetting', 'closeSetting', 'saveSetting', 'toggleSetting'];
'openSetting', 'closeSetting', 'saveSetting', 'toggleSetting']
functions.forEach(function (fn) {
it('check for scope functions to be defined : ' + fn, function () {
expect(scope[fn]).toBeDefined();
});
});
expect(scope[fn]).toBeDefined()
})
})
it('should set default value of "editorToggled" to false', function () {
expect(scope.editorToggled).toEqual(false);
});
expect(scope.editorToggled).toEqual(false)
})
it('should set "showSetting" to true when openSetting() is called', function () {
scope.openSetting();
expect(scope.showSetting).toEqual(true);
});
scope.openSetting()
expect(scope.showSetting).toEqual(true)
})
it('should set "showSetting" to false when closeSetting() is called', function () {
scope.closeSetting();
expect(scope.showSetting).toEqual(false);
});
scope.closeSetting()
expect(scope.showSetting).toEqual(false)
})
it('should return the correct value for getCronOptionNameFromValue()', function () {
let none = scope.getCronOptionNameFromValue();
let oneMin = scope.getCronOptionNameFromValue('0 0/1 * * * ?');
let fiveMin = scope.getCronOptionNameFromValue('0 0/5 * * * ?');
let oneHour = scope.getCronOptionNameFromValue('0 0 0/1 * * ?');
let threeHours = scope.getCronOptionNameFromValue('0 0 0/3 * * ?');
let sixHours = scope.getCronOptionNameFromValue('0 0 0/6 * * ?');
let twelveHours = scope.getCronOptionNameFromValue('0 0 0/12 * * ?');
let oneDay = scope.getCronOptionNameFromValue('0 0 0 * * ?');
let none = scope.getCronOptionNameFromValue()
let oneMin = scope.getCronOptionNameFromValue('0 0/1 * * * ?')
let fiveMin = scope.getCronOptionNameFromValue('0 0/5 * * * ?')
let oneHour = scope.getCronOptionNameFromValue('0 0 0/1 * * ?')
let threeHours = scope.getCronOptionNameFromValue('0 0 0/3 * * ?')
let sixHours = scope.getCronOptionNameFromValue('0 0 0/6 * * ?')
let twelveHours = scope.getCronOptionNameFromValue('0 0 0/12 * * ?')
let oneDay = scope.getCronOptionNameFromValue('0 0 0 * * ?')
expect(none).toEqual('');
expect(oneMin).toEqual('1m');
expect(fiveMin).toEqual('5m');
expect(oneHour).toEqual('1h');
expect(threeHours).toEqual('3h');
expect(sixHours).toEqual('6h');
expect(twelveHours).toEqual('12h');
expect(oneDay).toEqual('1d');
});
expect(none).toEqual('')
expect(oneMin).toEqual('1m')
expect(fiveMin).toEqual('5m')
expect(oneHour).toEqual('1h')
expect(threeHours).toEqual('3h')
expect(sixHours).toEqual('6h')
expect(twelveHours).toEqual('12h')
expect(oneDay).toEqual('1d')
})
it('should have "isNoteDirty" as null by default', function () {
expect(scope.isNoteDirty).toEqual(null);
});
expect(scope.isNoteDirty).toEqual(null)
})
it('should first call killSaveTimer() when calling startSaveTimer()', function () {
expect(scope.saveTimer).toEqual(null);
spyOn(scope, 'killSaveTimer');
scope.startSaveTimer();
expect(scope.killSaveTimer).toHaveBeenCalled();
});
expect(scope.saveTimer).toEqual(null)
spyOn(scope, 'killSaveTimer')
scope.startSaveTimer()
expect(scope.killSaveTimer).toHaveBeenCalled()
})
it('should set "saveTimer" when saveTimer() and killSaveTimer() are called', function () {
expect(scope.saveTimer).toEqual(null);
scope.startSaveTimer();
expect(scope.saveTimer).toBeTruthy();
scope.killSaveTimer();
expect(scope.saveTimer).toEqual(null);
});
expect(scope.saveTimer).toEqual(null)
scope.startSaveTimer()
expect(scope.saveTimer).toBeTruthy()
scope.killSaveTimer()
expect(scope.saveTimer).toEqual(null)
})
it('should NOT update note name when updateNoteName() is called with an invalid name', function () {
spyOn(websocketMsgSrvMock, 'renameNote');
scope.updateNoteName('');
expect(scope.note.name).toEqual(noteMock.name);
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled();
scope.updateNoteName(' ');
expect(scope.note.name).toEqual(noteMock.name);
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled();
scope.updateNoteName(scope.note.name);
expect(scope.note.name).toEqual(noteMock.name);
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled();
});
spyOn(websocketMsgSrvMock, 'renameNote')
scope.updateNoteName('')
expect(scope.note.name).toEqual(noteMock.name)
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled()
scope.updateNoteName(' ')
expect(scope.note.name).toEqual(noteMock.name)
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled()
scope.updateNoteName(scope.note.name)
expect(scope.note.name).toEqual(noteMock.name)
expect(websocketMsgSrvMock.renameNote).not.toHaveBeenCalled()
})
it('should update note name when updateNoteName() is called with a valid name', function () {
spyOn(websocketMsgSrvMock, 'renameNote');
let newName = 'Your Note';
scope.updateNoteName(newName);
expect(scope.note.name).toEqual(newName);
expect(websocketMsgSrvMock.renameNote).toHaveBeenCalled();
});
spyOn(websocketMsgSrvMock, 'renameNote')
let newName = 'Your Note'
scope.updateNoteName(newName)
expect(scope.note.name).toEqual(newName)
expect(websocketMsgSrvMock.renameNote).toHaveBeenCalled()
})
it('should reload note info once per one "setNoteMenu" event', function () {
spyOn(websocketMsgSrvMock, 'getNote');
spyOn(websocketMsgSrvMock, 'listRevisionHistory');
spyOn(websocketMsgSrvMock, 'getNote')
spyOn(websocketMsgSrvMock, 'listRevisionHistory')
scope.$broadcast('setNoteMenu');
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(0);
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(0);
scope.$broadcast('setNoteMenu')
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(0)
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(0)
websocketMsgSrvMock.getNote.calls.reset();
websocketMsgSrvMock.listRevisionHistory.calls.reset();
websocketMsgSrvMock.getNote.calls.reset()
websocketMsgSrvMock.listRevisionHistory.calls.reset()
scope.$broadcast('setNoteMenu');
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(0);
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(0);
});
});
scope.$broadcast('setNoteMenu')
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(0)
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(0)
})
})

File diff suppressed because it is too large Load diff

View file

@ -1,53 +1,53 @@
describe('Controller: ParagraphCtrl', function () {
beforeEach(angular.mock.module('zeppelinWebApp'));
beforeEach(angular.mock.module('zeppelinWebApp'))
let scope;
let websocketMsgSrvMock = {};
let scope
let websocketMsgSrvMock = {}
let paragraphMock = {
config: {},
settings: {
forms: {}
}
};
}
let route = {
current: {
pathParams: {
noteId: 'noteId'
}
}
};
}
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
$rootScope.notebookScope = $rootScope.$new(true, $rootScope);
scope = $rootScope.$new()
$rootScope.notebookScope = $rootScope.$new(true, $rootScope)
$controller('ParagraphCtrl', {
$scope: scope,
websocketMsgSrv: websocketMsgSrvMock,
$element: {},
$route: route
});
})
scope.init(paragraphMock);
}));
scope.init(paragraphMock)
}))
let functions = ['isRunning', 'getIframeDimensions', 'cancelParagraph', 'runParagraph', 'saveParagraph',
'moveUp', 'moveDown', 'insertNew', 'removeParagraph', 'toggleEditor', 'closeEditor', 'openEditor',
'closeTable', 'openTable', 'showTitle', 'hideTitle', 'setTitle', 'showLineNumbers', 'hideLineNumbers',
'changeColWidth', 'columnWidthClass', 'toggleOutput', 'loadForm',
'aceChanged', 'aceLoaded', 'getEditorValue', 'getProgress', 'getExecutionTime', 'isResultOutdated'];
'aceChanged', 'aceLoaded', 'getEditorValue', 'getProgress', 'getExecutionTime', 'isResultOutdated']
functions.forEach(function (fn) {
it('check for scope functions to be defined : ' + fn, function () {
expect(scope[fn]).toBeDefined();
});
});
expect(scope[fn]).toBeDefined()
})
})
it('should have this array of values for "colWidthOption"', function () {
expect(scope.colWidthOption).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
});
expect(scope.colWidthOption).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
})
it('should set default value of "paragraphFocused" as false', function () {
expect(scope.paragraphFocused).toEqual(false);
});
});
expect(scope.paragraphFocused).toEqual(false)
})
})

View file

@ -19,12 +19,12 @@ export const ParagraphStatus = {
FINISHED: 'FINISHED',
ABORT: 'ABORT',
ERROR: 'ERROR',
};
}
export function isParagraphRunning (paragraph) {
if (!paragraph) { return false; }
const status = paragraph.status;
if (!status) { return false; }
if (!paragraph) { return false }
const status = paragraph.status
if (!status) { return false }
return status === ParagraphStatus.PENDING || status === ParagraphStatus.RUNNING;
return status === ParagraphStatus.PENDING || status === ParagraphStatus.RUNNING
}

View file

@ -12,50 +12,50 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('NotebookReposCtrl', NotebookReposCtrl);
angular.module('zeppelinWebApp').controller('NotebookReposCtrl', NotebookReposCtrl)
function NotebookReposCtrl ($http, baseUrlSrv, ngToast) {
'ngInject';
'ngInject'
let vm = this;
vm.notebookRepos = [];
vm.showDropdownSelected = showDropdownSelected;
vm.saveNotebookRepo = saveNotebookRepo;
let vm = this
vm.notebookRepos = []
vm.showDropdownSelected = showDropdownSelected
vm.saveNotebookRepo = saveNotebookRepo
_init();
_init()
// Public functions
function saveNotebookRepo (valueform, repo, data) {
console.log('data %o', data);
console.log('data %o', data)
$http.put(baseUrlSrv.getRestApiBase() + '/notebook-repositories', {
'name': repo.className,
'settings': data
}).success(function (data) {
let index = _.findIndex(vm.notebookRepos, {'className': repo.className});
let index = _.findIndex(vm.notebookRepos, {'className': repo.className})
if (index >= 0) {
vm.notebookRepos[index] = data.body;
console.log('repos %o, data %o', vm.notebookRepos, data.body);
vm.notebookRepos[index] = data.body
console.log('repos %o, data %o', vm.notebookRepos, data.body)
}
valueform.$show();
valueform.$show()
}).error(function () {
ngToast.danger({
content: 'We couldn\'t save that NotebookRepo\'s settings',
verticalPosition: 'bottom',
timeout: '3000'
});
valueform.$show();
});
})
valueform.$show()
})
return 'manual';
return 'manual'
}
function showDropdownSelected (setting) {
let index = _.findIndex(setting.value, {'value': setting.selected});
let index = _.findIndex(setting.value, {'value': setting.selected})
if (index < 0) {
return 'No value';
return 'No value'
} else {
return setting.value[index].name;
return setting.value[index].name
}
}
@ -64,24 +64,24 @@ function NotebookReposCtrl ($http, baseUrlSrv, ngToast) {
function _getInterpreterSettings () {
$http.get(baseUrlSrv.getRestApiBase() + '/notebook-repositories')
.success(function (data, status, headers, config) {
vm.notebookRepos = data.body;
console.log('ya notebookRepos %o', vm.notebookRepos);
vm.notebookRepos = data.body
console.log('ya notebookRepos %o', vm.notebookRepos)
}).error(function (data, status, headers, config) {
if (status === 401) {
ngToast.danger({
content: 'You don\'t have permission on this page',
verticalPosition: 'bottom',
timeout: '3000'
});
})
setTimeout(function () {
window.location.replace('/');
}, 3000);
window.location.replace('/')
}, 3000)
}
console.log('Error %o %o', status, data.message);
});
console.log('Error %o %o', status, data.message)
})
}
function _init () {
_getInterpreterSettings();
_getInterpreterSettings()
}
}

View file

@ -12,43 +12,43 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('SearchResultCtrl', SearchResultCtrl);
angular.module('zeppelinWebApp').controller('SearchResultCtrl', SearchResultCtrl)
function SearchResultCtrl ($scope, $routeParams, searchService) {
'ngInject';
'ngInject'
$scope.isResult = true;
$scope.searchTerm = $routeParams.searchTerm;
let results = searchService.search({'q': $routeParams.searchTerm}).query();
$scope.isResult = true
$scope.searchTerm = $routeParams.searchTerm
let results = searchService.search({'q': $routeParams.searchTerm}).query()
results.$promise.then(function (result) {
$scope.notes = result.body.map(function (note) {
// redirect to notebook when search result is a notebook itself,
// not a paragraph
if (!/\/paragraph\//.test(note.id)) {
return note;
return note
}
note.id = note.id.replace('paragraph/', '?paragraph=') +
'&term=' + $routeParams.searchTerm;
'&term=' + $routeParams.searchTerm
return note;
});
return note
})
if ($scope.notes.length === 0) {
$scope.isResult = false;
$scope.isResult = false
} else {
$scope.isResult = true;
$scope.isResult = true
}
$scope.$on('$routeChangeStart', function (event, next, current) {
if (next.originalPath !== '/search/:searchTerm') {
searchService.searchTerm = '';
searchService.searchTerm = ''
}
});
});
})
})
$scope.page = 0;
$scope.allResults = false;
$scope.page = 0
$scope.allResults = false
$scope.highlightSearchResults = function (note) {
return function (_editor) {
@ -60,59 +60,59 @@ function SearchResultCtrl ($scope, $routeParams, searchService) {
'ace/mode/sql': /^%(\w*\.)?\wql/,
'ace/mode/markdown': /^%md/,
'ace/mode/sh': /^%sh/
};
}
return Object.keys(editorModes).reduce(function (res, mode) {
return editorModes[mode].test(text) ? mode : res;
}, 'ace/mode/scala');
return editorModes[mode].test(text) ? mode : res
}, 'ace/mode/scala')
}
let Range = ace.require('ace/range').Range;
let Range = ace.require('ace/range').Range
_editor.setOption('highlightActiveLine', false);
_editor.$blockScrolling = Infinity;
_editor.setReadOnly(true);
_editor.renderer.setShowGutter(false);
_editor.setTheme('ace/theme/chrome');
_editor.getSession().setMode(getEditorMode(note.text));
_editor.setOption('highlightActiveLine', false)
_editor.$blockScrolling = Infinity
_editor.setReadOnly(true)
_editor.renderer.setShowGutter(false)
_editor.setTheme('ace/theme/chrome')
_editor.getSession().setMode(getEditorMode(note.text))
function getIndeces (term) {
return function (str) {
let indeces = [];
let i = -1;
let indeces = []
let i = -1
while ((i = str.indexOf(term, i + 1)) >= 0) {
indeces.push(i);
indeces.push(i)
}
return indeces;
};
return indeces
}
}
let result = '';
let result = ''
if (note.header !== '') {
result = note.header + '\n\n' + note.snippet;
result = note.header + '\n\n' + note.snippet
} else {
result = note.snippet;
result = note.snippet
}
let lines = result
.split('\n')
.map(function (line, row) {
let match = line.match(/<B>(.+?)<\/B>/);
let match = line.match(/<B>(.+?)<\/B>/)
// return early if nothing to highlight
if (!match) {
return line;
return line
}
let term = match[1];
let term = match[1]
let __line = line
.replace(/<B>/g, '')
.replace(/<\/B>/g, '');
.replace(/<\/B>/g, '')
let indeces = getIndeces(term)(__line);
let indeces = getIndeces(term)(__line)
indeces.forEach(function (start) {
let end = start + term.length;
let end = start + term.length
if (note.header !== '' && row === 0) {
_editor
.getSession()
@ -120,14 +120,14 @@ function SearchResultCtrl ($scope, $routeParams, searchService) {
new Range(row, 0, row, line.length),
'search-results-highlight-header',
'background'
);
)
_editor
.getSession()
.addMarker(
new Range(row, start, row, end),
'search-results-highlight',
'line'
);
)
} else {
_editor
.getSession()
@ -135,19 +135,19 @@ function SearchResultCtrl ($scope, $routeParams, searchService) {
new Range(row, start, row, end),
'search-results-highlight',
'line'
);
)
}
});
return __line;
});
})
return __line
})
// resize editor based on content length
_editor.setOption(
'maxLines',
lines.reduce(function (len, line) { return len + line.length; }, 0)
);
lines.reduce(function (len, line) { return len + line.length }, 0)
)
_editor.getSession().setValue(lines.join('\n'));
};
};
_editor.getSession().setValue(lines.join('\n'))
}
}
}

View file

@ -18,8 +18,8 @@
export {
DefaultDisplayType,
SpellResult,
} from './spell-result';
} from './spell-result'
export {
SpellBase,
} from './spell-base';
} from './spell-base'

View file

@ -19,12 +19,12 @@
import {
DefaultDisplayType,
SpellResult,
} from './spell-result';
} from './spell-result'
/* eslint-enable no-unused-vars */
export class SpellBase {
constructor (magic) {
this.magic = magic;
this.magic = magic
}
/**
@ -35,7 +35,7 @@ export class SpellBase {
* @return {SpellResult}
*/
interpret (paragraphText, config) {
throw new Error('SpellBase.interpret() should be overrided');
throw new Error('SpellBase.interpret() should be overrided')
}
/**
@ -44,6 +44,6 @@ export class SpellBase {
* @return {string}
*/
getMagic () {
return this.magic;
return this.magic
}
}

View file

@ -21,7 +21,7 @@ export const DefaultDisplayType = {
HTML: 'HTML',
ANGULAR: 'ANGULAR',
TEXT: 'TEXT',
};
}
export const DefaultDisplayMagic = {
'%element': DefaultDisplayType.ELEMENT,
@ -29,12 +29,12 @@ export const DefaultDisplayMagic = {
'%html': DefaultDisplayType.HTML,
'%angular': DefaultDisplayType.ANGULAR,
'%text': DefaultDisplayType.TEXT,
};
}
export class DataWithType {
constructor (data, type, magic, text) {
this.data = data;
this.type = type;
this.data = data
this.type = type
/**
* keep for `DefaultDisplayType.ELEMENT` (function data type)
@ -44,29 +44,29 @@ export class DataWithType {
* since they don't have context where they are created.
*/
this.magic = magic;
this.text = text;
this.magic = magic
this.text = text
}
static handleDefaultMagic (m) {
// let's use default display type instead of magic in case of default
// to keep consistency with backend interpreter
if (DefaultDisplayMagic[m]) {
return DefaultDisplayMagic[m];
return DefaultDisplayMagic[m]
} else {
return m;
return m
}
}
static createPropagable (dataWithType) {
if (!SpellResult.isFunction(dataWithType.data)) {
return dataWithType;
return dataWithType
}
const data = dataWithType.getText();
const type = dataWithType.getMagic();
const data = dataWithType.getText()
const type = dataWithType.getMagic()
return new DataWithType(data, type);
return new DataWithType(data, type)
}
/**
@ -77,43 +77,43 @@ export class DataWithType {
*/
static parseStringData (data, customDisplayMagic) {
function availableMagic (magic) {
return magic && (DefaultDisplayMagic[magic] || customDisplayMagic[magic]);
return magic && (DefaultDisplayMagic[magic] || customDisplayMagic[magic])
}
const splited = data.split('\n');
const splited = data.split('\n')
const gensWithTypes = [];
let mergedGens = [];
let previousMagic = DefaultDisplayType.TEXT;
const gensWithTypes = []
let mergedGens = []
let previousMagic = DefaultDisplayType.TEXT
// create `DataWithType` whenever see available display type.
for (let i = 0; i < splited.length; i++) {
const g = splited[i];
const magic = SpellResult.extractMagic(g);
const g = splited[i]
const magic = SpellResult.extractMagic(g)
// create `DataWithType` only if see new magic
if (availableMagic(magic) && mergedGens.length > 0) {
gensWithTypes.push(new DataWithType(mergedGens.join(''), previousMagic));
mergedGens = [];
gensWithTypes.push(new DataWithType(mergedGens.join(''), previousMagic))
mergedGens = []
}
// accumulate `data` to mergedGens
if (availableMagic(magic)) {
const withoutMagic = g.split(magic)[1];
mergedGens.push(`${withoutMagic}\n`);
previousMagic = DataWithType.handleDefaultMagic(magic);
const withoutMagic = g.split(magic)[1]
mergedGens.push(`${withoutMagic}\n`)
previousMagic = DataWithType.handleDefaultMagic(magic)
} else {
mergedGens.push(`${g}\n`);
mergedGens.push(`${g}\n`)
}
}
// cleanup the last `DataWithType`
if (mergedGens.length > 0) {
previousMagic = DataWithType.handleDefaultMagic(previousMagic);
gensWithTypes.push(new DataWithType(mergedGens.join(''), previousMagic));
previousMagic = DataWithType.handleDefaultMagic(previousMagic)
gensWithTypes.push(new DataWithType(mergedGens.join(''), previousMagic))
}
return gensWithTypes;
return gensWithTypes
}
/**
@ -128,42 +128,42 @@ export class DataWithType {
*/
static produceMultipleData (dataWithType, customDisplayType,
magic, textWithoutMagic) {
const data = dataWithType.getData();
const type = dataWithType.getType();
const data = dataWithType.getData()
const type = dataWithType.getType()
// if the type is specified, just return it
// handle non-specified dataWithTypes only
if (type) {
return new Promise((resolve) => { resolve([dataWithType]); });
return new Promise((resolve) => { resolve([dataWithType]) })
}
let wrapped;
let wrapped
if (SpellResult.isFunction(data)) {
// if data is a function, we consider it as ELEMENT type.
wrapped = new Promise((resolve) => {
const dt = new DataWithType(
data, DefaultDisplayType.ELEMENT, magic, textWithoutMagic);
const result = [dt];
return resolve(result);
});
data, DefaultDisplayType.ELEMENT, magic, textWithoutMagic)
const result = [dt]
return resolve(result)
})
} else if (SpellResult.isPromise(data)) {
// if data is a promise,
wrapped = data.then(generated => {
const result =
DataWithType.parseStringData(generated, customDisplayType);
return result;
DataWithType.parseStringData(generated, customDisplayType)
return result
})
} else {
// if data is a object, parse it to multiples
wrapped = new Promise((resolve) => {
const result =
DataWithType.parseStringData(data, customDisplayType);
return resolve(result);
});
DataWithType.parseStringData(data, customDisplayType)
return resolve(result)
})
}
return wrapped;
return wrapped
}
/**
@ -176,7 +176,7 @@ export class DataWithType {
* @returns {*} `data` which can be object, function or promise.
*/
getData () {
return this.data;
return this.data
}
/**
@ -186,65 +186,65 @@ export class DataWithType {
* @returns {string}
*/
getType () {
return this.type;
return this.type
}
getMagic () {
return this.magic;
return this.magic
}
getText () {
return this.text;
return this.text
}
}
export class SpellResult {
constructor (resultData, resultType) {
this.dataWithTypes = [];
this.add(resultData, resultType);
this.dataWithTypes = []
this.add(resultData, resultType)
}
static isFunction (data) {
return (data && typeof data === 'function');
return (data && typeof data === 'function')
}
static isPromise (data) {
return (data && typeof data.then === 'function');
return (data && typeof data.then === 'function')
}
static isObject (data) {
return (data &&
!SpellResult.isFunction(data) &&
!SpellResult.isPromise(data));
!SpellResult.isPromise(data))
}
static extractMagic (allParagraphText) {
const pattern = /^\s*%(\S+)\s*/g;
const pattern = /^\s*%(\S+)\s*/g
try {
let match = pattern.exec(allParagraphText);
let match = pattern.exec(allParagraphText)
if (match) {
return `%${match[1].trim()}`;
return `%${match[1].trim()}`
}
} catch (error) {
// failed to parse, ignore
}
return undefined;
return undefined
}
static createPropagable (resultMsg) {
return resultMsg.map(dt => {
return DataWithType.createPropagable(dt);
return DataWithType.createPropagable(dt)
})
}
add (resultData, resultType) {
if (resultData) {
this.dataWithTypes.push(
new DataWithType(resultData, resultType));
new DataWithType(resultData, resultType))
}
return this;
return this
}
/**
@ -255,20 +255,20 @@ export class SpellResult {
getAllParsedDataWithTypes (customDisplayType, magic, textWithoutMagic) {
const promises = this.dataWithTypes.map(dt => {
return DataWithType.produceMultipleData(
dt, customDisplayType, magic, textWithoutMagic);
});
dt, customDisplayType, magic, textWithoutMagic)
})
// some promises can include an array so we need to flatten them
const flatten = Promise.all(promises).then(values => {
return values.reduce((acc, cur) => {
if (Array.isArray(cur)) {
return acc.concat(cur);
return acc.concat(cur)
} else {
return acc.concat([cur]);
return acc.concat([cur])
}
})
});
})
return flatten;
return flatten
}
}

View file

@ -13,7 +13,7 @@
*/
export function getCurrentChart(config) {
return config.chart.current;
return config.chart.current
}
export function getCurrentChartTransform(config) {
@ -43,7 +43,7 @@ export function useSharedAxis(config, chart) {
export function serializeSharedAxes(config) {
const availableCharts = getAvailableChartNames(config.spec.charts)
for (let i = 0; i < availableCharts.length; i++) {
const chartName = availableCharts[i];
const chartName = availableCharts[i]
if (useSharedAxis(config, chartName)) {
/** use reference :) in case of sharedAxis */
config.axis[chartName] = config.sharedAxis
@ -59,19 +59,19 @@ export const Widget = {
}
export function isInputWidget(paramSpec) {
return (paramSpec && !paramSpec.widget) || (paramSpec && paramSpec.widget === Widget.INPUT);
return (paramSpec && !paramSpec.widget) || (paramSpec && paramSpec.widget === Widget.INPUT)
}
export function isOptionWidget(paramSpec) {
return paramSpec && paramSpec.widget === Widget.OPTION;
return paramSpec && paramSpec.widget === Widget.OPTION
}
export function isCheckboxWidget(paramSpec) {
return paramSpec && paramSpec.widget === Widget.CHECKBOX;
return paramSpec && paramSpec.widget === Widget.CHECKBOX
}
export function isTextareaWidget(paramSpec) {
return paramSpec && paramSpec.widget === Widget.TEXTAREA;
return paramSpec && paramSpec.widget === Widget.TEXTAREA
}
export const ParameterValueType = {
@ -92,23 +92,23 @@ export function parseParameter(paramSpecs, param) {
if (paramSpec.valueType === ParameterValueType.INT &&
typeof parsed[name] !== 'number') {
try { parsed[name] = parseInt(parsed[name]); } catch (error) { parsed[name] = paramSpec.defaultValue; }
try { parsed[name] = parseInt(parsed[name]) } catch (error) { parsed[name] = paramSpec.defaultValue }
} else if (paramSpec.valueType === ParameterValueType.FLOAT &&
typeof parsed[name] !== 'number') {
try { parsed[name] = parseFloat(parsed[name]); } catch (error) { parsed[name] = paramSpec.defaultValue; }
try { parsed[name] = parseFloat(parsed[name]) } catch (error) { parsed[name] = paramSpec.defaultValue }
} else if (paramSpec.valueType === ParameterValueType.BOOLEAN) {
if (parsed[name] === 'false') {
parsed[name] = false;
parsed[name] = false
} else if (parsed[name] === 'true') {
parsed[name] = true;
parsed[name] = true
} else if (typeof parsed[name] !== 'boolean') {
parsed[name] = paramSpec.defaultValue;
parsed[name] = paramSpec.defaultValue
}
} else if (paramSpec.valueType === ParameterValueType.JSON) {
if (parsed[name] !== null && typeof parsed[name] !== 'object') {
try { parsed[name] = JSON.parse(parsed[name]); } catch (error) { parsed[name] = paramSpec.defaultValue; }
try { parsed[name] = JSON.parse(parsed[name]) } catch (error) { parsed[name] = paramSpec.defaultValue }
} else if (parsed[name] === null) {
parsed[name] = paramSpec.defaultValue;
parsed[name] = paramSpec.defaultValue
}
}
}
@ -142,12 +142,12 @@ export function isSingleDimensionAxis(axisSpec) {
* add the `name` field while converting to array to easily manipulate
*/
export function getSpecs(specObject) {
const specs = [];
const specs = []
for (let name in specObject) {
const singleSpec = specObject[name];
const singleSpec = specObject[name]
if (!singleSpec) { continue }
singleSpec.name = name;
specs.push(singleSpec);
singleSpec.name = name
specs.push(singleSpec)
}
return specs
@ -164,11 +164,11 @@ export function getAvailableChartNames(charts) {
export function applyMaxAxisCount(config, axisSpec) {
if (isSingleDimensionAxis(axisSpec) || typeof axisSpec.maxAxisCount === 'undefined') {
return;
return
}
const columns = getCurrentChartAxis(config)[axisSpec.name]
if (columns.length <= axisSpec.maxAxisCount) { return; }
if (columns.length <= axisSpec.maxAxisCount) { return }
const sliced = columns.slice(1)
getCurrentChartAxis(config)[axisSpec.name] = sliced
@ -205,23 +205,23 @@ export function initAxisConfig(config) {
const spec = config.spec
const availableCharts = getAvailableChartNames(spec.charts)
if (!config.axisSpecs) { config.axisSpecs = {}; }
if (!config.axisSpecs) { config.axisSpecs = {} }
for (let i = 0; i < availableCharts.length; i++) {
const chartName = availableCharts[i];
const chartName = availableCharts[i]
if (!config.axis[chartName]) {
config.axis[chartName] = {};
config.axis[chartName] = {}
}
const axisSpecs = getSpecs(spec.charts[chartName].axis)
if (!config.axisSpecs[chartName]) {
config.axisSpecs[chartName] = axisSpecs;
config.axisSpecs[chartName] = axisSpecs
}
/** initialize multi-dimension axes */
for (let i = 0; i < axisSpecs.length; i++) {
const axisSpec = axisSpecs[i]
if (isSingleDimensionAxis(axisSpec)) {
continue;
continue
}
/** intentionally nested if-stmt is used because order of conditions matter here */
@ -260,18 +260,18 @@ export function initParameterConfig(config) {
const spec = config.spec
const availableCharts = getAvailableChartNames(spec.charts)
if (!config.paramSpecs) { config.paramSpecs = {}; }
if (!config.paramSpecs) { config.paramSpecs = {} }
for (let i = 0; i < availableCharts.length; i++) {
const chartName = availableCharts[i];
const chartName = availableCharts[i]
if (!config.parameter[chartName]) { config.parameter[chartName] = {}; }
if (!config.parameter[chartName]) { config.parameter[chartName] = {} }
const paramSpecs = getSpecs(spec.charts[chartName].parameter)
if (!config.paramSpecs[chartName]) { config.paramSpecs[chartName] = paramSpecs; }
if (!config.paramSpecs[chartName]) { config.paramSpecs[chartName] = paramSpecs }
for (let i = 0; i < paramSpecs.length; i++) {
const paramSpec = paramSpecs[i];
const paramSpec = paramSpecs[i]
if (!config.parameter[chartName][paramSpec.name]) {
config.parameter[chartName][paramSpec.name] = paramSpec.defaultValue;
config.parameter[chartName][paramSpec.name] = paramSpec.defaultValue
}
}
}
@ -287,7 +287,7 @@ export function getSpecVersion(availableCharts, spec) {
const paramHash = {}
for (let i = 0; i < availableCharts.length; i++) {
const chartName = availableCharts[i];
const chartName = availableCharts[i]
const axisSpecs = getSpecs(spec.charts[chartName].axis)
axisHash[chartName] = axisSpecs
@ -333,12 +333,12 @@ export function initializeConfig(config, spec) {
spec.version.axis = axisVersion
spec.version.parameter = paramVersion
if (!config.spec || updated) { config.spec = spec; }
if (!config.spec || updated) { config.spec = spec }
if (!config.chart) {
config.chart = {};
config.chart.current = availableCharts[0];
config.chart.available = availableCharts;
config.chart = {}
config.chart.current = availableCharts[0]
config.chart.available = availableCharts
}
/** initialize config.axis, config.axisSpecs for each chart */
@ -354,7 +354,7 @@ export function getColumnsForMultipleAxes(axisType, axisSpecs, axis) {
let column = {}
for (let i = 0; i < axisSpecs.length; i++) {
const axisSpec = axisSpecs[i];
const axisSpec = axisSpecs[i]
if (axisType === AxisType.KEY && isKeyAxis(axisSpec)) {
axisNames.push(axisSpec.name)
@ -366,7 +366,7 @@ export function getColumnsForMultipleAxes(axisType, axisSpecs, axis) {
}
for (let axisName of axisNames) {
const columns = axis[axisName];
const columns = axis[axisName]
if (typeof axis[axisName] === 'undefined') { continue }
if (!column[axisName]) { column[axisName] = [] }
column[axisName] = column[axisName].concat(columns)
@ -376,35 +376,39 @@ export function getColumnsForMultipleAxes(axisType, axisSpecs, axis) {
}
export function getColumnsFromAxis(axisSpecs, axis) {
const keyAxisNames = [];
const groupAxisNames = [];
const aggrAxisNames = [];
const keyAxisNames = []
const groupAxisNames = []
const aggrAxisNames = []
for (let i = 0; i < axisSpecs.length; i++) {
const axisSpec = axisSpecs[i];
const axisSpec = axisSpecs[i]
if (isKeyAxis(axisSpec)) { keyAxisNames.push(axisSpec.name); }
else if (isGroupAxis(axisSpec)) { groupAxisNames.push(axisSpec.name); }
else if (isAggregatorAxis(axisSpec)) { aggrAxisNames.push(axisSpec.name); }
if (isKeyAxis(axisSpec)) {
keyAxisNames.push(axisSpec.name)
} else if (isGroupAxis(axisSpec)) {
groupAxisNames.push(axisSpec.name)
} else if (isAggregatorAxis(axisSpec)) {
aggrAxisNames.push(axisSpec.name)
}
}
let keyColumns = [];
let groupColumns = [];
let aggregatorColumns = [];
let customColumn = {};
let keyColumns = []
let groupColumns = []
let aggregatorColumns = []
let customColumn = {}
for (let axisName in axis) {
const columns = axis[axisName];
const columns = axis[axisName]
if (keyAxisNames.includes(axisName)) {
keyColumns = keyColumns.concat(columns);
keyColumns = keyColumns.concat(columns)
} else if (groupAxisNames.includes(axisName)) {
groupColumns = groupColumns.concat(columns);
groupColumns = groupColumns.concat(columns)
} else if (aggrAxisNames.includes(axisName)) {
aggregatorColumns = aggregatorColumns.concat(columns);
aggregatorColumns = aggregatorColumns.concat(columns)
} else {
const axisType = axisSpecs.filter(s => s.name === axisName)[0].axisType
if (!customColumn[axisType]) { customColumn[axisType] = []; }
customColumn[axisType] = customColumn[axisType].concat(columns);
if (!customColumn[axisType]) { customColumn[axisType] = [] }
customColumn[axisType] = customColumn[axisType].concat(columns)
}
}
@ -456,10 +460,10 @@ export function getTransformer(conf, rows, axisSpecs, axis) {
const method = transformSpec.method
const columns = getColumnsFromAxis(axisSpecs, axis);
const keyColumns = columns.key;
const groupColumns = columns.group;
const aggregatorColumns = columns.aggregator;
const columns = getColumnsFromAxis(axisSpecs, axis)
const keyColumns = columns.key
const groupColumns = columns.group
const aggregatorColumns = columns.aggregator
const customColumns = columns.custom
let column = {
@ -467,7 +471,7 @@ export function getTransformer(conf, rows, axisSpecs, axis) {
}
if (method === TransformMethod.RAW) {
transformer = () => { return rows; }
transformer = () => { return rows }
} else if (method === TransformMethod.OBJECT) {
transformer = () => {
const { cube, schema, keyColumnName, keyNames, groupNameSet, selectorNameWithIndex, } =
@ -569,31 +573,31 @@ export function getTransformer(conf, rows, axisSpecs, axis) {
const AggregatorFunctions = {
sum: function(a, b) {
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return varA + varB
},
count: function(a, b) {
const varA = (a !== undefined) ? parseInt(a) : 0;
const varB = (b !== undefined) ? 1 : 0;
return varA + varB;
const varA = (a !== undefined) ? parseInt(a) : 0
const varB = (b !== undefined) ? 1 : 0
return varA + varB
},
min: function(a, b) {
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.min(varA, varB);
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return Math.min(varA, varB)
},
max: function(a, b) {
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.max(varA, varB);
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return Math.max(varA, varB)
},
avg: function(a, b, c) {
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
const varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
const varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return varA + varB
}
};
}
const AggregatorFunctionDiv = {
sum: false,
@ -601,7 +605,7 @@ const AggregatorFunctionDiv = {
max: false,
count: false,
avg: true
};
}
/** nested cube `(key) -> (group) -> aggregator` */
export function getKGACube(rows, keyColumns, groupColumns, aggrColumns) {
@ -609,7 +613,7 @@ export function getKGACube(rows, keyColumns, groupColumns, aggrColumns) {
key: keyColumns.length !== 0,
group: groupColumns.length !== 0,
aggregator: aggrColumns.length !== 0,
};
}
let cube = {}
const entry = {}
@ -621,9 +625,9 @@ export function getKGACube(rows, keyColumns, groupColumns, aggrColumns) {
let indexCounter = 0
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
let e = entry;
let c = cube;
const row = rows[i]
let e = entry
let c = cube
// key: add to entry
let mergedKeyName
@ -716,7 +720,7 @@ export function getKAGCube(rows, keyColumns, groupColumns, aggrColumns) {
key: keyColumns.length !== 0,
group: groupColumns.length !== 0,
aggregator: aggrColumns.length !== 0,
};
}
let cube = {}
@ -727,8 +731,8 @@ export function getKAGCube(rows, keyColumns, groupColumns, aggrColumns) {
let indexCounter = 0
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
let c = cube;
const row = rows[i]
let c = cube
// key: add to entry
let mergedKeyName
@ -826,7 +830,7 @@ export function getKKGACube(rows, key1Columns, key2Columns, groupColumns, aggrCo
key2: key2Columns.length !== 0,
group: groupColumns.length !== 0,
aggregator: aggrColumns.length !== 0,
};
}
let cube = {}
const entry = {}
@ -840,9 +844,9 @@ export function getKKGACube(rows, key1Columns, key2Columns, groupColumns, aggrCo
let indexCounter = 0
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
let e = entry;
let c = cube;
const row = rows[i]
let e = entry
let c = cube
// key1: add to entry
let mergedKey1Name

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
import Transformation from './transformation';
import Transformation from './transformation'
import {
getCurrentChart, getCurrentChartAxis, getCurrentChartParam,
@ -23,19 +23,19 @@ import {
removeDuplicatedColumnsInMultiDimensionAxis, applyMaxAxisCount,
isInputWidget, isOptionWidget, isCheckboxWidget, isTextareaWidget, parseParameter,
getTransformer,
} from './advanced-transformation-util';
} from './advanced-transformation-util'
const SETTING_TEMPLATE = 'app/tabledata/advanced-transformation-setting.html';
const SETTING_TEMPLATE = 'app/tabledata/advanced-transformation-setting.html'
export default class AdvancedTransformation extends Transformation {
constructor(config, spec) {
super(config);
super(config)
this.columns = []; /** [{ name, index, comment }] */
this.props = {};
this.columns = [] /** [{ name, index, comment }] */
this.props = {}
this.spec = spec
initializeConfig(config, spec);
initializeConfig(config, spec)
}
emitConfigChange(conf) {
@ -57,8 +57,8 @@ export default class AdvancedTransformation extends Transformation {
}
getSetting() {
const self = this; /** for closure */
const configInstance = self.config; /** for closure */
const self = this /** for closure */
const configInstance = self.config /** for closure */
if (self.spec.initialized) {
self.spec.initialized = false
@ -123,13 +123,13 @@ export default class AdvancedTransformation extends Transformation {
getAxisTypeAnnotationColor: (axisSpec) => {
if (isAggregatorAxis(axisSpec)) {
return { 'background-color': '#5782bd' };
return { 'background-color': '#5782bd' }
} else if (isGroupAxis(axisSpec)) {
return { 'background-color': '#cd5c5c' };
return { 'background-color': '#cd5c5c' }
} else if (isKeyAxis(axisSpec)) {
return { 'background-color': '#906ebd' };
return { 'background-color': '#906ebd' }
} else {
return { 'background-color': '#62bda9' };
return { 'background-color': '#62bda9' }
}
},
@ -185,7 +185,7 @@ export default class AdvancedTransformation extends Transformation {
},
parameterOnKeyDown: function(event, paramSpec) {
const code = event.keyCode || event.which;
const code = event.keyCode || event.which
if (code === 13 && isInputWidget(paramSpec)) {
self.emitParameterChange(configInstance)
} else if (code === 13 && event.shiftKey && isTextareaWidget(paramSpec)) {
@ -200,7 +200,7 @@ export default class AdvancedTransformation extends Transformation {
}
transform(tableData) {
this.columns = tableData.columns; /** used in `getSetting` */
this.columns = tableData.columns /** used in `getSetting` */
/** initialize in `transform` instead of `getSetting` because this method is called before */
serializeSharedAxes(this.config)

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
import Transformation from './transformation';
import Transformation from './transformation'
/**
* select columns
@ -27,13 +27,13 @@ import Transformation from './transformation';
*/
export default class ColumnselectorTransformation extends Transformation {
constructor (config, columnSelectorProp) {
super(config);
this.props = columnSelectorProp;
super(config)
this.props = columnSelectorProp
}
getSetting () {
let self = this;
let configObj = self.config;
let self = this
let configObj = self.config
return {
template: 'app/tabledata/columnselector_settings.html',
scope: {
@ -41,40 +41,40 @@ export default class ColumnselectorTransformation extends Transformation {
props: self.props,
tableDataColumns: self.tableDataColumns,
save: function () {
self.emitConfig(configObj);
self.emitConfig(configObj)
},
remove: function (selectorName) {
configObj[selectorName] = null;
self.emitConfig(configObj);
configObj[selectorName] = null
self.emitConfig(configObj)
}
}
};
}
}
/**
* Method will be invoked when tableData or config changes
*/
transform (tableData) {
this.tableDataColumns = tableData.columns;
this.removeUnknown();
return tableData;
this.tableDataColumns = tableData.columns
this.removeUnknown()
return tableData
}
removeUnknown () {
let fields = this.config;
let fields = this.config
for (let f in fields) {
if (fields[f]) {
let found = false;
let found = false
for (let i = 0; i < this.tableDataColumns.length; i++) {
let a = fields[f];
let b = this.tableDataColumns[i];
let a = fields[f]
let b = this.tableDataColumns[i]
if (a.index === b.index && a.name === b.name) {
found = true;
break;
found = true
break
}
}
if (!found && (fields[f] instanceof Object) && !(fields[f] instanceof Array)) {
fields[f] = null;
fields[f] = null
}
}
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
import Transformation from './transformation';
import Transformation from './transformation'
/**
* passthough the data
@ -20,13 +20,13 @@ import Transformation from './transformation';
export default class PassthroughTransformation extends Transformation {
// eslint-disable-next-line no-useless-constructor
constructor (config) {
super(config);
super(config)
}
/**
* Method will be invoked when tableData or config changes
*/
transform (tableData) {
return tableData;
return tableData
}
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
import Transformation from './transformation';
import Transformation from './transformation'
/**
* pivot table data and return d3 chart data
@ -20,116 +20,116 @@ import Transformation from './transformation';
export default class PivotTransformation extends Transformation {
// eslint-disable-next-line no-useless-constructor
constructor (config) {
super(config);
super(config)
}
getSetting () {
let self = this;
let self = this
let configObj = self.config;
console.log('getSetting', configObj);
let configObj = self.config
console.log('getSetting', configObj)
return {
template: 'app/tabledata/pivot_settings.html',
scope: {
config: configObj.common.pivot,
tableDataColumns: self.tableDataColumns,
save: function () {
self.emitConfig(configObj);
self.emitConfig(configObj)
},
removeKey: function (idx) {
configObj.common.pivot.keys.splice(idx, 1);
self.emitConfig(configObj);
configObj.common.pivot.keys.splice(idx, 1)
self.emitConfig(configObj)
},
removeGroup: function (idx) {
configObj.common.pivot.groups.splice(idx, 1);
self.emitConfig(configObj);
configObj.common.pivot.groups.splice(idx, 1)
self.emitConfig(configObj)
},
removeValue: function (idx) {
configObj.common.pivot.values.splice(idx, 1);
self.emitConfig(configObj);
configObj.common.pivot.values.splice(idx, 1)
self.emitConfig(configObj)
},
setValueAggr: function (idx, aggr) {
configObj.common.pivot.values[idx].aggr = aggr;
self.emitConfig(configObj);
configObj.common.pivot.values[idx].aggr = aggr
self.emitConfig(configObj)
}
}
};
}
}
/**
* Method will be invoked when tableData or config changes
*/
transform (tableData) {
this.tableDataColumns = tableData.columns;
this.config.common = this.config.common || {};
this.config.common.pivot = this.config.common.pivot || {};
let config = this.config.common.pivot;
let firstTime = (!config.keys && !config.groups && !config.values);
this.tableDataColumns = tableData.columns
this.config.common = this.config.common || {}
this.config.common.pivot = this.config.common.pivot || {}
let config = this.config.common.pivot
let firstTime = (!config.keys && !config.groups && !config.values)
config.keys = config.keys || [];
config.groups = config.groups || [];
config.values = config.values || [];
config.keys = config.keys || []
config.groups = config.groups || []
config.values = config.values || []
this.removeUnknown();
this.removeUnknown()
if (firstTime) {
this.selectDefault();
this.selectDefault()
}
return this.pivot(
tableData,
config.keys,
config.groups,
config.values);
config.values)
}
removeUnknown () {
let config = this.config.common.pivot;
let tableDataColumns = this.tableDataColumns;
let config = this.config.common.pivot
let tableDataColumns = this.tableDataColumns
let unique = function (list) {
for (let i = 0; i < list.length; i++) {
for (let j = i + 1; j < list.length; j++) {
if (angular.equals(list[i], list[j])) {
list.splice(j, 1);
list.splice(j, 1)
}
}
}
};
}
let removeUnknown = function (list) {
for (let i = 0; i < list.length; i++) {
// remove non existing column
let found = false;
let found = false
for (let j = 0; j < tableDataColumns.length; j++) {
let a = list[i];
let b = tableDataColumns[j];
let a = list[i]
let b = tableDataColumns[j]
if (a.index === b.index && a.name === b.name) {
found = true;
break;
found = true
break
}
}
if (!found) {
list.splice(i, 1);
list.splice(i, 1)
}
}
};
}
unique(config.keys);
removeUnknown(config.keys);
unique(config.groups);
removeUnknown(config.groups);
removeUnknown(config.values);
unique(config.keys)
removeUnknown(config.keys)
unique(config.groups)
removeUnknown(config.groups)
removeUnknown(config.values)
}
selectDefault () {
let config = this.config.common.pivot;
let config = this.config.common.pivot
if (config.keys.length === 0 &&
config.groups.length === 0 &&
config.values.length === 0) {
if (config.keys.length === 0 && this.tableDataColumns.length > 0) {
config.keys.push(this.tableDataColumns[0]);
config.keys.push(this.tableDataColumns[0])
}
if (config.values.length === 0 && this.tableDataColumns.length > 1) {
config.values.push(this.tableDataColumns[1]);
config.values.push(this.tableDataColumns[1])
}
}
}
@ -137,31 +137,31 @@ export default class PivotTransformation extends Transformation {
pivot (data, keys, groups, values) {
let aggrFunc = {
sum: function (a, b) {
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return varA + varB
},
count: function (a, b) {
let varA = (a !== undefined) ? parseInt(a) : 0;
let varB = (b !== undefined) ? 1 : 0;
return varA + varB;
let varA = (a !== undefined) ? parseInt(a) : 0
let varB = (b !== undefined) ? 1 : 0
return varA + varB
},
min: function (a, b) {
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.min(varA, varB);
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return Math.min(varA, varB)
},
max: function (a, b) {
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.max(varA, varB);
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return Math.max(varA, varB)
},
avg: function (a, b, c) {
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
let varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0
let varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0
return varA + varB
}
};
}
let aggrFuncDiv = {
sum: false,
@ -169,18 +169,18 @@ export default class PivotTransformation extends Transformation {
min: false,
max: false,
avg: true
};
}
let schema = {};
let rows = {};
let schema = {}
let rows = {}
for (let i = 0; i < data.rows.length; i++) {
let row = data.rows[i];
let s = schema;
let p = rows;
let row = data.rows[i]
let s = schema
let p = rows
for (let k = 0; k < keys.length; k++) {
let key = keys[k];
let key = keys[k]
// add key to schema
if (!s[key.name]) {
@ -189,21 +189,21 @@ export default class PivotTransformation extends Transformation {
index: key.index,
type: 'key',
children: {}
};
}
}
s = s[key.name].children;
s = s[key.name].children
// add key to row
let keyKey = row[key.index];
let keyKey = row[key.index]
if (!p[keyKey]) {
p[keyKey] = {};
p[keyKey] = {}
}
p = p[keyKey];
p = p[keyKey]
}
for (let g = 0; g < groups.length; g++) {
let group = groups[g];
let groupKey = row[group.index];
let group = groups[g]
let groupKey = row[group.index]
// add group to schema
if (!s[groupKey]) {
@ -212,20 +212,20 @@ export default class PivotTransformation extends Transformation {
index: group.index,
type: 'group',
children: {}
};
}
}
s = s[groupKey].children;
s = s[groupKey].children
// add key to row
if (!p[groupKey]) {
p[groupKey] = {};
p[groupKey] = {}
}
p = p[groupKey];
p = p[groupKey]
}
for (let v = 0; v < values.length; v++) {
let value = values[v];
let valueKey = value.name + '(' + value.aggr + ')';
let value = values[v]
let valueKey = value.name + '(' + value.aggr + ')'
// add value to schema
if (!s[valueKey]) {
@ -233,7 +233,7 @@ export default class PivotTransformation extends Transformation {
type: 'value',
order: v,
index: value.index
};
}
}
// add value to row
@ -241,12 +241,12 @@ export default class PivotTransformation extends Transformation {
p[valueKey] = {
value: (value.aggr !== 'count') ? row[value.index] : 1,
count: 1
};
}
} else {
p[valueKey] = {
value: aggrFunc[value.aggr](p[valueKey].value, row[value.index], p[valueKey].count + 1),
count: (aggrFuncDiv[value.aggr]) ? p[valueKey].count + 1 : p[valueKey].count
};
}
}
}
}
@ -258,6 +258,6 @@ export default class PivotTransformation extends Transformation {
values: values,
schema: schema,
rows: rows
};
}
}
}

View file

@ -17,57 +17,57 @@
*/
export default class TableData {
constructor (columns, rows, comment) {
this.columns = columns || [];
this.rows = rows || [];
this.comment = comment || '';
this.columns = columns || []
this.rows = rows || []
this.comment = comment || ''
}
loadParagraphResult (paragraphResult) {
if (!paragraphResult || paragraphResult.type !== 'TABLE') {
console.log('Can not load paragraph result');
return;
console.log('Can not load paragraph result')
return
}
let columnNames = [];
let rows = [];
let array = [];
let textRows = paragraphResult.msg.split('\n');
let comment = '';
let commentRow = false;
let columnNames = []
let rows = []
let array = []
let textRows = paragraphResult.msg.split('\n')
let comment = ''
let commentRow = false
for (let i = 0; i < textRows.length; i++) {
let textRow = textRows[i];
let textRow = textRows[i]
if (commentRow) {
comment += textRow;
continue;
comment += textRow
continue
}
if (textRow === '' || textRow === '<!--TABLE_COMMENT-->') {
if (rows.length > 0) {
commentRow = true;
commentRow = true
}
continue;
continue
}
let textCols = textRow.split('\t');
let cols = [];
let cols2 = [];
let textCols = textRow.split('\t')
let cols = []
let cols2 = []
for (let j = 0; j < textCols.length; j++) {
let col = textCols[j];
let col = textCols[j]
if (i === 0) {
columnNames.push({name: col, index: j, aggr: 'sum'});
columnNames.push({name: col, index: j, aggr: 'sum'})
} else {
cols.push(col);
cols2.push({key: (columnNames[i]) ? columnNames[i].name : undefined, value: col});
cols.push(col)
cols2.push({key: (columnNames[i]) ? columnNames[i].name : undefined, value: col})
}
}
if (i !== 0) {
rows.push(cols);
array.push(cols2);
rows.push(cols)
array.push(cols2)
}
}
this.comment = comment;
this.columns = columnNames;
this.rows = rows;
this.comment = comment
this.columns = columnNames
this.rows = rows
}
}

View file

@ -12,30 +12,30 @@
* limitations under the License.
*/
import TableData from './tabledata.js';
import TableData from './tabledata.js'
describe('TableData build', function () {
let td;
let td
beforeEach(function () {
console.log(TableData);
td = new TableData();
});
console.log(TableData)
td = new TableData()
})
it('should initialize the default value', function () {
expect(td.columns.length).toBe(0);
expect(td.rows.length).toBe(0);
expect(td.comment).toBe('');
});
expect(td.columns.length).toBe(0)
expect(td.rows.length).toBe(0)
expect(td.comment).toBe('')
})
it('should able to create Tabledata from paragraph result', function () {
td.loadParagraphResult({
type: 'TABLE',
msg: 'key\tvalue\na\t10\nb\t20\n\nhello'
});
})
expect(td.columns.length).toBe(2);
expect(td.rows.length).toBe(2);
expect(td.comment).toBe('hello');
});
});
expect(td.columns.length).toBe(2)
expect(td.rows.length).toBe(2)
expect(td.comment).toBe('hello')
})
})

View file

@ -17,8 +17,8 @@
*/
export default class Transformation {
constructor (config) {
this.config = config;
this._emitter = () => {};
this.config = config
this._emitter = () => {}
}
/**
@ -42,62 +42,62 @@ export default class Transformation {
* render setting
*/
renderSetting (targetEl) {
let setting = this.getSetting();
let setting = this.getSetting()
if (!setting) {
return;
return
}
// already readered
if (this._scope) {
let self = this;
let self = this
this._scope.$apply(function () {
for (let k in setting.scope) {
self._scope[k] = setting.scope[k];
self._scope[k] = setting.scope[k]
}
for (let k in self._prevSettingScope) {
if (!setting.scope[k]) {
self._scope[k] = setting.scope[k];
self._scope[k] = setting.scope[k]
}
}
});
return;
})
return
} else {
this._prevSettingScope = setting.scope;
this._prevSettingScope = setting.scope
}
let scope = this._createNewScope();
let scope = this._createNewScope()
for (let k in setting.scope) {
scope[k] = setting.scope[k];
scope[k] = setting.scope[k]
}
let template = setting.template;
let template = setting.template
if (template.split('\n').length === 1 &&
template.endsWith('.html')) { // template is url
let self = this;
let self = this
this._templateRequest(template).then(function (t) {
self._render(targetEl, t, scope);
});
self._render(targetEl, t, scope)
})
} else {
this._render(targetEl, template, scope);
this._render(targetEl, template, scope)
}
}
_render (targetEl, template, scope) {
this._targetEl = targetEl;
targetEl.html(template);
this._compile(targetEl.contents())(scope);
this._scope = scope;
this._targetEl = targetEl
targetEl.html(template)
this._compile(targetEl.contents())(scope)
this._scope = scope
}
setConfig (config) {
this.config = config;
this.config = config
}
/**
* Emit config. config will sent to server and saved.
*/
emitConfig (config) {
this._emitter(config);
this._emitter(config)
}
}

View file

@ -12,25 +12,25 @@
* limitations under the License.
*/
import Nvd3ChartVisualization from './visualization-nvd3chart';
import PivotTransformation from '../../tabledata/pivot';
import Nvd3ChartVisualization from './visualization-nvd3chart'
import PivotTransformation from '../../tabledata/pivot'
/**
* Visualize data in area chart
*/
export default class AreachartVisualization extends Nvd3ChartVisualization {
constructor (targetEl, config) {
super(targetEl, config);
super(targetEl, config)
this.pivot = new PivotTransformation(config);
this.pivot = new PivotTransformation(config)
}
type () {
return 'stackedAreaChart';
return 'stackedAreaChart'
}
getTransformation () {
return this.pivot;
return this.pivot
}
render (pivot) {
@ -42,36 +42,36 @@ export default class AreachartVisualization extends Nvd3ChartVisualization {
pivot.values,
false,
true,
false);
false)
this.xLabels = d3Data.xLabels;
super.render(d3Data);
this.xLabels = d3Data.xLabels
super.render(d3Data)
}
/**
* Set new config
*/
setConfig (config) {
super.setConfig(config);
this.pivot.setConfig(config);
super.setConfig(config)
this.pivot.setConfig(config)
}
configureChart (chart) {
let self = this;
chart.xAxis.tickFormat(function (d) { return self.xAxisTickFormat(d, self.xLabels); });
chart.yAxis.tickFormat(function (d) { return self.yAxisTickFormat(d); });
chart.yAxis.axisLabelDistance(50);
chart.useInteractiveGuideline(true); // for better UX and performance issue. (https://github.com/novus/nvd3/issues/691)
let self = this
chart.xAxis.tickFormat(function (d) { return self.xAxisTickFormat(d, self.xLabels) })
chart.yAxis.tickFormat(function (d) { return self.yAxisTickFormat(d) })
chart.yAxis.axisLabelDistance(50)
chart.useInteractiveGuideline(true) // for better UX and performance issue. (https://github.com/novus/nvd3/issues/691)
this.chart.style(this.config.style || 'stack');
this.chart.style(this.config.style || 'stack')
this.chart.dispatch.on('stateChange', function (s) {
self.config.style = s.style;
self.config.style = s.style
// give some time to animation finish
setTimeout(function () {
self.emitConfig(self.config);
}, 500);
});
self.emitConfig(self.config)
}, 500)
})
}
}

View file

@ -12,25 +12,25 @@
* limitations under the License.
*/
import Nvd3ChartVisualization from './visualization-nvd3chart';
import PivotTransformation from '../../tabledata/pivot';
import Nvd3ChartVisualization from './visualization-nvd3chart'
import PivotTransformation from '../../tabledata/pivot'
/**
* Visualize data in bar char
*/
export default class BarchartVisualization extends Nvd3ChartVisualization {
constructor (targetEl, config) {
super(targetEl, config);
super(targetEl, config)
this.pivot = new PivotTransformation(config);
this.pivot = new PivotTransformation(config)
}
type () {
return 'multiBarChart';
return 'multiBarChart'
}
getTransformation () {
return this.pivot;
return this.pivot
}
render (pivot) {
@ -42,7 +42,7 @@ export default class BarchartVisualization extends Nvd3ChartVisualization {
pivot.values,
true,
true,
true);
true)
super.render(d3Data);
this.config.changeXLabel(this.config.xLabelStatus);
@ -52,8 +52,8 @@ export default class BarchartVisualization extends Nvd3ChartVisualization {
* Set new config
*/
setConfig (config) {
super.setConfig(config);
this.pivot.setConfig(config);
super.setConfig(config)
this.pivot.setConfig(config)
}
configureChart (chart) {

View file

@ -12,29 +12,29 @@
* limitations under the License.
*/
import Nvd3ChartVisualization from './visualization-nvd3chart';
import PivotTransformation from '../../tabledata/pivot';
import Nvd3ChartVisualization from './visualization-nvd3chart'
import PivotTransformation from '../../tabledata/pivot'
/**
* Visualize data in line chart
*/
export default class LinechartVisualization extends Nvd3ChartVisualization {
constructor (targetEl, config) {
super(targetEl, config);
super(targetEl, config)
this.pivot = new PivotTransformation(config);
this.pivot = new PivotTransformation(config)
}
type () {
if (this.config.lineWithFocus) {
return 'lineWithFocusChart';
return 'lineWithFocusChart'
} else {
return 'lineChart';
return 'lineChart'
}
}
getTransformation () {
return this.pivot;
return this.pivot
}
render (pivot) {
@ -46,49 +46,49 @@ export default class LinechartVisualization extends Nvd3ChartVisualization {
pivot.values,
false,
true,
false);
false)
this.xLabels = d3Data.xLabels;
super.render(d3Data);
this.xLabels = d3Data.xLabels
super.render(d3Data)
}
/**
* Set new config
*/
setConfig (config) {
super.setConfig(config);
this.pivot.setConfig(config);
super.setConfig(config)
this.pivot.setConfig(config)
// change mode
if (this.currentMode !== config.lineWithFocus) {
super.destroy();
this.currentMode = config.lineWithFocus;
super.destroy()
this.currentMode = config.lineWithFocus
}
}
configureChart (chart) {
let self = this;
chart.xAxis.tickFormat(function (d) { return self.xAxisTickFormat(d, self.xLabels); });
let self = this
chart.xAxis.tickFormat(function (d) { return self.xAxisTickFormat(d, self.xLabels) })
chart.yAxis.tickFormat(function (d) {
if (d === undefined) {
return 'N/A';
return 'N/A'
}
return self.yAxisTickFormat(d, self.xLabels);
});
chart.yAxis.axisLabelDistance(50);
return self.yAxisTickFormat(d, self.xLabels)
})
chart.yAxis.axisLabelDistance(50)
if (chart.useInteractiveGuideline) { // lineWithFocusChart hasn't got useInteractiveGuideline
chart.useInteractiveGuideline(true); // for better UX and performance issue. (https://github.com/novus/nvd3/issues/691)
chart.useInteractiveGuideline(true) // for better UX and performance issue. (https://github.com/novus/nvd3/issues/691)
}
if (this.config.forceY) {
chart.forceY([0]); // force y-axis minimum to 0 for line chart.
chart.forceY([0]) // force y-axis minimum to 0 for line chart.
} else {
chart.forceY([]);
chart.forceY([])
}
}
getSetting (chart) {
let self = this;
let configObj = self.config;
let self = this
let configObj = self.config
return {
template: `<div>
@ -110,13 +110,13 @@ export default class LinechartVisualization extends Nvd3ChartVisualization {
scope: {
config: configObj,
save: function () {
self.emitConfig(configObj);
self.emitConfig(configObj)
}
}
};
}
}
defaultY () {
return undefined;
return undefined
}
}

View file

@ -12,42 +12,42 @@
* limitations under the License.
*/
import Visualization from '../visualization';
import Visualization from '../visualization'
/**
* Visualize data in table format
*/
export default class Nvd3ChartVisualization extends Visualization {
constructor (targetEl, config) {
super(targetEl, config);
this.targetEl.append('<svg></svg>');
super(targetEl, config)
this.targetEl.append('<svg></svg>')
}
refresh () {
if (this.chart) {
this.chart.update();
this.chart.update()
}
}
render (data) {
let type = this.type();
let d3g = data.d3g;
let type = this.type()
let d3g = data.d3g
if (!this.chart) {
this.chart = nv.models[type]();
this.chart = nv.models[type]()
}
this.configureChart(this.chart);
this.configureChart(this.chart)
let animationDuration = 300;
let numberOfDataThreshold = 150;
let height = this.targetEl.height();
let animationDuration = 300
let numberOfDataThreshold = 150
let height = this.targetEl.height()
// turn off animation when dataset is too large. (for performance issue)
// still, since dataset is large, the chart content sequentially appears like animated
try {
if (d3g[0].values.length > numberOfDataThreshold) {
animationDuration = 0;
animationDuration = 0
}
} catch (err) { /** ignore */ }
@ -56,8 +56,8 @@ export default class Nvd3ChartVisualization extends Visualization {
.datum(d3g)
.transition()
.duration(animationDuration)
.call(this.chart);
d3.select('#' + this.targetEl[0].id + ' svg').style.height = height + 'px';
.call(this.chart)
d3.select('#' + this.targetEl[0].id + ' svg').style.height = height + 'px'
}
type () {
@ -69,175 +69,175 @@ export default class Nvd3ChartVisualization extends Visualization {
}
groupedThousandsWith3DigitsFormatter (x) {
return d3.format(',')(d3.round(x, 3));
return d3.format(',')(d3.round(x, 3))
}
customAbbrevFormatter (x) {
let s = d3.format('.3s')(x);
let s = d3.format('.3s')(x)
switch (s[s.length - 1]) {
case 'G': return s.slice(0, -1) + 'B';
case 'G': return s.slice(0, -1) + 'B'
}
return s;
return s
}
defaultY () {
return 0;
return 0
}
xAxisTickFormat (d, xLabels) {
if (xLabels[d] && (isNaN(parseFloat(xLabels[d])) || !isFinite(xLabels[d]))) { // to handle string type xlabel
return xLabels[d];
return xLabels[d]
} else {
return d;
return d
}
}
yAxisTickFormat (d) {
if (Math.abs(d) >= Math.pow(10, 6)) {
return this.customAbbrevFormatter(d);
return this.customAbbrevFormatter(d)
}
return this.groupedThousandsWith3DigitsFormatter(d);
return this.groupedThousandsWith3DigitsFormatter(d)
}
d3DataFromPivot (
schema, rows, keys, groups, values, allowTextXAxis, fillMissingValues, multiBarChart) {
let self = this;
let self = this
// construct table data
let d3g = [];
let d3g = []
let concat = function (o, n) {
if (!o) {
return n;
return n
} else {
return o + '.' + n;
return o + '.' + n
}
};
}
const getSchemaUnderKey = function (key, s) {
for (let c in key.children) {
s[c] = {};
getSchemaUnderKey(key.children[c], s[c]);
s[c] = {}
getSchemaUnderKey(key.children[c], s[c])
}
};
}
const traverse = function (sKey, s, rKey, r, func, rowName, rowValue, colName) {
// console.log("TRAVERSE sKey=%o, s=%o, rKey=%o, r=%o, rowName=%o, rowValue=%o, colName=%o", sKey, s, rKey, r, rowName, rowValue, colName);
if (s.type === 'key') {
rowName = concat(rowName, sKey);
rowValue = concat(rowValue, rKey);
rowName = concat(rowName, sKey)
rowValue = concat(rowValue, rKey)
} else if (s.type === 'group') {
colName = concat(colName, rKey);
colName = concat(colName, rKey)
} else if (s.type === 'value' && sKey === rKey || valueOnly) {
colName = concat(colName, rKey);
func(rowName, rowValue, colName, r);
colName = concat(colName, rKey)
func(rowName, rowValue, colName, r)
}
for (let c in s.children) {
if (fillMissingValues && s.children[c].type === 'group' && r[c] === undefined) {
let cs = {};
getSchemaUnderKey(s.children[c], cs);
traverse(c, s.children[c], c, cs, func, rowName, rowValue, colName);
continue;
let cs = {}
getSchemaUnderKey(s.children[c], cs)
traverse(c, s.children[c], c, cs, func, rowName, rowValue, colName)
continue
}
for (let j in r) {
if (s.children[c].type === 'key' || c === j) {
traverse(c, s.children[c], j, r[j], func, rowName, rowValue, colName);
traverse(c, s.children[c], j, r[j], func, rowName, rowValue, colName)
}
}
}
};
}
const valueOnly = (keys.length === 0 && groups.length === 0 && values.length > 0);
let noKey = (keys.length === 0);
let isMultiBarChart = multiBarChart;
const valueOnly = (keys.length === 0 && groups.length === 0 && values.length > 0)
let noKey = (keys.length === 0)
let isMultiBarChart = multiBarChart
let sKey = Object.keys(schema)[0];
let sKey = Object.keys(schema)[0]
let rowNameIndex = {};
let rowIdx = 0;
let colNameIndex = {};
let colIdx = 0;
let rowIndexValue = {};
let rowNameIndex = {}
let rowIdx = 0
let colNameIndex = {}
let colIdx = 0
let rowIndexValue = {}
for (let k in rows) {
traverse(sKey, schema[sKey], k, rows[k], function (rowName, rowValue, colName, value) {
// console.log("RowName=%o, row=%o, col=%o, value=%o", rowName, rowValue, colName, value);
if (rowNameIndex[rowValue] === undefined) {
rowIndexValue[rowIdx] = rowValue;
rowNameIndex[rowValue] = rowIdx++;
rowIndexValue[rowIdx] = rowValue
rowNameIndex[rowValue] = rowIdx++
}
if (colNameIndex[colName] === undefined) {
colNameIndex[colName] = colIdx++;
colNameIndex[colName] = colIdx++
}
let i = colNameIndex[colName];
let i = colNameIndex[colName]
if (noKey && isMultiBarChart) {
i = 0;
i = 0
}
if (!d3g[i]) {
d3g[i] = {
values: [],
key: (noKey && isMultiBarChart) ? 'values' : colName
};
}
}
let xVar = isNaN(rowValue) ? ((allowTextXAxis) ? rowValue : rowNameIndex[rowValue]) : parseFloat(rowValue);
let yVar = self.defaultY();
if (xVar === undefined) { xVar = colName; }
let xVar = isNaN(rowValue) ? ((allowTextXAxis) ? rowValue : rowNameIndex[rowValue]) : parseFloat(rowValue)
let yVar = self.defaultY()
if (xVar === undefined) { xVar = colName }
if (value !== undefined) {
yVar = isNaN(value.value) ? self.defaultY() : parseFloat(value.value) / parseFloat(value.count);
yVar = isNaN(value.value) ? self.defaultY() : parseFloat(value.value) / parseFloat(value.count)
}
d3g[i].values.push({
x: xVar,
y: yVar
});
});
})
})
}
// clear aggregation name, if possible
let namesWithoutAggr = {};
let colName;
let withoutAggr;
let namesWithoutAggr = {}
let colName
let withoutAggr
// TODO - This part could use som refactoring - Weird if/else with similar actions and variable names
for (colName in colNameIndex) {
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
withoutAggr = colName.substring(0, colName.lastIndexOf('('))
if (!namesWithoutAggr[withoutAggr]) {
namesWithoutAggr[withoutAggr] = 1;
namesWithoutAggr[withoutAggr] = 1
} else {
namesWithoutAggr[withoutAggr]++;
namesWithoutAggr[withoutAggr]++
}
}
if (valueOnly) {
for (let valueIndex = 0; valueIndex < d3g[0].values.length; valueIndex++) {
colName = d3g[0].values[valueIndex].x;
colName = d3g[0].values[valueIndex].x
if (!colName) {
continue;
continue
}
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
withoutAggr = colName.substring(0, colName.lastIndexOf('('))
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[0].values[valueIndex].x = withoutAggr;
d3g[0].values[valueIndex].x = withoutAggr
}
}
} else {
for (let d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
colName = d3g[d3gIndex].key
withoutAggr = colName.substring(0, colName.lastIndexOf('('))
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[d3gIndex].key = withoutAggr;
d3g[d3gIndex].key = withoutAggr
}
}
// use group name instead of group.value as a column name, if there're only one group and one value selected.
if (groups.length === 1 && values.length === 1) {
for (let d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
colName = colName.split('.').slice(0, -1).join('.');
d3g[d3gIndex].key = colName;
colName = d3g[d3gIndex].key
colName = colName.split('.').slice(0, -1).join('.')
d3g[d3gIndex].key = colName
}
}
}
@ -245,7 +245,7 @@ export default class Nvd3ChartVisualization extends Visualization {
return {
xLabels: rowIndexValue,
d3g: d3g
};
}
}
/**
@ -254,8 +254,8 @@ export default class Nvd3ChartVisualization extends Visualization {
*/
destroy () {
if (this.chart) {
d3.selectAll('#' + this.targetEl[0].id + ' svg > *').remove();
this.chart = undefined;
d3.selectAll('#' + this.targetEl[0].id + ' svg > *').remove()
this.chart = undefined
}
}
}

View file

@ -12,29 +12,29 @@
* limitations under the License.
*/
import Nvd3ChartVisualization from './visualization-nvd3chart';
import PivotTransformation from '../../tabledata/pivot';
import Nvd3ChartVisualization from './visualization-nvd3chart'
import PivotTransformation from '../../tabledata/pivot'
/**
* Visualize data in pie chart
*/
export default class PiechartVisualization extends Nvd3ChartVisualization {
constructor (targetEl, config) {
super(targetEl, config);
this.pivot = new PivotTransformation(config);
super(targetEl, config)
this.pivot = new PivotTransformation(config)
}
type () {
return 'pieChart';
return 'pieChart'
}
getTransformation () {
return this.pivot;
return this.pivot
}
render (pivot) {
// [ZEPPELIN-2253] New chart function will be created each time inside super.render()
this.chart = null;
this.chart = null
const d3Data = this.d3DataFromPivot(
pivot.schema,
pivot.rows,
@ -43,41 +43,41 @@ export default class PiechartVisualization extends Nvd3ChartVisualization {
pivot.values,
true,
false,
false);
const d = d3Data.d3g;
false)
const d = d3Data.d3g
let generateLabel;
let generateLabel
// data is grouped
if (pivot.groups && pivot.groups.length > 0) {
generateLabel = (suffix, prefix) => `${prefix}.${suffix}`;
generateLabel = (suffix, prefix) => `${prefix}.${suffix}`
} else { // data isn't grouped
generateLabel = suffix => suffix;
generateLabel = suffix => suffix
}
let d3g = d.map(group => {
return group.values.map(row => ({
label: generateLabel(row.x, group.key),
value: row.y
}));
});
}))
})
// the map function returns d3g as a nested array
// [].concat flattens it, http://stackoverflow.com/a/10865042/5154397
d3g = [].concat.apply([], d3g); // eslint-disable-line prefer-spread
super.render({d3g: d3g});
d3g = [].concat.apply([], d3g) // eslint-disable-line prefer-spread
super.render({d3g: d3g})
}
/**
* Set new config
*/
setConfig (config) {
super.setConfig(config);
this.pivot.setConfig(config);
super.setConfig(config)
this.pivot.setConfig(config)
}
configureChart (chart) {
chart.x(function (d) { return d.label; })
.y(function (d) { return d.value; })
chart.x(function (d) { return d.label })
.y(function (d) { return d.value })
.showLabels(false)
.showTooltipPercent(true);
.showTooltipPercent(true)
}
}

View file

@ -12,15 +12,15 @@
* limitations under the License.
*/
import Nvd3ChartVisualization from './visualization-nvd3chart';
import ColumnselectorTransformation from '../../tabledata/columnselector';
import Nvd3ChartVisualization from './visualization-nvd3chart'
import ColumnselectorTransformation from '../../tabledata/columnselector'
/**
* Visualize data in scatter char
*/
export default class ScatterchartVisualization extends Nvd3ChartVisualization {
constructor (targetEl, config) {
super(targetEl, config);
super(targetEl, config)
this.columnselectorProps = [
{
@ -41,196 +41,196 @@ export default class ScatterchartVisualization extends Nvd3ChartVisualization {
or the number of distinct values are bigger than 5% of total number of values.</li>
<li>Size field button turns to grey when the option you chose is not valid.</li>`
}
];
this.columnselector = new ColumnselectorTransformation(config, this.columnselectorProps);
]
this.columnselector = new ColumnselectorTransformation(config, this.columnselectorProps)
}
type () {
return 'scatterChart';
return 'scatterChart'
}
getTransformation () {
return this.columnselector;
return this.columnselector
}
render (tableData) {
this.tableData = tableData;
this.selectDefault();
let d3Data = this.setScatterChart(tableData, true);
this.xLabels = d3Data.xLabels;
this.yLabels = d3Data.yLabels;
this.tableData = tableData
this.selectDefault()
let d3Data = this.setScatterChart(tableData, true)
this.xLabels = d3Data.xLabels
this.yLabels = d3Data.yLabels
super.render(d3Data);
super.render(d3Data)
}
configureChart (chart) {
let self = this;
let self = this
chart.xAxis.tickFormat(function (d) { // TODO remove round after bump to nvd3 > 1.8.5
return self.xAxisTickFormat(Math.round(d * 1e3) / 1e3, self.xLabels);
});
return self.xAxisTickFormat(Math.round(d * 1e3) / 1e3, self.xLabels)
})
chart.yAxis.tickFormat(function (d) { // TODO remove round after bump to nvd3 > 1.8.5
return self.yAxisTickFormat(Math.round(d * 1e3) / 1e3, self.yLabels);
});
return self.yAxisTickFormat(Math.round(d * 1e3) / 1e3, self.yLabels)
})
chart.showDistX(true).showDistY(true);
chart.showDistX(true).showDistY(true)
// handle the problem of tooltip not showing when muliple points have same value.
}
yAxisTickFormat (d, yLabels) {
if (yLabels[d] && (isNaN(parseFloat(yLabels[d])) || !isFinite(yLabels[d]))) { // to handle string type xlabel
return yLabels[d];
return yLabels[d]
} else {
return super.yAxisTickFormat(d);
return super.yAxisTickFormat(d)
}
}
selectDefault () {
if (!this.config.xAxis && !this.config.yAxis) {
if (this.tableData.columns.length > 1) {
this.config.xAxis = this.tableData.columns[0];
this.config.yAxis = this.tableData.columns[1];
this.config.xAxis = this.tableData.columns[0]
this.config.yAxis = this.tableData.columns[1]
} else if (this.tableData.columns.length === 1) {
this.config.xAxis = this.tableData.columns[0];
this.config.xAxis = this.tableData.columns[0]
}
}
}
setScatterChart (data, refresh) {
let xAxis = this.config.xAxis;
let yAxis = this.config.yAxis;
let group = this.config.group;
let size = this.config.size;
let xAxis = this.config.xAxis
let yAxis = this.config.yAxis
let group = this.config.group
let size = this.config.size
let xValues = [];
let yValues = [];
let rows = {};
let d3g = [];
let xValues = []
let yValues = []
let rows = {}
let d3g = []
let rowNameIndex = {};
let colNameIndex = {};
let grpNameIndex = {};
let rowIndexValue = {};
let colIndexValue = {};
let grpIndexValue = {};
let rowIdx = 0;
let colIdx = 0;
let grpIdx = 0;
let grpName = '';
let rowNameIndex = {}
let colNameIndex = {}
let grpNameIndex = {}
let rowIndexValue = {}
let colIndexValue = {}
let grpIndexValue = {}
let rowIdx = 0
let colIdx = 0
let grpIdx = 0
let grpName = ''
let xValue;
let yValue;
let row;
let xValue
let yValue
let row
if (!xAxis && !yAxis) {
return {
d3g: []
};
}
}
for (let i = 0; i < data.rows.length; i++) {
row = data.rows[i];
row = data.rows[i]
if (xAxis) {
xValue = row[xAxis.index];
xValues[i] = xValue;
xValue = row[xAxis.index]
xValues[i] = xValue
}
if (yAxis) {
yValue = row[yAxis.index];
yValues[i] = yValue;
yValue = row[yAxis.index]
yValues[i] = yValue
}
}
let isAllDiscrete = ((xAxis && yAxis && this.isDiscrete(xValues) && this.isDiscrete(yValues)) ||
(!xAxis && this.isDiscrete(yValues)) ||
(!yAxis && this.isDiscrete(xValues)));
(!yAxis && this.isDiscrete(xValues)))
if (isAllDiscrete) {
rows = this.setDiscreteScatterData(data);
rows = this.setDiscreteScatterData(data)
} else {
rows = data.rows;
rows = data.rows
}
if (!group && isAllDiscrete) {
grpName = 'count';
grpName = 'count'
} else if (!group && !size) {
if (xAxis && yAxis) {
grpName = '(' + xAxis.name + ', ' + yAxis.name + ')';
grpName = '(' + xAxis.name + ', ' + yAxis.name + ')'
} else if (xAxis && !yAxis) {
grpName = xAxis.name;
grpName = xAxis.name
} else if (!xAxis && yAxis) {
grpName = yAxis.name;
grpName = yAxis.name
}
} else if (!group && size) {
grpName = size.name;
grpName = size.name
}
let epsilon = 1e-4; // TODO remove after bump to nvd3 > 1.8.5
let epsilon = 1e-4 // TODO remove after bump to nvd3 > 1.8.5
for (let i = 0; i < rows.length; i++) {
row = rows[i];
row = rows[i]
if (xAxis) {
xValue = row[xAxis.index];
xValue = row[xAxis.index]
}
if (yAxis) {
yValue = row[yAxis.index];
yValue = row[yAxis.index]
}
if (group) {
grpName = row[group.index];
grpName = row[group.index]
}
let sz = (isAllDiscrete) ? row[row.length - 1] : ((size) ? row[size.index] : 1);
let sz = (isAllDiscrete) ? row[row.length - 1] : ((size) ? row[size.index] : 1)
if (grpNameIndex[grpName] === undefined) {
grpIndexValue[grpIdx] = grpName;
grpNameIndex[grpName] = grpIdx++;
grpIndexValue[grpIdx] = grpName
grpNameIndex[grpName] = grpIdx++
}
if (xAxis && rowNameIndex[xValue] === undefined) {
rowIndexValue[rowIdx] = xValue;
rowNameIndex[xValue] = rowIdx++;
rowIndexValue[rowIdx] = xValue
rowNameIndex[xValue] = rowIdx++
}
if (yAxis && colNameIndex[yValue] === undefined) {
colIndexValue[colIdx] = yValue;
colNameIndex[yValue] = colIdx++;
colIndexValue[colIdx] = yValue
colNameIndex[yValue] = colIdx++
}
if (!d3g[grpNameIndex[grpName]]) {
d3g[grpNameIndex[grpName]] = {
key: grpName,
values: []
};
}
}
// TODO remove epsilon jitter after bump to nvd3 > 1.8.5
let xval = 0
let yval = 0;
let yval = 0
if (xAxis) {
xval = (isNaN(xValue) ? rowNameIndex[xValue] : parseFloat(xValue)) + Math.random() * epsilon;
xval = (isNaN(xValue) ? rowNameIndex[xValue] : parseFloat(xValue)) + Math.random() * epsilon
}
if (yAxis) {
yval = (isNaN(yValue) ? colNameIndex[yValue] : parseFloat(yValue)) + Math.random() * epsilon;
yval = (isNaN(yValue) ? colNameIndex[yValue] : parseFloat(yValue)) + Math.random() * epsilon
}
d3g[grpNameIndex[grpName]].values.push({
x: xval,
y: yval,
size: isNaN(parseFloat(sz)) ? 1 : parseFloat(sz)
});
})
}
// TODO remove sort and dedup after bump to nvd3 > 1.8.5
let d3gvalues = d3g[grpNameIndex[grpName]].values;
let d3gvalues = d3g[grpNameIndex[grpName]].values
d3gvalues.sort(function (a, b) {
return ((a['x'] - b['x']) || (a['y'] - b['y']))
});
})
for (let i = 0; i < d3gvalues.length - 1;) {
if ((Math.abs(d3gvalues[i]['x'] - d3gvalues[i + 1]['x']) < epsilon) &&
(Math.abs(d3gvalues[i]['y'] - d3gvalues[i + 1]['y']) < epsilon)) {
d3gvalues.splice(i + 1, 1);
d3gvalues.splice(i + 1, 1)
} else {
i++;
i++
}
}
@ -238,33 +238,33 @@ export default class ScatterchartVisualization extends Nvd3ChartVisualization {
xLabels: rowIndexValue,
yLabels: colIndexValue,
d3g: d3g
};
}
}
setDiscreteScatterData (data) {
let xAxis = this.config.xAxis;
let yAxis = this.config.yAxis;
let group = this.config.group;
let xAxis = this.config.xAxis
let yAxis = this.config.yAxis
let group = this.config.group
let xValue;
let yValue;
let grp;
let xValue
let yValue
let grp
let rows = {};
let rows = {}
for (let i = 0; i < data.rows.length; i++) {
let row = data.rows[i];
let row = data.rows[i]
if (xAxis) {
xValue = row[xAxis.index];
xValue = row[xAxis.index]
}
if (yAxis) {
yValue = row[yAxis.index];
yValue = row[yAxis.index]
}
if (group) {
grp = row[group.index];
grp = row[group.index]
}
let key = xValue + ',' + yValue + ',' + grp;
let key = xValue + ',' + yValue + ',' + grp
if (!rows[key]) {
rows[key] = {
@ -272,89 +272,89 @@ export default class ScatterchartVisualization extends Nvd3ChartVisualization {
y: yValue,
group: grp,
size: 1
};
}
} else {
rows[key].size++;
rows[key].size++
}
}
// change object into array
let newRows = [];
let newRows = []
for (let r in rows) {
let newRow = [];
if (xAxis) { newRow[xAxis.index] = rows[r].x; }
if (yAxis) { newRow[yAxis.index] = rows[r].y; }
if (group) { newRow[group.index] = rows[r].group; }
newRow[data.rows[0].length] = rows[r].size;
newRows.push(newRow);
let newRow = []
if (xAxis) { newRow[xAxis.index] = rows[r].x }
if (yAxis) { newRow[yAxis.index] = rows[r].y }
if (group) { newRow[group.index] = rows[r].group }
newRow[data.rows[0].length] = rows[r].size
newRows.push(newRow)
}
return newRows;
return newRows
}
isDiscrete (field) {
let getUnique = function (f) {
let uniqObj = {};
let uniqArr = [];
let j = 0;
let uniqObj = {}
let uniqArr = []
let j = 0
for (let i = 0; i < f.length; i++) {
let item = f[i];
let item = f[i]
if (uniqObj[item] !== 1) {
uniqObj[item] = 1;
uniqArr[j++] = item;
uniqObj[item] = 1
uniqArr[j++] = item
}
}
return uniqArr;
};
return uniqArr
}
for (let i = 0; i < field.length; i++) {
if (isNaN(parseFloat(field[i])) &&
(typeof field[i] === 'string' || field[i] instanceof String)) {
return true;
return true
}
}
let threshold = 0.05;
let unique = getUnique(field);
let threshold = 0.05
let unique = getUnique(field)
if (unique.length / field.length < threshold) {
return true;
return true
} else {
return false;
return false
}
}
isValidSizeOption (options) {
let xValues = [];
let yValues = [];
let rows = this.tableData.rows;
let xValues = []
let yValues = []
let rows = this.tableData.rows
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
let size = row[options.size.index];
let row = rows[i]
let size = row[options.size.index]
// check if the field is numeric
if (isNaN(parseFloat(size)) || !isFinite(size)) {
return false;
return false
}
if (options.xAxis) {
let x = row[options.xAxis.index];
xValues[i] = x;
let x = row[options.xAxis.index]
xValues[i] = x
}
if (options.yAxis) {
let y = row[options.yAxis.index];
yValues[i] = y;
let y = row[options.yAxis.index]
yValues[i] = y
}
}
// check if all existing fields are discrete
let isAllDiscrete = ((options.xAxis && options.yAxis && this.isDiscrete(xValues) && this.isDiscrete(yValues)) ||
(!options.xAxis && this.isDiscrete(yValues)) ||
(!options.yAxis && this.isDiscrete(xValues)));
(!options.yAxis && this.isDiscrete(xValues)))
if (isAllDiscrete) {
return false;
return false
}
return true;
return true
}
}

View file

@ -12,52 +12,52 @@
* limitations under the License.
*/
import Visualization from '../visualization';
import PassthroughTransformation from '../../tabledata/passthrough';
import HandsonHelper from '../../handsontable/handsonHelper';
import Visualization from '../visualization'
import PassthroughTransformation from '../../tabledata/passthrough'
import HandsonHelper from '../../handsontable/handsonHelper'
/**
* Visualize data in table format
*/
export default class TableVisualization extends Visualization {
constructor (targetEl, config) {
super(targetEl, config);
console.log('Init table viz');
targetEl.addClass('table');
this.passthrough = new PassthroughTransformation(config);
super(targetEl, config)
console.log('Init table viz')
targetEl.addClass('table')
this.passthrough = new PassthroughTransformation(config)
}
refresh () {
this.hot.render();
this.hot.render()
}
render (tableData) {
let height = this.targetEl.height();
let container = this.targetEl.css('height', height).get(0);
let resultRows = tableData.rows;
let columnNames = _.pluck(tableData.columns, 'name');
let height = this.targetEl.height()
let container = this.targetEl.css('height', height).get(0)
let resultRows = tableData.rows
let columnNames = _.pluck(tableData.columns, 'name')
// eslint-disable-next-line prefer-spread
let columns = Array.apply(null, Array(tableData.columns.length)).map(function () {
return {type: 'text'};
});
return {type: 'text'}
})
if (this.hot) {
this.hot.destroy();
this.hot.destroy()
}
let handsonHelper = new HandsonHelper();
let handsonHelper = new HandsonHelper()
this.hot = new Handsontable(container, handsonHelper.getHandsonTableConfig(
columns, columnNames, resultRows));
this.hot.validateCells(null);
columns, columnNames, resultRows))
this.hot.validateCells(null)
}
destroy () {
if (this.hot) {
this.hot.destroy();
this.hot.destroy()
}
}
getTransformation () {
return this.passthrough;
return this.passthrough
}
}

View file

@ -17,11 +17,11 @@
*/
export default class Visualization {
constructor (targetEl, config) {
this.targetEl = targetEl;
this.config = config;
this._dirty = false;
this._active = false;
this._emitter = () => {};
this.targetEl = targetEl
this.config = config
this._dirty = false
this._active = false
this._emitter = () => {}
}
/**
@ -68,24 +68,24 @@ export default class Visualization {
*/
activate () {
if (!this._active || this._dirty) {
this.refresh();
this._dirty = false;
this.refresh()
this._dirty = false
}
this._active = true;
this._active = true
}
/**
* Activate. invoked when visualization is de selected
*/
deactivate () {
this._active = false;
this._active = false
}
/**
* Is active
*/
isActive () {
return this._active;
return this._active
}
/**
@ -93,9 +93,9 @@ export default class Visualization {
*/
resize () {
if (this.isActive()) {
this.refresh();
this.refresh()
} else {
this._dirty = true;
this._dirty = true
}
}
@ -103,11 +103,11 @@ export default class Visualization {
* Set new config
*/
setConfig (config) {
this.config = config;
this.config = config
if (this.isActive()) {
this.refresh();
this.refresh()
} else {
this._dirty = true;
this._dirty = true
}
}
@ -115,57 +115,57 @@ export default class Visualization {
* Emit config. config will sent to server and saved.
*/
emitConfig (config) {
this._emitter(config);
this._emitter(config)
}
/**
* render setting
*/
renderSetting (targetEl) {
let setting = this.getSetting();
let setting = this.getSetting()
if (!setting) {
return;
return
}
// already readered
if (this._scope) {
let self = this;
let self = this
this._scope.$apply(function () {
for (let k in setting.scope) {
self._scope[k] = setting.scope[k];
self._scope[k] = setting.scope[k]
}
for (let k in self._prevSettingScope) {
if (!setting.scope[k]) {
self._scope[k] = setting.scope[k];
self._scope[k] = setting.scope[k]
}
}
});
return;
})
return
} else {
this._prevSettingScope = setting.scope;
this._prevSettingScope = setting.scope
}
let scope = this._createNewScope();
let scope = this._createNewScope()
for (let k in setting.scope) {
scope[k] = setting.scope[k];
scope[k] = setting.scope[k]
}
let template = setting.template;
let template = setting.template
if (template.split('\n').length === 1 &&
template.endsWith('.html')) { // template is url
this._templateRequest(template).then(t =>
_renderSetting(this, targetEl, t, scope)
);
)
} else {
_renderSetting(this, targetEl, template, scope);
_renderSetting(this, targetEl, template, scope)
}
}
}
function _renderSetting (instance, targetEl, template, scope) {
instance._targetEl = targetEl;
targetEl.html(template);
instance._compile(targetEl.contents())(scope);
instance._scope = scope;
instance._targetEl = targetEl
targetEl.html(template)
instance._compile(targetEl.contents())(scope)
instance._scope = scope
}

View file

@ -12,25 +12,25 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('arrayOrderingSrv', arrayOrderingSrv);
angular.module('zeppelinWebApp').service('arrayOrderingSrv', arrayOrderingSrv)
function arrayOrderingSrv (TRASH_FOLDER_ID) {
'ngInject';
'ngInject'
let arrayOrderingSrv = this;
let arrayOrderingSrv = this
this.noteListOrdering = function (note) {
if (note.id === TRASH_FOLDER_ID) {
return '\uFFFF';
return '\uFFFF'
}
return arrayOrderingSrv.getNoteName(note);
};
return arrayOrderingSrv.getNoteName(note)
}
this.getNoteName = function (note) {
if (note.name === undefined || note.name.trim() === '') {
return 'Note ' + note.id;
return 'Note ' + note.id
} else {
return note.name;
return note.name
}
};
}
}

View file

@ -12,37 +12,37 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('baseUrlSrv', baseUrlSrv);
angular.module('zeppelinWebApp').service('baseUrlSrv', baseUrlSrv)
function baseUrlSrv () {
this.getPort = function () {
let port = Number(location.port);
let port = Number(location.port)
if (!port) {
port = 80;
port = 80
if (location.protocol === 'https:') {
port = 443;
port = 443
}
}
// Exception for when running locally via grunt
if (port === process.env.WEB_PORT) {
port = process.env.SERVER_PORT;
port = process.env.SERVER_PORT
}
return port;
};
return port
}
this.getWebsocketUrl = function () {
let wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
let wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'
return wsProtocol + '//' + location.hostname + ':' + this.getPort() +
skipTrailingSlash(location.pathname) + '/ws';
};
skipTrailingSlash(location.pathname) + '/ws'
}
this.getRestApiBase = function () {
return location.protocol + '//' + location.hostname + ':' +
this.getPort() + skipTrailingSlash(location.pathname) +
'/api';
};
'/api'
}
const skipTrailingSlash = function (path) {
return path.replace(/\/$/, '');
};
return path.replace(/\/$/, '')
}
}

View file

@ -12,28 +12,28 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('browserDetectService', browserDetectService);
angular.module('zeppelinWebApp').service('browserDetectService', browserDetectService)
function browserDetectService () {
this.detectIE = function () {
let ua = window.navigator.userAgent;
let msie = ua.indexOf('MSIE ');
let ua = window.navigator.userAgent
let msie = ua.indexOf('MSIE ')
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10)
}
let trident = ua.indexOf('Trident/');
let trident = ua.indexOf('Trident/')
if (trident > 0) {
// IE 11 => return version number
let rv = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
let rv = ua.indexOf('rv:')
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10)
}
let edge = ua.indexOf('Edge/');
let edge = ua.indexOf('Edge/')
if (edge > 0) {
// IE 12 (aka Edge) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10)
}
// other browser
return false;
};
return false
}
}

View file

@ -11,24 +11,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('clipboardCtrl', clipboardCtrl);
angular.module('zeppelinWebApp').controller('clipboardCtrl', clipboardCtrl)
function clipboardCtrl ($scope) {
'ngInject';
'ngInject'
$scope.complete = function (e) {
$scope.copied = true;
$scope.tooltip = 'Copied!';
$scope.copied = true
$scope.tooltip = 'Copied!'
setTimeout(function () {
$scope.tooltip = 'Copy to clipboard';
}, 400);
};
$scope.tooltip = 'Copy to clipboard'
}, 400)
}
$scope.$watch('input', function () {
$scope.copied = false;
$scope.tooltip = 'Copy to clipboard';
});
$scope.copied = false
$scope.tooltip = 'Copy to clipboard'
})
$scope.clipError = function (e) {
console.log('Error: ' + e.name + ' - ' + e.message);
$scope.tooltip = 'Not supported browser';
};
console.log('Error: ' + e.name + ' - ' + e.message)
$scope.tooltip = 'Not supported browser'
}
}

View file

@ -12,15 +12,15 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('dropdownInput', dropdownInput);
angular.module('zeppelinWebApp').directive('dropdownInput', dropdownInput)
function dropdownInput () {
return {
restrict: 'A',
link: function (scope, element) {
element.bind('click', function (event) {
event.stopPropagation();
});
event.stopPropagation()
})
}
};
}
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('codeEditor', codeEditor);
angular.module('zeppelinWebApp').directive('codeEditor', codeEditor)
function codeEditor ($templateRequest, $compile) {
return {
@ -27,12 +27,12 @@ function codeEditor ($templateRequest, $compile) {
},
link: function (scope, element, attrs, controller) {
$templateRequest('components/editor/ace.editor.directive.html').then(function (editorHtml) {
let editor = angular.element(editorHtml);
editor.attr('id', scope.paragraphId + '_editor');
element.append(editor);
$compile(editor)(scope);
console.log('codeEditor directive revision view is ' + scope.revisionView);
});
let editor = angular.element(editorHtml)
editor.attr('id', scope.paragraphId + '_editor')
element.append(editor)
$compile(editor)(scope)
console.log('codeEditor directive revision view is ' + scope.revisionView)
})
}
};
}
}

View file

@ -12,10 +12,10 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('ElasticInputCtrl', ElasticInputCtrl);
angular.module('zeppelinWebApp').controller('ElasticInputCtrl', ElasticInputCtrl)
function ElasticInputCtrl () {
let vm = this;
vm.showEditor = false;
vm.value = '';
let vm = this
vm.showEditor = false
vm.value = ''
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('expandCollapse', expandCollapse);
angular.module('zeppelinWebApp').directive('expandCollapse', expandCollapse)
function expandCollapse () {
return {
@ -20,18 +20,18 @@ function expandCollapse () {
link: function (scope, element, attrs) {
angular.element(element).click(function (event) {
if (angular.element(element).find('.expandable:visible').length > 1) {
angular.element(element).find('.expandable:visible').slideUp('slow');
angular.element(element).find('i.icon-folder-alt').toggleClass('icon-folder icon-folder-alt');
angular.element(element).find('.expandable:visible').slideUp('slow')
angular.element(element).find('i.icon-folder-alt').toggleClass('icon-folder icon-folder-alt')
} else {
angular.element(element).find('.expandable').first().slideToggle('200', function () {
// do not toggle trash folder
if (angular.element(element).find('.fa-trash-o').length === 0) {
angular.element(element).find('i').first().toggleClass('icon-folder icon-folder-alt');
angular.element(element).find('i').first().toggleClass('icon-folder icon-folder-alt')
}
});
})
}
event.stopPropagation();
});
event.stopPropagation()
})
}
};
}
}

View file

@ -16,73 +16,73 @@ export const HeliumConfFieldType = {
NUMBER: 'number',
JSON: 'json',
STRING: 'string',
};
}
/**
* @param persisted <Object> including `type`, `description`, `defaultValue` for each conf key
* @param spec <Object> including `value` for each conf key
*/
export function mergePersistedConfWithSpec (persisted, spec) {
const confs = [];
const confs = []
for (let name in spec) {
const specField = spec[name];
const persistedValue = persisted[name];
const specField = spec[name]
const persistedValue = persisted[name]
const value = (persistedValue) ? persistedValue : specField.defaultValue;
const value = (persistedValue) ? persistedValue : specField.defaultValue
const merged = {
name: name,
type: specField.type,
description: specField.description,
value: value,
defaultValue: specField.defaultValue,
};
}
confs.push(merged);
confs.push(merged)
}
return confs;
return confs
}
export function createAllPackageConfigs (defaultPackages, persistedConfs) {
let packageConfs = {};
let packageConfs = {}
for (let name in defaultPackages) {
const pkgSearchResult = defaultPackages[name];
const pkgSearchResult = defaultPackages[name]
const spec = pkgSearchResult.pkg.config;
if (!spec) { continue; }
const spec = pkgSearchResult.pkg.config
if (!spec) { continue }
const artifact = pkgSearchResult.pkg.artifact;
if (!artifact) { continue; }
const artifact = pkgSearchResult.pkg.artifact
if (!artifact) { continue }
let persistedConf = {};
let persistedConf = {}
if (persistedConfs[artifact]) {
persistedConf = persistedConfs[artifact];
persistedConf = persistedConfs[artifact]
}
const confs = mergePersistedConfWithSpec(persistedConf, spec);
packageConfs[name] = confs;
const confs = mergePersistedConfWithSpec(persistedConf, spec)
packageConfs[name] = confs
}
return packageConfs;
return packageConfs
}
export function parseConfigValue (type, stringified) {
let value = stringified;
let value = stringified
try {
if (HeliumConfFieldType.NUMBER === type) {
value = parseFloat(stringified);
value = parseFloat(stringified)
} else if (HeliumConfFieldType.JSON === type) {
value = JSON.parse(stringified);
value = JSON.parse(stringified)
}
} catch (error) {
// return just the stringified one
console.error(`Failed to parse conf type ${type}, value ${value}`);
console.error(`Failed to parse conf type ${type}, value ${value}`)
}
return value;
return value
}
/**
@ -91,9 +91,9 @@ export function parseConfigValue (type, stringified) {
*/
export function createPersistableConfig (currentConfs) {
const filtered = currentConfs.reduce((acc, c) => {
acc[c.name] = parseConfigValue(c.type, c.value);
return acc;
}, {});
acc[c.name] = parseConfigValue(c.type, c.value)
return acc
}, {})
return filtered;
return filtered
}

View file

@ -14,18 +14,18 @@
export function createDefaultPackage (pkgSearchResult, sce) {
for (let pkgIdx in pkgSearchResult) {
const pkg = pkgSearchResult[pkgIdx];
pkg.pkg.icon = sce.trustAsHtml(pkg.pkg.icon);
const pkg = pkgSearchResult[pkgIdx]
pkg.pkg.icon = sce.trustAsHtml(pkg.pkg.icon)
if (pkg.enabled) {
pkgSearchResult.splice(pkgIdx, 1);
return pkg;
pkgSearchResult.splice(pkgIdx, 1)
return pkg
}
}
// show first available version if package is not enabled
const result = pkgSearchResult[0];
pkgSearchResult.splice(0, 1);
return result;
const result = pkgSearchResult[0]
pkgSearchResult.splice(0, 1)
return result
}
/**
@ -36,12 +36,12 @@ export function createDefaultPackage (pkgSearchResult, sce) {
* @returns {Object} including {name, pkgInfo}
*/
export function createDefaultPackages (pkgSearchResults, sce) {
const defaultPackages = {};
const defaultPackages = {}
// show enabled version if any version of package is enabled
for (let name in pkgSearchResults) {
const pkgSearchResult = pkgSearchResults[name];
const pkgSearchResult = pkgSearchResults[name]
defaultPackages[name] = createDefaultPackage(pkgSearchResult, sce)
}
return defaultPackages;
return defaultPackages
}

View file

@ -12,26 +12,26 @@
* limitations under the License.
*/
import { HeliumType, } from './helium-type';
import { HeliumType, } from './helium-type'
import {
createAllPackageConfigs,
createPersistableConfig,
mergePersistedConfWithSpec,
} from './helium-conf';
} from './helium-conf'
import {
createDefaultPackages,
} from './helium-package';
} from './helium-package'
angular.module('zeppelinWebApp').service('heliumService', heliumService);
angular.module('zeppelinWebApp').service('heliumService', heliumService)
export default function heliumService ($http, $sce, baseUrlSrv) {
'ngInject';
'ngInject'
let visualizationBundles = [];
let visualizationBundles = []
// name `heliumBundles` should be same as `HeliumBundleFactory.HELIUM_BUNDLES_VAR`
let heliumBundles = [];
let heliumBundles = []
// map for `{ magic: interpreter }`
let spellPerMagic = {};
let spellPerMagic = {}
// map for `{ magic: package-name }`
let pkgNamePerMagic = {}
@ -40,39 +40,39 @@ export default function heliumService ($http, $sce, baseUrlSrv) {
* @returns {SpellBase} undefined if magic is not registered
*/
this.getSpellByMagic = function (magic) {
return spellPerMagic[magic];
};
return spellPerMagic[magic]
}
this.executeSpell = function (magic, textWithoutMagic) {
const promisedConf = this.getSinglePackageConfigUsingMagic(magic)
.then(confs => createPersistableConfig(confs));
.then(confs => createPersistableConfig(confs))
return promisedConf.then(conf => {
const spell = this.getSpellByMagic(magic);
const spellResult = spell.interpret(textWithoutMagic, conf);
const spell = this.getSpellByMagic(magic)
const spellResult = spell.interpret(textWithoutMagic, conf)
const parsed = spellResult.getAllParsedDataWithTypes(
spellPerMagic, magic, textWithoutMagic);
spellPerMagic, magic, textWithoutMagic)
return parsed;
});
};
return parsed
})
}
this.executeSpellAsDisplaySystem = function (magic, textWithoutMagic) {
const promisedConf = this.getSinglePackageConfigUsingMagic(magic)
.then(confs => createPersistableConfig(confs));
.then(confs => createPersistableConfig(confs))
return promisedConf.then(conf => {
const spell = this.getSpellByMagic(magic);
const spellResult = spell.interpret(textWithoutMagic.trim(), conf);
const parsed = spellResult.getAllParsedDataWithTypes(spellPerMagic);
const spell = this.getSpellByMagic(magic)
const spellResult = spell.interpret(textWithoutMagic.trim(), conf)
const parsed = spellResult.getAllParsedDataWithTypes(spellPerMagic)
return parsed;
});
};
return parsed
})
}
this.getVisualizationBundles = function () {
return visualizationBundles;
};
return visualizationBundles
}
/**
* @returns {Promise} which returns bundleOrder
@ -80,45 +80,45 @@ export default function heliumService ($http, $sce, baseUrlSrv) {
this.getVisualizationPackageOrder = function () {
return $http.get(baseUrlSrv.getRestApiBase() + '/helium/order/visualization')
.then(function (response, status) {
return response.data.body;
return response.data.body
})
.catch(function (error) {
console.error('Can not get bundle order', error);
});
};
console.error('Can not get bundle order', error)
})
}
this.setVisualizationPackageOrder = function (list) {
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/order/visualization', list);
};
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/order/visualization', list)
}
this.enable = function (name, artifact) {
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/enable/' + name, artifact);
};
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/enable/' + name, artifact)
}
this.disable = function (name) {
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/disable/' + name);
};
return $http.post(baseUrlSrv.getRestApiBase() + '/helium/disable/' + name)
}
this.saveConfig = function (pkg, defaultPackageConfig, closeConfigPanelCallback) {
// in case of local package, it will include `/`
const pkgArtifact = encodeURIComponent(pkg.artifact);
const pkgName = pkg.name;
const filtered = createPersistableConfig(defaultPackageConfig);
const pkgArtifact = encodeURIComponent(pkg.artifact)
const pkgName = pkg.name
const filtered = createPersistableConfig(defaultPackageConfig)
if (!pkgName || !pkgArtifact || !filtered) {
console.error(
`Can't save config for helium package '${pkgArtifact}'`, filtered);
return;
`Can't save config for helium package '${pkgArtifact}'`, filtered)
return
}
const url = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`;
const url = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`
return $http.post(url, filtered)
.then(() => {
if (closeConfigPanelCallback) { closeConfigPanelCallback(); }
if (closeConfigPanelCallback) { closeConfigPanelCallback() }
}).catch((error) => {
console.error(`Failed to save config for ${pkgArtifact}`, error);
});
};
console.error(`Failed to save config for ${pkgArtifact}`, error)
})
}
/**
* @returns {Promise<Object>} which including {name, Array<package info for artifact>}
@ -126,50 +126,50 @@ export default function heliumService ($http, $sce, baseUrlSrv) {
this.getAllPackageInfo = function () {
return $http.get(`${baseUrlSrv.getRestApiBase()}/helium/package`)
.then(function (response, status) {
return response.data.body;
return response.data.body
})
.catch(function (error) {
console.error('Failed to get all package infos', error);
});
};
console.error('Failed to get all package infos', error)
})
}
this.getAllEnabledPackages = function () {
return $http.get(`${baseUrlSrv.getRestApiBase()}/helium/enabledPackage`)
.then(function (response, status) {
return response.data.body;
return response.data.body
})
.catch(function (error) {
console.error('Failed to get all enabled package infos', error);
});
};
console.error('Failed to get all enabled package infos', error)
})
}
this.getSingleBundle = function (pkgName) {
let url = `${baseUrlSrv.getRestApiBase()}/helium/bundle/load/${pkgName}`
if (process.env.HELIUM_BUNDLE_DEV) {
url = url + '?refresh=true';
url = url + '?refresh=true'
}
return $http.get(url)
.then(function (response, status) {
const bundle = response.data
if (bundle.substring(0, 'ERROR:'.length) === 'ERROR:') {
console.error(`Failed to get bundle: ${pkgName}`, bundle);
console.error(`Failed to get bundle: ${pkgName}`, bundle)
return '' // empty bundle will be filtered later
}
return bundle
})
.catch(function (error) {
console.error(`Failed to get single bundle: ${pkgName}`, error);
});
console.error(`Failed to get single bundle: ${pkgName}`, error)
})
}
this.getDefaultPackages = function () {
return this.getAllPackageInfo()
.then(pkgSearchResults => {
return createDefaultPackages(pkgSearchResults, $sce);
});
};
return createDefaultPackages(pkgSearchResults, $sce)
})
}
this.getAllPackageInfoAndDefaultPackages = function () {
return this.getAllPackageInfo()
@ -177,73 +177,73 @@ export default function heliumService ($http, $sce, baseUrlSrv) {
return {
pkgSearchResults: pkgSearchResults,
defaultPackages: createDefaultPackages(pkgSearchResults, $sce),
};
});
};
}
})
}
/**
* get all package configs.
* @return { Promise<{name, Array<Object>}> }
*/
this.getAllPackageConfigs = function () {
const promisedDefaultPackages = this.getDefaultPackages();
const promisedDefaultPackages = this.getDefaultPackages()
const promisedPersistedConfs =
$http.get(`${baseUrlSrv.getRestApiBase()}/helium/config`)
.then(function (response, status) {
return response.data.body;
});
return response.data.body
})
return Promise.all([promisedDefaultPackages, promisedPersistedConfs])
.then(values => {
const defaultPackages = values[0];
const persistedConfs = values[1];
const defaultPackages = values[0]
const persistedConfs = values[1]
return createAllPackageConfigs(defaultPackages, persistedConfs);
return createAllPackageConfigs(defaultPackages, persistedConfs)
})
.catch(function (error) {
console.error('Failed to get all package configs', error);
});
};
console.error('Failed to get all package configs', error)
})
}
/**
* get the package config which is persisted in server.
* @return { Promise<Array<Object>> }
*/
this.getSinglePackageConfigs = function (pkg) {
const pkgName = pkg.name;
const pkgName = pkg.name
// in case of local package, it will include `/`
const pkgArtifact = encodeURIComponent(pkg.artifact);
const pkgArtifact = encodeURIComponent(pkg.artifact)
if (!pkgName || !pkgArtifact) {
console.error('Failed to fetch config for\n', pkg);
return Promise.resolve([]);
console.error('Failed to fetch config for\n', pkg)
return Promise.resolve([])
}
const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`;
const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`
const promisedConf = $http.get(confUrl)
.then(function (response, status) {
return response.data.body;
});
return response.data.body
})
return promisedConf.then(({confSpec, confPersisted}) => {
const merged = mergePersistedConfWithSpec(confPersisted, confSpec)
return merged;
});
};
return merged
})
}
this.getSinglePackageConfigUsingMagic = function (magic) {
const pkgName = pkgNamePerMagic[magic];
const pkgName = pkgNamePerMagic[magic]
const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/spell/config/${pkgName}`;
const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/spell/config/${pkgName}`
const promisedConf = $http.get(confUrl)
.then(function (response, status) {
return response.data.body;
});
return response.data.body
})
return promisedConf.then(({confSpec, confPersisted}) => {
const merged = mergePersistedConfWithSpec(confPersisted, confSpec)
return merged;
});
return merged
})
}
const p = this.getAllEnabledPackages()
@ -260,7 +260,7 @@ export default function heliumService ($http, $sce, baseUrlSrv) {
// filter out empty bundle
if (b === '') { return acc }
acc.push(b)
return acc;
return acc
}, [])
})

View file

@ -12,20 +12,20 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('interpreterDirective', interpreterDirective);
angular.module('zeppelinWebApp').directive('interpreterDirective', interpreterDirective)
function interpreterDirective ($timeout) {
'ngInject';
'ngInject'
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
let id = 'ngRenderFinished';
scope.$emit(id);
});
let id = 'ngRenderFinished'
scope.$emit(id)
})
}
}
};
}
}

View file

@ -12,15 +12,15 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('LoginCtrl', LoginCtrl);
angular.module('zeppelinWebApp').controller('LoginCtrl', LoginCtrl)
function LoginCtrl ($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv, $location, $timeout) {
'ngInject';
'ngInject'
$scope.SigningIn = false;
$scope.loginParams = {};
$scope.SigningIn = false
$scope.loginParams = {}
$scope.login = function () {
$scope.SigningIn = true;
$scope.SigningIn = true
$http({
method: 'POST',
url: baseUrlSrv.getRestApiBase() + '/login',
@ -32,53 +32,53 @@ function LoginCtrl ($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv,
'password': $scope.loginParams.password
})
}).then(function successCallback (response) {
$rootScope.ticket = response.data.body;
angular.element('#loginModal').modal('toggle');
$rootScope.$broadcast('loginSuccess', true);
$rootScope.userName = $scope.loginParams.userName;
$scope.SigningIn = false;
$rootScope.ticket = response.data.body
angular.element('#loginModal').modal('toggle')
$rootScope.$broadcast('loginSuccess', true)
$rootScope.userName = $scope.loginParams.userName
$scope.SigningIn = false
// redirect to the page from where the user originally was
if ($location.search() && $location.search()['ref']) {
$timeout(function () {
let redirectLocation = $location.search()['ref'];
$location.$$search = {};
$location.path(redirectLocation);
}, 100);
let redirectLocation = $location.search()['ref']
$location.$$search = {}
$location.path(redirectLocation)
}, 100)
}
}, function errorCallback (errorResponse) {
$scope.loginParams.errorText = 'The username and password that you entered don\'t match.';
$scope.SigningIn = false;
});
};
$scope.loginParams.errorText = 'The username and password that you entered don\'t match.'
$scope.SigningIn = false
})
}
let initValues = function () {
$scope.loginParams = {
userName: '',
password: ''
};
};
}
}
// handle session logout message received from WebSocket
$rootScope.$on('session_logout', function (event, data) {
if ($rootScope.userName !== '') {
$rootScope.userName = '';
$rootScope.ticket = undefined;
$rootScope.userName = ''
$rootScope.ticket = undefined
setTimeout(function () {
$scope.loginParams = {};
$scope.loginParams.errorText = data.info;
angular.element('.nav-login-btn').click();
}, 1000);
let locationPath = $location.path();
$location.path('/').search('ref', locationPath);
$scope.loginParams = {}
$scope.loginParams.errorText = data.info
angular.element('.nav-login-btn').click()
}, 1000)
let locationPath = $location.path()
$location.path('/').search('ref', locationPath)
}
});
})
/*
** $scope.$on functions below
*/
$scope.$on('initLoginValues', function () {
initValues();
});
initValues()
})
}

View file

@ -12,109 +12,109 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('NavCtrl', NavCtrl);
angular.module('zeppelinWebApp').controller('NavCtrl', NavCtrl)
function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
noteListDataFactory, baseUrlSrv, websocketMsgSrv,
arrayOrderingSrv, searchService, TRASH_FOLDER_ID) {
'ngInject';
'ngInject'
let vm = this;
vm.arrayOrderingSrv = arrayOrderingSrv;
vm.connected = websocketMsgSrv.isConnected();
vm.isActive = isActive;
vm.logout = logout;
vm.notes = noteListDataFactory;
vm.search = search;
vm.searchForm = searchService;
vm.showLoginWindow = showLoginWindow;
vm.TRASH_FOLDER_ID = TRASH_FOLDER_ID;
vm.isFilterNote = isFilterNote;
let vm = this
vm.arrayOrderingSrv = arrayOrderingSrv
vm.connected = websocketMsgSrv.isConnected()
vm.isActive = isActive
vm.logout = logout
vm.notes = noteListDataFactory
vm.search = search
vm.searchForm = searchService
vm.showLoginWindow = showLoginWindow
vm.TRASH_FOLDER_ID = TRASH_FOLDER_ID
vm.isFilterNote = isFilterNote
$scope.query = {q: ''};
$scope.query = {q: ''}
initController();
initController()
function getZeppelinVersion () {
$http.get(baseUrlSrv.getRestApiBase() + '/version').success(
function (data, status, headers, config) {
$rootScope.zeppelinVersion = data.body;
$rootScope.zeppelinVersion = data.body
}).error(
function (data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
console.log('Error %o %o', status, data.message)
})
}
function initController () {
$scope.isDrawNavbarNoteList = false;
angular.element('#notebook-list').perfectScrollbar({suppressScrollX: true});
$scope.isDrawNavbarNoteList = false
angular.element('#notebook-list').perfectScrollbar({suppressScrollX: true})
angular.element(document).click(function () {
$scope.query.q = '';
});
$scope.query.q = ''
})
getZeppelinVersion();
loadNotes();
getZeppelinVersion()
loadNotes()
}
function isFilterNote (note) {
if (!$scope.query.q) {
return true;
return true
}
let noteName = note.name;
let noteName = note.name
if (noteName.toLowerCase().indexOf($scope.query.q.toLowerCase()) > -1) {
return true;
return true
}
return false;
return false
}
function isActive (noteId) {
return ($routeParams.noteId === noteId);
return ($routeParams.noteId === noteId)
}
function listConfigurations () {
websocketMsgSrv.listConfigurations();
websocketMsgSrv.listConfigurations()
}
function loadNotes () {
websocketMsgSrv.getNoteList();
websocketMsgSrv.getNoteList()
}
function getHomeNote () {
websocketMsgSrv.getHomeNote();
websocketMsgSrv.getHomeNote()
}
function logout () {
let logoutURL = baseUrlSrv.getRestApiBase() + '/login/logout';
let logoutURL = baseUrlSrv.getRestApiBase() + '/login/logout'
// for firefox and safari
logoutURL = logoutURL.replace('//', '//false:false@');
logoutURL = logoutURL.replace('//', '//false:false@')
$http.post(logoutURL).error(function () {
// force authcBasic (if configured) to logout
$http.post(logoutURL).error(function () {
$rootScope.userName = '';
$rootScope.ticket.principal = '';
$rootScope.ticket.ticket = '';
$rootScope.ticket.roles = '';
$rootScope.userName = ''
$rootScope.ticket.principal = ''
$rootScope.ticket.ticket = ''
$rootScope.ticket.roles = ''
BootstrapDialog.show({
message: 'Logout Success'
});
})
setTimeout(function () {
window.location.replace('/');
}, 1000);
});
});
window.location.replace('/')
}, 1000)
})
})
}
function search (searchTerm) {
$location.path('/search/' + searchTerm);
$location.path('/search/' + searchTerm)
}
function showLoginWindow () {
setTimeout(function () {
angular.element('#userName').focus();
}, 500);
angular.element('#userName').focus()
}, 500)
}
/*
@ -122,19 +122,19 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
*/
$scope.$on('setNoteMenu', function (event, notes) {
noteListDataFactory.setNotes(notes);
initNotebookListEventListener();
});
noteListDataFactory.setNotes(notes)
initNotebookListEventListener()
})
$scope.$on('setConnectedStatus', function (event, param) {
vm.connected = param;
});
vm.connected = param
})
$scope.$on('loginSuccess', function (event, param) {
listConfigurations();
loadNotes();
getHomeNote();
});
listConfigurations()
loadNotes()
getHomeNote()
})
/*
** Performance optimization for Browser Render.
@ -142,12 +142,12 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
function initNotebookListEventListener () {
angular.element(document).ready(function () {
angular.element('.notebook-list-dropdown').on('show.bs.dropdown', function () {
$scope.isDrawNavbarNoteList = true;
});
$scope.isDrawNavbarNoteList = true
})
angular.element('.notebook-list-dropdown').on('hide.bs.dropdown', function () {
$scope.isDrawNavbarNoteList = false;
});
});
$scope.isDrawNavbarNoteList = false
})
})
}
}

View file

@ -1,18 +1,18 @@
describe('Controller: NavCtrl', function () {
// load the controller's module
beforeEach(angular.mock.module('zeppelinWebApp'));
let NavCtrl;
let scope;
beforeEach(angular.mock.module('zeppelinWebApp'))
let NavCtrl
let scope
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
scope = $rootScope.$new()
NavCtrl = $controller('NavCtrl', {
$scope: scope
});
})
it('NavCtrl to toBeDefined', function () {
expect(NavCtrl).toBeDefined();
expect(NavCtrl.loadNotes).toBeDefined();
});
}));
});
expect(NavCtrl).toBeDefined()
expect(NavCtrl.loadNotes).toBeDefined()
})
}))
})

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('ngEnter', ngEnter);
angular.module('zeppelinWebApp').directive('ngEnter', ngEnter)
function ngEnter () {
return function (scope, element, attrs) {
@ -20,11 +20,11 @@ function ngEnter () {
if (event.which === 13) {
if (!event.shiftKey) {
scope.$apply(function () {
scope.$eval(attrs.ngEnter);
});
scope.$eval(attrs.ngEnter)
})
}
event.preventDefault();
event.preventDefault()
}
});
};
})
}
}

View file

@ -1,19 +1,19 @@
describe('Directive: ngEnter', function () {
// load the directive's module
beforeEach(angular.mock.module('zeppelinWebApp'));
beforeEach(angular.mock.module('zeppelinWebApp'))
let element;
let scope;
let element
let scope
beforeEach(inject(function ($rootScope) {
scope = $rootScope.$new();
}));
scope = $rootScope.$new()
}))
it('should be define', inject(function ($compile) {
element = angular.element('<ng-enter></ng-enter>');
element = $compile(element)(scope);
expect(element.text()).toBeDefined();
}));
element = angular.element('<ng-enter></ng-enter>')
element = $compile(element)(scope)
expect(element.text()).toBeDefined()
}))
// Test the rest of function in ngEnter
/* it('should make hidden element visible', inject(function ($compile) {
@ -21,4 +21,4 @@ describe('Directive: ngEnter', function () {
element = $compile(element)(scope);
expect(element.text()).toBe('this is the ngEnter directive');
})); */
});
})

View file

@ -12,17 +12,17 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('ngEscape', ngEscape);
angular.module('zeppelinWebApp').directive('ngEscape', ngEscape)
function ngEscape () {
return function (scope, element, attrs) {
element.bind('keydown keyup', function (event) {
if (event.which === 27) {
scope.$apply(function () {
scope.$eval(attrs.ngEscape);
});
event.preventDefault();
scope.$eval(attrs.ngEscape)
})
event.preventDefault()
}
});
};
})
}
}

View file

@ -12,10 +12,10 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('noteActionSrv', noteActionSrv);
angular.module('zeppelinWebApp').service('noteActionSrv', noteActionSrv)
function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFactory) {
'ngInject';
'ngInject'
this.moveNoteToTrash = function (noteId, redirectToHome) {
BootstrapDialog.confirm({
@ -24,14 +24,14 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'This note will be moved to <strong>trash</strong>.',
callback: function (result) {
if (result) {
websocketMsgSrv.moveNoteToTrash(noteId);
websocketMsgSrv.moveNoteToTrash(noteId)
if (redirectToHome) {
$location.path('/');
$location.path('/')
}
}
}
});
};
})
}
this.moveFolderToTrash = function (folderId) {
BootstrapDialog.confirm({
@ -40,11 +40,11 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'This folder will be moved to <strong>trash</strong>.',
callback: function (result) {
if (result) {
websocketMsgSrv.moveFolderToTrash(folderId);
websocketMsgSrv.moveFolderToTrash(folderId)
}
}
});
};
})
}
this.removeNote = function (noteId, redirectToHome) {
BootstrapDialog.confirm({
@ -54,14 +54,14 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'This cannot be undone. Are you sure?',
callback: function (result) {
if (result) {
websocketMsgSrv.deleteNote(noteId);
websocketMsgSrv.deleteNote(noteId)
if (redirectToHome) {
$location.path('/');
$location.path('/')
}
}
}
});
};
})
}
this.removeFolder = function (folderId) {
BootstrapDialog.confirm({
@ -71,11 +71,11 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'This cannot be undone. Are you sure?',
callback: function (result) {
if (result) {
websocketMsgSrv.removeFolder(folderId);
websocketMsgSrv.removeFolder(folderId)
}
}
});
};
})
}
this.restoreAll = function () {
BootstrapDialog.confirm({
@ -85,11 +85,11 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
'<strong>merged</strong> into their original position.',
callback: function (result) {
if (result) {
websocketMsgSrv.restoreAll();
websocketMsgSrv.restoreAll()
}
}
});
};
})
}
this.emptyTrash = function () {
BootstrapDialog.confirm({
@ -99,11 +99,11 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'This cannot be undone. Are you sure?',
callback: function (result) {
if (result) {
websocketMsgSrv.emptyTrash();
websocketMsgSrv.emptyTrash()
}
}
});
};
})
}
this.clearAllParagraphOutput = function (noteId) {
BootstrapDialog.confirm({
@ -112,28 +112,28 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'Do you want to clear all output?',
callback: function (result) {
if (result) {
websocketMsgSrv.clearAllParagraphOutput(noteId);
websocketMsgSrv.clearAllParagraphOutput(noteId)
}
}
});
};
})
}
this.renameNote = function (noteId, notePath) {
renameSrv.openRenameModal({
title: 'Rename note',
oldName: notePath,
callback: function (newName) {
websocketMsgSrv.renameNote(noteId, newName);
websocketMsgSrv.renameNote(noteId, newName)
}
});
};
})
}
this.renameFolder = function (folderId) {
renameSrv.openRenameModal({
title: 'Rename folder',
oldName: folderId,
callback: function (newName) {
let newFolderId = normalizeFolderId(newName);
let newFolderId = normalizeFolderId(newName)
if (_.has(noteListDataFactory.flatFolderMap, newFolderId)) {
BootstrapDialog.confirm({
type: BootstrapDialog.TYPE_WARNING,
@ -142,42 +142,42 @@ function noteActionSrv (websocketMsgSrv, $location, renameSrv, noteListDataFacto
message: 'The folder will be merged into <strong>' + newFolderId + '</strong>. Are you sure?',
callback: function (result) {
if (result) {
websocketMsgSrv.renameFolder(folderId, newFolderId);
websocketMsgSrv.renameFolder(folderId, newFolderId)
}
}
});
})
} else {
websocketMsgSrv.renameFolder(folderId, newFolderId);
websocketMsgSrv.renameFolder(folderId, newFolderId)
}
}
});
};
})
}
function normalizeFolderId (folderId) {
folderId = folderId.trim();
folderId = folderId.trim()
while (folderId.indexOf('\\') > -1) {
folderId = folderId.replace('\\', '/');
folderId = folderId.replace('\\', '/')
}
while (folderId.indexOf('///') > -1) {
folderId = folderId.replace('///', '/');
folderId = folderId.replace('///', '/')
}
folderId = folderId.replace('//', '/');
folderId = folderId.replace('//', '/')
if (folderId === '/') {
return '/';
return '/'
}
if (folderId[0] === '/') {
folderId = folderId.substring(1);
folderId = folderId.substring(1)
}
if (folderId.slice(-1) === '/') {
folderId = folderId.slice(0, -1);
folderId = folderId.slice(0, -1)
}
return folderId;
return folderId
}
}

View file

@ -12,10 +12,10 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').factory('noteListDataFactory', noteListDataFactory);
angular.module('zeppelinWebApp').factory('noteListDataFactory', noteListDataFactory)
function noteListDataFactory (TRASH_FOLDER_ID) {
'ngInject';
'ngInject'
const notes = {
root: {children: []},
@ -26,24 +26,24 @@ function noteListDataFactory (TRASH_FOLDER_ID) {
// a flat list to boost searching
notes.flatList = _.map(notesList, (note) => {
note.isTrash = note.name
? note.name.split('/')[0] === TRASH_FOLDER_ID : false;
return note;
});
? note.name.split('/')[0] === TRASH_FOLDER_ID : false
return note
})
// construct the folder-based tree
notes.root = {children: []};
notes.flatFolderMap = {};
notes.root = {children: []}
notes.flatFolderMap = {}
_.reduce(notesList, function (root, note) {
let noteName = note.name || note.id;
let nodes = noteName.match(/([^\/][^\/]*)/g);
let noteName = note.name || note.id
let nodes = noteName.match(/([^\/][^\/]*)/g)
// recursively add nodes
addNode(root, nodes, note.id);
addNode(root, nodes, note.id)
return root;
}, notes.root);
return root
}, notes.root)
}
};
}
const addNode = function (curDir, nodes, noteId) {
if (nodes.length === 1) { // the leaf
@ -52,13 +52,13 @@ function noteListDataFactory (TRASH_FOLDER_ID) {
id: noteId,
path: curDir.id ? curDir.id + '/' + nodes[0] : nodes[0],
isTrash: curDir.id ? curDir.id.split('/')[0] === TRASH_FOLDER_ID : false
});
})
} else { // a folder node
let node = nodes.shift();
let node = nodes.shift()
let dir = _.find(curDir.children,
function (c) { return c.name === node && c.children !== undefined; });
function (c) { return c.name === node && c.children !== undefined })
if (dir !== undefined) { // found an existing dir
addNode(dir, nodes, noteId);
addNode(dir, nodes, noteId)
} else {
let newDir = {
id: curDir.id ? curDir.id + '/' + node : node,
@ -66,16 +66,16 @@ function noteListDataFactory (TRASH_FOLDER_ID) {
hidden: true,
children: [],
isTrash: curDir.id ? curDir.id.split('/')[0] === TRASH_FOLDER_ID : false
};
}
// add the folder to flat folder map
notes.flatFolderMap[newDir.id] = newDir;
notes.flatFolderMap[newDir.id] = newDir
curDir.children.push(newDir);
addNode(newDir, nodes, noteId);
curDir.children.push(newDir)
addNode(newDir, nodes, noteId)
}
}
};
}
return notes;
return notes
}

View file

@ -1,13 +1,13 @@
describe('Factory: NoteList', function () {
let noteList;
let noteList
beforeEach(function () {
angular.mock.module('zeppelinWebApp');
angular.mock.module('zeppelinWebApp')
inject(function ($injector) {
noteList = $injector.get('noteListDataFactory');
});
});
noteList = $injector.get('noteListDataFactory')
})
})
it('should generate both flat list and folder-based list properly', function () {
let notesList = [
@ -20,56 +20,56 @@ describe('Factory: NoteList', function () {
{name: '/C/CB/CBA', id: '000007'}, // same name with another note
{name: 'C///CB//CBB', id: '000008'},
{name: 'D/D[A/DA]B', id: '000009'} // check if '[' and ']' considered as folder seperator
];
noteList.setNotes(notesList);
]
noteList.setNotes(notesList)
let flatList = noteList.flatList;
expect(flatList.length).toBe(9);
expect(flatList[0].name).toBe('A');
expect(flatList[0].id).toBe('000001');
expect(flatList[1].name).toBe('B');
expect(flatList[2].name).toBeUndefined();
expect(flatList[3].name).toBe('/C/CA');
expect(flatList[4].name).toBe('/C/CB');
expect(flatList[5].name).toBe('/C/CB/CBA');
expect(flatList[6].name).toBe('/C/CB/CBA');
expect(flatList[7].name).toBe('C///CB//CBB');
expect(flatList[8].name).toBe('D/D[A/DA]B');
let flatList = noteList.flatList
expect(flatList.length).toBe(9)
expect(flatList[0].name).toBe('A')
expect(flatList[0].id).toBe('000001')
expect(flatList[1].name).toBe('B')
expect(flatList[2].name).toBeUndefined()
expect(flatList[3].name).toBe('/C/CA')
expect(flatList[4].name).toBe('/C/CB')
expect(flatList[5].name).toBe('/C/CB/CBA')
expect(flatList[6].name).toBe('/C/CB/CBA')
expect(flatList[7].name).toBe('C///CB//CBB')
expect(flatList[8].name).toBe('D/D[A/DA]B')
let folderList = noteList.root.children;
expect(folderList.length).toBe(5);
expect(folderList[0].name).toBe('A');
expect(folderList[0].id).toBe('000001');
expect(folderList[1].name).toBe('B');
expect(folderList[2].name).toBe('000003');
expect(folderList[3].name).toBe('C');
expect(folderList[3].id).toBe('C');
expect(folderList[3].children.length).toBe(3);
expect(folderList[3].children[0].name).toBe('CA');
expect(folderList[3].children[0].id).toBe('000004');
expect(folderList[3].children[0].children).toBeUndefined();
expect(folderList[3].children[1].name).toBe('CB');
expect(folderList[3].children[1].id).toBe('000005');
expect(folderList[3].children[1].children).toBeUndefined();
expect(folderList[3].children[2].name).toBe('CB');
expect(folderList[3].children[2].id).toBe('C/CB');
expect(folderList[3].children[2].children.length).toBe(3);
expect(folderList[3].children[2].children[0].name).toBe('CBA');
expect(folderList[3].children[2].children[0].id).toBe('000006');
expect(folderList[3].children[2].children[0].children).toBeUndefined();
expect(folderList[3].children[2].children[1].name).toBe('CBA');
expect(folderList[3].children[2].children[1].id).toBe('000007');
expect(folderList[3].children[2].children[1].children).toBeUndefined();
expect(folderList[3].children[2].children[2].name).toBe('CBB');
expect(folderList[3].children[2].children[2].id).toBe('000008');
expect(folderList[3].children[2].children[2].children).toBeUndefined();
expect(folderList[4].name).toBe('D');
expect(folderList[4].id).toBe('D');
expect(folderList[4].children.length).toBe(1);
expect(folderList[4].children[0].name).toBe('D[A');
expect(folderList[4].children[0].id).toBe('D/D[A');
expect(folderList[4].children[0].children[0].name).toBe('DA]B');
expect(folderList[4].children[0].children[0].id).toBe('000009');
expect(folderList[4].children[0].children[0].children).toBeUndefined();
});
});
let folderList = noteList.root.children
expect(folderList.length).toBe(5)
expect(folderList[0].name).toBe('A')
expect(folderList[0].id).toBe('000001')
expect(folderList[1].name).toBe('B')
expect(folderList[2].name).toBe('000003')
expect(folderList[3].name).toBe('C')
expect(folderList[3].id).toBe('C')
expect(folderList[3].children.length).toBe(3)
expect(folderList[3].children[0].name).toBe('CA')
expect(folderList[3].children[0].id).toBe('000004')
expect(folderList[3].children[0].children).toBeUndefined()
expect(folderList[3].children[1].name).toBe('CB')
expect(folderList[3].children[1].id).toBe('000005')
expect(folderList[3].children[1].children).toBeUndefined()
expect(folderList[3].children[2].name).toBe('CB')
expect(folderList[3].children[2].id).toBe('C/CB')
expect(folderList[3].children[2].children.length).toBe(3)
expect(folderList[3].children[2].children[0].name).toBe('CBA')
expect(folderList[3].children[2].children[0].id).toBe('000006')
expect(folderList[3].children[2].children[0].children).toBeUndefined()
expect(folderList[3].children[2].children[1].name).toBe('CBA')
expect(folderList[3].children[2].children[1].id).toBe('000007')
expect(folderList[3].children[2].children[1].children).toBeUndefined()
expect(folderList[3].children[2].children[2].name).toBe('CBB')
expect(folderList[3].children[2].children[2].id).toBe('000008')
expect(folderList[3].children[2].children[2].children).toBeUndefined()
expect(folderList[4].name).toBe('D')
expect(folderList[4].id).toBe('D')
expect(folderList[4].children.length).toBe(1)
expect(folderList[4].children[0].name).toBe('D[A')
expect(folderList[4].children[0].id).toBe('D/D[A')
expect(folderList[4].children[0].children[0].name).toBe('DA]B')
expect(folderList[4].children[0].children[0].id).toBe('000009')
expect(folderList[4].children[0].children[0].children).toBeUndefined()
})
})

View file

@ -12,37 +12,37 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('NotenameCtrl', NotenameCtrl);
angular.module('zeppelinWebApp').controller('NotenameCtrl', NotenameCtrl)
function NotenameCtrl ($scope, noteListDataFactory, $routeParams, websocketMsgSrv) {
'ngInject';
'ngInject'
let vm = this;
vm.clone = false;
vm.notes = noteListDataFactory;
vm.websocketMsgSrv = websocketMsgSrv;
$scope.note = {};
$scope.interpreterSettings = {};
$scope.note.defaultInterpreter = null;
let vm = this
vm.clone = false
vm.notes = noteListDataFactory
vm.websocketMsgSrv = websocketMsgSrv
$scope.note = {}
$scope.interpreterSettings = {}
$scope.note.defaultInterpreter = null
vm.createNote = function () {
if (!vm.clone) {
let defaultInterpreterId = '';
let defaultInterpreterId = ''
if ($scope.note.defaultInterpreter !== null) {
defaultInterpreterId = $scope.note.defaultInterpreter.id;
defaultInterpreterId = $scope.note.defaultInterpreter.id
}
vm.websocketMsgSrv.createNotebook($scope.note.notename, defaultInterpreterId);
$scope.note.defaultInterpreter = $scope.interpreterSettings[0];
vm.websocketMsgSrv.createNotebook($scope.note.notename, defaultInterpreterId)
$scope.note.defaultInterpreter = $scope.interpreterSettings[0]
} else {
let noteId = $routeParams.noteId;
vm.websocketMsgSrv.cloneNote(noteId, $scope.note.notename);
let noteId = $routeParams.noteId
vm.websocketMsgSrv.cloneNote(noteId, $scope.note.notename)
}
};
}
vm.handleNameEnter = function () {
angular.element('#noteNameModal').modal('toggle');
vm.createNote();
};
angular.element('#noteNameModal').modal('toggle')
vm.createNote()
}
vm.preVisible = function(clone, sourceNoteName, path) {
vm.clone = clone;
@ -54,11 +54,11 @@ function NotenameCtrl ($scope, noteListDataFactory, $routeParams, websocketMsgSr
vm.newNoteName = function(path) {
var newCount = 1;
angular.forEach(vm.notes.flatList, function (noteName) {
noteName = noteName.name;
noteName = noteName.name
if (noteName.match(/^Untitled Note [0-9]*$/)) {
let lastCount = noteName.substr(14) * 1;
let lastCount = noteName.substr(14) * 1
if (newCount <= lastCount) {
newCount = lastCount + 1;
newCount = lastCount + 1
}
}
});
@ -66,39 +66,39 @@ function NotenameCtrl ($scope, noteListDataFactory, $routeParams, websocketMsgSr
};
vm.cloneNoteName = function () {
let copyCount = 1;
let newCloneName = '';
let lastIndex = vm.sourceNoteName.lastIndexOf(' ');
let endsWithNumber = !!vm.sourceNoteName.match('^.+?\\s\\d$');
let noteNamePrefix = endsWithNumber ? vm.sourceNoteName.substr(0, lastIndex) : vm.sourceNoteName;
let regexp = new RegExp('^' + noteNamePrefix + ' .+');
let copyCount = 1
let newCloneName = ''
let lastIndex = vm.sourceNoteName.lastIndexOf(' ')
let endsWithNumber = !!vm.sourceNoteName.match('^.+?\\s\\d$')
let noteNamePrefix = endsWithNumber ? vm.sourceNoteName.substr(0, lastIndex) : vm.sourceNoteName
let regexp = new RegExp('^' + noteNamePrefix + ' .+')
angular.forEach(vm.notes.flatList, function (noteName) {
noteName = noteName.name;
noteName = noteName.name
if (noteName.match(regexp)) {
let lastCopyCount = noteName.substr(lastIndex).trim();
newCloneName = noteNamePrefix;
lastCopyCount = parseInt(lastCopyCount);
let lastCopyCount = noteName.substr(lastIndex).trim()
newCloneName = noteNamePrefix
lastCopyCount = parseInt(lastCopyCount)
if (copyCount <= lastCopyCount) {
copyCount = lastCopyCount + 1;
copyCount = lastCopyCount + 1
}
}
});
})
if (!newCloneName) {
newCloneName = vm.sourceNoteName;
newCloneName = vm.sourceNoteName
}
return newCloneName + ' ' + copyCount;
};
return newCloneName + ' ' + copyCount
}
vm.getInterpreterSettings = function () {
vm.websocketMsgSrv.getInterpreterSettings();
};
vm.websocketMsgSrv.getInterpreterSettings()
}
$scope.$on('interpreterSettings', function (event, data) {
$scope.interpreterSettings = data.interpreterSettings;
$scope.interpreterSettings = data.interpreterSettings
// initialize default interpreter with Spark interpreter
$scope.note.defaultInterpreter = data.interpreterSettings[0];
});
$scope.note.defaultInterpreter = data.interpreterSettings[0]
})
}

View file

@ -1,18 +1,18 @@
describe('Controller: NotenameCtrl', function () {
beforeEach(angular.mock.module('zeppelinWebApp'));
beforeEach(angular.mock.module('zeppelinWebApp'))
let scope;
let ctrl;
let noteList;
let scope
let ctrl
let noteList
beforeEach(inject(function ($injector, $rootScope, $controller) {
noteList = $injector.get('noteListDataFactory');
scope = $rootScope.$new();
noteList = $injector.get('noteListDataFactory')
scope = $rootScope.$new()
ctrl = $controller('NotenameCtrl', {
$scope: scope,
noteListDataFactory: noteList
});
}));
})
}))
it('should create a new name from current name when cloneNoteName is called', function () {
let notesList = [
@ -21,19 +21,19 @@ describe('Controller: NotenameCtrl', function () {
{name: 'test name', id: '3'},
{name: 'aa bb cc', id: '4'},
{name: 'Untitled Note 6', id: '4'}
];
]
noteList.setNotes(notesList);
noteList.setNotes(notesList)
ctrl.sourceNoteName = 'test name';
expect(ctrl.cloneNoteName()).toEqual('test name 1');
ctrl.sourceNoteName = 'aa bb cc';
expect(ctrl.cloneNoteName()).toEqual('aa bb cc 1');
ctrl.sourceNoteName = 'Untitled Note 6';
expect(ctrl.cloneNoteName()).toEqual('Untitled Note 7');
ctrl.sourceNoteName = 'My_note';
expect(ctrl.cloneNoteName()).toEqual('My_note 1');
ctrl.sourceNoteName = 'dsds 2';
expect(ctrl.cloneNoteName()).toEqual('dsds 3');
});
});
ctrl.sourceNoteName = 'test name'
expect(ctrl.cloneNoteName()).toEqual('test name 1')
ctrl.sourceNoteName = 'aa bb cc'
expect(ctrl.cloneNoteName()).toEqual('aa bb cc 1')
ctrl.sourceNoteName = 'Untitled Note 6'
expect(ctrl.cloneNoteName()).toEqual('Untitled Note 7')
ctrl.sourceNoteName = 'My_note'
expect(ctrl.cloneNoteName()).toEqual('My_note 1')
ctrl.sourceNoteName = 'dsds 2'
expect(ctrl.cloneNoteName()).toEqual('dsds 3')
})
})

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('modalvisible', modalvisible);
angular.module('zeppelinWebApp').directive('modalvisible', modalvisible)
function modalvisible () {
return {
@ -24,8 +24,8 @@ function modalvisible () {
},
link: function (scope, element, attrs) {
// Add some listeners
let previsibleMethod = scope.preVisibleCallback;
let postVisibleMethod = scope.postVisibleCallback;
let previsibleMethod = scope.preVisibleCallback
let postVisibleMethod = scope.postVisibleCallback
element.on('show.bs.modal', function (e) {
var relatedTarget = angular.element(e.relatedTarget);
var clone = relatedTarget.data('clone');
@ -36,10 +36,10 @@ function modalvisible () {
});
element.on('shown.bs.modal', function (e) {
if (scope.targetinput) {
angular.element(e.target).find('input#' + scope.targetinput).select();
angular.element(e.target).find('input#' + scope.targetinput).select()
}
postVisibleMethod();
});
postVisibleMethod()
})
}
};
}
}

View file

@ -12,74 +12,74 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('NoteImportCtrl', NoteImportCtrl);
angular.module('zeppelinWebApp').controller('NoteImportCtrl', NoteImportCtrl)
function NoteImportCtrl ($scope, $timeout, websocketMsgSrv) {
'ngInject';
'ngInject'
let vm = this;
$scope.note = {};
$scope.note.step1 = true;
$scope.note.step2 = false;
$scope.maxLimit = '';
let limit = 0;
let vm = this
$scope.note = {}
$scope.note.step1 = true
$scope.note.step2 = false
$scope.maxLimit = ''
let limit = 0
websocketMsgSrv.listConfigurations();
websocketMsgSrv.listConfigurations()
$scope.$on('configurationsInfo', function (scope, event) {
limit = event.configurations['zeppelin.websocket.max.text.message.size'];
$scope.maxLimit = Math.round(limit / 1048576);
});
limit = event.configurations['zeppelin.websocket.max.text.message.size']
$scope.maxLimit = Math.round(limit / 1048576)
})
vm.resetFlags = function () {
$scope.note = {};
$scope.note.step1 = true;
$scope.note.step2 = false;
angular.element('#noteImportFile').val('');
};
$scope.note = {}
$scope.note.step1 = true
$scope.note.step2 = false
angular.element('#noteImportFile').val('')
}
$scope.uploadFile = function () {
angular.element('#noteImportFile').click();
};
angular.element('#noteImportFile').click()
}
$scope.importFile = function (element) {
$scope.note.errorText = '';
$scope.note.importFile = element.files[0];
let file = $scope.note.importFile;
let reader = new FileReader();
$scope.note.errorText = ''
$scope.note.importFile = element.files[0]
let file = $scope.note.importFile
let reader = new FileReader()
if (file.size > limit) {
$scope.note.errorText = 'File size limit Exceeded!';
$scope.$apply();
return;
$scope.note.errorText = 'File size limit Exceeded!'
$scope.$apply()
return
}
reader.onloadend = function () {
vm.processImportJson(reader.result);
};
vm.processImportJson(reader.result)
}
if (file) {
reader.readAsText(file);
reader.readAsText(file)
}
};
}
$scope.uploadURL = function () {
$scope.note.errorText = '';
$scope.note.step1 = false;
$scope.note.errorText = ''
$scope.note.step1 = false
$timeout(function () {
$scope.note.step2 = true;
}, 400);
};
$scope.note.step2 = true
}, 400)
}
vm.importBack = function () {
$scope.note.errorText = '';
$scope.note.errorText = ''
$timeout(function () {
$scope.note.step1 = true;
}, 400);
$scope.note.step2 = false;
};
$scope.note.step1 = true
}, 400)
$scope.note.step2 = false
}
vm.importNote = function () {
$scope.note.errorText = '';
$scope.note.errorText = ''
if ($scope.note.importUrl) {
jQuery.ajax({
url: $scope.note.importUrl,
@ -90,47 +90,47 @@ function NoteImportCtrl ($scope, $timeout, websocketMsgSrv) {
withCredentials: false
},
error: function (xhr, ajaxOptions, thrownError) {
$scope.note.errorText = 'Unable to Fetch URL';
$scope.$apply();
$scope.note.errorText = 'Unable to Fetch URL'
$scope.$apply()
}}).done(function (data) {
vm.processImportJson(data);
});
vm.processImportJson(data)
})
} else {
$scope.note.errorText = 'Enter URL';
$scope.$apply();
$scope.note.errorText = 'Enter URL'
$scope.$apply()
}
};
}
vm.processImportJson = function (result) {
if (typeof result !== 'object') {
try {
result = JSON.parse(result);
result = JSON.parse(result)
} catch (e) {
$scope.note.errorText = 'JSON parse exception';
$scope.$apply();
return;
$scope.note.errorText = 'JSON parse exception'
$scope.$apply()
return
}
}
if (result.paragraphs && result.paragraphs.length > 0) {
if (!$scope.note.noteImportName) {
$scope.note.noteImportName = result.name;
$scope.note.noteImportName = result.name
} else {
result.name = $scope.note.noteImportName;
result.name = $scope.note.noteImportName
}
websocketMsgSrv.importNote(result);
websocketMsgSrv.importNote(result)
// angular.element('#noteImportModal').modal('hide');
} else {
$scope.note.errorText = 'Invalid JSON';
$scope.note.errorText = 'Invalid JSON'
}
$scope.$apply();
};
$scope.$apply()
}
/*
** $scope.$on functions below
*/
$scope.$on('setNoteMenu', function (event, notes) {
vm.resetFlags();
angular.element('#noteImportModal').modal('hide');
});
vm.resetFlags()
angular.element('#noteImportModal').modal('hide')
})
}

View file

@ -12,28 +12,28 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('noteVarShareService', noteVarShareService);
angular.module('zeppelinWebApp').service('noteVarShareService', noteVarShareService)
function noteVarShareService () {
'ngInject';
'ngInject'
let store = {};
let store = {}
this.clear = function () {
store = {};
};
store = {}
}
this.put = function (key, value) {
store[key] = value;
};
store[key] = value
}
this.get = function (key) {
return store[key];
};
return store[key]
}
this.del = function (key) {
let v = store[key];
delete store[key];
return v;
};
let v = store[key]
delete store[key]
return v
}
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('popoverHtmlUnsafePopup', popoverHtmlUnsafePopup);
angular.module('zeppelinWebApp').directive('popoverHtmlUnsafePopup', popoverHtmlUnsafePopup)
function popoverHtmlUnsafePopup () {
return {
@ -20,5 +20,5 @@ function popoverHtmlUnsafePopup () {
replace: true,
scope: {title: '@', content: '@', placement: '@', animation: '&', isOpen: '&'},
templateUrl: 'components/popover-html-unsafe/popover-html-unsafe-popup.html'
};
}
}

View file

@ -12,10 +12,10 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('popoverHtmlUnsafe', popoverHtmlUnsafe);
angular.module('zeppelinWebApp').directive('popoverHtmlUnsafe', popoverHtmlUnsafe)
function popoverHtmlUnsafe ($tooltip) {
'ngInject';
'ngInject'
return $tooltip('popoverHtmlUnsafe', 'popover', 'click');
return $tooltip('popoverHtmlUnsafe', 'popover', 'click')
}

View file

@ -12,35 +12,35 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').controller('RenameCtrl', RenameCtrl);
angular.module('zeppelinWebApp').controller('RenameCtrl', RenameCtrl)
function RenameCtrl ($scope) {
'ngInject';
'ngInject'
let self = this;
let self = this
$scope.params = {newName: ''};
$scope.isValid = true;
$scope.params = {newName: ''}
$scope.isValid = true
$scope.rename = function () {
angular.element('#renameModal').modal('hide');
self.callback($scope.params.newName);
};
angular.element('#renameModal').modal('hide')
self.callback($scope.params.newName)
}
$scope.$on('openRenameModal', function (event, options) {
self.validator = options.validator || defaultValidator;
self.callback = options.callback || function () {};
self.validator = options.validator || defaultValidator
self.callback = options.callback || function () {}
$scope.title = options.title || 'Rename';
$scope.params.newName = options.oldName || '';
$scope.title = options.title || 'Rename'
$scope.params.newName = options.oldName || ''
$scope.validate = function () {
$scope.isValid = self.validator($scope.params.newName);
};
$scope.isValid = self.validator($scope.params.newName)
}
angular.element('#renameModal').modal('show');
});
angular.element('#renameModal').modal('show')
})
function defaultValidator (str) {
return !!str.trim();
return !!str.trim()
}
}

View file

@ -12,12 +12,12 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('renameSrv', renameSrv);
angular.module('zeppelinWebApp').service('renameSrv', renameSrv)
function renameSrv ($rootScope) {
'ngInject';
'ngInject'
let self = this;
let self = this
/**
* <options schema>
@ -27,6 +27,6 @@ function renameSrv ($rootScope) {
* validator: (str: string)=>boolean - input validator
*/
self.openRenameModal = function (options) {
$rootScope.$broadcast('openRenameModal', options);
};
$rootScope.$broadcast('openRenameModal', options)
}
}

View file

@ -12,7 +12,7 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').directive('resizable', resizable);
angular.module('zeppelinWebApp').directive('resizable', resizable)
function resizable () {
let resizableConfig = {
@ -20,9 +20,9 @@ function resizable () {
handles: 'se',
helper: 'resizable-helper',
stop: function () {
angular.element(this).css({'width': '100%', 'height': '100%'});
angular.element(this).css({'width': '100%', 'height': '100%'})
}
};
}
return {
restrict: 'A',
@ -32,38 +32,38 @@ function resizable () {
link: function postLink (scope, elem, attrs) {
attrs.$observe('resize', function (resize) {
let resetResize = function (elem, resize) {
let colStep = window.innerWidth / 12;
elem.off('resizestop');
let conf = angular.copy(resizableConfig);
let colStep = window.innerWidth / 12
elem.off('resizestop')
let conf = angular.copy(resizableConfig)
if (resize.graphType === 'TABLE' || resize.graphType === 'TEXT') {
conf.grid = [colStep, 10];
conf.minHeight = 100;
conf.grid = [colStep, 10]
conf.minHeight = 100
} else {
conf.grid = [colStep, 10000];
conf.minHeight = 0;
conf.grid = [colStep, 10000]
conf.minHeight = 0
}
conf.maxWidth = window.innerWidth;
conf.maxWidth = window.innerWidth
elem.resizable(conf);
elem.resizable(conf)
elem.on('resizestop', function () {
if (scope.callback) {
let height = elem.height();
let height = elem.height()
if (height < 50) {
height = 300;
height = 300
}
scope.callback({width: Math.ceil(elem.width() / colStep), height: height});
scope.callback({width: Math.ceil(elem.width() / colStep), height: height})
}
});
};
resize = JSON.parse(resize);
if (resize.allowresize === 'true') {
resetResize(elem, resize);
angular.element(window).resize(function () {
resetResize(elem, resize);
});
})
}
});
resize = JSON.parse(resize)
if (resize.allowresize === 'true') {
resetResize(elem, resize)
angular.element(window).resize(function () {
resetResize(elem, resize)
})
}
})
}
};
}
}

View file

@ -12,40 +12,40 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('saveAsService', saveAsService);
angular.module('zeppelinWebApp').service('saveAsService', saveAsService)
function saveAsService (browserDetectService) {
'ngInject';
'ngInject'
this.saveAs = function (content, filename, extension) {
let BOM = '\uFEFF';
let BOM = '\uFEFF'
if (browserDetectService.detectIE()) {
angular.element('body').append('<iframe id="SaveAsId" style="display: none"></iframe>');
let frameSaveAs = angular.element('body > iframe#SaveAsId')[0].contentWindow;
content = BOM + content;
frameSaveAs.document.open('text/json', 'replace');
frameSaveAs.document.write(content);
frameSaveAs.document.close();
frameSaveAs.focus();
let t1 = Date.now();
frameSaveAs.document.execCommand('SaveAs', false, filename + '.' + extension);
let t2 = Date.now();
angular.element('body').append('<iframe id="SaveAsId" style="display: none"></iframe>')
let frameSaveAs = angular.element('body > iframe#SaveAsId')[0].contentWindow
content = BOM + content
frameSaveAs.document.open('text/json', 'replace')
frameSaveAs.document.write(content)
frameSaveAs.document.close()
frameSaveAs.focus()
let t1 = Date.now()
frameSaveAs.document.execCommand('SaveAs', false, filename + '.' + extension)
let t2 = Date.now()
// This means, this version of IE dosen't support auto download of a file with extension provided in param
// falling back to ".txt"
if (t1 === t2) {
frameSaveAs.document.execCommand('SaveAs', true, filename + '.txt');
frameSaveAs.document.execCommand('SaveAs', true, filename + '.txt')
}
angular.element('body > iframe#SaveAsId').remove();
angular.element('body > iframe#SaveAsId').remove()
} else {
content = 'data:image/svg;charset=utf-8,' + BOM + encodeURIComponent(content);
angular.element('body').append('<a id="SaveAsId"></a>');
let saveAsElement = angular.element('body > a#SaveAsId');
saveAsElement.attr('href', content);
saveAsElement.attr('download', filename + '.' + extension);
saveAsElement.attr('target', '_blank');
saveAsElement[0].click();
saveAsElement.remove();
content = 'data:image/svg;charset=utf-8,' + BOM + encodeURIComponent(content)
angular.element('body').append('<a id="SaveAsId"></a>')
let saveAsElement = angular.element('body > a#SaveAsId')
saveAsElement.attr('href', content)
saveAsElement.attr('download', filename + '.' + extension)
saveAsElement.attr('target', '_blank')
saveAsElement[0].click()
saveAsElement.remove()
}
};
}
}

View file

@ -12,22 +12,22 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('searchService', searchService);
angular.module('zeppelinWebApp').service('searchService', searchService)
function searchService ($resource, baseUrlSrv) {
'ngInject';
'ngInject'
this.search = function (term) {
this.searchTerm = term.q;
console.log('Searching for: %o', term.q);
this.searchTerm = term.q
console.log('Searching for: %o', term.q)
if (!term.q) { // TODO(bzz): empty string check
return;
return
}
let encQuery = window.encodeURIComponent(term.q);
let encQuery = window.encodeURIComponent(term.q)
return $resource(baseUrlSrv.getRestApiBase() + '/notebook/search?q=' + encQuery, {}, {
query: {method: 'GET'}
});
};
})
}
this.searchTerm = '';
this.searchTerm = ''
}

View file

@ -12,91 +12,91 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').factory('websocketEvents', websocketEvents);
angular.module('zeppelinWebApp').factory('websocketEvents', websocketEvents)
function websocketEvents ($rootScope, $websocket, $location, baseUrlSrv) {
'ngInject';
'ngInject'
let websocketCalls = {};
let pingIntervalId;
let websocketCalls = {}
let pingIntervalId
websocketCalls.ws = $websocket(baseUrlSrv.getWebsocketUrl());
websocketCalls.ws.reconnectIfNotNormalClose = true;
websocketCalls.ws = $websocket(baseUrlSrv.getWebsocketUrl())
websocketCalls.ws.reconnectIfNotNormalClose = true
websocketCalls.ws.onOpen(function () {
console.log('Websocket created');
$rootScope.$broadcast('setConnectedStatus', true);
console.log('Websocket created')
$rootScope.$broadcast('setConnectedStatus', true)
pingIntervalId = setInterval(function () {
websocketCalls.sendNewEvent({op: 'PING'});
}, 10000);
});
websocketCalls.sendNewEvent({op: 'PING'})
}, 10000)
})
websocketCalls.sendNewEvent = function (data) {
if ($rootScope.ticket !== undefined) {
data.principal = $rootScope.ticket.principal;
data.ticket = $rootScope.ticket.ticket;
data.roles = $rootScope.ticket.roles;
data.principal = $rootScope.ticket.principal
data.ticket = $rootScope.ticket.ticket
data.roles = $rootScope.ticket.roles
} else {
data.principal = '';
data.ticket = '';
data.roles = '';
data.principal = ''
data.ticket = ''
data.roles = ''
}
console.log('Send >> %o, %o, %o, %o, %o', data.op, data.principal, data.ticket, data.roles, data);
websocketCalls.ws.send(JSON.stringify(data));
};
console.log('Send >> %o, %o, %o, %o, %o', data.op, data.principal, data.ticket, data.roles, data)
websocketCalls.ws.send(JSON.stringify(data))
}
websocketCalls.isConnected = function () {
return (websocketCalls.ws.socket.readyState === 1);
};
return (websocketCalls.ws.socket.readyState === 1)
}
websocketCalls.ws.onMessage(function (event) {
let payload;
let payload
if (event.data) {
payload = angular.fromJson(event.data);
payload = angular.fromJson(event.data)
}
console.log('Receive Json << %o', event.data)
console.log('Receive << %o, %o', payload.op, payload);
let op = payload.op;
let data = payload.data;
if (op === 'NOTE') {
$rootScope.$broadcast('setNoteContent', data.note);
$rootScope.$broadcast('setNoteContent', data.note)
} else if (op === 'NEW_NOTE') {
$location.path('/notebook/' + data.note.id);
$location.path('/notebook/' + data.note.id)
} else if (op === 'NOTES_INFO') {
$rootScope.$broadcast('setNoteMenu', data.notes);
$rootScope.$broadcast('setNoteMenu', data.notes)
} else if (op === 'LIST_NOTE_JOBS') {
$rootScope.$broadcast('setNoteJobs', data.noteJobs);
$rootScope.$broadcast('setNoteJobs', data.noteJobs)
} else if (op === 'LIST_UPDATE_NOTE_JOBS') {
$rootScope.$broadcast('setUpdateNoteJobs', data.noteRunningJobs);
$rootScope.$broadcast('setUpdateNoteJobs', data.noteRunningJobs)
} else if (op === 'AUTH_INFO') {
let btn = [];
let btn = []
if ($rootScope.ticket.roles === '[]') {
btn = [{
label: 'Close',
action: function (dialog) {
dialog.close();
dialog.close()
}
}];
}]
} else {
btn = [{
label: 'Login',
action: function (dialog) {
dialog.close();
dialog.close()
angular.element('#loginModal').modal({
show: 'true'
});
})
}
}, {
label: 'Cancel',
action: function (dialog) {
dialog.close();
dialog.close()
// using $rootScope.apply to trigger angular digest cycle
// changing $location.path inside bootstrap modal wont trigger digest
$rootScope.$apply(function () {
$location.path('/');
});
$location.path('/')
})
}
}];
}]
}
BootstrapDialog.show({
@ -106,39 +106,39 @@ function websocketEvents ($rootScope, $websocket, $location, baseUrlSrv) {
title: 'Insufficient privileges',
message: data.info.toString(),
buttons: btn
});
})
} else if (op === 'PARAGRAPH') {
$rootScope.$broadcast('updateParagraph', data);
$rootScope.$broadcast('updateParagraph', data)
} else if (op === 'RUN_PARAGRAPH_USING_SPELL') {
$rootScope.$broadcast('runParagraphUsingSpell', data);
$rootScope.$broadcast('runParagraphUsingSpell', data)
} else if (op === 'PARAGRAPH_APPEND_OUTPUT') {
$rootScope.$broadcast('appendParagraphOutput', data);
$rootScope.$broadcast('appendParagraphOutput', data)
} else if (op === 'PARAGRAPH_UPDATE_OUTPUT') {
$rootScope.$broadcast('updateParagraphOutput', data);
$rootScope.$broadcast('updateParagraphOutput', data)
} else if (op === 'PROGRESS') {
$rootScope.$broadcast('updateProgress', data);
$rootScope.$broadcast('updateProgress', data)
} else if (op === 'COMPLETION_LIST') {
$rootScope.$broadcast('completionList', data);
$rootScope.$broadcast('completionList', data)
} else if (op === 'EDITOR_SETTING') {
$rootScope.$broadcast('editorSetting', data);
$rootScope.$broadcast('editorSetting', data)
} else if (op === 'ANGULAR_OBJECT_UPDATE') {
$rootScope.$broadcast('angularObjectUpdate', data);
$rootScope.$broadcast('angularObjectUpdate', data)
} else if (op === 'ANGULAR_OBJECT_REMOVE') {
$rootScope.$broadcast('angularObjectRemove', data);
$rootScope.$broadcast('angularObjectRemove', data)
} else if (op === 'APP_APPEND_OUTPUT') {
$rootScope.$broadcast('appendAppOutput', data);
$rootScope.$broadcast('appendAppOutput', data)
} else if (op === 'APP_UPDATE_OUTPUT') {
$rootScope.$broadcast('updateAppOutput', data);
$rootScope.$broadcast('updateAppOutput', data)
} else if (op === 'APP_LOAD') {
$rootScope.$broadcast('appLoad', data);
$rootScope.$broadcast('appLoad', data)
} else if (op === 'APP_STATUS_CHANGE') {
$rootScope.$broadcast('appStatusChange', data);
$rootScope.$broadcast('appStatusChange', data)
} else if (op === 'LIST_REVISION_HISTORY') {
$rootScope.$broadcast('listRevisionHistory', data);
$rootScope.$broadcast('listRevisionHistory', data)
} else if (op === 'NOTE_REVISION') {
$rootScope.$broadcast('noteRevision', data);
$rootScope.$broadcast('noteRevision', data)
} else if (op === 'INTERPRETER_BINDINGS') {
$rootScope.$broadcast('interpreterBindings', data);
$rootScope.$broadcast('interpreterBindings', data)
} else if (op === 'ERROR_INFO') {
BootstrapDialog.show({
closable: false,
@ -150,46 +150,46 @@ function websocketEvents ($rootScope, $websocket, $location, baseUrlSrv) {
// close all the dialogs when there are error on running all paragraphs
label: 'Close',
action: function () {
BootstrapDialog.closeAll();
BootstrapDialog.closeAll()
}
}]
});
})
} else if (op === 'SESSION_LOGOUT') {
$rootScope.$broadcast('session_logout', data);
$rootScope.$broadcast('session_logout', data)
} else if (op === 'CONFIGURATIONS_INFO') {
$rootScope.$broadcast('configurationsInfo', data);
$rootScope.$broadcast('configurationsInfo', data)
} else if (op === 'INTERPRETER_SETTINGS') {
$rootScope.$broadcast('interpreterSettings', data);
$rootScope.$broadcast('interpreterSettings', data)
} else if (op === 'PARAGRAPH_ADDED') {
$rootScope.$broadcast('addParagraph', data.paragraph, data.index);
$rootScope.$broadcast('addParagraph', data.paragraph, data.index)
} else if (op === 'PARAGRAPH_REMOVED') {
$rootScope.$broadcast('removeParagraph', data.id);
$rootScope.$broadcast('removeParagraph', data.id)
} else if (op === 'PARAGRAPH_MOVED') {
$rootScope.$broadcast('moveParagraph', data.id, data.index);
$rootScope.$broadcast('moveParagraph', data.id, data.index)
} else if (op === 'NOTE_UPDATED') {
$rootScope.$broadcast('updateNote', data.name, data.config, data.info);
$rootScope.$broadcast('updateNote', data.name, data.config, data.info)
} else if (op === 'SET_NOTE_REVISION') {
$rootScope.$broadcast('setNoteRevisionResult', data);
$rootScope.$broadcast('setNoteRevisionResult', data)
} else if (op === 'PARAS_INFO') {
$rootScope.$broadcast('updateParaInfos', data);
$rootScope.$broadcast('updateParaInfos', data)
} else {
console.error(`unknown websocket op: ${op}`);
console.error(`unknown websocket op: ${op}`)
}
});
})
websocketCalls.ws.onError(function (event) {
console.log('error message: ', event);
$rootScope.$broadcast('setConnectedStatus', false);
});
console.log('error message: ', event)
$rootScope.$broadcast('setConnectedStatus', false)
})
websocketCalls.ws.onClose(function (event) {
console.log('close message: ', event);
console.log('close message: ', event)
if (pingIntervalId !== undefined) {
clearInterval(pingIntervalId);
pingIntervalId = undefined;
clearInterval(pingIntervalId)
pingIntervalId = undefined
}
$rootScope.$broadcast('setConnectedStatus', false);
});
$rootScope.$broadcast('setConnectedStatus', false)
})
return websocketCalls;
return websocketCalls
}

View file

@ -12,15 +12,15 @@
* limitations under the License.
*/
angular.module('zeppelinWebApp').service('websocketMsgSrv', websocketMsgSrv);
angular.module('zeppelinWebApp').service('websocketMsgSrv', websocketMsgSrv)
function websocketMsgSrv ($rootScope, websocketEvents) {
'ngInject';
'ngInject'
return {
getHomeNote: function () {
websocketEvents.sendNewEvent({op: 'GET_HOME_NOTE'});
websocketEvents.sendNewEvent({op: 'GET_HOME_NOTE'})
},
createNotebook: function (noteName, defaultInterpreterId) {
@ -30,79 +30,79 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
name: noteName,
defaultInterpreterId: defaultInterpreterId
}
});
})
},
moveNoteToTrash: function (noteId) {
websocketEvents.sendNewEvent({op: 'MOVE_NOTE_TO_TRASH', data: {id: noteId}});
websocketEvents.sendNewEvent({op: 'MOVE_NOTE_TO_TRASH', data: {id: noteId}})
},
moveFolderToTrash: function (folderId) {
websocketEvents.sendNewEvent({op: 'MOVE_FOLDER_TO_TRASH', data: {id: folderId}});
websocketEvents.sendNewEvent({op: 'MOVE_FOLDER_TO_TRASH', data: {id: folderId}})
},
restoreNote: function (noteId) {
websocketEvents.sendNewEvent({op: 'RESTORE_NOTE', data: {id: noteId}});
websocketEvents.sendNewEvent({op: 'RESTORE_NOTE', data: {id: noteId}})
},
restoreFolder: function (folderId) {
websocketEvents.sendNewEvent({op: 'RESTORE_FOLDER', data: {id: folderId}});
websocketEvents.sendNewEvent({op: 'RESTORE_FOLDER', data: {id: folderId}})
},
restoreAll: function () {
websocketEvents.sendNewEvent({op: 'RESTORE_ALL'});
websocketEvents.sendNewEvent({op: 'RESTORE_ALL'})
},
deleteNote: function (noteId) {
websocketEvents.sendNewEvent({op: 'DEL_NOTE', data: {id: noteId}});
websocketEvents.sendNewEvent({op: 'DEL_NOTE', data: {id: noteId}})
},
removeFolder: function (folderId) {
websocketEvents.sendNewEvent({op: 'REMOVE_FOLDER', data: {id: folderId}});
websocketEvents.sendNewEvent({op: 'REMOVE_FOLDER', data: {id: folderId}})
},
emptyTrash: function () {
websocketEvents.sendNewEvent({op: 'EMPTY_TRASH'});
websocketEvents.sendNewEvent({op: 'EMPTY_TRASH'})
},
cloneNote: function (noteIdToClone, newNoteName) {
websocketEvents.sendNewEvent({op: 'CLONE_NOTE', data: {id: noteIdToClone, name: newNoteName}});
websocketEvents.sendNewEvent({op: 'CLONE_NOTE', data: {id: noteIdToClone, name: newNoteName}})
},
getNoteList: function () {
websocketEvents.sendNewEvent({op: 'LIST_NOTES'});
websocketEvents.sendNewEvent({op: 'LIST_NOTES'})
},
reloadAllNotesFromRepo: function () {
websocketEvents.sendNewEvent({op: 'RELOAD_NOTES_FROM_REPO'});
websocketEvents.sendNewEvent({op: 'RELOAD_NOTES_FROM_REPO'})
},
getNote: function (noteId) {
websocketEvents.sendNewEvent({op: 'GET_NOTE', data: {id: noteId}});
websocketEvents.sendNewEvent({op: 'GET_NOTE', data: {id: noteId}})
},
updateNote: function (noteId, noteName, noteConfig) {
websocketEvents.sendNewEvent({op: 'NOTE_UPDATE', data: {id: noteId, name: noteName, config: noteConfig}});
websocketEvents.sendNewEvent({op: 'NOTE_UPDATE', data: {id: noteId, name: noteName, config: noteConfig}})
},
updatePersonalizedMode: function (noteId, modeValue) {
websocketEvents.sendNewEvent({op: 'UPDATE_PERSONALIZED_MODE', data: {id: noteId, personalized: modeValue}});
websocketEvents.sendNewEvent({op: 'UPDATE_PERSONALIZED_MODE', data: {id: noteId, personalized: modeValue}})
},
renameNote: function (noteId, noteName) {
websocketEvents.sendNewEvent({op: 'NOTE_RENAME', data: {id: noteId, name: noteName}});
websocketEvents.sendNewEvent({op: 'NOTE_RENAME', data: {id: noteId, name: noteName}})
},
renameFolder: function (folderId, folderName) {
websocketEvents.sendNewEvent({op: 'FOLDER_RENAME', data: {id: folderId, name: folderName}});
websocketEvents.sendNewEvent({op: 'FOLDER_RENAME', data: {id: folderId, name: folderName}})
},
moveParagraph: function (paragraphId, newIndex) {
websocketEvents.sendNewEvent({op: 'MOVE_PARAGRAPH', data: {id: paragraphId, index: newIndex}});
websocketEvents.sendNewEvent({op: 'MOVE_PARAGRAPH', data: {id: paragraphId, index: newIndex}})
},
insertParagraph: function (newIndex) {
websocketEvents.sendNewEvent({op: 'INSERT_PARAGRAPH', data: {index: newIndex}});
websocketEvents.sendNewEvent({op: 'INSERT_PARAGRAPH', data: {index: newIndex}})
},
copyParagraph: function (newIndex, paragraphTitle, paragraphData,
@ -116,7 +116,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
config: paragraphConfig,
params: paragraphParams
}
});
})
},
updateAngularObject: function (noteId, paragraphId, name, value, interpreterGroupId) {
@ -129,7 +129,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
value: value,
interpreterGroupId: interpreterGroupId
}
});
})
},
clientBindAngularObject: function (noteId, name, value, paragraphId) {
@ -141,7 +141,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
value: value,
paragraphId: paragraphId
}
});
})
},
clientUnbindAngularObject: function (noteId, name, paragraphId) {
@ -152,11 +152,11 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
name: name,
paragraphId: paragraphId
}
});
})
},
cancelParagraphRun: function (paragraphId) {
websocketEvents.sendNewEvent({op: 'CANCEL_PARAGRAPH', data: {id: paragraphId}});
websocketEvents.sendNewEvent({op: 'CANCEL_PARAGRAPH', data: {id: paragraphId}})
},
paragraphExecutedBySpell: function (paragraphId, paragraphTitle,
@ -172,8 +172,8 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
results: {
code: paragraphStatus,
msg: paragraphResultsMsg.map(dataWithType => {
let serializedData = dataWithType.data;
return { type: dataWithType.type, data: serializedData, };
let serializedData = dataWithType.data
return { type: dataWithType.type, data: serializedData, }
})
},
status: paragraphStatus,
@ -181,7 +181,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
config: paragraphConfig,
params: paragraphParams
}
});
})
},
runParagraph: function (paragraphId, paragraphTitle, paragraphData, paragraphConfig, paragraphParams) {
@ -194,7 +194,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
config: paragraphConfig,
params: paragraphParams
}
});
})
},
runAllParagraphs: function (noteId, paragraphs) {
@ -204,19 +204,19 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
noteId: noteId,
paragraphs: JSON.stringify(paragraphs)
}
});
})
},
removeParagraph: function (paragraphId) {
websocketEvents.sendNewEvent({op: 'PARAGRAPH_REMOVE', data: {id: paragraphId}});
websocketEvents.sendNewEvent({op: 'PARAGRAPH_REMOVE', data: {id: paragraphId}})
},
clearParagraphOutput: function (paragraphId) {
websocketEvents.sendNewEvent({op: 'PARAGRAPH_CLEAR_OUTPUT', data: {id: paragraphId}});
websocketEvents.sendNewEvent({op: 'PARAGRAPH_CLEAR_OUTPUT', data: {id: paragraphId}})
},
clearAllParagraphOutput: function (noteId) {
websocketEvents.sendNewEvent({op: 'PARAGRAPH_CLEAR_ALL_OUTPUT', data: {id: noteId}});
websocketEvents.sendNewEvent({op: 'PARAGRAPH_CLEAR_ALL_OUTPUT', data: {id: noteId}})
},
completion: function (paragraphId, buf, cursor) {
@ -227,7 +227,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
buf: buf,
cursor: cursor
}
});
})
},
commitParagraph: function (paragraphId, paragraphTitle, paragraphData, paragraphConfig, paragraphParams) {
@ -240,7 +240,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
config: paragraphConfig,
params: paragraphParams
}
});
})
},
importNote: function (note) {
@ -249,7 +249,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
data: {
note: note
}
});
})
},
checkpointNote: function (noteId, commitMessage) {
@ -259,7 +259,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
noteId: noteId,
commitMessage: commitMessage
}
});
})
},
setNoteRevision: function (noteId, revisionId) {
@ -269,7 +269,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
noteId: noteId,
revisionId: revisionId
}
});
})
},
listRevisionHistory: function (noteId) {
@ -278,7 +278,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
data: {
noteId: noteId
}
});
})
},
getNoteByRevision: function (noteId, revisionId) {
@ -288,7 +288,7 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
noteId: noteId,
revisionId: revisionId
}
});
})
},
getEditorSetting: function (paragraphId, replName) {
@ -298,43 +298,43 @@ function websocketMsgSrv ($rootScope, websocketEvents) {
paragraphId: paragraphId,
magic: replName
}
});
})
},
isConnected: function () {
return websocketEvents.isConnected();
return websocketEvents.isConnected()
},
getNoteJobsList: function () {
websocketEvents.sendNewEvent({op: 'LIST_NOTE_JOBS'});
websocketEvents.sendNewEvent({op: 'LIST_NOTE_JOBS'})
},
getUpdateNoteJobsList: function (lastUpdateServerUnixTime) {
websocketEvents.sendNewEvent(
{op: 'LIST_UPDATE_NOTE_JOBS', data: {lastUpdateUnixTime: lastUpdateServerUnixTime * 1}}
);
)
},
unsubscribeJobManager: function () {
websocketEvents.sendNewEvent({op: 'UNSUBSCRIBE_UPDATE_NOTE_JOBS'});
websocketEvents.sendNewEvent({op: 'UNSUBSCRIBE_UPDATE_NOTE_JOBS'})
},
getInterpreterBindings: function (noteId) {
websocketEvents.sendNewEvent({op: 'GET_INTERPRETER_BINDINGS', data: {noteId: noteId}});
websocketEvents.sendNewEvent({op: 'GET_INTERPRETER_BINDINGS', data: {noteId: noteId}})
},
saveInterpreterBindings: function (noteId, selectedSettingIds) {
websocketEvents.sendNewEvent({op: 'SAVE_INTERPRETER_BINDINGS',
data: {noteId: noteId, selectedSettingIds: selectedSettingIds}});
data: {noteId: noteId, selectedSettingIds: selectedSettingIds}})
},
listConfigurations: function () {
websocketEvents.sendNewEvent({op: 'LIST_CONFIGURATIONS'});
websocketEvents.sendNewEvent({op: 'LIST_CONFIGURATIONS'})
},
getInterpreterSettings: function () {
websocketEvents.sendNewEvent({op: 'GET_INTERPRETER_SETTINGS'});
websocketEvents.sendNewEvent({op: 'GET_INTERPRETER_SETTINGS'})
},
};
}
}

View file

@ -12,65 +12,65 @@
* limitations under the License.
*/
import './app/app.js';
import './app/app.controller.js';
import './app/home/home.controller.js';
import './app/handsontable/handsonHelper.js';
import './app/notebook/notebook.controller.js';
import './app/app.js'
import './app/app.controller.js'
import './app/home/home.controller.js'
import './app/handsontable/handsonHelper.js'
import './app/notebook/notebook.controller.js'
import './app/tabledata/tabledata.js';
import './app/tabledata/transformation.js';
import './app/tabledata/pivot.js';
import './app/tabledata/passthrough.js';
import './app/tabledata/columnselector.js';
import './app/tabledata/advanced-transformation.js';
import './app/visualization/visualization.js';
import './app/visualization/builtins/visualization-table.js';
import './app/visualization/builtins/visualization-nvd3chart.js';
import './app/visualization/builtins/visualization-barchart.js';
import './app/visualization/builtins/visualization-piechart.js';
import './app/visualization/builtins/visualization-areachart.js';
import './app/visualization/builtins/visualization-linechart.js';
import './app/visualization/builtins/visualization-scatterchart.js';
import './app/tabledata/tabledata.js'
import './app/tabledata/transformation.js'
import './app/tabledata/pivot.js'
import './app/tabledata/passthrough.js'
import './app/tabledata/columnselector.js'
import './app/tabledata/advanced-transformation.js'
import './app/visualization/visualization.js'
import './app/visualization/builtins/visualization-table.js'
import './app/visualization/builtins/visualization-nvd3chart.js'
import './app/visualization/builtins/visualization-barchart.js'
import './app/visualization/builtins/visualization-piechart.js'
import './app/visualization/builtins/visualization-areachart.js'
import './app/visualization/builtins/visualization-linechart.js'
import './app/visualization/builtins/visualization-scatterchart.js'
import './app/jobmanager/jobmanager.controller.js';
import './app/jobmanager/jobs/job.controller.js';
import './app/jobmanager/jobmanager.filter.js';
import './app/interpreter/interpreter.controller.js';
import './app/interpreter/interpreter.filter.js';
import './app/credential/credential.controller.js';
import './app/configuration/configuration.controller.js';
import './app/notebook/paragraph/paragraph.controller.js';
import './app/notebook/paragraph/result/result.controller.js';
import './app/search/result-list.controller.js';
import './app/notebookRepos/notebookRepos.controller.js';
import './app/helium';
import './components/arrayOrderingSrv/arrayOrdering.service.js';
import './components/clipboard/clipboard.controller.js';
import './components/navbar/navbar.controller.js';
import './components/ngescape/ngescape.directive.js';
import './components/interpreter/interpreter.directive.js';
import './components/expandCollapse/expandCollapse.directive.js';
import './components/noteName-create/notename.controller.js';
import './components/noteName-import/notenameImport.controller.js';
import './components/popover-html-unsafe/popover-html-unsafe.directive.js';
import './components/popover-html-unsafe/popover-html-unsafe-popup.directive.js';
import './components/editor/codeEditor.directive.js';
import './components/ngenter/ngenter.directive.js';
import './components/dropdowninput/dropdowninput.directive.js';
import './components/resizable/resizable.directive.js';
import './components/noteName-create/visible.directive.js';
import './components/websocketEvents/websocketMsg.service.js';
import './components/websocketEvents/websocketEvents.factory.js';
import './components/noteListDataFactory/noteList.datafactory.js';
import './components/baseUrl/baseUrl.service.js';
import './components/browser-detect/browserDetect.service.js';
import './components/saveAs/saveAs.service.js';
import './components/searchService/search.service.js';
import './components/login/login.controller.js';
import './components/elasticInputCtrl/elasticInput.controller.js';
import './components/noteAction/noteAction.service.js';
import './components/notevarshareService/notevarshare.service.js';
import './components/rename/rename.controller.js';
import './components/rename/rename.service.js';
import './components/helium/helium.service.js';
import './app/jobmanager/jobmanager.controller.js'
import './app/jobmanager/jobs/job.controller.js'
import './app/jobmanager/jobmanager.filter.js'
import './app/interpreter/interpreter.controller.js'
import './app/interpreter/interpreter.filter.js'
import './app/credential/credential.controller.js'
import './app/configuration/configuration.controller.js'
import './app/notebook/paragraph/paragraph.controller.js'
import './app/notebook/paragraph/result/result.controller.js'
import './app/search/result-list.controller.js'
import './app/notebookRepos/notebookRepos.controller.js'
import './app/helium'
import './components/arrayOrderingSrv/arrayOrdering.service.js'
import './components/clipboard/clipboard.controller.js'
import './components/navbar/navbar.controller.js'
import './components/ngescape/ngescape.directive.js'
import './components/interpreter/interpreter.directive.js'
import './components/expandCollapse/expandCollapse.directive.js'
import './components/noteName-create/notename.controller.js'
import './components/noteName-import/notenameImport.controller.js'
import './components/popover-html-unsafe/popover-html-unsafe.directive.js'
import './components/popover-html-unsafe/popover-html-unsafe-popup.directive.js'
import './components/editor/codeEditor.directive.js'
import './components/ngenter/ngenter.directive.js'
import './components/dropdowninput/dropdowninput.directive.js'
import './components/resizable/resizable.directive.js'
import './components/noteName-create/visible.directive.js'
import './components/websocketEvents/websocketMsg.service.js'
import './components/websocketEvents/websocketEvents.factory.js'
import './components/noteListDataFactory/noteList.datafactory.js'
import './components/baseUrl/baseUrl.service.js'
import './components/browser-detect/browserDetect.service.js'
import './components/saveAs/saveAs.service.js'
import './components/searchService/search.service.js'
import './components/login/login.controller.js'
import './components/elasticInputCtrl/elasticInput.controller.js'
import './components/noteAction/noteAction.service.js'
import './components/notevarshareService/notevarshare.service.js'
import './components/rename/rename.controller.js'
import './components/rename/rename.service.js'
import './components/helium/helium.service.js'