X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FUI.git;a=blobdiff_plain;f=skyquake%2Fplugins%2Fcomposer%2Fsrc%2Fsrc%2Fstores%2FComposerAppStore.js;h=c9675b70c60ce120d839f97080476641b86c7e72;hp=3671890b5a060d285eb74841badc22ecb7386c26;hb=801c5f0d12068c77bad6891d60ea166856ade85d;hpb=5e37df206e5667d681be1b9b4c450024733c4617 diff --git a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js index 3671890b5..c9675b70c 100644 --- a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js +++ b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js @@ -18,7 +18,14 @@ */ 'use strict'; -import _ from 'lodash' +import _isNumber from 'lodash/isNumber' +import _cloneDeep from 'lodash/cloneDeep' +import _isEmpty from 'lodash/isEmpty' +import _mergeWith from 'lodash/mergeWith' +import _uniqBy from 'lodash/uniqBy' +import _isEqual from 'lodash/isEqual' +import _findIndex from 'lodash/findIndex' +import _remove from 'lodash/remove' import d3 from 'd3' import alt from '../alt' import UID from '../libraries/UniqueId' @@ -41,6 +48,9 @@ import React from 'react'; //Hack for crouton fix. Should eventually put composer in skyquake alt context import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx'; let NotificationError = null; + +import utils from '../libraries/utils'; + class ComponentBridge extends React.Component { constructor(props) { super(props); @@ -53,7 +63,7 @@ class ComponentBridge extends React.Component { const getDefault = (name, defaultValue) => { const val = window.localStorage.getItem('defaults-' + name); if (val) { - if (_.isNumber(val)) { + if (_isNumber(val)) { if (val < 0) { return setDefault(name, 0); } @@ -125,6 +135,8 @@ class ComposerAppStore { this.files = false; this.filesState = {}; this.downloadJobs = {}; + this.containers = []; + this.newPathName = ''; //End File manager values this.bindListeners({ onResize: PanelResizeAction.RESIZE, @@ -156,14 +168,17 @@ class ComposerAppStore { showDescriptor: ComposerAppActions.showDescriptor, getFilelistSuccess: FileManagerActions.getFilelistSuccess, updateFileLocationInput: FileManagerActions.updateFileLocationInput, - sendDownloadFileRequst: FileManagerActions.sendDownloadFileRequst, + sendDownloadFileRequest: FileManagerActions.sendDownloadFileRequest, addFileSuccess: FileManagerActions.addFileSuccess, deletePackageFile: FileManagerActions.deletePackageFile, deleteFileSuccess: FileManagerActions.deleteFileSuccess, + deleteFileError: FileManagerActions.deleteFileError, closeFileManagerSockets: FileManagerActions.closeFileManagerSockets, openFileManagerSockets: FileManagerActions.openFileManagerSockets, openDownloadMonitoringSocketSuccess: FileManagerActions.openDownloadMonitoringSocketSuccess, - getFilelistSocketSuccess: FileManagerActions.getFilelistSocketSuccess + getFilelistSocketSuccess: FileManagerActions.getFilelistSocketSuccess, + newPathNameUpdated: FileManagerActions.newPathNameUpdated, + createDirectory: FileManagerActions.createDirectory }); this.exportPublicMethods({ closeFileManagerSockets: this.closeFileManagerSockets.bind(this) @@ -201,8 +216,17 @@ class ComposerAppStore { } updateItem(item) { + const self = this; + let containers = []; + let cpNumber = 0; if(!document.body.classList.contains('resizing')) { - this.setState({item: _.cloneDeep(item)}); + containers = [item].reduce(DescriptorModelFactory.buildCatalogItemFactory(CatalogDataStore.getState().catalogs), []); + + containers.filter(d => DescriptorModelFactory.isConnectionPoint(d)).forEach(d => { + d.cpNumber = ++cpNumber; + containers.filter(d => DescriptorModelFactory.isVnfdConnectionPointRef(d)).filter(ref => ref.key === d.key).forEach(ref => ref.cpNumber = d.cpNumber); + }); + this.setState({containers: containers, item: _cloneDeep(item)}); } SelectionManager.refreshOutline(); } @@ -218,7 +242,9 @@ class ComposerAppStore { } SelectionManager.select(item); this.updateItem(item); - this.openFileManagerSockets(item) + if (item) { + this.openFileManagerSockets(item); + } } catalogItemMetaDataChanged(item) { this.updateItem(item); @@ -251,7 +277,7 @@ class ComposerAppStore { applyDefaultLayout() { if (this.item && this.item.uiState && this.item.uiState.containerPositionMap) { - if (!_.isEmpty(this.item.uiState.containerPositionMap)) { + if (!_isEmpty(this.item.uiState.containerPositionMap)) { this.item.uiState.containerPositionMap = {}; CatalogItemsActions.catalogItemMetaDataChanged.defer(this.item); } @@ -394,7 +420,7 @@ class ComposerAppStore { if (isFullScreen()) { const layout = comp.layout; - const restoreLayout = _.cloneDeep(layout); + const restoreLayout = _cloneDeep(layout); uiTransientState.restoreLayout = restoreLayout; layout.left = 0; layout.right = 0; @@ -459,15 +485,14 @@ class ComposerAppStore { if (self.fileMonitoringSocketID) { let newState = {}; if(data.hasOwnProperty('contents')) { - filesState = addInputState( _.cloneDeep(this.filesState),data); - // filesState = _.merge(self.filesState, addInputState({},data)); + filesState = updateFileState( _cloneDeep(this.filesState),data); let normalizedData = normalizeTree(data); newState = { files: { - data: _.mergeWith(normalizedData.data, self.files.data, function(obj, src) { - return _.uniqBy(obj? obj.concat(src) : src, 'name'); + data: _mergeWith(normalizedData.data, self.files.data, function(obj, src) { + return _uniqBy(obj? obj.concat(src) : src, 'name'); }), - id: self.files.id || normalizedData.id + id: normalizedData.id }, filesState: filesState } @@ -476,15 +501,16 @@ class ComposerAppStore { files: false } } + if(!_isEqual(newState.files, this.files) || ! _isEqual(newState.fileState, this.fileState)) { + this.setState(newState); + } - this.setState(newState); } function normalizeTree(data) { let f = { id:[], data:{} }; - data.contents.map(getContents); function getContents(d) { if(d.hasOwnProperty('contents')) { let contents = []; @@ -499,44 +525,61 @@ class ComposerAppStore { f.data[d.name] = contents; } } + getContents(data); return f; } - function addInputState(obj, d) { + function updateFileState(obj, d) { d.newFile = ''; if(d.hasOwnProperty('contents')) { - d.contents.map(addInputState.bind(null, obj)) - } - if(!obj[d.name]) { - obj[d.name] = ''; + d.contents.map(updateFileState.bind(null, obj)) } + // override any "pending" state we may have initialized + obj[d.name] = ''; return obj; } } - sendDownloadFileRequst(data) { + sendDownloadFileRequest(data) { let id = data.id || this.item.id; let type = data.type || this.item.uiState.type; + let assetType = data.assetType; let path = data.path; let url = data.url; - this.getInstance().addFile(id, type, path, url); + this.getInstance().addFile(id, type, assetType, path, url, data.refresh); } updateFileLocationInput = (data) => { let name = data.name; let value = data.value; - var filesState = _.cloneDeep(this.filesState); + var filesState = _cloneDeep(this.filesState); filesState[name] = value; this.setState({ filesState: filesState }); } addFileSuccess = (data) => { - let path = data.path; - let fileName = data.fileName; - let files = _.cloneDeep(this.files); - let loadingIndex = files.data[path].push({ - status: 'DOWNLOADING', - name: path + '/' + fileName - }) - 1; - this.setState({files: files}); + if(!data.refresh) { + let path = data.path; + if (path.startsWith('readme')) { + // this asset type stuff should be in a more common location + // this is a wee bit of a hack till it is + path = '.' + path.slice(6); + } + let fileName = data.fileName; + let files = _cloneDeep(this.files); + let assetGroup = files.data[path] || []; + if (fileName) { + let name = path + '/' + fileName; + if (assetGroup.findIndex(f => f.name === name) == -1){ + assetGroup.push({name}); + } + } + files.data[path] = assetGroup; + if (files.id.indexOf(path) == -1){ + files.id.push(path); + } + let filesState = _cloneDeep(this.filesState); + filesState[name] = "DOWNLOADING"; + this.setState({files, filesState}); + } } startWatchingJob = () => { @@ -548,7 +591,7 @@ class ComposerAppStore { openDownloadMonitoringSocketSuccess = (id) => { let self = this; let ws = window.multiplexer.channel(id); - let downloadJobs = _.cloneDeep(self.downloadJobs); + let downloadJobs = _cloneDeep(self.downloadJobs); let newFiles = false; ws.onmessage = (socket) => { if (self.files && self.files.length > 0) { @@ -556,14 +599,14 @@ class ComposerAppStore { try { jobs = JSON.parse(socket.data); } catch(e) {} - newFiles = _.cloneDeep(self.files); + newFiles = _cloneDeep(self.files); jobs.map(function(j) { //check if not in completed state let fullPath = j['package-path']; let path = fullPath.split('/'); let fileName = path.pop(); path = path.join('/'); - let index = _.findIndex(self.files.data[path], function(o){ + let index = _findIndex(self.files.data[path], function(o){ return fullPath == o.name }); if((index > -1) && newFiles.data[path][index]) { @@ -605,6 +648,11 @@ class ComposerAppStore { } this.setState({ + filesState: [], + files: { + id:[], + data:{} + }, fileMonitoringSocketID: id, fileMonitoringSocket: ws }) @@ -634,25 +682,63 @@ class ComposerAppStore { endWatchingJob(id) { } - deletePackageFile(name) { + deletePackageFile(asset) { + let {assetType, path} = asset; let id = this.item.id; let type = this.item.uiState.type; - this.getInstance().deleteFile(id, type, name); + this.getInstance().deleteFile(id, type, assetType, path); } deleteFileSuccess = (data) => { - let path = data.path.split('/') - let files = _.cloneDeep(this.files); - path.pop(); - path = path.join('/'); - let pathFiles = files.data[path] - _.remove(pathFiles, function(c) { - return c.name == data.path; + let name = null; + let path = null; + if (data.assetFolder === 'readme'){ + // freak'n root folder is special + name = data.path; + path = ['.']; + } else { + name = data.assetFolder + '/' + data.path; + path = name.split('/'); + path.pop(); + } + let files = _cloneDeep(this.files); + let filesForPath = files.data[path.join('/')] + _remove(filesForPath, function(c) { + return c.name == name; }); this.setState({ 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({ + newPathName: value + }) + } + createDirectory = (assetType) => { + console.log(this.newPathName); + this.sendDownloadFileRequest({ + id: this.item.id, + type: this.item.uiState.type, + assetType: assetType, + path: this.newPathName, + url: utils.getSearchParams(window.location).dev_download_server || window.location.protocol + '//' + window.location.host, + refresh: true + }); + this.setState({ + newPathName: '' + }) + } } export default alt.createStore(ComposerAppStore, 'ComposerAppStore');