You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by ku...@apache.org on 2017/07/14 16:07:08 UTC
[3/5] zeppelin git commit: [ZEPPELIN-2749] Use scalable file
structure for zeppelin web
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/elasticInputCtrl/elasticInput.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/elasticInputCtrl/elasticInput.controller.js b/zeppelin-web/src/components/elasticInputCtrl/elasticInput.controller.js
deleted file mode 100644
index 507b2f6..0000000
--- a/zeppelin-web/src/components/elasticInputCtrl/elasticInput.controller.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-angular.module('zeppelinWebApp').controller('ElasticInputCtrl', ElasticInputCtrl)
-
-function ElasticInputCtrl () {
- let vm = this
- vm.showEditor = false
- vm.value = ''
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/expandCollapse/expandCollapse.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/expandCollapse/expandCollapse.css b/zeppelin-web/src/components/expandCollapse/expandCollapse.css
deleted file mode 100644
index b1a60d8..0000000
--- a/zeppelin-web/src/components/expandCollapse/expandCollapse.css
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- .expandable {
- display: none;
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/expandCollapse/expandCollapse.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/expandCollapse/expandCollapse.directive.js b/zeppelin-web/src/components/expandCollapse/expandCollapse.directive.js
deleted file mode 100644
index c71fae0..0000000
--- a/zeppelin-web/src/components/expandCollapse/expandCollapse.directive.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-angular.module('zeppelinWebApp').directive('expandCollapse', expandCollapse)
-
-function expandCollapse () {
- return {
- restrict: 'EA',
- 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.fa-folder-open').toggleClass('fa-folder fa-folder-open')
- } 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('fa-folder fa-folder-open')
- }
- })
- }
-
- let target = event.target
-
- // add note
- if (target.classList !== undefined && target.classList.contains('fa-plus') &&
- target.tagName.toLowerCase() === 'i') {
- return
- }
-
- event.stopPropagation()
- })
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/filterNoteNames/filter-note-names.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/filterNoteNames/filter-note-names.html b/zeppelin-web/src/components/filterNoteNames/filter-note-names.html
deleted file mode 100644
index 071cba4..0000000
--- a/zeppelin-web/src/components/filterNoteNames/filter-note-names.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<input type="text"
- class="note-name-query form-control"
- ng-click="$event.stopPropagation()"
- placeholder=" Filter"
- ng-model="$parent.query.q"
- ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 300, 'blur': 0 } }" />
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/helium/helium-conf.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/helium/helium-conf.js b/zeppelin-web/src/components/helium/helium-conf.js
deleted file mode 100644
index 10ca18a..0000000
--- a/zeppelin-web/src/components/helium/helium-conf.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-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 = []
-
- for (let name in spec) {
- const specField = spec[name]
- const persistedValue = persisted[name]
-
- const value = (persistedValue) ? persistedValue : specField.defaultValue
- const merged = {
- name: name,
- type: specField.type,
- description: specField.description,
- value: value,
- defaultValue: specField.defaultValue,
- }
-
- confs.push(merged)
- }
-
- return confs
-}
-
-export function createAllPackageConfigs (defaultPackages, persistedConfs) {
- let packageConfs = {}
-
- for (let name in defaultPackages) {
- const pkgSearchResult = defaultPackages[name]
-
- const spec = pkgSearchResult.pkg.config
- if (!spec) { continue }
-
- const artifact = pkgSearchResult.pkg.artifact
- if (!artifact) { continue }
-
- let persistedConf = {}
- if (persistedConfs[artifact]) {
- persistedConf = persistedConfs[artifact]
- }
-
- const confs = mergePersistedConfWithSpec(persistedConf, spec)
- packageConfs[name] = confs
- }
-
- return packageConfs
-}
-
-export function parseConfigValue (type, stringified) {
- let value = stringified
-
- try {
- if (HeliumConfFieldType.NUMBER === type) {
- value = parseFloat(stringified)
- } else if (HeliumConfFieldType.JSON === type) {
- value = JSON.parse(stringified)
- }
- } catch (error) {
- // return just the stringified one
- console.error(`Failed to parse conf type ${type}, value ${value}`)
- }
-
- return value
-}
-
-/**
- * persist key-value only
- * since other info (e.g type, desc) can be provided by default config
- */
-export function createPersistableConfig (currentConfs) {
- const filtered = currentConfs.reduce((acc, c) => {
- acc[c.name] = parseConfigValue(c.type, c.value)
- return acc
- }, {})
-
- return filtered
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/helium/helium-package.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/helium/helium-package.js b/zeppelin-web/src/components/helium/helium-package.js
deleted file mode 100644
index 88d191a..0000000
--- a/zeppelin-web/src/components/helium/helium-package.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-export function createDefaultPackage (pkgSearchResult, sce) {
- for (let pkgIdx in pkgSearchResult) {
- const pkg = pkgSearchResult[pkgIdx]
- pkg.pkg.icon = sce.trustAsHtml(pkg.pkg.icon)
- if (pkg.enabled) {
- 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
-}
-
-/**
- * create default packages based on `enabled` field and `latest` version.
- *
- * @param pkgSearchResults
- * @param sce angular `$sce` object
- * @returns {Object} including {name, pkgInfo}
- */
-export function createDefaultPackages (pkgSearchResults, sce) {
- const defaultPackages = {}
- // show enabled version if any version of package is enabled
- for (let name in pkgSearchResults) {
- const pkgSearchResult = pkgSearchResults[name]
- defaultPackages[name] = createDefaultPackage(pkgSearchResult, sce)
- }
-
- return defaultPackages
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/helium/helium-type.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/helium/helium-type.js b/zeppelin-web/src/components/helium/helium-type.js
deleted file mode 100644
index 27b34fa..0000000
--- a/zeppelin-web/src/components/helium/helium-type.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-export const HeliumType = {
- VISUALIZATION: 'VISUALIZATION',
- SPELL: 'SPELL',
- INTERPRETER: 'INTERPRETER',
- APPLICATION: 'APPLICATION',
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/helium/helium.service.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/helium/helium.service.js b/zeppelin-web/src/components/helium/helium.service.js
deleted file mode 100644
index 46fcc85..0000000
--- a/zeppelin-web/src/components/helium/helium.service.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { HeliumType, } from './helium-type'
-import {
- createAllPackageConfigs,
- createPersistableConfig,
- mergePersistedConfWithSpec,
-} from './helium-conf'
-import {
- createDefaultPackages,
-} from './helium-package'
-
-angular.module('zeppelinWebApp').service('heliumService', heliumService)
-
-export default function heliumService ($http, $sce, baseUrlSrv) {
- 'ngInject'
-
- let visualizationBundles = []
- let visualizationPackageOrder = []
- // name `heliumBundles` should be same as `HeliumBundleFactory.HELIUM_BUNDLES_VAR`
- let heliumBundles = []
- // map for `{ magic: interpreter }`
- let spellPerMagic = {}
- // map for `{ magic: package-name }`
- let pkgNamePerMagic = {}
-
- /**
- * @param magic {string} e.g `%flowchart`
- * @returns {SpellBase} undefined if magic is not registered
- */
- this.getSpellByMagic = function (magic) {
- return spellPerMagic[magic]
- }
-
- this.executeSpell = function (magic, textWithoutMagic) {
- const promisedConf = this.getSinglePackageConfigUsingMagic(magic)
- .then(confs => createPersistableConfig(confs))
-
- return promisedConf.then(conf => {
- const spell = this.getSpellByMagic(magic)
- const spellResult = spell.interpret(textWithoutMagic, conf)
- const parsed = spellResult.getAllParsedDataWithTypes(
- spellPerMagic, magic, textWithoutMagic)
-
- return parsed
- })
- }
-
- this.executeSpellAsDisplaySystem = function (magic, textWithoutMagic) {
- const promisedConf = this.getSinglePackageConfigUsingMagic(magic)
- .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)
-
- return parsed
- })
- }
-
- this.getVisualizationCachedPackages = function () {
- return visualizationBundles
- }
-
- this.getVisualizationCachedPackageOrder = function () {
- return visualizationPackageOrder
- }
-
- /**
- * @returns {Promise} which returns bundleOrder and cache it in `visualizationPackageOrder`
- */
- this.getVisualizationPackageOrder = function () {
- return $http.get(baseUrlSrv.getRestApiBase() + '/helium/order/visualization')
- .then(function (response, status) {
- const order = response.data.body
- visualizationPackageOrder = order
- return order
- })
- .catch(function (error) {
- console.error('Can not get bundle order', error)
- })
- }
-
- this.setVisualizationPackageOrder = function (list) {
- return $http.post(baseUrlSrv.getRestApiBase() + '/helium/order/visualization', list)
- }
-
- this.enable = function (name, artifact) {
- return $http.post(baseUrlSrv.getRestApiBase() + '/helium/enable/' + name, artifact)
- }
-
- this.disable = function (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)
-
- if (!pkgName || !pkgArtifact || !filtered) {
- console.error(
- `Can't save config for helium package '${pkgArtifact}'`, filtered)
- return
- }
-
- const url = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`
- return $http.post(url, filtered)
- .then(() => {
- if (closeConfigPanelCallback) { closeConfigPanelCallback() }
- }).catch((error) => {
- console.error(`Failed to save config for ${pkgArtifact}`, error)
- })
- }
-
- /**
- * @returns {Promise<Object>} which including {name, Array<package info for artifact>}
- */
- this.getAllPackageInfo = function () {
- return $http.get(`${baseUrlSrv.getRestApiBase()}/helium/package`)
- .then(function (response, status) {
- return response.data.body
- })
- .catch(function (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
- })
- .catch(function (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'
- }
-
- 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)
- return '' // empty bundle will be filtered later
- }
-
- return bundle
- })
- .catch(function (error) {
- console.error(`Failed to get single bundle: ${pkgName}`, error)
- })
- }
-
- this.getDefaultPackages = function () {
- return this.getAllPackageInfo()
- .then(pkgSearchResults => {
- return createDefaultPackages(pkgSearchResults, $sce)
- })
- }
-
- this.getAllPackageInfoAndDefaultPackages = function () {
- return this.getAllPackageInfo()
- .then(pkgSearchResults => {
- return {
- pkgSearchResults: pkgSearchResults,
- defaultPackages: createDefaultPackages(pkgSearchResults, $sce),
- }
- })
- }
-
- /**
- * get all package configs.
- * @return { Promise<{name, Array<Object>}> }
- */
- this.getAllPackageConfigs = function () {
- const promisedDefaultPackages = this.getDefaultPackages()
- const promisedPersistedConfs =
- $http.get(`${baseUrlSrv.getRestApiBase()}/helium/config`)
- .then(function (response, status) {
- return response.data.body
- })
-
- return Promise.all([promisedDefaultPackages, promisedPersistedConfs])
- .then(values => {
- const defaultPackages = values[0]
- const persistedConfs = values[1]
-
- return createAllPackageConfigs(defaultPackages, persistedConfs)
- })
- .catch(function (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
- // in case of local package, it will include `/`
- const pkgArtifact = encodeURIComponent(pkg.artifact)
-
- if (!pkgName || !pkgArtifact) {
- console.error('Failed to fetch config for\n', pkg)
- return Promise.resolve([])
- }
-
- const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/config/${pkgName}/${pkgArtifact}`
- const promisedConf = $http.get(confUrl)
- .then(function (response, status) {
- return response.data.body
- })
-
- return promisedConf.then(({confSpec, confPersisted}) => {
- const merged = mergePersistedConfWithSpec(confPersisted, confSpec)
- return merged
- })
- }
-
- this.getSinglePackageConfigUsingMagic = function (magic) {
- const pkgName = pkgNamePerMagic[magic]
-
- const confUrl = `${baseUrlSrv.getRestApiBase()}/helium/spell/config/${pkgName}`
- const promisedConf = $http.get(confUrl)
- .then(function (response, status) {
- return response.data.body
- })
-
- return promisedConf.then(({confSpec, confPersisted}) => {
- const merged = mergePersistedConfWithSpec(confPersisted, confSpec)
- return merged
- })
- }
-
- const p = this.getAllEnabledPackages()
- .then(enabledPackageSearchResults => {
- const promises = enabledPackageSearchResults.map(packageSearchResult => {
- const pkgName = packageSearchResult.pkg.name
- return this.getSingleBundle(pkgName)
- })
-
- return Promise.all(promises)
- })
- .then(bundles => {
- return bundles.reduce((acc, b) => {
- // filter out empty bundle
- if (b === '') { return acc }
- acc.push(b)
- return acc
- }, [])
- })
-
- // load should be promise
- this.load = p.then(availableBundles => {
- // evaluate bundles
- availableBundles.map(b => {
- // eslint-disable-next-line no-eval
- eval(b)
- })
-
- // extract bundles by type
- heliumBundles.map(b => {
- if (b.type === HeliumType.SPELL) {
- const spell = new b.class() // eslint-disable-line new-cap
- const pkgName = b.id
- spellPerMagic[spell.getMagic()] = spell
- pkgNamePerMagic[spell.getMagic()] = pkgName
- } else if (b.type === HeliumType.VISUALIZATION) {
- visualizationBundles.push(b)
- }
- })
- })
-
- this.init = function() {
- this.getVisualizationPackageOrder()
- }
-
- // init
- this.init()
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/interpreter/interpreter.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/interpreter/interpreter.directive.js b/zeppelin-web/src/components/interpreter/interpreter.directive.js
deleted file mode 100644
index 7080760..0000000
--- a/zeppelin-web/src/components/interpreter/interpreter.directive.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-angular.module('zeppelinWebApp').directive('interpreterDirective', interpreterDirective)
-
-function interpreterDirective ($timeout) {
- 'ngInject'
-
- return {
- restrict: 'A',
- link: function (scope, element, attr) {
- if (scope.$last === true) {
- $timeout(function () {
- let id = 'ngRenderFinished'
- scope.$emit(id)
- })
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/interpreter/widget/widget.number.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/interpreter/widget/widget.number.directive.js b/zeppelin-web/src/components/interpreter/widget/widget.number.directive.js
deleted file mode 100644
index 5d66cd1..0000000
--- a/zeppelin-web/src/components/interpreter/widget/widget.number.directive.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-angular.module('zeppelinWebApp').directive('widgetNumber', numericOnly)
-
-function numericOnly() {
- return {
- require: 'ngModel',
- link: function (scope, element, attrs, modelCtrl) {
- modelCtrl.$parsers.push(function (inputValue) {
- let transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g, '') : null
- if (transformedInput !== inputValue) {
- modelCtrl.$setViewValue(transformedInput)
- modelCtrl.$render()
- }
- return transformedInput
- })
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/login/login.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/login/login.html b/zeppelin-web/src/components/login/login.html
index cd3b604..d4a94a6 100644
--- a/zeppelin-web/src/components/login/login.html
+++ b/zeppelin-web/src/components/login/login.html
@@ -17,7 +17,7 @@ limitations under the License.
<div class="modal-dialog">
<!-- Modal content-->
- <div class="modal-content" id="NoteImportCtrl" ng-init="NoteImportInit">
+ <div id="loginModalContent" class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Login</h4>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/modal-shortcut/modal-shortcut.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/modal-shortcut/modal-shortcut.html b/zeppelin-web/src/components/modal-shortcut/modal-shortcut.html
deleted file mode 100644
index 775da4f..0000000
--- a/zeppelin-web/src/components/modal-shortcut/modal-shortcut.html
+++ /dev/null
@@ -1,312 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="shortcut-modal-header">
- <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
- <h4 class="shortcut-modal-title" id="myModalLabel">Keyboard shortcuts</h4>
- </div>
- <div class="table-scroll">
- <table class="table table-shortcut">
- <tr>
- <th style="width:70%">Note Keyboard Shortcuts</th>
- <th></th>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Run paragraph</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Shift</kbd> + <kbd class="kbd-default">Enter</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Cancel</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">C</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move cursor Up</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">P</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move cursor Down</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">N</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Remove paragraph</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">D</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Insert new paragraph above</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">A</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Insert new paragraph below</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">B</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Insert copy of paragraph below</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">Shift</kbd> + <kbd class="kbd-default">C</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move paragraph Up</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">K</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move paragraph Down</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">J</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Enable/Disable run paragraph</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt' }}</kbd> + <kbd class="kbd-default">R</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Toggle output</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">O</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Toggle editor</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">E</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Toggle line number</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">M</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Toggle title</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">T</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Clear output</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">L</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Link this paragraph</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-default">W</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Reduce paragraph width</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">Shift</kbd> + <kbd class="kbd-default">-</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Increase paragraph width</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">Shift</kbd> + <kbd class="kbd-default">+</kbd>
- </div>
- </td>
- </tr>
-
- <tr class="sub-title">
- <th style="width:70%">Editor Keyboard Shortcuts</th>
- <th></th>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Auto-completion</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">.</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Cut the line</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">K</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Paste the line</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">Y</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Search inside the code</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">S</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move cursor to the beginning</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">A</kbd>
- </div>
- </td>
- </tr>
-
- <tr>
- <td>
- <div class="col-md-8">Move cursor at the end</div>
- </td>
- <td>
- <div class="keys">
- <kbd class="kbd-default">Ctrl</kbd> + <kbd class="kbd-default">E</kbd>
- </div>
- </td>
- </tr>
- </table>
- </div>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.css b/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.css
new file mode 100644
index 0000000..b1a60d8
--- /dev/null
+++ b/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.css
@@ -0,0 +1,17 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ .expandable {
+ display: none;
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.directive.js b/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.directive.js
new file mode 100644
index 0000000..95e0681
--- /dev/null
+++ b/zeppelin-web/src/components/navbar/expand-collapse/expand-collapse.directive.js
@@ -0,0 +1,48 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import './expand-collapse.css'
+
+angular.module('zeppelinWebApp').directive('expandCollapse', expandCollapseDirective)
+
+function expandCollapseDirective() {
+ return {
+ restrict: 'EA',
+ 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.fa-folder-open').toggleClass('fa-folder fa-folder-open')
+ } 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('fa-folder fa-folder-open')
+ }
+ })
+ }
+
+ let target = event.target
+
+ // add note
+ if (target.classList !== undefined && target.classList.contains('fa-plus') &&
+ target.tagName.toLowerCase() === 'i') {
+ return
+ }
+
+ event.stopPropagation()
+ })
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/navbar-note-list-elem.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/navbar-note-list-elem.html b/zeppelin-web/src/components/navbar/navbar-note-list-elem.html
new file mode 100644
index 0000000..cb36cfa
--- /dev/null
+++ b/zeppelin-web/src/components/navbar/navbar-note-list-elem.html
@@ -0,0 +1,50 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<a class="notebook-list-item" ng-if="navbar.isFilterNote(node) && !node.children" href="#/notebook/{{node.id}}">
+ <i style="font-size: 10px; margin-right: 5px;" ng-class="query.q && node.isTrash ? 'fa fa-trash-o' : 'icon-doc'" ></i>
+ <span>{{noteName(node)}}</span>
+</a>
+
+<li ng-if="node.children">
+ <expand-collapse>
+ <div ng-mouseenter="showFolderButton=true" ng-mouseleave="showFolderButton=false">
+ <a class="notebook-list-item" href="javascript:void(0)">
+ <div ng-if="node.id !== navbar.TRASH_FOLDER_ID">
+ <i style="font-size: 10px; margin-right: 5px;" class="fa fa-folder"></i>
+ <span>{{noteName(node)}}</span>
+ <i data-toggle="modal" data-target="#noteCreateModal" ng-controller="NoteCreateCtrl as noteCreateCtrl"
+ ng-click="noteCreateCtrl.getInterpreterSettings()" data-path="{{node.id}}"
+ style="font-size: 12px; margin-left: 5px; margin-right: 5px;"
+ ng-show="showFolderButton" class="fa fa-plus"
+ uib-tooltip="Create new note"
+ tooltip-placement="{{calculateTooltipPlacement(node)}}">
+ </i>
+ </div>
+ <div ng-if="node.id === navbar.TRASH_FOLDER_ID">
+ <i style="font-size: 12px; margin-right: 5px;" class="fa fa-trash-o"></i>
+ <span>Trash</span>
+ </div>
+ </a>
+ </div>
+ <div class="expandable" style="color: black;">
+ <ul>
+ <li ng-repeat="node in node.children | orderBy:node:false:navbar.arrayOrderingSrv.noteComparator track by $index"
+ ng-class="{'active' : navbar.isActive(node.id)}"
+ ng-include="'components/navbar/navbar-note-list-elem.html'">
+ </li>
+ </ul>
+ </div>
+ </expand-collapse>
+</li>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/navbar-noteList-elem.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/navbar-noteList-elem.html b/zeppelin-web/src/components/navbar/navbar-noteList-elem.html
deleted file mode 100644
index 6cba04a..0000000
--- a/zeppelin-web/src/components/navbar/navbar-noteList-elem.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<a class="notebook-list-item" ng-if="navbar.isFilterNote(node) && !node.children" href="#/notebook/{{node.id}}">
- <i style="font-size: 10px; margin-right: 5px;" ng-class="query.q && node.isTrash ? 'fa fa-trash-o' : 'icon-doc'" ></i>
- <span>{{noteName(node)}}</span>
-</a>
-
-<li ng-if="node.children">
- <expand-collapse>
- <div ng-mouseenter="showFolderButton=true" ng-mouseleave="showFolderButton=false">
- <a class="notebook-list-item" href="javascript:void(0)">
- <div ng-if="node.id !== navbar.TRASH_FOLDER_ID">
- <i style="font-size: 10px; margin-right: 5px;" class="fa fa-folder"></i>
- <span>{{noteName(node)}}</span>
- <i data-toggle="modal" data-target="#noteNameModal" ng-controller="NotenameCtrl as notenamectrl"
- ng-click="notenamectrl.getInterpreterSettings()" data-path="{{node.id}}"
- style="font-size: 12px; margin-left: 5px; margin-right: 5px;"
- ng-show="showFolderButton" class="fa fa-plus"
- uib-tooltip="Create new note"
- tooltip-placement="{{calculateTooltipPlacement(node)}}">
- </i>
- </div>
- <div ng-if="node.id === navbar.TRASH_FOLDER_ID">
- <i style="font-size: 12px; margin-right: 5px;" class="fa fa-trash-o"></i>
- <span>Trash</span>
- </div>
- </a>
- </div>
- <div class="expandable" style="color: black;">
- <ul>
- <li ng-repeat="node in node.children | orderBy:node:false:navbar.arrayOrderingSrv.noteComparator track by $index"
- ng-class="{'active' : navbar.isActive(node.id)}"
- ng-include="'components/navbar/navbar-noteList-elem.html'">
- </li>
- </ul>
- </div>
- </expand-collapse>
-</li>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/navbar.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/navbar.controller.js b/zeppelin-web/src/components/navbar/navbar.controller.js
index 28a900e..0ac2f18 100644
--- a/zeppelin-web/src/components/navbar/navbar.controller.js
+++ b/zeppelin-web/src/components/navbar/navbar.controller.js
@@ -15,7 +15,7 @@
angular.module('zeppelinWebApp').controller('NavCtrl', NavCtrl)
function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
- noteListDataFactory, baseUrlSrv, websocketMsgSrv,
+ noteListFactory, baseUrlSrv, websocketMsgSrv,
arrayOrderingSrv, searchService, TRASH_FOLDER_ID) {
'ngInject'
@@ -24,7 +24,7 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
vm.connected = websocketMsgSrv.isConnected()
vm.isActive = isActive
vm.logout = logout
- vm.notes = noteListDataFactory
+ vm.notes = noteListFactory
vm.search = search
vm.searchForm = searchService
vm.showLoginWindow = showLoginWindow
@@ -123,7 +123,7 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location,
*/
$scope.$on('setNoteMenu', function (event, notes) {
- noteListDataFactory.setNotes(notes)
+ noteListFactory.setNotes(notes)
initNotebookListEventListener()
})
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/navbar/navbar.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/navbar/navbar.html b/zeppelin-web/src/components/navbar/navbar.html
index d5e6668..597ed51 100644
--- a/zeppelin-web/src/components/navbar/navbar.html
+++ b/zeppelin-web/src/components/navbar/navbar.html
@@ -37,23 +37,23 @@ limitations under the License.
<span>Notebook</span>
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
- <li ng-controller="NotenameCtrl as notenamectrl">
- <a href="" data-toggle="modal" data-target="#noteNameModal" ng-click="notenamectrl.getInterpreterSettings()">
+ <li ng-controller="NoteCreateCtrl as noteCreateCtrl">
+ <a href="" data-toggle="modal" data-target="#noteCreateModal" ng-click="noteCreateCtrl.getInterpreterSettings()">
<i class="fa fa-plus"></i>
Create new note
</a>
</li>
<li class="divider hidden-xs"></li>
<div id="notebook-list" class="scrollbar-container" ng-if="isDrawNavbarNoteList">
- <li class="filter-names" ng-include="'components/filterNoteNames/filter-note-names.html'"></li>
+ <li class="filter-names" ng-include="'components/note-name-filter/note-name-filter.html'"></li>
<div ng-if="!query.q || query.q === ''">
<li ng-repeat="node in navbar.notes.root.children | orderBy:node:false:navbar.arrayOrderingSrv.noteComparator track by node.id"
- ng-class="{'active' : navbar.isActive(node.id)}" ng-include="'components/navbar/navbar-noteList-elem.html'">
+ ng-class="{'active' : navbar.isActive(node.id)}" ng-include="'components/navbar/navbar-note-list-elem.html'">
</li>
</div>
<div ng-if="query.q">
<li ng-repeat="node in navbar.notes.flatList | filter : query.q | orderBy:navbar.arrayOrderingSrv.noteFlatListOrdering track by node.id"
- ng-class="{'active' : navbar.isActive(node.id)}" ng-include="'components/navbar/navbar-noteList-elem.html'">
+ ng-class="{'active' : navbar.isActive(node.id)}" ng-include="'components/navbar/navbar-note-list-elem.html'">
</li>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ng-enter/ng-enter.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ng-enter/ng-enter.directive.js b/zeppelin-web/src/components/ng-enter/ng-enter.directive.js
new file mode 100644
index 0000000..98bc067
--- /dev/null
+++ b/zeppelin-web/src/components/ng-enter/ng-enter.directive.js
@@ -0,0 +1,30 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+angular.module('zeppelinWebApp').directive('ngEnter', NgEnterDirective)
+
+function NgEnterDirective() {
+ return function (scope, element, attrs) {
+ element.bind('keydown keypress', function (event) {
+ if (event.which === 13) {
+ if (!event.shiftKey) {
+ scope.$apply(function () {
+ scope.$eval(attrs.ngEnter)
+ })
+ }
+ event.preventDefault()
+ }
+ })
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ng-enter/ng-enter.directive.test.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ng-enter/ng-enter.directive.test.js b/zeppelin-web/src/components/ng-enter/ng-enter.directive.test.js
new file mode 100644
index 0000000..49f97cc
--- /dev/null
+++ b/zeppelin-web/src/components/ng-enter/ng-enter.directive.test.js
@@ -0,0 +1,24 @@
+describe('Directive: ngEnter', function () {
+ // load the directive's module
+ beforeEach(angular.mock.module('zeppelinWebApp'))
+
+ let element
+ let scope
+
+ beforeEach(inject(function ($rootScope) {
+ 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()
+ }))
+
+ // Test the rest of function in ngEnter
+ /* it('should make hidden element visible', inject(function ($compile) {
+ element = angular.element('<ng-enter></ng-enter>');
+ element = $compile(element)(scope);
+ expect(element.text()).toBe('this is the ngEnter directive');
+ })); */
+})
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ng-escape/ng-escape.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ng-escape/ng-escape.directive.js b/zeppelin-web/src/components/ng-escape/ng-escape.directive.js
new file mode 100644
index 0000000..a3d35ea
--- /dev/null
+++ b/zeppelin-web/src/components/ng-escape/ng-escape.directive.js
@@ -0,0 +1,28 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+angular.module('zeppelinWebApp').directive('ngEscape', NgEscapeDirective)
+
+function NgEscapeDirective() {
+ return function (scope, element, attrs) {
+ element.bind('keydown keyup', function (event) {
+ if (event.which === 27) {
+ scope.$apply(function () {
+ scope.$eval(attrs.ngEscape)
+ })
+ event.preventDefault()
+ }
+ })
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ngenter/ngenter.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ngenter/ngenter.directive.js b/zeppelin-web/src/components/ngenter/ngenter.directive.js
deleted file mode 100644
index 57ec01c..0000000
--- a/zeppelin-web/src/components/ngenter/ngenter.directive.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-angular.module('zeppelinWebApp').directive('ngEnter', ngEnter)
-
-function ngEnter () {
- return function (scope, element, attrs) {
- element.bind('keydown keypress', function (event) {
- if (event.which === 13) {
- if (!event.shiftKey) {
- scope.$apply(function () {
- scope.$eval(attrs.ngEnter)
- })
- }
- event.preventDefault()
- }
- })
- }
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ngenter/ngenter.directive.test.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ngenter/ngenter.directive.test.js b/zeppelin-web/src/components/ngenter/ngenter.directive.test.js
deleted file mode 100644
index 49f97cc..0000000
--- a/zeppelin-web/src/components/ngenter/ngenter.directive.test.js
+++ /dev/null
@@ -1,24 +0,0 @@
-describe('Directive: ngEnter', function () {
- // load the directive's module
- beforeEach(angular.mock.module('zeppelinWebApp'))
-
- let element
- let scope
-
- beforeEach(inject(function ($rootScope) {
- 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()
- }))
-
- // Test the rest of function in ngEnter
- /* it('should make hidden element visible', inject(function ($compile) {
- element = angular.element('<ng-enter></ng-enter>');
- element = $compile(element)(scope);
- expect(element.text()).toBe('this is the ngEnter directive');
- })); */
-})
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/ngescape/ngescape.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/ngescape/ngescape.directive.js b/zeppelin-web/src/components/ngescape/ngescape.directive.js
deleted file mode 100644
index b52a7a7..0000000
--- a/zeppelin-web/src/components/ngescape/ngescape.directive.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-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()
- }
- })
- }
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-action/note-action.service.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-action/note-action.service.js b/zeppelin-web/src/components/note-action/note-action.service.js
new file mode 100644
index 0000000..8e00c0f
--- /dev/null
+++ b/zeppelin-web/src/components/note-action/note-action.service.js
@@ -0,0 +1,183 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+angular.module('zeppelinWebApp').service('noteActionService', noteActionService)
+
+function noteActionService(websocketMsgSrv, $location, noteRenameService, noteListFactory) {
+ 'ngInject'
+
+ this.moveNoteToTrash = function (noteId, redirectToHome) {
+ BootstrapDialog.confirm({
+ closable: true,
+ title: 'Move this note to trash?',
+ message: 'This note will be moved to <strong>trash</strong>.',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.moveNoteToTrash(noteId)
+ if (redirectToHome) {
+ $location.path('/')
+ }
+ }
+ }
+ })
+ }
+
+ this.moveFolderToTrash = function (folderId) {
+ BootstrapDialog.confirm({
+ closable: true,
+ title: 'Move this folder to trash?',
+ message: 'This folder will be moved to <strong>trash</strong>.',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.moveFolderToTrash(folderId)
+ }
+ }
+ })
+ }
+
+ this.removeNote = function (noteId, redirectToHome) {
+ BootstrapDialog.confirm({
+ type: BootstrapDialog.TYPE_WARNING,
+ closable: true,
+ title: 'WARNING! This note will be removed permanently',
+ message: 'This cannot be undone. Are you sure?',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.deleteNote(noteId)
+ if (redirectToHome) {
+ $location.path('/')
+ }
+ }
+ }
+ })
+ }
+
+ this.removeFolder = function (folderId) {
+ BootstrapDialog.confirm({
+ type: BootstrapDialog.TYPE_WARNING,
+ closable: true,
+ title: 'WARNING! This folder will be removed permanently',
+ message: 'This cannot be undone. Are you sure?',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.removeFolder(folderId)
+ }
+ }
+ })
+ }
+
+ this.restoreAll = function () {
+ BootstrapDialog.confirm({
+ closable: true,
+ title: 'Are you sure want to restore all notes in the trash?',
+ message: 'Folders and notes in the trash will be ' +
+ '<strong>merged</strong> into their original position.',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.restoreAll()
+ }
+ }
+ })
+ }
+
+ this.emptyTrash = function () {
+ BootstrapDialog.confirm({
+ type: BootstrapDialog.TYPE_WARNING,
+ closable: true,
+ title: 'WARNING! Notes under trash will be removed permanently',
+ message: 'This cannot be undone. Are you sure?',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.emptyTrash()
+ }
+ }
+ })
+ }
+
+ this.clearAllParagraphOutput = function (noteId) {
+ BootstrapDialog.confirm({
+ closable: true,
+ title: '',
+ message: 'Do you want to clear all output?',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.clearAllParagraphOutput(noteId)
+ }
+ }
+ })
+ }
+
+ this.renameNote = function (noteId, notePath) {
+ noteRenameService.openRenameModal({
+ title: 'Rename note',
+ oldName: notePath,
+ callback: function (newName) {
+ websocketMsgSrv.renameNote(noteId, newName)
+ }
+ })
+ }
+
+ this.renameFolder = function (folderId) {
+ noteRenameService.openRenameModal({
+ title: 'Rename folder',
+ oldName: folderId,
+ callback: function (newName) {
+ let newFolderId = normalizeFolderId(newName)
+ if (_.has(noteListFactory.flatFolderMap, newFolderId)) {
+ BootstrapDialog.confirm({
+ type: BootstrapDialog.TYPE_WARNING,
+ closable: true,
+ title: 'WARNING! The folder will be MERGED',
+ message: 'The folder will be merged into <strong>' + newFolderId + '</strong>. Are you sure?',
+ callback: function (result) {
+ if (result) {
+ websocketMsgSrv.renameFolder(folderId, newFolderId)
+ }
+ }
+ })
+ } else {
+ websocketMsgSrv.renameFolder(folderId, newFolderId)
+ }
+ }
+ })
+ }
+
+ function normalizeFolderId (folderId) {
+ folderId = folderId.trim()
+
+ while (folderId.indexOf('\\') > -1) {
+ folderId = folderId.replace('\\', '/')
+ }
+
+ while (folderId.indexOf('///') > -1) {
+ folderId = folderId.replace('///', '/')
+ }
+
+ folderId = folderId.replace('//', '/')
+
+ if (folderId === '/') {
+ return '/'
+ }
+
+ if (folderId[0] === '/') {
+ folderId = folderId.substring(1)
+ }
+
+ if (folderId.slice(-1) === '/') {
+ folderId = folderId.slice(0, -1)
+ }
+
+ return folderId
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-create/note-create.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-create/note-create.controller.js b/zeppelin-web/src/components/note-create/note-create.controller.js
new file mode 100644
index 0000000..c999c20
--- /dev/null
+++ b/zeppelin-web/src/components/note-create/note-create.controller.js
@@ -0,0 +1,106 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import './note-create.css'
+
+angular.module('zeppelinWebApp').controller('NoteCreateCtrl', NoteCreateCtrl)
+
+function NoteCreateCtrl ($scope, noteListFactory, $routeParams, websocketMsgSrv) {
+ 'ngInject'
+
+ let vm = this
+ vm.clone = false
+ vm.notes = noteListFactory
+ vm.websocketMsgSrv = websocketMsgSrv
+ $scope.note = {}
+ $scope.interpreterSettings = {}
+ $scope.note.defaultInterpreter = null
+
+ vm.createNote = function () {
+ if (!vm.clone) {
+ let defaultInterpreterId = ''
+ if ($scope.note.defaultInterpreter !== null) {
+ defaultInterpreterId = $scope.note.defaultInterpreter.id
+ }
+ 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)
+ }
+ }
+
+ vm.handleNameEnter = function () {
+ angular.element('#noteCreateModal').modal('toggle')
+ vm.createNote()
+ }
+
+ vm.preVisible = function(clone, sourceNoteName, path) {
+ vm.clone = clone
+ vm.sourceNoteName = sourceNoteName
+ $scope.note.notename = vm.clone ? vm.cloneNoteName() : vm.newNoteName(path)
+ $scope.$apply()
+ }
+
+ vm.newNoteName = function(path) {
+ let newCount = 1
+ angular.forEach(vm.notes.flatList, function (noteName) {
+ noteName = noteName.name
+ if (noteName.match(/^Untitled Note [0-9]*$/)) {
+ let lastCount = noteName.substr(14) * 1
+ if (newCount <= lastCount) {
+ newCount = lastCount + 1
+ }
+ }
+ })
+ return (path ? path + '/' : '') + 'Untitled Note ' + newCount
+ }
+
+ 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 + ' .+')
+
+ angular.forEach(vm.notes.flatList, function (noteName) {
+ noteName = noteName.name
+ if (noteName.match(regexp)) {
+ let lastCopyCount = noteName.substr(lastIndex).trim()
+ newCloneName = noteNamePrefix
+ lastCopyCount = parseInt(lastCopyCount)
+ if (copyCount <= lastCopyCount) {
+ copyCount = lastCopyCount + 1
+ }
+ }
+ })
+
+ if (!newCloneName) {
+ newCloneName = vm.sourceNoteName
+ }
+ return newCloneName + ' ' + copyCount
+ }
+
+ vm.getInterpreterSettings = function () {
+ vm.websocketMsgSrv.getInterpreterSettings()
+ }
+
+ $scope.$on('interpreterSettings', function (event, data) {
+ $scope.interpreterSettings = data.interpreterSettings
+
+ // initialize default interpreter with Spark interpreter
+ $scope.note.defaultInterpreter = data.interpreterSettings[0]
+ })
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-create/note-create.controller.test.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-create/note-create.controller.test.js b/zeppelin-web/src/components/note-create/note-create.controller.test.js
new file mode 100644
index 0000000..d409a14
--- /dev/null
+++ b/zeppelin-web/src/components/note-create/note-create.controller.test.js
@@ -0,0 +1,39 @@
+describe('Controller: NoteCreateCtrl', function () {
+ beforeEach(angular.mock.module('zeppelinWebApp'))
+
+ let scope
+ let ctrl
+ let noteList
+
+ beforeEach(inject(function ($injector, $rootScope, $controller) {
+ noteList = $injector.get('noteListFactory')
+ scope = $rootScope.$new()
+ ctrl = $controller('NoteCreateCtrl', {
+ $scope: scope,
+ noteListFactory: noteList
+ })
+ }))
+
+ it('should create a new name from current name when cloneNoteName is called', function () {
+ let notesList = [
+ {name: 'dsds 1', id: '1'},
+ {name: 'dsds 2', id: '2'},
+ {name: 'test name', id: '3'},
+ {name: 'aa bb cc', id: '4'},
+ {name: 'Untitled Note 6', id: '4'}
+ ]
+
+ 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')
+ })
+})
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-create/note-create.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-create/note-create.css b/zeppelin-web/src/components/note-create/note-create.css
new file mode 100644
index 0000000..22249ad
--- /dev/null
+++ b/zeppelin-web/src/components/note-create/note-create.css
@@ -0,0 +1,49 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.modal-header-note-name {
+ background-color: #3071a9;
+ border: 2px solid #3071a9;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+.modal-header-note-name > .modal-title {
+ font-weight: 300;
+ font-size: 20px;
+ color: white;
+}
+
+.modal-header-note-name > .close {
+ color: #cfcfcf;
+ opacity: 1;
+}
+
+.modal-body-note-name label {
+ font-size: 17px;
+ font-weight: 400;
+}
+
+.note-name-create-input {
+ margin-top: 5px;
+}
+
+.note-name-desc-panel {
+ margin-top: 20px;
+ margin-bottom: 4px;
+}
+
+.default-interpreter-select {
+ margin-top: 12px;
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-create/note-create.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-create/note-create.html b/zeppelin-web/src/components/note-create/note-create.html
new file mode 100644
index 0000000..dbfb9e2
--- /dev/null
+++ b/zeppelin-web/src/components/note-create/note-create.html
@@ -0,0 +1,66 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<div id="noteCreateModal" class="modal fade" role="dialog"
+ modalvisible previsiblecallback="noteCreateCtrl.preVisible"
+ targetinput="noteName" tabindex="-1">
+ <div class="modal-dialog">
+
+ <!-- modal content-->
+ <div class="modal-content" id="NoteCreateCtrl">
+ <!-- modal header -->
+ <div class="modal-header modal-header-note-name">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title" ng-show="!noteCreateCtrl.clone">Create New Note</h4>
+ <h4 class="modal-title" ng-show="noteCreateCtrl.clone">Clone Note</h4>
+ </div>
+
+ <!-- modal body-->
+ <div class="modal-body modal-body-note-name">
+ <div class="form-group">
+ <!-- note name -->
+ <div>
+ <label for="noteName">Note Name</label>
+ <input placeholder="Insert Note Name" type="text"
+ class="form-control note-name-create-input"
+ id="noteName" ng-model="note.notename"
+ ng-enter="noteCreateCtrl.handleNameEnter()" />
+ </div>
+ <!-- default interpreter -->
+ <div class="btn-group default-interpreter-select" ng-show="!noteCreateCtrl.clone">
+ <label for="defaultInterpreter">Default Interpreter</label>
+ <select id="defaultInterpreter"
+ name="defaultInterpreter"
+ class="form-control"
+ ng-model="note.defaultInterpreter"
+ ng-options="option.name for option in interpreterSettings">
+ </select>
+ </div>
+ </div> <!-- end: form-group -->
+ <div class="panel panel-default note-name-desc-panel">
+ <div class="panel-heading">
+ Use '/' to create folders. Example: /NoteDirA/Note1
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" id="createNoteButton"
+ class="btn btn-primary"
+ data-dismiss="modal" ng-click="noteCreateCtrl.createNote()">
+ <span ng-show="!noteCreateCtrl.clone">Create</span>
+ <span ng-show="noteCreateCtrl.clone">Clone</span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-create/visible.directive.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-create/visible.directive.js b/zeppelin-web/src/components/note-create/visible.directive.js
new file mode 100644
index 0000000..48c170f
--- /dev/null
+++ b/zeppelin-web/src/components/note-create/visible.directive.js
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+angular.module('zeppelinWebApp').directive('modalvisible', modalvisible)
+
+function modalvisible () {
+ return {
+ restrict: 'A',
+ scope: {
+ preVisibleCallback: '&previsiblecallback',
+ postVisibleCallback: '&postvisiblecallback',
+ targetinput: '@targetinput'
+ },
+ link: function (scope, element, attrs) {
+ // Add some listeners
+ let previsibleMethod = scope.preVisibleCallback
+ let postVisibleMethod = scope.postVisibleCallback
+ element.on('show.bs.modal', function (e) {
+ let relatedTarget = angular.element(e.relatedTarget)
+ let clone = relatedTarget.data('clone')
+ let sourceNoteName = relatedTarget.data('source-note-name')
+ let path = relatedTarget.data('path')
+ let cloneNote = clone ? true : false
+ previsibleMethod()(cloneNote, sourceNoteName, path)
+ })
+ element.on('shown.bs.modal', function (e) {
+ if (scope.targetinput) {
+ angular.element(e.target).find('input#' + scope.targetinput).select()
+ }
+ postVisibleMethod()
+ })
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-import/note-import.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-import/note-import.controller.js b/zeppelin-web/src/components/note-import/note-import.controller.js
new file mode 100644
index 0000000..8cec890
--- /dev/null
+++ b/zeppelin-web/src/components/note-import/note-import.controller.js
@@ -0,0 +1,138 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import './note-import.css'
+
+angular.module('zeppelinWebApp').controller('NoteImportCtrl', NoteImportCtrl)
+
+function NoteImportCtrl ($scope, $timeout, websocketMsgSrv) {
+ 'ngInject'
+
+ let vm = this
+ $scope.note = {}
+ $scope.note.step1 = true
+ $scope.note.step2 = false
+ $scope.maxLimit = ''
+ let limit = 0
+
+ websocketMsgSrv.listConfigurations()
+ $scope.$on('configurationsInfo', function (scope, event) {
+ 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.uploadFile = function () {
+ 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()
+
+ if (file.size > limit) {
+ $scope.note.errorText = 'File size limit Exceeded!'
+ $scope.$apply()
+ return
+ }
+
+ reader.onloadend = function () {
+ vm.processImportJson(reader.result)
+ }
+
+ if (file) {
+ reader.readAsText(file)
+ }
+ }
+
+ $scope.uploadURL = function () {
+ $scope.note.errorText = ''
+ $scope.note.step1 = false
+ $timeout(function () {
+ $scope.note.step2 = true
+ }, 400)
+ }
+
+ vm.importBack = function () {
+ $scope.note.errorText = ''
+ $timeout(function () {
+ $scope.note.step1 = true
+ }, 400)
+ $scope.note.step2 = false
+ }
+
+ vm.importNote = function () {
+ $scope.note.errorText = ''
+ if ($scope.note.importUrl) {
+ jQuery.ajax({
+ url: $scope.note.importUrl,
+ type: 'GET',
+ dataType: 'json',
+ jsonp: false,
+ xhrFields: {
+ withCredentials: false
+ },
+ error: function (xhr, ajaxOptions, thrownError) {
+ $scope.note.errorText = 'Unable to Fetch URL'
+ $scope.$apply()
+ }}).done(function (data) {
+ vm.processImportJson(data)
+ })
+ } else {
+ $scope.note.errorText = 'Enter URL'
+ $scope.$apply()
+ }
+ }
+
+ vm.processImportJson = function (result) {
+ if (typeof result !== 'object') {
+ try {
+ result = JSON.parse(result)
+ } catch (e) {
+ $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
+ } else {
+ result.name = $scope.note.noteImportName
+ }
+ websocketMsgSrv.importNote(result)
+ // angular.element('#noteImportModal').modal('hide');
+ } else {
+ $scope.note.errorText = 'Invalid JSON'
+ }
+ $scope.$apply()
+ }
+
+ /*
+ ** $scope.$on functions below
+ */
+
+ $scope.$on('setNoteMenu', function (event, notes) {
+ vm.resetFlags()
+ angular.element('#noteImportModal').modal('hide')
+ })
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-import/note-import.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-import/note-import.css b/zeppelin-web/src/components/note-import/note-import.css
new file mode 100644
index 0000000..81e276a
--- /dev/null
+++ b/zeppelin-web/src/components/note-import/note-import.css
@@ -0,0 +1,91 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.modal-header-import {
+ background-color: #3071a9;
+ border: 2px solid #3071a9;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+.modal-header-import .close {
+ color: #cfcfcf;
+ opacity: 1;
+}
+
+.modal-header-import .modal-title {
+ color: white;
+ font-size: 20px;
+ font-weight: 300;
+}
+
+.modal-body-import .note-name-input {
+ margin-left: 7px;
+ margin-right: 7px;
+}
+
+.modal-body-import label {
+ font-size: 15px;
+ font-weight: 400;
+ margin-bottom: 10px;
+ margin-top: 15px;
+}
+
+.modal-body-import {
+ min-height: 420px;
+ overflow: hidden;
+}
+
+.modal-body-import .import-btn-image-group {
+ margin-top: 4px;
+}
+
+.modal-body-import .import-btn-image {
+ display: inline-block;
+ margin-left: 8px;
+}
+
+.modal-body-import .import-btn-image a {
+ background: #fff;
+ border: 1px solid #e6e6e6;
+ /*border-radius: 20px;*/
+ border-radius: 20%;
+ color: #7c828e;
+ cursor: pointer;
+ display: block;
+ float: left;
+ font-size: 98px;
+ text-align: center;
+ text-decoration: none;
+ height: 240px;
+ padding-top: 60px;
+ margin: 0 10px 0px 10px;
+ width: 250px;
+}
+
+.modal-body-import .import-btn-image a:hover {
+ background: #eee;
+}
+
+.modal-body-import .modal-body-import-desc {
+ font-size: 15px;
+ font-weight: 400;
+ margin-top: 30px;
+ color: black;
+ font-family: 'Roboto', sans-serif;
+}
+
+.modal-footer-import {
+ min-height: 65px;
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/6bd6c708/zeppelin-web/src/components/note-import/note-import.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/note-import/note-import.html b/zeppelin-web/src/components/note-import/note-import.html
new file mode 100644
index 0000000..848a93b
--- /dev/null
+++ b/zeppelin-web/src/components/note-import/note-import.html
@@ -0,0 +1,80 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<div id="noteImportModal" class="modal fade" role="dialog" tabindex="-1"
+ data-backdrop="static" data-keyboard="false">
+
+ <div class="modal-dialog">
+ <div class="modal-content" id="NoteImportCtrl" ng-init="NoteImportInit">
+
+ <!-- modal-header -->
+ <div class="modal-header modal-header-import">
+ <button type="button" class="close" data-dismiss="modal"
+ ng-click="noteImportCtrl.resetFlags()">×</button>
+ <h4 class="modal-title">Import New Note</h4>
+ </div>
+
+ <!-- modal-body -->
+ <div class="modal-body modal-body-import">
+ <div class="form-group">
+ <label for="noteImportName">Import As</label>
+ <input class="form-control note-name-input" id="noteImportName"
+ placeholder="Insert Note Name" type="text"
+ ng-model="note.noteImportName" />
+ </div>
+
+ <div class="form-group" ng-show="note.errorText">
+ <div class="alert alert-danger">{{note.errorText}}</div>
+ </div>
+
+ <label>JSON file size cannot exceed {{maxLimit}} MB</label>
+
+ <div class="form-group slide-left import-btn-image-group" ng-show="note.step1">
+ <div class="import-btn-image">
+ <a class="fa fa-cloud-upload import-file-upload" ng-click="uploadFile()">
+ <p class="modal-body-import-desc">Select JSON File </p>
+ </a>
+ <div style="display: none">
+ <input class="form-control note-name-input" id="noteImportFile"
+ placeholder="Note name" type="file"
+ ng-model="note.importFile" onchange="angular.element(this).scope().importFile(this)" />
+ </div>
+ </div>
+ <div class="import-btn-image">
+ <a href="javascript:void(0);" ng-click="uploadURL()" class="fa fa-link">
+ <p class="modal-body-import-desc">Add from URL</p>
+ </a>
+ </div>
+ </div>
+
+ <div class="form-group slide-right" ng-show="note.step2">
+
+ <label for="noteImportUrl">URL</label>
+ <input placeholder="Note URL" type="text" class="form-control" id="noteImportUrl"
+ ng-model="note.importUrl" />
+ </div>
+
+ </div>
+ <div class="modal-footer modal-footer-import" ng-show="note.step2">
+ <button type="button" id="importBackButton"
+ class="btn btn-default"
+ ng-click="noteImportCtrl.importBack()">Back
+ </button>
+ <button type="button" id="importNoteButton"
+ class="btn btn-default"
+ ng-click="noteImportCtrl.importNote()">Import Note
+ </button>
+ </div>
+ </div>
+ </div>
+</div>