3 * Copyright 2016 RIFT.IO Inc
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
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';
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;
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);
46 //updateFileLocationInput
47 class FileManager extends React.Component {
51 componentWillMount() {
52 // FileManagerActions.openFileManagerSockets()
54 componentWillUnmount() {
55 // FileManagerActions.closeFileManagerSockets();
57 generateFolder(data, nesting) {
58 let nestingLevel = nesting || 1;
63 FileManagerActions.deletePackageFile(name);
67 updateFileLocationInput(name) {
69 FileManagerActions.updateFileLocationInput({
75 sendDownloadFileRequst = (url, path) => {
78 if(!url || url == "") {
79 return self.props.actions.showNotification.defer({type: 'error', msg: 'Value missing in download request'});;
81 let files = self.props.files.data;
82 let folder = path.split('/');
83 let splitUrl = url.split('/');
84 let fileName = splitUrl[splitUrl.length - 1];
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;
93 if (fileIndex == -1) {
94 FileManagerActions.sendDownloadFileRequst({
99 self.props.actions.showNotification('It seems you\'re attempting to upload a file with a duplicate file name');
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} />
114 {self.props.files && self.props.files.id && buildList(self, self.props.files) }
123 function buildList(self, data) {
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));
128 return toReturn.reverse();
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);
136 <Panel title={path} key={key} itemClassName="nested" no-corners>
137 <div className="folder">
139 folder.map(function(f, i) {
140 if( !f.hasOwnProperty('contents') ){
141 return contentFile(context, f, path, i, deleteFn);
145 <Panel className="addFileSection" no-corners>
146 <ItemUpload type={type} id={id} path={path} key={key} dropZone={onboardDropZone} />
147 <div style={{marginLeft: '0.5rem'}}>
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)}/>
160 class ItemUpload extends React.Component {
164 componentDidMount() {
165 if (this.props.dropZone) {
166 const dropTarget = this;
167 const dropZone = this.props.dropZone(dropTarget);
171 let {type, id, path, key, ...props} = this.props;
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"/>
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 const downloadHost = API_SERVER.match('localhost') || API_SERVER.match('127.0.0.1') ? `${window.location.protocol}//${window.location.hostname}` : API_SERVER;
187 //{`${window.location.protocol}//${API_SERVER}:4567/api/package${type}/${id}/${path}/${name}`}
189 <div className="file" key={key}>
190 <div className="file-section">
191 <div className="file-info">
192 <div className="file-status" style={{display: (file.status && file.status.toLowerCase() != 'completed') ? 'inherit' : 'none', color: (file.status == 'FAILED' ? 'red' : 'inherit')}}>
193 {file.status && (file.status == 'IN_PROGRESS' || file.status == 'DOWNLOADING' ) ? <LoadingIndicator size={2} /> : file.status }
195 <div className="file-name">
196 <a target="_blank" href={`${downloadHost}:4567/api/package/${type}/${id}/${path}/${name}`}>{name}</a>
199 <div className="file-action" style={{display: (!file.status || (file && file.status.toLowerCase() != 'loading...')) ? 'inherit' : 'none', cursor: 'pointer'}} onClick={deleteFn(file.name)}>X</div>
205 function stripPath(name, path, returnPath) {
206 let stripSlash = (name.indexOf('/') > -1) ? '/' : '';
207 // return name.split(path + stripSlash)[1].replace('/', '');
208 let split = name.split(path + stripSlash)[returnPath ? 0 : 1];
209 return split ? split.replace('/', '') : name;
214 export default SkyquakeComponent(FileManager)
222 // "name": "pong_vnfd",
225 // "name": "pong_vnfd/checksums.txt",
226 // "last_modified_time": 1474458399.6218443,
230 // "name": "pong_vnfd/pong_vnfd.yaml",
231 // "last_modified_time": 1474458399.6258445,
235 // "name": "pong_vnfd/icons",
238 // "name": "pong_vnfd/icons/rift_logo.png",
239 // "last_modified_time": 1474458399.6218443,
243 // "last_modified_time": 1474458399.6218443,
247 // "name": "pong_vnfd/cloud_init",
250 // "name": "pong_vnfd/cloud_init/pong_cloud_init.cfg",
251 // "last_modified_time": 1474458399.6258445,
255 // "last_modified_time": 1474458399.6258445,
259 // "last_modified_time": 1474458399.6258445,
263 // "last_modified_time": 1474458399.6218443,