1616
1717import { createStyles , Theme , withStyles } from "@material-ui/core/styles" ;
1818import Grid from "@material-ui/core/Grid" ;
19- import { Button } from "@material-ui/core" ;
20- import Typography from "@material-ui/core/Typography" ;
2119import TextField from "@material-ui/core/TextField" ;
2220import InputAdornment from "@material-ui/core/InputAdornment" ;
2321import SearchIcon from "@material-ui/icons/Search" ;
2422import { BucketObject , BucketObjectsList } from "./types" ;
2523import api from "../../../../../../common/api" ;
26- import React , { useEffect , useState } from "react" ;
24+ import React from "react" ;
2725import TableWrapper from "../../../../Common/TableWrapper/TableWrapper" ;
28- import { MinTablePaginationActions } from "../../../../../../common/MinTablePaginationActions" ;
29- import { CreateIcon } from "../../.././../../../icons" ;
3026import { niceBytes } from "../../../../../../common/utils" ;
31- import Moment from "react-moment" ;
3227import DeleteObject from "./DeleteObject" ;
28+
3329import {
3430 actionsTray ,
3531 containerForHeader ,
3632 searchField ,
3733} from "../../../../Common/FormComponents/common/styleLibrary" ;
3834import PageHeader from "../../../../Common/PageHeader/PageHeader" ;
3935import storage from "local-storage-fallback" ;
36+ import { isNullOrUndefined } from "util" ;
37+ import { Button , Input } from "@material-ui/core" ;
38+ import * as reactMoment from "react-moment" ;
39+ import { CreateIcon } from "../../../../../../icons" ;
40+ import Snackbar from "@material-ui/core/Snackbar" ;
4041
4142const styles = ( theme : Theme ) =>
4243 createStyles ( {
@@ -88,6 +89,8 @@ interface IListObjectsState {
8889 selectedObject : string ;
8990 selectedBucket : string ;
9091 filterObjects : string ;
92+ openSnackbar : boolean ;
93+ snackBarMessage : string ;
9194}
9295
9396class ListObjects extends React . Component <
@@ -104,6 +107,8 @@ class ListObjects extends React.Component<
104107 selectedObject : "" ,
105108 selectedBucket : "" ,
106109 filterObjects : "" ,
110+ openSnackbar : false ,
111+ snackBarMessage : "" ,
107112 } ;
108113
109114 fetchRecords = ( ) => {
@@ -141,6 +146,73 @@ class ListObjects extends React.Component<
141146 } ) ;
142147 }
143148
149+ showSnackBarMessage ( text : string ) {
150+ this . setState ( { openSnackbar : true , snackBarMessage : text } ) ;
151+ }
152+
153+ closeSnackBar ( ) {
154+ this . setState ( { openSnackbar : false , snackBarMessage : `` } ) ;
155+ }
156+
157+ upload ( e : any , bucketName : string , path : string ) {
158+ let listObjects = this ;
159+ if ( isNullOrUndefined ( e ) || isNullOrUndefined ( e . target ) ) {
160+ return ;
161+ }
162+ const token : string = storage . getItem ( "token" ) ! ;
163+ e . preventDefault ( ) ;
164+ let file = e . target . files [ 0 ] ;
165+ const fileName = file . name ;
166+
167+ const objectName = `${ path } ${ fileName } ` ;
168+ let uploadUrl = `/api/v1/buckets/${ bucketName } /objects/upload?prefix=${ objectName } ` ;
169+ let xhr = new XMLHttpRequest ( ) ;
170+
171+ xhr . open ( "POST" , uploadUrl , true ) ;
172+ xhr . setRequestHeader ( "Authorization" , `Bearer ${ token } ` ) ;
173+
174+ xhr . withCredentials = false ;
175+ xhr . onload = function ( event ) {
176+ // TODO: handle status
177+ if ( xhr . status == 401 || xhr . status == 403 ) {
178+ listObjects . showSnackBarMessage (
179+ "An error occurred while uploading the file."
180+ ) ;
181+ }
182+ if ( xhr . status == 500 ) {
183+ listObjects . showSnackBarMessage (
184+ "An error occurred while uploading the file."
185+ ) ;
186+ }
187+ if ( xhr . status == 200 ) {
188+ listObjects . showSnackBarMessage ( "Object uploaded successfully." ) ;
189+ listObjects . fetchRecords ( ) ;
190+ }
191+ } ;
192+
193+ xhr . upload . addEventListener ( "error" , ( event ) => {
194+ // TODO: handle error
195+ this . showSnackBarMessage ( "An error occurred while uploading the file." ) ;
196+ } ) ;
197+
198+ xhr . upload . addEventListener ( "progress" , ( event ) => {
199+ // TODO: handle progress with event.loaded, event.total
200+ } ) ;
201+
202+ xhr . onerror = ( ) => {
203+ listObjects . showSnackBarMessage (
204+ "An error occurred while uploading the file."
205+ ) ;
206+ } ;
207+
208+ var formData = new FormData ( ) ;
209+ var blobFile = new Blob ( [ file ] ) ;
210+
211+ formData . append ( "upfile" , blobFile ) ;
212+ xhr . send ( formData ) ;
213+ e . target . value = null ;
214+ }
215+
144216 download ( bucketName : string , objectName : string ) {
145217 var anchor = document . createElement ( "a" ) ;
146218 document . body . appendChild ( anchor ) ;
@@ -184,9 +256,11 @@ class ListObjects extends React.Component<
184256 selectedBucket,
185257 deleteOpen,
186258 filterObjects,
259+ snackBarMessage,
260+ openSnackbar,
187261 } = this . state ;
188262 const displayParsedDate = ( date : string ) => {
189- return < Moment > { date } </ Moment > ;
263+ return < reactMoment . default > { date } </ reactMoment . default > ;
190264 } ;
191265
192266 const confirmDeleteObject = ( object : string ) => {
@@ -197,6 +271,25 @@ class ListObjects extends React.Component<
197271 this . download ( selectedBucket , object ) ;
198272 } ;
199273
274+ const uploadObject = ( e : any ) : void => {
275+ // TODO: handle deeper paths/folders
276+ let file = e . target . files [ 0 ] ;
277+ this . showSnackBarMessage ( `Uploading: ${ file . name } ` ) ;
278+ this . upload ( e , selectedBucket , "" ) ;
279+ } ;
280+
281+ const snackBarAction = (
282+ < Button
283+ color = "secondary"
284+ size = "small"
285+ onClick = { ( ) => {
286+ this . closeSnackBar ( ) ;
287+ } }
288+ >
289+ Dismiss
290+ </ Button >
291+ ) ;
292+
200293 const tableActions = [
201294 { type : "download" , onClick : downloadObject , sendOnlyId : true } ,
202295 { type : "delete" , onClick : confirmDeleteObject , sendOnlyId : true } ,
@@ -226,6 +319,11 @@ class ListObjects extends React.Component<
226319 } }
227320 />
228321 ) }
322+ < Snackbar
323+ open = { openSnackbar }
324+ message = { snackBarMessage }
325+ action = { snackBarAction }
326+ />
229327 < PageHeader label = "Objects" />
230328 < Grid container >
231329 < Grid item xs = { 12 } className = { classes . container } >
@@ -249,6 +347,23 @@ class ListObjects extends React.Component<
249347 ) ,
250348 } }
251349 />
350+
351+ < >
352+ < Button
353+ variant = "contained"
354+ color = "primary"
355+ startIcon = { < CreateIcon /> }
356+ component = "label"
357+ >
358+ Upload Object
359+ < Input
360+ type = "file"
361+ onChange = { ( e ) => uploadObject ( e ) }
362+ id = "file-input"
363+ style = { { display : "none" } }
364+ />
365+ </ Button >
366+ </ >
252367 </ Grid >
253368 < Grid item xs = { 12 } >
254369 < br />
0 commit comments