RIFT-15726 - optimize download size -> lodash usage in UI
[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 sendDownloadFileRequst: FileManagerActions.sendDownloadFileRequst,
172 addFileSuccess: FileManagerActions.addFileSuccess,
173 deletePackageFile: FileManagerActions.deletePackageFile,
174 deleteFileSuccess: FileManagerActions.deleteFileSuccess,
175 closeFileManagerSockets: FileManagerActions.closeFileManagerSockets,
176 openFileManagerSockets: FileManagerActions.openFileManagerSockets,
177 openDownloadMonitoringSocketSuccess: FileManagerActions.openDownloadMonitoringSocketSuccess,
178 getFilelistSocketSuccess: FileManagerActions.getFilelistSocketSuccess,
179 newPathNameUpdated: FileManagerActions.newPathNameUpdated,
180 createDirectory: FileManagerActions.createDirectory
181 });
182 this.exportPublicMethods({
183 closeFileManagerSockets: this.closeFileManagerSockets.bind(this)
184 })
185 }
186
187 onResize(e) {
188 if (e.type === 'resize-manager.resize.catalog-panel') {
189 const layout = Object.assign({}, this.layout);
190 layout.left = Math.max(0, layout.left - e.moved.x);
191 if (layout.left !== this.layout.left) {
192 this.setState({layout: layout});
193 }
194 } else if (e.type === 'resize-manager.resize.details-panel') {
195 const layout = Object.assign({}, this.layout);
196 layout.right = Math.max(0, layout.right + e.moved.x);
197 if (layout.right !== this.layout.right) {
198 this.setState({layout: layout});
199 }
200 } else if (/^resize-manager\.resize\.canvas-panel-tray/.test(e.type)) {
201 const layout = Object.assign({}, this.layout);
202 layout.bottom = Math.max(25, layout.bottom + e.moved.y);
203 if (layout.bottom !== this.layout.bottom) {
204 const zoom = autoZoomCanvasScale(layout.bottom) ;
205 if (this.zoom !== zoom) {
206 this.setState({layout: layout, zoom: zoom});
207 } else {
208 this.setState({layout: layout});
209 }
210 }
211 } else if (e.type !== 'resize') {
212 console.log('no resize handler for ', e.type, '. Do you need to add a handler in ComposerAppStore::onResize()?')
213 }
214 SelectionManager.refreshOutline();
215 }
216
217 updateItem(item) {
218 const self = this;
219 let containers = [];
220 let cpNumber = 0;
221 if(!document.body.classList.contains('resizing')) {
222 containers = [item].reduce(DescriptorModelFactory.buildCatalogItemFactory(CatalogDataStore.getState().catalogs), []);
223
224 containers.filter(d => DescriptorModelFactory.isConnectionPoint(d)).forEach(d => {
225 d.cpNumber = ++cpNumber;
226 containers.filter(d => DescriptorModelFactory.isVnfdConnectionPointRef(d)).filter(ref => ref.key === d.key).forEach(ref => ref.cpNumber = d.cpNumber);
227 });
228 this.setState({containers: containers, item: _cloneDeep(item)});
229 }
230 SelectionManager.refreshOutline();
231 }
232
233 editCatalogItem(item) {
234 let self = this;
235 self.closeFileManagerSockets();
236 if (item && item.uiState) {
237 item.uiState.isOpenForEdit = true;
238 if (item.uiState.type !== 'nsd') {
239 this.closeCanvasPanelTray();
240 }
241 }
242 SelectionManager.select(item);
243 this.updateItem(item);
244 this.openFileManagerSockets(item)
245 }
246 catalogItemMetaDataChanged(item) {
247 this.updateItem(item);
248 }
249
250 catalogItemDescriptorChanged(itemDescriptor) {
251 this.catalogItemMetaDataChanged(itemDescriptor.model);
252 }
253
254 showMoreInfo() {
255 this.setState({showMore: true});
256 }
257
258 showLessInfo() {
259 this.setState({showMore: false});
260 }
261
262 showError(data) {
263 NotificationError.defer({msg: data.errorMessage, type: 'error'})
264 // this.setState({message: data.errorMessage, messageType: 'error'});
265 }
266
267 clearError() {
268 this.setState({message: '', messageType: ''});
269 }
270
271 toggleShowMoreInfo() {
272 this.setState({showMore: !this.showMore});
273 }
274
275 applyDefaultLayout() {
276 if (this.item && this.item.uiState && this.item.uiState.containerPositionMap) {
277 if (!_isEmpty(this.item.uiState.containerPositionMap)) {
278 this.item.uiState.containerPositionMap = {};
279 CatalogItemsActions.catalogItemMetaDataChanged.defer(this.item);
280 }
281 }
282 }
283
284 addVirtualLinkDescriptor(dropCoordinates = null) {
285 let vld;
286 if (this.item) {
287 if (this.item.uiState.type === 'nsd') {
288 const nsdc = DescriptorModelFactory.newNetworkService(this.item);
289 vld = nsdc.createVld();
290 } else if (this.item.uiState.type === 'vnfd') {
291 const vnfd = DescriptorModelFactory.newVirtualNetworkFunction(this.item);
292 vld = vnfd.createVld();
293 }
294 if (vld) {
295 vld.uiState.dropCoordinates = dropCoordinates;
296 SelectionManager.clearSelectionAndRemoveOutline();
297 SelectionManager.addSelection(vld);
298 this.updateItem(vld.getRoot().model);
299 CatalogItemsActions.catalogItemDescriptorChanged.defer(vld.getRoot());
300 }
301 }
302 }
303
304 addForwardingGraphDescriptor(dropCoordinates = null) {
305 if (this.item && this.item.uiState.type === 'nsd') {
306 const nsdc = DescriptorModelFactory.newNetworkService(this.item);
307 const fg = nsdc.createVnffgd();
308 fg.uiState.dropCoordinates = dropCoordinates;
309 SelectionManager.clearSelectionAndRemoveOutline();
310 SelectionManager.addSelection(fg);
311 this.updateItem(nsdc.model);
312 CatalogItemsActions.catalogItemDescriptorChanged.defer(nsdc);
313 }
314 }
315
316 addVirtualDeploymentDescriptor(dropCoordinates = null) {
317 if (this.item.uiState.type === 'vnfd') {
318 const vnfd = DescriptorModelFactory.newVirtualNetworkFunction(this.item);
319 const vdu = vnfd.createVdu();
320 vdu.uiState.dropCoordinates = dropCoordinates;
321 SelectionManager.clearSelectionAndRemoveOutline();
322 SelectionManager.addSelection(vdu);
323 this.updateItem(vdu.getRoot().model);
324 CatalogItemsActions.catalogItemDescriptorChanged.defer(vdu.getRoot());
325 }
326 }
327
328 selectModel(container) {
329 if (SelectionManager.select(container)) {
330 const model = DescriptorModelFactory.isContainer(container) ? container.getRoot().model : container;
331 this.catalogItemMetaDataChanged(model);
332 }
333 }
334
335 outlineModel(obj) {
336 const uid = UID.from(obj);
337 requestAnimationFrame(() => {
338 SelectionManager.outline(Array.from(document.querySelectorAll(`[data-uid="${uid}"]`)));
339 });
340 }
341
342 clearSelection() {
343 SelectionManager.clearSelectionAndRemoveOutline();
344 this.catalogItemMetaDataChanged(this.item);
345 }
346
347 setDragState(dragState) {
348 this.setState({drag: dragState});
349 }
350
351 filterCatalogByType(typeValue) {
352 this.setState({filterCatalogByTypeValue: typeValue})
353 }
354
355 setCanvasZoom(zoom) {
356 this.setState({zoom: zoom});
357 }
358
359 showJsonViewer() {
360 this.setState({showJSONViewer: true});
361 }
362
363 closeJsonViewer() {
364 this.setState({showJSONViewer: false});
365 }
366
367 toggleCanvasPanelTray() {
368 const layout = this.layout;
369 if (layout.bottom > 25) {
370 this.closeCanvasPanelTray();
371 } else {
372 this.openCanvasPanelTray();
373 }
374 }
375
376 openCanvasPanelTray() {
377 const layout = {
378 left: this.layout.left,
379 right: this.layout.right,
380 bottom: 300
381 };
382 const zoom = defaults.defaultPanelTrayOpenZoom;
383 if (this.zoom !== zoom) {
384 this.setState({layout: layout, zoom: zoom, restoreZoom: this.zoom});
385 } else {
386 this.setState({layout: layout});
387 }
388 }
389
390 closeCanvasPanelTray() {
391 const layout = {
392 left: this.layout.left,
393 right: this.layout.right,
394 bottom: 25
395 };
396 const zoom = this.restoreZoom || autoZoomCanvasScale(layout.bottom);
397 if (this.zoom !== zoom) {
398 this.setState({layout: layout, zoom: zoom, restoreZoom: null});
399 } else {
400 this.setState({layout: layout, restoreZoom: null});
401 }
402 }
403
404 enterFullScreenMode() {
405
406 /**
407 * https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
408 * This is an experimental api but works our target browsers and ignored by others
409 */
410 const eventNames = ['fullscreenchange', 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange'];
411
412 const appRoot = document.body;//.getElementById('RIFT_wareLaunchpadComposerAppRoot');
413
414 const comp = this;
415
416 function onFullScreenChange() {
417
418 if (isFullScreen()) {
419 const layout = comp.layout;
420 const restoreLayout = _cloneDeep(layout);
421 uiTransientState.restoreLayout = restoreLayout;
422 layout.left = 0;
423 layout.right = 0;
424 comp.setState({fullScreenMode: true, layout: layout, restoreLayout: restoreLayout});
425 } else {
426 comp.setState({fullScreenMode: false, layout: uiTransientState.restoreLayout});
427 }
428
429 }
430
431 if (this.fullScreenMode === false) {
432
433 if (appRoot.requestFullscreen) {
434 appRoot.requestFullscreen();
435 } else if (appRoot.msRequestFullscreen) {
436 appRoot.msRequestFullscreen();
437 } else if (appRoot.mozRequestFullScreen) {
438 appRoot.mozRequestFullScreen();
439 } else if (appRoot.webkitRequestFullscreen) {
440 appRoot.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
441 }
442
443 eventNames.map(name => {
444 document.removeEventListener(name, onFullScreenChange);
445 document.addEventListener(name, onFullScreenChange);
446 });
447
448 }
449
450 }
451
452 exitFullScreenMode() {
453
454 if (document.exitFullscreen) {
455 document.exitFullscreen();
456 } else if (document.msExitFullscreen) {
457 document.msExitFullscreen();
458 } else if (document.mozCancelFullScreen) {
459 document.mozCancelFullScreen();
460 } else if (document.webkitExitFullscreen) {
461 document.webkitExitFullscreen();
462 }
463
464 this.setState({fullScreenMode: false});
465
466 }
467 showAssets() {
468 this.setState({
469 panelTabShown: 'assets'
470 });
471 }
472 showDescriptor() {
473 this.setState({
474 panelTabShown: 'descriptor'
475 });
476 }
477
478 //File Manager methods
479 getFilelistSuccess(data) {
480 let self = this;
481 let filesState = null;
482 if (self.fileMonitoringSocketID) {
483 let newState = {};
484 if(data.hasOwnProperty('contents')) {
485 filesState = addInputState( _cloneDeep(this.filesState),data);
486 let normalizedData = normalizeTree(data);
487 newState = {
488 files: {
489 data: _mergeWith(normalizedData.data, self.files.data, function(obj, src) {
490 return _uniqBy(obj? obj.concat(src) : src, 'name');
491 }),
492 id: normalizedData.id
493 },
494 filesState: filesState
495 }
496 } else {
497 newState = {
498 files: false
499 }
500 }
501 if(!_isEqual(newState.files, this.files) || ! _isEqual(newState.fileState, this.fileState)) {
502 this.setState(newState);
503 }
504
505 }
506 function normalizeTree(data) {
507 let f = {
508 id:[],
509 data:{}
510 };
511 data.contents.map(getContents);
512 function getContents(d) {
513 if(d.hasOwnProperty('contents')) {
514 let contents = [];
515 d.contents.map(function(c,i) {
516 if (!c.hasOwnProperty('contents')) {
517 contents.push(c);
518 } else {
519 getContents(c);
520 }
521 })
522 f.id.push(d.name);
523 f.data[d.name] = contents;
524 }
525 }
526 return f;
527 }
528 function addInputState(obj, d) {
529 d.newFile = '';
530 if(d.hasOwnProperty('contents')) {
531 d.contents.map(addInputState.bind(null, obj))
532 }
533 if(!obj[d.name]) {
534 obj[d.name] = '';
535 }
536 return obj;
537 }
538 }
539 sendDownloadFileRequst(data) {
540 let id = data.id || this.item.id;
541 let type = data.type || this.item.uiState.type;
542 let path = data.path;
543 let url = data.url;
544 this.getInstance().addFile(id, type, path, url, data.refresh);
545 }
546 updateFileLocationInput = (data) => {
547 let name = data.name;
548 let value = data.value;
549 var filesState = _cloneDeep(this.filesState);
550 filesState[name] = value;
551 this.setState({
552 filesState: filesState
553 });
554 }
555 addFileSuccess = (data) => {
556 if(!data.refresh) {
557 let path = data.path;
558 let fileName = data.fileName;
559 let files = _cloneDeep(this.files);
560 let loadingIndex = files.data[path].push({
561 status: 'DOWNLOADING',
562 name: path + '/' + fileName
563 }) - 1;
564 this.setState({files: files});
565 }
566
567 }
568 startWatchingJob = () => {
569 let ws = window.multiplexer.channel(this.jobSocketId);
570 this.setState({
571 jobSocket:null
572 })
573 }
574 openDownloadMonitoringSocketSuccess = (id) => {
575 let self = this;
576 let ws = window.multiplexer.channel(id);
577 let downloadJobs = _cloneDeep(self.downloadJobs);
578 let newFiles = false;
579 ws.onmessage = (socket) => {
580 if (self.files && self.files.length > 0) {
581 let jobs = [];
582 try {
583 jobs = JSON.parse(socket.data);
584 } catch(e) {}
585 newFiles = _cloneDeep(self.files);
586 jobs.map(function(j) {
587 //check if not in completed state
588 let fullPath = j['package-path'];
589 let path = fullPath.split('/');
590 let fileName = path.pop();
591 path = path.join('/');
592 let index = _findIndex(self.files.data[path], function(o){
593 return fullPath == o.name
594 });
595 if((index > -1) && newFiles.data[path][index]) {
596 newFiles.data[path][index].status = j.status
597 } else {
598 if(j.status.toUpperCase() == 'LOADING...' || j.status.toUpperCase() == 'IN_PROGRESS') {
599 newFiles.data[path].push({
600 status: j.status,
601 name: fullPath
602 })
603 } else {
604 // if ()
605 }
606 }
607 })
608 self.setState({
609 files: newFiles
610 })
611 // console.log(JSON.parse(socket.data));
612 }
613 }
614 this.setState({
615 jobSocketId: id,
616 jobSocket: ws
617 })
618
619 }
620 getFilelistSocketSuccess = (id) => {
621 let self = this;
622 let ws = window.multiplexer.channel(id);
623 ws.onmessage = (socket) => {
624 if (self.fileMonitoringSocketID) {
625 let data = [];
626 try {
627 data = JSON.parse(socket.data);
628 } catch(e) {}
629 self.getFilelistSuccess(data)
630 }
631 }
632
633 this.setState({
634 fileMonitoringSocketID: id,
635 fileMonitoringSocket: ws
636 })
637
638 }
639 closeFileManagerSockets() {
640 this.fileMonitoringSocketID = null;
641 this.setState({
642 jobSocketId : null,
643 fileMonitoringSocketID : null
644 // jobSocket : null,
645 // fileMonitoringSocket : null,
646 });
647 this.jobSocket && this.jobSocket.close();
648 this.fileMonitoringSocket && this.fileMonitoringSocket.close();
649 console.log('closing');
650 }
651 openFileManagerSockets(i) {
652 let self = this;
653 let item = i || self.item;
654 // this.closeFileManagerSockets();
655 this.getInstance().openFileMonitoringSocket(item.id, item.uiState.type).then(function() {
656 // // self.getInstance().openDownloadMonitoringSocket(item.id);
657 });
658 this.getInstance().openDownloadMonitoringSocket(item.id);
659 }
660 endWatchingJob(id) {
661
662 }
663 deletePackageFile(name) {
664 let id = this.item.id;
665 let type = this.item.uiState.type;
666 this.getInstance().deleteFile(id, type, name);
667 }
668 deleteFileSuccess = (data) => {
669 let path = data.path.split('/')
670 let files = _cloneDeep(this.files);
671 path.pop();
672 path = path.join('/');
673 let pathFiles = files.data[path]
674 _remove(pathFiles, function(c) {
675 return c.name == data.path;
676 });
677
678 this.setState({
679 files: files
680 })
681 }
682 newPathNameUpdated = (event) => {
683 const value = event.target.value;
684 this.setState({
685 newPathName: value
686 })
687 }
688 createDirectory = () => {
689 console.log(this.newPathName);
690 this.sendDownloadFileRequst({
691 id: this.item.id,
692 type: this.item.uiState.type,
693 path: this.item.name + '/' + this.newPathName,
694 url: utils.getSearchParams(window.location).dev_download_server || window.location.protocol + '//' + window.location.host,
695 refresh: true
696 });
697 this.setState({
698 newPathName: ''
699 })
700 }
701 }
702
703 export default alt.createStore(ComposerAppStore, 'ComposerAppStore');