Folder creation for onboarded packages
[osm/UI.git] / skyquake / plugins / composer / src / src / components / filemanager / FileManager.jsx
1 /*
2  *
3  *   Copyright 2016 RIFT.IO Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18
19
20 //https://raw.githubusercontent.com/RIFTIO/RIFT.ware/master/rift-shell
21 import _ from 'lodash'
22 import React from 'react';
23 import ReactDOM from 'react-dom';
24 import TreeView from 'react-treeview';
25 import TextInput from 'widgets/form_controls/textInput.jsx';
26 import Button from '../Button';
27 import './FileMananger.scss';
28 import FileManagerActions from './FileManagerActions.js';
29 import imgSave from '../../../../node_modules/open-iconic/svg/data-transfer-upload.svg'
30 import {Panel, PanelWrapper} from 'widgets/panel/panel';
31 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
32 import LoadingIndicator from 'widgets/loading-indicator/loadingIndicator.jsx';
33
34 import DropZone from 'dropzone'
35 import Utils from '../../libraries/utils'
36 import FileManagerUploadDropZone from '../../libraries/FileManagerUploadDropZone';
37 let API_SERVER = require('utils/rw.js').getSearchParams(window.location).api_server;
38
39 const createDropZone = function (action, clickable, type, id, path, dropTarget) {
40     const dropZone = new FileManagerUploadDropZone(ReactDOM.findDOMNode(dropTarget), [clickable], action, type, id, path);
41     // dropZone.on('dragover', this.onDragOver);
42     // dropZone.on('dragend', this.onDragEnd);
43     // dropZone.on('addedfile', this.onFileAdded);
44     return dropZone;
45 };
46 //updateFileLocationInput
47 class FileManager extends React.Component {
48     constructor(props) {
49         super(props)
50     }
51     componentWillMount() {
52         // FileManagerActions.openFileManagerSockets()
53     }
54     componentWillUnmount() {
55         // FileManagerActions.closeFileManagerSockets();
56     }
57     generateFolder(data, nesting) {
58         let nestingLevel = nesting || 1;
59
60     }
61     deleteFile(name) {
62         return function(e) {
63             FileManagerActions.deletePackageFile(name);
64         }
65
66     }
67     updateFileLocationInput(name) {
68         return function(e) {
69             FileManagerActions.updateFileLocationInput({
70                 name: name,
71                 value: e.target.value
72             });
73         }
74     }
75     sendDownloadFileRequst = (url, path) => {
76         let self = this;
77         return function(e) {
78             if(!url || url == "") {
79                 return self.props.actions.showNotification.defer({type: 'error', msg: 'Value missing in download request'});;
80             }
81             let files = self.props.files.data;
82             let folder = path.split('/');
83             let splitUrl = url.split('/');
84             let fileName = splitUrl[splitUrl.length - 1];
85             folder.pop;
86             let fullPath = _.cloneDeep(folder);
87             fullPath.push(fileName);
88             fullPath = fullPath.join('/');
89             folder = folder.join('/');
90             let fileIndex = _.findIndex(files[folder], function(f) {
91                 return f.name == fullPath;
92             })
93             if (fileIndex == -1) {
94                 FileManagerActions.sendDownloadFileRequst({
95                     url: url,
96                     path: path
97                 });
98             } else {
99                 self.props.actions.showNotification('It seems you\'re attempting to upload a file with a duplicate file name');
100             }
101         }
102     }
103     render() {
104         let self = this;
105         let html = (
106             <div className="FileManager">
107                 <PanelWrapper style={{flexDirection: 'column'}}>
108                 <Panel className="addFileSection" style={{backgroundColor: 'transparent'}} no-corners>
109                     <div className="inputSection">
110                         <TextInput placeholder="some/path" value={this.props.newPathName} label="create a new directory" onChange={FileManagerActions.newPathNameUpdated} />
111                         <Button label="Create" onClick={FileManagerActions.createDirectory} />
112                     </div>
113                 </Panel>
114                 {self.props.files && self.props.files.id && buildList(self, self.props.files) }
115                 </PanelWrapper>
116             </div>
117         )
118         return html;
119     }
120
121 }
122
123 function buildList(self, data) {
124     let toReturn = [];
125     data.id.map(function(k,i) {
126         toReturn.push (contentFolder(self, data.data[k], k, i, self.props.filesState, self.updateFileLocationInput, self.sendDownloadFileRequst, self.deleteFile));
127     });
128     return toReturn.reverse();
129 }
130
131 function contentFolder(context, folder, path, key, inputState, updateFn, sendDownloadFileRequst, deleteFn) {
132     let type = context.props.type;
133     let id = context.props.item.id;
134     const onboardDropZone = createDropZone.bind(this, FileManagerUploadDropZone.ACTIONS.onboard, '.ComposerAppAddFile.' + path.replace(/\//g, '-'), type, id, path);
135     return (
136         <Panel title={path} key={key} itemClassName="nested" no-corners>
137         <div className="folder">
138             {
139                 folder.map(function(f, i) {
140                     if( !f.hasOwnProperty('contents') ){
141                         return contentFile(context, f, path, i, deleteFn);
142                     }
143                 })
144             }
145             <Panel className="addFileSection" no-corners>
146                 <ItemUpload type={type} id={id} path={path} key={key} dropZone={onboardDropZone} />
147                 <div style={{marginLeft: '0.5rem'}}>
148                     OR
149                 </div>
150                 <div className="inputSection">
151                     <TextInput placeholder="URL" className="" label="External URL" value={inputState[path]} onChange={updateFn(path)} />
152                     <Button className='ComposerAppSave' label="DOWNLOAD" onClick={sendDownloadFileRequst(inputState[path], path)}/>
153                 </div>
154             </Panel>
155
156             </div>
157         </Panel>
158     );
159 }
160 class ItemUpload extends React.Component {
161     constructor(props) {
162         super(props);
163     }
164     componentDidMount() {
165         if (this.props.dropZone) {
166             const dropTarget = this;
167             const dropZone = this.props.dropZone(dropTarget);
168         }
169     }
170     render() {
171         let {type, id, path, key, ...props} = this.props;
172         return (
173             <div className="inputSection">
174                 <label className="sqTextInput" style={{flexDirection: 'row', alignItems:'center'}}>
175                     <span>Upload File</span>
176                     <Button className={'ComposerAppAddFile ' + path.replace(/\//g, '-')} label="BROWSE"/>
177                 </label>
178             </div>
179         )
180     }
181 }
182 function contentFile(context, file, path, key, deleteFn) {
183     const name = stripPath(file.name, path);
184     const id = context.props.item.id;
185     const type = context.props.type;
186     //{`${window.location.protocol}//${API_SERVER}:4567/api/package${type}/${id}/${path}/${name}`}
187     return (
188         <div className="file" key={key}>
189             <div className="file-section">
190                 <div className="file-info">
191                     <div className="file-status" style={{display: (file.status && file.status.toLowerCase() != 'completed') ? 'inherit' : 'none', color: (file.status == 'FAILED' ? 'red' : 'inherit')}}>
192                         {file.status && (file.status == 'IN_PROGRESS' || file.status == 'DOWNLOADING'  )  ? <LoadingIndicator size={2} /> : file.status }
193                     </div>
194                     <div className="file-name">
195                         <a target="_blank" href={`${API_SERVER}:4567/api/package/${type}/${id}/${path}/${name}`}>{name}</a>
196                     </div>
197                 </div>
198                 <div className="file-action" style={{display: (!file.status || (file && file.status.toLowerCase() != 'loading...')) ? 'inherit' : 'none', cursor: 'pointer'}} onClick={deleteFn(file.name)}>X</div>
199             </div>
200         </div>
201     )
202 }
203
204 function stripPath(name, path, returnPath) {
205     let stripSlash = (name.indexOf('/') > -1) ? '/' : '';
206     // return name.split(path + stripSlash)[1].replace('/', '');
207     let split = name.split(path + stripSlash)[returnPath ? 0 : 1];
208     return split ? split.replace('/', '') : name;
209 }
210
211
212
213 export default SkyquakeComponent(FileManager)
214 /**
215  * Sample Data
216  */
217 // let files = {
218 //   "name": ".",
219 //   "contents": [
220 //     {
221 //       "name": "pong_vnfd",
222 //       "contents": [
223 //         {
224 //           "name": "pong_vnfd/checksums.txt",
225 //           "last_modified_time": 1474458399.6218443,
226 //           "byte_size": 168
227 //         },
228 //         {
229 //           "name": "pong_vnfd/pong_vnfd.yaml",
230 //           "last_modified_time": 1474458399.6258445,
231 //           "byte_size": 3514
232 //         },
233 //         {
234 //           "name": "pong_vnfd/icons",
235 //           "contents": [
236 //             {
237 //               "name": "pong_vnfd/icons/rift_logo.png",
238 //               "last_modified_time": 1474458399.6218443,
239 //               "byte_size": 1658
240 //             }
241 //           ],
242 //           "last_modified_time": 1474458399.6218443,
243 //           "byte_size": 3
244 //         },
245 //         {
246 //           "name": "pong_vnfd/cloud_init",
247 //           "contents": [
248 //             {
249 //               "name": "pong_vnfd/cloud_init/pong_cloud_init.cfg",
250 //               "last_modified_time": 1474458399.6258445,
251 //               "byte_size": 227
252 //             }
253 //           ],
254 //           "last_modified_time": 1474458399.6258445,
255 //           "byte_size": 3
256 //         }
257 //       ],
258 //       "last_modified_time": 1474458399.6258445,
259 //       "byte_size": 6
260 //     }
261 //   ],
262 //   "last_modified_time": 1474458399.6218443,
263 //   "byte_size": 3
264 // };