ce490a0e0091aa0c81ede5ee3adcd83ff4403cca
[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                     {self.props.files && self.props.files.id && buildList(self, self.props.files) }
109                 </PanelWrapper>
110             </div>
111         )
112         return html;
113     }
114
115 }
116
117 function buildList(self, data) {
118     let toReturn = [];
119     data.id.map(function(k,i) {
120         toReturn.push (contentFolder(self, data.data[k], k, i, self.props.filesState, self.updateFileLocationInput, self.sendDownloadFileRequst, self.deleteFile));
121     });
122     return toReturn.reverse();
123 }
124
125 function contentFolder(context, folder, path, key, inputState, updateFn, sendDownloadFileRequst, deleteFn) {
126     let type = context.props.type;
127     let id = context.props.item.id;
128     const onboardDropZone = createDropZone.bind(this, FileManagerUploadDropZone.ACTIONS.onboard, '.ComposerAppAddFile.' + path.replace('/', '-'), type, id, path);
129     return (
130         <Panel title={path} key={key} itemClassName="nested" no-corners>
131         <div className="folder">
132             {
133                 folder.map(function(f, i) {
134                     if( !f.hasOwnProperty('contents') ){
135                         return contentFile(context, f, path, i, deleteFn);
136                     }
137                 })
138             }
139             <Panel className="addFileSection" no-corners>
140                 <ItemUpload type={type} id={id} path={path} key={key} dropZone={onboardDropZone} />
141                 <div style={{marginLeft: '0.5rem'}}>
142                     OR
143                 </div>
144                 <div className="inputSection">
145                     <TextInput placeholder="URL" className="" label="External URL" value={inputState[path]} onChange={updateFn(path)} />
146                     <Button className='ComposerAppSave' label="DOWNLOAD" onClick={sendDownloadFileRequst(inputState[path], path)}/>
147                 </div>
148             </Panel>
149
150             </div>
151         </Panel>
152     );
153 }
154 class ItemUpload extends React.Component {
155     constructor(props) {
156         super(props);
157     }
158     componentDidMount() {
159         if (this.props.dropZone) {
160             const dropTarget = this;
161             const dropZone = this.props.dropZone(dropTarget);
162         }
163     }
164     render() {
165         let {type, id, path, key, ...props} = this.props;
166         return (
167             <div className="inputSection">
168                 <label className="sqTextInput" style={{flexDirection: 'row', alignItems:'center'}}>
169                     <span>Upload File</span>
170                     <Button className={'ComposerAppAddFile ' + path.replace('/', '-')} label="BROWSE"/>
171                 </label>
172             </div>
173         )
174     }
175 }
176 function contentFile(context, file, path, key, deleteFn) {
177     const name = stripPath(file.name, path);
178     const id = context.props.item.id;
179     const type = context.props.type;
180     //{`${window.location.protocol}//${API_SERVER}:4567/api/package${type}/${id}/${path}/${name}`}
181     return (
182         <div className="file" key={key}>
183             <div className="file-section">
184                 <div className="file-info">
185                     <div className="file-status" style={{display: (file.status && file.status.toLowerCase() != 'completed') ? 'inherit' : 'none', color: (file.status == 'FAILED' ? 'red' : 'inherit')}}>
186                         {file.status && (file.status == 'IN_PROGRESS' || file.status == 'DOWNLOADING'  )  ? <LoadingIndicator size={2} /> : file.status }
187                     </div>
188                     <div className="file-name">
189                         <a target="_blank" href={`${API_SERVER}:4567/api/package/${type}/${id}/${path}/${name}`}>{name}</a>
190                     </div>
191                 </div>
192                 <div className="file-action" style={{display: (!file.status || (file && file.status.toLowerCase() != 'loading...')) ? 'inherit' : 'none', cursor: 'pointer'}} onClick={deleteFn(file.name)}>X</div>
193             </div>
194         </div>
195     )
196 }
197
198 function stripPath(name, path, returnPath) {
199     let stripSlash = (name.indexOf('/') > -1) ? '/' : '';
200     // return name.split(path + stripSlash)[1].replace('/', '');
201     let split = name.split(path + stripSlash)[returnPath ? 0 : 1];
202     return split ? split.replace('/', '') : name;
203 }
204
205
206
207 export default SkyquakeComponent(FileManager)
208 /**
209  * Sample Data
210  */
211 // let files = {
212 //   "name": ".",
213 //   "contents": [
214 //     {
215 //       "name": "pong_vnfd",
216 //       "contents": [
217 //         {
218 //           "name": "pong_vnfd/checksums.txt",
219 //           "last_modified_time": 1474458399.6218443,
220 //           "byte_size": 168
221 //         },
222 //         {
223 //           "name": "pong_vnfd/pong_vnfd.yaml",
224 //           "last_modified_time": 1474458399.6258445,
225 //           "byte_size": 3514
226 //         },
227 //         {
228 //           "name": "pong_vnfd/icons",
229 //           "contents": [
230 //             {
231 //               "name": "pong_vnfd/icons/rift_logo.png",
232 //               "last_modified_time": 1474458399.6218443,
233 //               "byte_size": 1658
234 //             }
235 //           ],
236 //           "last_modified_time": 1474458399.6218443,
237 //           "byte_size": 3
238 //         },
239 //         {
240 //           "name": "pong_vnfd/cloud_init",
241 //           "contents": [
242 //             {
243 //               "name": "pong_vnfd/cloud_init/pong_cloud_init.cfg",
244 //               "last_modified_time": 1474458399.6258445,
245 //               "byte_size": 227
246 //             }
247 //           ],
248 //           "last_modified_time": 1474458399.6258445,
249 //           "byte_size": 3
250 //         }
251 //       ],
252 //       "last_modified_time": 1474458399.6258445,
253 //       "byte_size": 6
254 //     }
255 //   ],
256 //   "last_modified_time": 1474458399.6218443,
257 //   "byte_size": 3
258 // };