UNPKG

meteor-interface

Version:

Simple Content Management System to generate your administration interface for Meteor and React.

306 lines (282 loc) 11.8 kB
import React, { Component } from 'react'; import { Transition, Spring } from 'react-spring'; import { withTracker } from 'meteor/react-meteor-data'; // Packages import { Segment, Header, Button, Modal, List, Image, Icon, } from 'semantic-ui-react'; import styled from 'styled-components'; // Components import Confirmation from '../../components/Confirmation'; import ErrorHandler from '../../../utils/ErrorHandler'; import FolderCreator from './FolderCreator'; import FileCreator from './FileCreator'; class MediaBrowser extends Component { state = { changes: false, loaded: false, path: '/', files: [], folders: [], route: '/', error: null, loading: false } componentDidMount(){ this.goFolder() } goFolder = (file) => { const method = 'interface.media.list.directories'; this.setState({ confirmation: false, loading: true }) const self = this Meteor.call(method, { path: file }, function(error, result = {} ){ self.setState({ loading: false }) if(result){ const { CommonPrefixes, Contents, Prefix, link, err } = result console.log(result) if(err){ self.setState({ error: err }) } else { self.setState({ folders: CommonPrefixes, files: Contents, route: Prefix, link }) } } else if (error){ notify.error(error.reason) } }) } deleteObject = () => { const { objectToDelete, route } = this.state const method = 'interface.media.delete.object'; this.setState({ confirmation: false, loading: true }) const self = this Meteor.call(method, { file: objectToDelete }, function(error, result = {} ){ self.setState({ loading: false }) if(result){ console.log(result) self.goFolder(route) self.closeConfirm() } else if (error){ notify.error(error.reason) self.closeConfirm() } }) } closeConfirm = () => this.setState({ confirmation: false}) openConfirmDeletionObject = (object) => { this.setState({ confirmation: true, objectToDelete: object, confirmationObject: { title: "Are you sure ?", text: `You're about to delete ${object.replace(this.state.route, '')}`, cancel: this.closeConfirm, confirm: this.deleteObject, } }) } togglePictureModal = (object) => this.setState({ selectedPicture: object }); render(){ const { changes, loaded, confirmation, confirmationObject, loading, folders, files, route, link, error, selectedPicture } = this.state; const { interfaceSettings = {}, history, ready, selector, updatePicture, currentPicture, config } = this.props; if(error){ throw new Error(error.message) } const refresh = () =>this.goFolder(route) const isAuthorized = Roles.userIsInRole(Meteor.userId(), config.media_roles); return( <MediaBrowserStyle> <Spring from={{ opacity: 0, marginLeft: 600 }} to={{ opacity: 1, marginLeft: 0 }}> { styles => <Segment style={{...styles, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> <Header content='Media Manager' as="h5" /> <div> <Button icon="refresh" onClick={refresh} color="teal" size='mini' labelPosition="left" content="Refresh" /> {isAuthorized && <FileCreator refresh={refresh} route={route} />} {isAuthorized && <FolderCreator refresh={refresh} route={route} />} </div> </Segment> } </Spring> <Spring from={{ opacity: 0, marginTop: 600 }} to={{ opacity: 1, marginTop: 0 }}> { styles => <Segment loading={loading} style={styles} color="green" className="browser-container"> <List divided relaxed size='huge'> { route !== '' && <List.Item key={Random.id()}> <Icon name="left arrow" color="green" /> <List.Content> <List.Header onClick={() => this.goFolder('')} >Go Back</List.Header> </List.Content> </List.Item> } { folders.map((folder, i) => { const onClick = () => this.goFolder(folder.Prefix) return ( <List.Item key={Random.id()}> {isAuthorized && <List.Content floated='right'> <Button icon="trash" circular size="small" color="red" onClick={() => this.openConfirmDeletionObject(folder.Prefix)} /> </List.Content>} <Icon name="folder" /> <List.Content> <List.Header onClick={onClick} >{folder.Prefix.replace(route, '')}</List.Header> </List.Content> </List.Item> ) }) } { files.map((file, i) => { const isImage = file.Key.match(/\.(jpeg|jpg|gif|png|svg)$/) const isRoot = file.Key === route const onClick = () => this.goFolder(folder.Prefix) if(isRoot){ return null } else if(!isImage){ return( <List.Item key={Random.id()}> { isAuthorized && <List.Content floated='right'> <Button icon="trash" circular size="small" color="red" onClick={() => this.openConfirmDeletionObject(file.Key)} /> </List.Content>} <Icon name="file" /> <List.Content> <List.Header onClick={onClick} >{file.Key.replace(route, '')}</List.Header> </List.Content> </List.Item> ) } return ( <List.Item key={Random.id()} className={currentPicture === link + file.Key ? "active-picture" : null }> { isAuthorized && <List.Content floated='right'> <Button icon="trash" circular size="small" color="red" onClick={() => this.openConfirmDeletionObject(file.Key)} /> </List.Content>} <Image size="mini" src={link + file.Key} /> <List.Content> <List.Header onClick={ selector ? (e) => updatePicture(e, link + file.Key) : () => this.togglePictureModal(file) } > {file.Key.replace(route, '')} </List.Header> </List.Content> </List.Item> ) }) } </List> </Segment> } </Spring> <Confirmation confirmation={confirmation} loading={loading} confirmationObject={confirmationObject} /> {!!selectedPicture && <PictureModal link={link + selectedPicture.Key} togglePictureModal={this.togglePictureModal} selectedPicture={selectedPicture} /> } </MediaBrowserStyle> ) } } export default ErrorHandler(MediaBrowser) const MediaBrowserStyle = styled.div` h5.header { letter-spacing:2px; margin-bottom: 0; } .button { transition: all 0.3s ease-in !important; } .browser-container { min-height: 200px; .item { display: flex; align-items: center; transition: all 0.2s ease-in; cursor: pointer; &:hover { color: #21ba45 !important; text-shadow: 1px 1px 2px rgba(150, 150, 150, 1); } .content { } } .active-picture { color: #21ba45 !important; } } ` const PictureModal = ({ selectedPicture, link, togglePictureModal }) => ( <Modal size='small' open={!!selectedPicture} > <Icon name="close" onClick={() => togglePictureModal()} /> <Header icon='picture' content='Picture' /> <Modal.Content style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-around', flexDirection: 'column' }} > <Image size="big" src={link} /> </Modal.Content> </Modal> )