From: kashalkar Date: Tue, 4 Apr 2017 21:57:18 +0000 (+0200) Subject: Merge "RIFT-15944 - editing an ‘id’ field is troublesome as focus is lost on each... X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FUI.git;a=commitdiff_plain;h=61b1762cb6a657c5a8eb09d52fbf9a35a2a73aff;hp=a74726581355bf8dfa748f340e0632993e2328ed Merge "RIFT-15944 - editing an ‘id’ field is troublesome as focus is lost on each char typed - fixed use of id as html element id - bit of code clean up - made use of knowing when a ‘key’ on a component needs to be unique (only amongst siblings)" --- diff --git a/skyquake/framework/widgets/header/header.jsx b/skyquake/framework/widgets/header/header.jsx index 21f4c10b7..3cfaaf6e2 100644 --- a/skyquake/framework/widgets/header/header.jsx +++ b/skyquake/framework/widgets/header/header.jsx @@ -1,5 +1,5 @@ /* - * + * * Copyright 2016 RIFT.IO Inc * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -55,6 +55,7 @@ export default class AppHeader extends React.Component { type={"error"} hidden={!(this.state.validateErrorEvent && this.state.validateErrorMsg)} onDismiss={HeaderStore.validateReset} + timeout= {5000} /> // html = ( diff --git a/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx b/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx index d53d85f20..d83c83647 100644 --- a/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx +++ b/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx @@ -106,6 +106,7 @@ export default class skyquakeContainer extends React.Component { type={notificationType} hidden={!(displayNotification && notificationMessage)} onDismiss={SkyquakeContainerActions.hideNotification} + timeout= {5000} /> { if (e.keyCode == 13) { - if (this.props.edit) { + if (this.props.params.name != 'create') { this.update(e); } else { this.create(e); diff --git a/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx b/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx index d1e5c9370..ed9ea93a5 100644 --- a/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx +++ b/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx @@ -124,7 +124,7 @@ class FileManager extends React.Component { function buildList(self, data) { let toReturn = []; data.id.map(function(k,i) { - toReturn.push (contentFolder(self, data.data[k], k, i, self.props.filesState, self.updateFileLocationInput, self.sendDownloadFileRequst, self.deleteFile)); + toReturn.push (contentFolder(self, data.data[k], k, k+i, self.props.filesState, self.updateFileLocationInput, self.sendDownloadFileRequst, self.deleteFile)); }); return toReturn.reverse(); } @@ -132,7 +132,8 @@ function buildList(self, data) { function contentFolder(context, folder, path, key, inputState, updateFn, sendDownloadFileRequst, deleteFn) { let type = context.props.type; let id = context.props.item.id; - const onboardDropZone = createDropZone.bind(this, FileManagerUploadDropZone.ACTIONS.onboard, '.ComposerAppAddFile.' + path.replace(/\//g, '-'), type, id, path); + let classId = `DZ-${path.replace(/\/|\s+/g, '-')}`; + const onboardDropZone = createDropZone.bind(this, FileManagerUploadDropZone.ACTIONS.onboard, '.ComposerAppAddFile.' + classId, type, id, path); return (
@@ -170,11 +171,12 @@ class ItemUpload extends React.Component { } render() { let {type, id, path, key, ...props} = this.props; + let classId = `DZ-${path.replace(/\/|\s+/g, '-')}`; return (
) diff --git a/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js b/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js index 4b36277ae..1f0fd80f9 100644 --- a/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js +++ b/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js @@ -100,16 +100,26 @@ const FileManagerSource = { beforeSend: Utils.addAuthorizationStub, url: 'api/file-manager?api_server=' + utils.getSearchParams(window.location).api_server +'&package_type=' + type + '&package_id=' + id + '&package_path=' + path , success: function(data) { - resolve({ - data: data, - path: path - }); + if (data.output.status == 'True') { + resolve({ + data: data, + path: path + }); + } else { + reject({ + data: data, + path: path + }) + } }, error: function(error) { if (typeof error == 'string') { error = JSON.parse(error); } - reject(error); + reject({ + path: path, + data: error + }); } }).fail(function(xhr){ //Authentication and the handling of fail states should be wrapped up into a connection class. diff --git a/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js b/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js index 9345bc39f..3e4ac7f11 100644 --- a/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js +++ b/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js @@ -1,6 +1,6 @@ /* - * + * * Copyright 2016 RIFT.IO Inc * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -591,6 +591,13 @@ class CatalogDataStore { this.resetSelectionState(); } } + saveCatalogItemError(data){ + let error = JSON.parse(data.error.responseText); + const errorMsg = error && error.body && error.body['rpc-reply'] && JSON.stringify(error.body['rpc-reply']['rpc-error'], null, ' ') + ComposerAppActions.showError.defer({ + errorMessage: 'Unable to save the descriptor.\n' + errorMsg + }); + } } export default alt.createStore(CatalogDataStore, 'CatalogDataStore'); diff --git a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js index c07fffd64..c677a44a6 100644 --- a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js +++ b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js @@ -172,6 +172,7 @@ class ComposerAppStore { addFileSuccess: FileManagerActions.addFileSuccess, deletePackageFile: FileManagerActions.deletePackageFile, deleteFileSuccess: FileManagerActions.deleteFileSuccess, + deleteFileError: FileManagerActions.deleteFileError, closeFileManagerSockets: FileManagerActions.closeFileManagerSockets, openFileManagerSockets: FileManagerActions.openFileManagerSockets, openDownloadMonitoringSocketSuccess: FileManagerActions.openDownloadMonitoringSocketSuccess, @@ -681,6 +682,15 @@ class ComposerAppStore { files: files }) } + deleteFileError = (error) => { + const filepath = error.path; + const message = error.data && error.data.output ? ' (' + error.data.output['error-trace'] + ')' : ' (server error)'; + console.log('Unable to delete', filepath, 'Error:', message); + ComposerAppActions.showError.defer({ + errorMessage: 'Unable to delete ' + filepath + message + '. ' + }); + } + newPathNameUpdated = (event) => { const value = event.target.value; this.setState({ diff --git a/skyquake/plugins/debug/src/crash.jsx b/skyquake/plugins/debug/src/crash.jsx index 6c659c3d7..bed1dbf63 100644 --- a/skyquake/plugins/debug/src/crash.jsx +++ b/skyquake/plugins/debug/src/crash.jsx @@ -21,114 +21,126 @@ import './crash.scss'; import TreeView from 'react-treeview'; import '../node_modules/react-treeview/react-treeview.css'; import AppHeader from 'widgets/header/header.jsx'; +import ScreenLoader from 'widgets/screen-loader/screenLoader.jsx'; var crashActions = require('./crashActions.js'); var crashStore = require('./crashStore.js'); // var MissionControlStore = require('../missioncontrol/missionControlStore.js'); function openDashboard() { - window.location.hash = "#/"; + window.location.hash = "#/"; } class CrashDetails extends React.Component { - constructor(props) { - super(props) - var self = this; - this.state = crashStore.getState(); - crashStore.listen(this.storeListener); - } - storeListener = (data) => { - this.setState({ - list:data.crashList, - noDebug:!this.hasDebugData(data.crashList) - }); - } - componentWillUnmount(){ - crashStore.unlisten(this.storeListener); - } - componentWillMount() { - crashStore.get(); - } - hasDebugData(list) { - console.log(list); - if (list && list.length > 0) { - for (let i = 0; i < list.length; i++) { - var trace = list[i].backtrace; - for (let j = 0; j < trace.length; j++) { - console.log(trace[j]) - if (trace[j].detail) { - return true; - } + constructor(props) { + super(props) + this.state = crashStore.getState(); + crashStore.listen(this.storeListener); + } + storeListener = (data) => { + this.setState({ + isLoading: data.isLoading, + list: data.crashList, + noDebug: !this.hasDebugData(data.crashList) + }); + } + componentWillUnmount() { + crashStore.unlisten(this.storeListener); + } + componentWillMount() { + crashStore.get(); + } + hasDebugData(list) { + console.log(list); + if (list && list.length > 0) { + for (let i = 0; i < list.length; i++) { + var trace = list[i].backtrace; + for (let j = 0; j < trace.length; j++) { + console.log(trace[j]) + if (trace[j].detail) { + return true; + } + } + } } - } + return false; } - return false; - } - downloadFile(fileName, urlData) { - var replacedNewLines = urlData.replace(/\\n/g, '\n'); - var replacedTabs = replacedNewLines.replace(/\\t/g, '\t'); - var replacedQuotes= replacedTabs.replace(/\\"/g, '"'); - var textFileBlob = new Blob([replacedQuotes], {type: 'text/plain;charset=UTF-8'}); - var aLink = document.createElement('a'); - var evt = document.createEvent("HTMLEvents"); - evt.initEvent("click"); - aLink.download = fileName; - aLink.href = window.URL.createObjectURL(textFileBlob); - aLink.dispatchEvent(evt); - } - render() { - let html; - var list = null; - if (this.state != null) { - var tree =
No Debug Information Available
; - if (!this.state.noDebug) - { - var tree = this.state.list && this.state.list.map((node, i) => { - var vm = node.name; - var vm_label = {vm}; - var backtrace = node.backtrace; - return ( - - {backtrace.map(details => { - - //Needed to decode HTML - var text_temp = document.createElement("textarea") - text_temp.innerHTML = details.detail; - var text_temp = text_temp.value; - var arr = text_temp.split(/\n/); - var text = []; - for (let i = 0; i < arr.length; i++) { - text.push(arr[i]); - text.push(
) - } + downloadFile(fileName) { + // wait till download selected to create text blob + let urlData = JSON.stringify(this.state.list, null, 2); + let replacedNewLines = urlData.replace(/\\n/g, '\n'); + let replacedTabs = replacedNewLines.replace(/\\t/g, '\t'); + let replacedQuotes = replacedTabs.replace(/\\"/g, '"'); + let textFileBlob = new Blob([replacedQuotes], { type: 'text/plain;charset=UTF-8' }); + let aLink = document.createElement('a'); + aLink.download = fileName; + aLink.href = window.URL.createObjectURL(textFileBlob); + aLink.click(); // suprise, this works without being on the page + // it seems to cause no problems cleaning up the blob right away + window.URL.revokeObjectURL(aLink.href); + // assuming aLink just goes away when this function ends + } + render() { + let html; + if (this.state != null) { + if (!this.state.noDebug) { + let tree = this.state.list && this.state.list.map((node, i) => { + const vm = node.name; + const vm_label = {vm}; + const backtrace = node.backtrace; + return ( + + {backtrace.map(details => { + // do some trickery to normalize details 'new line' char(s) + let textareaElement = document.createElement("textarea") + textareaElement.innerHTML = details.detail; + let detailsFormatted = textareaElement.value; + let arr = detailsFormatted.split(/\n/); + let text = []; + for (let i = 0; i < arr.length; i++) { + text.push(arr[i]); + text.push(
); // react likes keys on array children + } - return ( - {details.id}} key={vm + '||' + details.id} defaultCollapsed={false}> -

{text}

-
- ); - })} -
- ); - })} - html = ( -
-
- -
-
-

Debug Information

-
{tree}
-
-
- ); - } else { - html =
- }; - let refPage = window.sessionStorage.getItem('refPage'); - refPage = JSON.parse(refPage); - return ( + return ( + {details.id}} key={vm + '||' + details.id} defaultCollapsed={false}> +

{text}

+
+ ); + })} +
+ ); + }); + let doDownload = this.downloadFile.bind(this, 'crash.txt'); + html = ( +
+
+ +
+
+

Debug Information

+
{tree}
+
+
+ ); + } else { + let text = this.state.isLoading ? "Loading Debug Information" : "No Debug Information Available" + html = ( +
+
+
{text}
+
+
+ ); + } + } else { + html =
+ }; + let refPage = window.sessionStorage.getItem('refPage'); + refPage = JSON.parse(refPage); + return (
- {html} + {html} +
- ); - } + ); + } } export default CrashDetails; diff --git a/skyquake/plugins/debug/src/crashStore.js b/skyquake/plugins/debug/src/crashStore.js index 51857d51f..0b04445be 100644 --- a/skyquake/plugins/debug/src/crashStore.js +++ b/skyquake/plugins/debug/src/crashStore.js @@ -20,18 +20,29 @@ import Alt from 'widgets/skyquake_container/skyquakeAltInstance'; function crashStore () { this.exportAsync(require('./crashSource.js')); this.bindActions(require('./crashActions.js')); + this.isLoading = false; + this.crashList = null; } crashStore.prototype.getCrashDetailsSuccess = function(list) { this.setState({ - crashList:list + isLoading: false, + crashList: list }) - console.log('success', list) + console.log('Crash details load success', list) }; crashStore.prototype.getCrashDetailsLoading = function(info) { + this.setState({ + isLoading: true, + crashList: null, + }) console.log('Loading crash details...', info) }; crashStore.prototype.getCrashDetailsFailure = function(info) { + this.setState({ + isLoading: false, + error: info + }) console.log('Failed to retrieve crash/debug details', info) }; diff --git a/skyquake/plugins/launchpad/api/launchpad.js b/skyquake/plugins/launchpad/api/launchpad.js index 6fb01704a..d74bb3e2e 100644 --- a/skyquake/plugins/launchpad/api/launchpad.js +++ b/skyquake/plugins/launchpad/api/launchpad.js @@ -790,8 +790,14 @@ NSR.addVnfrDataPromise = function(req, nsrs) { try { if (nsr["monitoring-param"]) { nsr["monitoring-param"].map(function(m) { - var vnfr = vnfrs[m["vnfr-id"]] || {}; + // var vnfr = vnfrs[m["vnfr-id"]] || {}; + // m["vnfr-name"] = vnfr['name'] ? vnfr['name'] : (vnfr['short-name'] ? vnfr['short-name'] : 'VNFR'); + var groupTag = m['group-tag']; + var vnfrId = m['vnfr-mon-param-ref'] && m['vnfr-mon-param-ref'][0] && m['vnfr-mon-param-ref'][0]['vnfr-id-ref']; + var vnfr = vnfrs[vnfrId] || {}; m["vnfr-name"] = vnfr['name'] ? vnfr['name'] : (vnfr['short-name'] ? vnfr['short-name'] : 'VNFR'); + m['group-tag'] = (groupTag ? (groupTag + ' - ') : '') + m['vnfr-name'] + (vnfrId ? ' (' + vnfrId.substring(1,8) + '...)' : ''); + }); } } catch (e) {