Support new package file management scheme
[osm/UI.git] / skyquake / plugins / composer / src / src / stores / ComposerAppStore.js
1
2 /*
3 *
4 * Copyright 2016 RIFT.IO Inc
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19 'use strict';
20
21 import _isNumber from 'lodash/isNumber'
22 import _cloneDeep from 'lodash/cloneDeep'
23 import _isEmpty from 'lodash/isEmpty'
24 import _mergeWith from 'lodash/mergeWith'
25 import _uniqBy from 'lodash/uniqBy'
26 import _isEqual from 'lodash/isEqual'
27 import _findIndex from 'lodash/findIndex'
28 import _remove from 'lodash/remove'
29 import d3 from 'd3'
30 import alt from '../alt'
31 import UID from '../libraries/UniqueId'
32 import DescriptorModelFactory from '../libraries/model/DescriptorModelFactory'
33 import PanelResizeAction from '../actions/PanelResizeAction'
34 import CatalogItemsActions from '../actions/CatalogItemsActions'
35 import CanvasEditorActions from '../actions/CanvasEditorActions'
36 import ComposerAppActions from '../actions/ComposerAppActions'
37 import CatalogFilterActions from '../actions/CatalogFilterActions'
38 import CanvasPanelTrayActions from '../actions/CanvasPanelTrayActions'
39 import SelectionManager from '../libraries/SelectionManager'
40 import CatalogDataStore from '../stores/CatalogDataStore'
41 import isFullScreen from '../libraries/isFullScreen'
42
43 import FileManagerSource from '../components/filemanager/FileManagerSource';
44 import FileManagerActions from '../components/filemanager/FileManagerActions';
45
46 import React from 'react';
47
48 //Hack for crouton fix. Should eventually put composer in skyquake alt context
49 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
50 let NotificationError = null;
51
52 import utils from '../libraries/utils';
53
54 class ComponentBridge extends React.Component {
55 constructor(props) {
56 super(props);
57 NotificationError = this.props.flux.actions.global.showNotification;
58 }
59 render(){
60 return <i></i>
61 }
62 }
63 const getDefault = (name, defaultValue) => {
64 const val = window.localStorage.getItem('defaults-' + name);
65 if (val) {
66 if (_isNumber(val)) {
67 if (val < 0) {
68 return setDefault(name, 0);
69 }
70 }
71 return Number(val);
72 }
73 setDefault(name, defaultValue);
74 return defaultValue;
75 };
76
77 const setDefault = (name, defaultValue) => {
78 window.localStorage.setItem('defaults-' + name, defaultValue);
79 return defaultValue;
80 };
81
82 /* the top and bottom positions are managed by css; requires div to be display: absolute*/
83 const defaults = {
84 left: getDefault('catalog-panel-start-width', 300),
85 right: getDefault('details-panel-start-width', 365),
86 bottom: 25 + getDefault('defaults-forwarding-graphs-panel-start-height', 0),
87 showMore: false,
88 zoom: getDefault('zoom', 100),
89 filterCatalogBy: 'nsd',
90 defaultPanelTrayOpenZoom: (() => {
91 let zoom = parseFloat(getDefault('panel-tray-zoom', 75));
92 if (isNaN(zoom)) {
93 zoom = 75;
94 }
95 zoom = Math.min(100, zoom);
96 zoom = Math.max(25, zoom);
97 setDefault('panel-tray-zoom', zoom);
98 return zoom;
99 })()
100 };
101
102 const autoZoomCanvasScale = d3.scale.linear().domain([0, 300]).range([100, 50]).clamp(true);
103
104 const uiTransientState = {};
105
106 class ComposerAppStore {
107
108 constructor() {
109 //Bridge for crouton fix
110 this.ComponentBridgeElement = SkyquakeComponent(ComponentBridge);
111
112 this.exportAsync(FileManagerSource)
113 // the catalog item currently being edited in the composer
114 this.item = null;
115 // the left and right sides of the canvas area
116 this.layout = {
117 left: defaults.left,
118 right: defaults.right,
119 bottom: defaults.bottom
120 };
121 uiTransientState.restoreLayout = this.layout;
122 this.zoom = defaults.zoom;
123 this.showMore = defaults.showMore;
124 this.filterCatalogByTypeValue = defaults.filterCatalogBy;
125 // transient ui state
126 this.drag = null;
127 this.message = '';
128 this.messageType = '';
129 this.showJSONViewer = false;
130 this.showClassifiers = {};
131 this.editPathsMode = false;
132 this.fullScreenMode = false;
133 this.panelTabShown = 'descriptor';
134 //File manager values
135 this.files = false;
136 this.filesState = {};
137 this.downloadJobs = {};
138 this.containers = [];
139 this.newPathName = '';
140 //End File manager values
141 this.bindListeners({
142 onResize: PanelResizeAction.RESIZE,
143 editCatalogItem: CatalogItemsActions.EDIT_CATALOG_ITEM,
144 catalogItemMetaDataChanged: CatalogItemsActions.CATALOG_ITEM_META_DATA_CHANGED,
145 catalogItemDescriptorChanged: CatalogItemsActions.CATALOG_ITEM_DESCRIPTOR_CHANGED,
146 toggleShowMoreInfo: CanvasEditorActions.TOGGLE_SHOW_MORE_INFO,
147 showMoreInfo: CanvasEditorActions.SHOW_MORE_INFO,
148 showLessInfo: CanvasEditorActions.SHOW_LESS_INFO,
149 applyDefaultLayout: CanvasEditorActions.APPLY_DEFAULT_LAYOUT,
150 addVirtualLinkDescriptor: CanvasEditorActions.ADD_VIRTUAL_LINK_DESCRIPTOR,
151 addForwardingGraphDescriptor: CanvasEditorActions.ADD_FORWARDING_GRAPH_DESCRIPTOR,
152 addVirtualDeploymentDescriptor: CanvasEditorActions.ADD_VIRTUAL_DEPLOYMENT_DESCRIPTOR,
153 selectModel: ComposerAppActions.SELECT_MODEL,
154 outlineModel: ComposerAppActions.OUTLINE_MODEL,
155 showError: ComposerAppActions.SHOW_ERROR,
156 clearError: ComposerAppActions.CLEAR_ERROR,
157 setDragState: ComposerAppActions.SET_DRAG_STATE,
158 filterCatalogByType: CatalogFilterActions.FILTER_BY_TYPE,
159 setCanvasZoom: CanvasEditorActions.SET_CANVAS_ZOOM,
160 showJsonViewer: ComposerAppActions.SHOW_JSON_VIEWER,
161 closeJsonViewer: ComposerAppActions.CLOSE_JSON_VIEWER,
162 toggleCanvasPanelTray: CanvasPanelTrayActions.TOGGLE_OPEN_CLOSE,
163 openCanvasPanelTray: CanvasPanelTrayActions.OPEN,
164 closeCanvasPanelTray: CanvasPanelTrayActions.CLOSE,
165 enterFullScreenMode: ComposerAppActions.ENTER_FULL_SCREEN_MODE,
166 exitFullScreenMode: ComposerAppActions.EXIT_FULL_SCREEN_MODE,
167 showAssets: ComposerAppActions.showAssets,
168 showDescriptor: ComposerAppActions.showDescriptor,
169 getFilelistSuccess: FileManagerActions.getFilelistSuccess,
170 updateFileLocationInput: FileManagerActions.updateFileLocationInput,
171 sendDownloadFileRequest: FileManagerActions.sendDownloadFileRequest,
172 addFileSuccess: FileManagerActions.addFileSuccess,
173 deletePackageFile: FileManagerActions.deletePackageFile,
174 deleteFileSuccess: FileManagerActions.deleteFileSuccess,
175 deleteFileError: FileManagerActions.deleteFileError,
176 closeFileManagerSockets: FileManagerActions.closeFileManagerSockets,
177 openFileManagerSockets: FileManagerActions.openFileManagerSockets,
178 openDownloadMonitoringSocketSuccess: FileManagerActions.openDownloadMonitoringSocketSuccess,
179 getFilelistSocketSuccess: FileManagerActions.getFilelistSocketSuccess,
180 newPathNameUpdated: FileManagerActions.newPathNameUpdated,
181 createDirectory: FileManagerActions.createDirectory
182 });
183 this.exportPublicMethods({
184 closeFileManagerSockets: this.closeFileManagerSockets.bind(this)
185 })
186 }
187
188 onResize(e) {
189 if (e.type === 'resize-manager.resize.catalog-panel') {
190 const layout = Object.assign({}, this.layout);
191 layout.left = Math.max(0, layout.left - e.moved.x);
192 if (layout.left !== this.layout.left) {
193 this.setState({layout: layout});
194 }
195 } else if (e.type === 'resize-manager.resize.details-panel') {
196 const layout = Object.assign({}, this.layout);
197 layout.right = Math.max(0, layout.right + e.moved.x);
198 if (layout.right !== this.layout.right) {
199 this.setState({layout: layout});
200 }
201 } else if (/^resize-manager\.resize\.canvas-panel-tray/.test(e.type)) {
202 const layout = Object.assign({}, this.layout);
203 layout.bottom = Math.max(25, layout.bottom + e.moved.y);
204 if (layout.bottom !== this.layout.bottom) {
205 const zoom = autoZoomCanvasScale(layout.bottom) ;
206 if (this.zoom !== zoom) {
207 this.setState({layout: layout, zoom: zoom});
208 } else {
209 this.setState({layout: layout});
210 }
211 }
212 } else if (e.type !== 'resize') {
213 console.log('no resize handler for ', e.type, '. Do you need to add a handler in ComposerAppStore::onResize()?')
214 }
215 SelectionManager.refreshOutline();
216 }
217
218 updateItem(item) {
219 const self = this;
220 let containers = [];
221 let cpNumber = 0;
222 if(!document.body.classList.contains('resizing')) {
223 containers = [item].reduce(DescriptorModelFactory.buildCatalogItemFactory(CatalogDataStore.getState().catalogs), []);
224
225 containers.filter(d => DescriptorModelFactory.isConnectionPoint(d)).forEach(d => {
226 d.cpNumber = ++cpNumber;
227 containers.filter(d => DescriptorModelFactory.isVnfdConnectionPointRef(d)).filter(ref => ref.key === d.key).forEach(ref => ref.cpNumber = d.cpNumber);
228 });
229 this.setState({containers: containers, item: _cloneDeep(item)});
230 }
231 SelectionManager.refreshOutline();
232 }
233
234 editCatalogItem(item) {
235 let self = this;
236 self.closeFileManagerSockets();
237 if (item && item.uiState) {
238 item.uiState.isOpenForEdit = true;
239 if (item.uiState.type !== 'nsd') {
240 this.closeCanvasPanelTray();
241 }
242 }
243 SelectionManager.select(item);
244 this.updateItem(item);
245 if (item) {
246 this.openFileManagerSockets(item);
247 }
248 }
249 catalogItemMetaDataChanged(item) {
250 this.updateItem(item);
251 }
252
253 catalogItemDescriptorChanged(itemDescriptor) {
254 this.catalogItemMetaDataChanged(itemDescriptor.model);
255 }
256
257 showMoreInfo() {
258 this.setState({showMore: true});
259 }
260
261 showLessInfo() {
262 this.setState({showMore: false});
263 }
264
265 showError(data) {
266 NotificationError.defer({msg: data.errorMessage, type: 'error'})
267 // this.setState({message: data.errorMessage, messageType: 'error'});
268 }
269
270 clearError() {
271 this.setState({message: '', messageType: ''});
272 }
273
274 toggleShowMoreInfo() {
275 this.setState({showMore: !this.showMore});
276 }
277
278 applyDefaultLayout() {
279 if (this.item && this.item.uiState && this.item.uiState.containerPositionMap) {
280 if (!_isEmpty(this.item.uiState.containerPositionMap)) {
281 this.item.uiState.containerPositionMap = {};
282 CatalogItemsActions.catalogItemMetaDataChanged.defer(this.item);
283 }
284 }
285 }
286
287 addVirtualLinkDescriptor(dropCoordinates = null) {
288 let vld;
289 if (this.item) {
290 if (this.item.uiState.type === 'nsd') {
291 const nsdc = DescriptorModelFactory.newNetworkService(this.item);
292 vld = nsdc.createVld();
293 } else if (this.item.uiState.type === 'vnfd') {
294 const vnfd = DescriptorModelFactory.newVirtualNetworkFunction(this.item);
295 vld = vnfd.createVld();
296 }
297 if (vld) {
298 vld.uiState.dropCoordinates = dropCoordinates;
299 SelectionManager.clearSelectionAndRemoveOutline();
300 SelectionManager.addSelection(vld);
301 this.updateItem(vld.getRoot().model);
302 CatalogItemsActions.catalogItemDescriptorChanged.defer(vld.getRoot());
303 }
304 }
305 }
306
307 addForwardingGraphDescriptor(dropCoordinates = null) {
308 if (this.item && this.item.uiState.type === 'nsd') {
309 const nsdc = DescriptorModelFactory.newNetworkService(this.item);
310 const fg = nsdc.createVnffgd();
311 fg.uiState.dropCoordinates = dropCoordinates;
312 SelectionManager.clearSelectionAndRemoveOutline();
313 SelectionManager.addSelection(fg);
314 this.updateItem(nsdc.model);
315 CatalogItemsActions.catalogItemDescriptorChanged.defer(nsdc);
316 }
317 }
318
319 addVirtualDeploymentDescriptor(dropCoordinates = null) {
320 if (this.item.uiState.type === 'vnfd') {
321 const vnfd = DescriptorModelFactory.newVirtualNetworkFunction(this.item);
322 const vdu = vnfd.createVdu();
323 vdu.uiState.dropCoordinates = dropCoordinates;
324 SelectionManager.clearSelectionAndRemoveOutline();
325 SelectionManager.addSelection(vdu);
326 this.updateItem(vdu.getRoot().model);
327 CatalogItemsActions.catalogItemDescriptorChanged.defer(vdu.getRoot());
328 }
329 }
330
331 selectModel(container) {
332 if (SelectionManager.select(container)) {
333 const model = DescriptorModelFactory.isContainer(container) ? container.getRoot().model : container;
334 this.catalogItemMetaDataChanged(model);
335 }
336 }
337
338 outlineModel(obj) {
339 const uid = UID.from(obj);
340 requestAnimationFrame(() => {
341 SelectionManager.outline(Array.from(document.querySelectorAll(`[data-uid="${uid}"]`)));
342 });
343 }
344
345 clearSelection() {
346 SelectionManager.clearSelectionAndRemoveOutline();
347 this.catalogItemMetaDataChanged(this.item);
348 }
349
350 setDragState(dragState) {
351 this.setState({drag: dragState});
352 }
353
354 filterCatalogByType(typeValue) {
355 this.setState({filterCatalogByTypeValue: typeValue})
356 }
357
358 setCanvasZoom(zoom) {
359 this.setState({zoom: zoom});
360 }
361
362 showJsonViewer() {
363 this.setState({showJSONViewer: true});
364 }
365
366 closeJsonViewer() {
367 this.setState({showJSONViewer: false});
368 }
369
370 toggleCanvasPanelTray() {
371 const layout = this.layout;
372 if (layout.bottom > 25) {
373 this.closeCanvasPanelTray();
374 } else {
375 this.openCanvasPanelTray();
376 }
377 }
378
379 openCanvasPanelTray() {
380 const layout = {
381 left: this.layout.left,
382 right: this.layout.right,
383 bottom: 300
384 };
385 const zoom = defaults.defaultPanelTrayOpenZoom;
386 if (this.zoom !== zoom) {
387 this.setState({layout: layout, zoom: zoom, restoreZoom: this.zoom});
388 } else {
389 this.setState({layout: layout});
390 }
391 }
392
393 closeCanvasPanelTray() {
394 const layout = {
395 left: this.layout.left,
396 right: this.layout.right,
397 bottom: 25
398 };
399 const zoom = this.restoreZoom || autoZoomCanvasScale(layout.bottom);
400 if (this.zoom !== zoom) {
401 this.setState({layout: layout, zoom: zoom, restoreZoom: null});
402 } else {
403 this.setState({layout: layout, restoreZoom: null});
404 }
405 }
406
407 enterFullScreenMode() {
408
409 /**
410 * https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
411 * This is an experimental api but works our target browsers and ignored by others
412 */
413 const eventNames = ['fullscreenchange', 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange'];
414
415 const appRoot = document.body;//.getElementById('RIFT_wareLaunchpadComposerAppRoot');
416
417 const comp = this;
418
419 function onFullScreenChange() {
420
421 if (isFullScreen()) {
422 const layout = comp.layout;
423 const restoreLayout = _cloneDeep(layout);
424 uiTransientState.restoreLayout = restoreLayout;
425 layout.left = 0;
426 layout.right = 0;
427 comp.setState({fullScreenMode: true, layout: layout, restoreLayout: restoreLayout});
428 } else {
429 comp.setState({fullScreenMode: false, layout: uiTransientState.restoreLayout});
430 }
431
432 }
433
434 if (this.fullScreenMode === false) {
435
436 if (appRoot.requestFullscreen) {
437 appRoot.requestFullscreen();
438 } else if (appRoot.msRequestFullscreen) {
439 appRoot.msRequestFullscreen();
440 } else if (appRoot.mozRequestFullScreen) {
441 appRoot.mozRequestFullScreen();
442 } else if (appRoot.webkitRequestFullscreen) {
443 appRoot.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
444 }
445
446 eventNames.map(name => {
447 document.removeEventListener(name, onFullScreenChange);
448 document.addEventListener(name, onFullScreenChange);
449 });
450
451 }
452
453 }
454
455 exitFullScreenMode() {
456
457 if (document.exitFullscreen) {
458 document.exitFullscreen();
459 } else if (document.msExitFullscreen) {
460 document.msExitFullscreen();
461 } else if (document.mozCancelFullScreen) {
462 document.mozCancelFullScreen();
463 } else if (document.webkitExitFullscreen) {
464 document.webkitExitFullscreen();
465 }
466
467 this.setState({fullScreenMode: false});
468
469 }
470 showAssets() {
471 this.setState({
472 panelTabShown: 'assets'
473 });
474 }
475 showDescriptor() {
476 this.setState({
477 panelTabShown: 'descriptor'
478 });
479 }
480
481 //File Manager methods
482 getFilelistSuccess(data) {
483 let self = this;
484 let filesState = null;
485 if (self.fileMonitoringSocketID) {
486 let newState = {};
487 if(data.hasOwnProperty('contents')) {
488 filesState = updateFileState( _cloneDeep(this.filesState),data);
489 let normalizedData = normalizeTree(data);
490 newState = {
491 files: {
492 data: _mergeWith(normalizedData.data, self.files.data, function(obj, src) {
493 return _uniqBy(obj? obj.concat(src) : src, 'name');
494 }),
495 id: normalizedData.id
496 },
497 filesState: filesState
498 }
499 } else {
500 newState = {
501 files: false
502 }
503 }
504 if(!_isEqual(newState.files, this.files) || ! _isEqual(newState.fileState, this.fileState)) {
505 this.setState(newState);
506 }
507
508 }
509 function normalizeTree(data) {
510 let f = {
511 id:[],
512 data:{}
513 };
514 function getContents(d) {
515 if(d.hasOwnProperty('contents')) {
516 let contents = [];
517 d.contents.map(function(c,i) {
518 if (!c.hasOwnProperty('contents')) {
519 contents.push(c);
520 } else {
521 getContents(c);
522 }
523 })
524 f.id.push(d.name);
525 f.data[d.name] = contents;
526 }
527 }
528 getContents(data);
529 return f;
530 }
531 function updateFileState(obj, d) {
532 d.newFile = '';
533 if(d.hasOwnProperty('contents')) {
534 d.contents.map(updateFileState.bind(null, obj))
535 }
536 // override any "pending" state we may have initialized
537 obj[d.name] = '';
538 return obj;
539 }
540 }
541 sendDownloadFileRequest(data) {
542 let id = data.id || this.item.id;
543 let type = data.type || this.item.uiState.type;
544 let assetType = data.assetType;
545 let path = data.path;
546 let url = data.url;
547 this.getInstance().addFile(id, type, assetType, path, url, data.refresh);
548 }
549 updateFileLocationInput = (data) => {
550 let name = data.name;
551 let value = data.value;
552 var filesState = _cloneDeep(this.filesState);
553 filesState[name] = value;
554 this.setState({
555 filesState: filesState
556 });
557 }
558 addFileSuccess = (data) => {
559 if(!data.refresh) {
560 let path = data.path;
561 if (path.startsWith('readme')) {
562 // this asset type stuff should be in a more common location
563 // this is a wee bit of a hack till it is
564 path = '.' + path.slice(6);
565 }
566 let fileName = data.fileName;
567 let files = _cloneDeep(this.files);
568 let assetGroup = files.data[path] || [];
569 if (fileName) {
570 let name = path + '/' + fileName;
571 if (assetGroup.findIndex(f => f.name === name) == -1){
572 assetGroup.push({name});
573 }
574 }
575 files.data[path] = assetGroup;
576 if (files.id.indexOf(path) == -1){
577 files.id.push(path);
578 }
579 let filesState = _cloneDeep(this.filesState);
580 filesState[name] = "DOWNLOADING";
581 this.setState({files, filesState});
582 }
583
584 }
585 startWatchingJob = () => {
586 let ws = window.multiplexer.channel(this.jobSocketId);
587 this.setState({
588 jobSocket:null
589 })
590 }
591 openDownloadMonitoringSocketSuccess = (id) => {
592 let self = this;
593 let ws = window.multiplexer.channel(id);
594 let downloadJobs = _cloneDeep(self.downloadJobs);
595 let newFiles = false;
596 ws.onmessage = (socket) => {
597 if (self.files && self.files.length > 0) {
598 let jobs = [];
599 try {
600 jobs = JSON.parse(socket.data);
601 } catch(e) {}
602 newFiles = _cloneDeep(self.files);
603 jobs.map(function(j) {
604 //check if not in completed state
605 let fullPath = j['package-path'];
606 let path = fullPath.split('/');
607 let fileName = path.pop();
608 path = path.join('/');
609 let index = _findIndex(self.files.data[path], function(o){
610 return fullPath == o.name
611 });
612 if((index > -1) && newFiles.data[path][index]) {
613 newFiles.data[path][index].status = j.status
614 } else {
615 if(j.status.toUpperCase() == 'LOADING...' || j.status.toUpperCase() == 'IN_PROGRESS') {
616 newFiles.data[path].push({
617 status: j.status,
618 name: fullPath
619 })
620 } else {
621 // if ()
622 }
623 }
624 })
625 self.setState({
626 files: newFiles
627 })
628 // console.log(JSON.parse(socket.data));
629 }
630 }
631 this.setState({
632 jobSocketId: id,
633 jobSocket: ws
634 })
635
636 }
637 getFilelistSocketSuccess = (id) => {
638 let self = this;
639 let ws = window.multiplexer.channel(id);
640 ws.onmessage = (socket) => {
641 if (self.fileMonitoringSocketID) {
642 let data = [];
643 try {
644 data = JSON.parse(socket.data);
645 } catch(e) {}
646 self.getFilelistSuccess(data)
647 }
648 }
649
650 this.setState({
651 filesState: [],
652 files: {
653 id:[],
654 data:{}
655 },
656 fileMonitoringSocketID: id,
657 fileMonitoringSocket: ws
658 })
659
660 }
661 closeFileManagerSockets() {
662 this.fileMonitoringSocketID = null;
663 this.setState({
664 jobSocketId : null,
665 fileMonitoringSocketID : null
666 // jobSocket : null,
667 // fileMonitoringSocket : null,
668 });
669 this.jobSocket && this.jobSocket.close();
670 this.fileMonitoringSocket && this.fileMonitoringSocket.close();
671 console.log('closing');
672 }
673 openFileManagerSockets(i) {
674 let self = this;
675 let item = i || self.item;
676 // this.closeFileManagerSockets();
677 this.getInstance().openFileMonitoringSocket(item.id, item.uiState.type).then(function() {
678 // // self.getInstance().openDownloadMonitoringSocket(item.id);
679 });
680 this.getInstance().openDownloadMonitoringSocket(item.id);
681 }
682 endWatchingJob(id) {
683
684 }
685 deletePackageFile(asset) {
686 let {assetType, path} = asset;
687 let id = this.item.id;
688 let type = this.item.uiState.type;
689 this.getInstance().deleteFile(id, type, assetType, path);
690 }
691 deleteFileSuccess = (data) => {
692 let name = null;
693 let path = null;
694 if (data.assetFolder === 'readme'){
695 // freak'n root folder is special
696 name = data.path;
697 path = ['.'];
698 } else {
699 name = data.assetFolder + '/' + data.path;
700 path = name.split('/');
701 path.pop();
702 }
703 let files = _cloneDeep(this.files);
704 let filesForPath = files.data[path.join('/')]
705 _remove(filesForPath, function(c) {
706 return c.name == name;
707 });
708
709 this.setState({
710 files: files
711 })
712 }
713 deleteFileError = (error) => {
714 const filepath = error.path;
715 const message = error.data && error.data.output ? ' (' + error.data.output['error-trace'] + ')' : ' (server error)';
716 console.log('Unable to delete', filepath, 'Error:', message);
717 ComposerAppActions.showError.defer({
718 errorMessage: 'Unable to delete ' + filepath + message + '. '
719 });
720 }
721
722 newPathNameUpdated = (event) => {
723 const value = event.target.value;
724 this.setState({
725 newPathName: value
726 })
727 }
728 createDirectory = (assetType) => {
729 console.log(this.newPathName);
730 this.sendDownloadFileRequest({
731 id: this.item.id,
732 type: this.item.uiState.type,
733 assetType: assetType,
734 path: this.newPathName,
735 url: utils.getSearchParams(window.location).dev_download_server || window.location.protocol + '//' + window.location.host,
736 refresh: true
737 });
738 this.setState({
739 newPathName: ''
740 })
741 }
742 }
743
744 export default alt.createStore(ComposerAppStore, 'ComposerAppStore');