Preview: http://dashboards.webkom.co/react/airframe
This commit is contained in:
Tomasz Owczarczyk
2019-08-15 00:54:44 +02:00
parent f975443095
commit 37092d1d6c
626 changed files with 56691 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
import React from 'react';
import classNames from 'classnames';
import FileDrop from 'react-dropzone';
import _ from 'lodash';
import {
Container,
Divider,
Badge,
Button,
ButtonGroup
} from './../../../components';
import {
FilesGrid,
FilesList
} from './components';
import { HeaderMain } from "../../components/HeaderMain";
export class Dropzone extends React.Component {
state = {
isOver: false,
files: [],
listStyle: 'grid'
}
render() {
const { isOver, files, listStyle } = this.state;
const dropzoneClass = classNames({
'dropzone--active': isOver
}, 'dropzone');
return (
<Container>
<HeaderMain
title="Dropzone"
className="mb-5 mt-4"
/>
{ /* DropZone */ }
<div className="mb-4">
<p className="mb-3">
Simple HTML5-compliant drag&apos;n&apos;drop zone for files built with React.js.
</p>
<FileDrop
multiple
onDragEnter={() => { this.setState({isOver: true}) }}
onDragLeave={() => { this.setState({isOver: false}) }}
onDrop={this._filesDropped}
>
{
({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className={dropzoneClass}>
<i className="fa fa-cloud-upload fa-fw fa-3x mb-3"></i>
<h5 className='mt-0'>
Upload Your files
</h5>
<p>
Drag a file here or <span className='text-primary'>browse</span> for a file to upload.
</p>
<p className="small">
JPG, GIF, PNG, MOV, and AVI. Please choose files under 2GB for upload. File sizes are 400x300px.
</p>
<input { ...getInputProps() } />
</div>
)
}
</FileDrop>
</div>
{ /* Files List */}
{
files.length > 0 && (
<div className="mt-2">
<div className="d-flex">
<Divider
position="left"
className="flex-shrink-1 flex-grow-1"
>
<div className="px-2">
Attachments
<Badge
className="ml-1 text-white"
pill
color="secondary"
>
{ files.length }
</Badge>
</div>
</Divider>
<ButtonGroup className="flex-grow-0 flex-shrink-0 pl-2">
<Button
active={ listStyle === 'list' }
onClick={() => {this.setState({listStyle: 'list'})}}
size="sm"
outline
>
<i className='fa fa-bars fa-fw'></i>
</Button>
<Button
active={ listStyle === 'grid' }
onClick={() => {this.setState({listStyle: 'grid'})}}
size="sm"
outline
>
<i className='fa fa-th-large fa-fw'></i>
</Button>
</ButtonGroup>
</div>
{
listStyle === 'grid' ?
<FilesGrid files={ files } onFileRemove={this._removeFile} /> :
<FilesList files={ files } onFileRemove={this._removeFile} />
}
</div>
)
}
</Container>
);
}
_filesDropped = (files) => {
this.setState({
files: [...this.state.files, ...files],
isOver: false
})
}
_removeFile = (file) => {
this.setState({
files: _.reject(this.state.files, file)
})
}
}

View File

@@ -0,0 +1,64 @@
import React from 'react';
import _ from 'lodash';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import numeral from 'numeral';
import moment from 'moment';
import {
Col,
Row,
Card,
CardBody,
Button,
UncontrolledTooltip
} from './../../../../components';
import classes from './common.scss';
import {
getFileIcon
} from './../utilities';
export const FilesGrid = ({ files, onFileRemove }) => (
<Row className="mt-4">
{
_.map(files, (file, index) => (
<Col lg={ 4 } md={ 6 } key={index}>
<Card className="mb-3">
<div className={ classNames("card-img-top", classes['ph--large']) }>
<i className={`fa fa-fw fa-3x ${getFileIcon(file)}`} />
</div>
<CardBody className="pt-2">
<div className="d-flex align-items-center mb-0 mt-0">
<h6 className="text-truncate mb-0">
{ file.name }
</h6>
<Button
color="link"
onClick={() => {onFileRemove(file)}}
size="sm"
id={`delete-file-${index}`}
>
<i className="fa fa-times fa-fw text-danger"></i>
</Button>
<UncontrolledTooltip placement="left" target={`delete-file-${index}`}>
Delete File
</UncontrolledTooltip>
</div>
<div className="mb-0">
by You &middot; <span className='text-uppercase'>{`${numeral(file.size).format('0.00a')}B`}</span>
</div>
<div className='mb-0'>
{ moment(file.modifiedDate).format('DD-MMM-YYYY, HH:mm') }
</div>
</CardBody>
</Card>
</Col>
))
}
</Row>
);
FilesGrid.propTypes = {
files: PropTypes.array,
onFileRemove: PropTypes.func
}

View File

@@ -0,0 +1,73 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import numeral from 'numeral';
import moment from 'moment';
import {
Table,
Button,
UncontrolledTooltip
} from './../../../../components';
import classes from './common.scss';
import {
getFileIcon
} from './../utilities';
export const FilesList = ({ files, onFileRemove }) => (
<Table responsive hover className="mt-3">
<thead>
<tr>
<th className="bt-0"></th>
<th className="bt-0">File Name</th>
<th className="bt-0">Size</th>
<th className="bt-0">Owner</th>
<th className="bt-0">Modified Date</th>
<th className="bt-0 text-right">Actions</th>
</tr>
</thead>
<tbody>
{
_.map(files, (file, index) => (
<tr key={ index }>
<td className="align-middle">
<div className={ classes['ph--small'] }>
<i className={`fa fa-fw fa-2x ${getFileIcon(file)}`} />
</div>
</td>
<td className="align-middle">
{ file.name }
</td>
<td className="align-middle text-uppercase">
{ numeral(file.size).format('0.00a') }B
</td>
<td className="align-middle">
You
</td>
<td className="align-middle">
{ moment(file.modifiedDate).format('DD-MMM-YYYY, HH:mm') }
</td>
<td className="text-right align-middle">
<Button
color="link"
onClick={() => {onFileRemove(file)}}
size="sm"
id={`delete-file-${index}`}
>
<i className="fa fa-times fa-fw text-danger"></i>
</Button>
<UncontrolledTooltip placement="left" target={`delete-file-${index}`}>
Delete File
</UncontrolledTooltip>
</td>
</tr>
))
}
</tbody>
</Table>
);
FilesList.propTypes = {
files: PropTypes.array,
onFileRemove: PropTypes.func
}

View File

@@ -0,0 +1,25 @@
@import "./../../../../styles/variables.scss";
.ph--large {
display: flex;
align-items: center;
justify-content: center;
min-height: 200px;
background-color: $gray-400;
margin-bottom: 5px;
> i {
color: #fff;
}
}
.ph--small {
display: inline-block;
background-color: $gray-400;
padding: 7px 5px;
border-radius: 7px;
> i {
color: #fff;
}
}

View File

@@ -0,0 +1,2 @@
export * from './FilesGrid';
export * from './FilesList';

View File

@@ -0,0 +1,3 @@
import { Dropzone } from './Dropzone';
export default Dropzone;

View File

@@ -0,0 +1,32 @@
export const typeToIcon = type => {
const map = {
['application/msword']: 'fa-file-word-o',
['application/excel']: 'fa-file-excel-o',
['application/vnd.oasis.opendocument.spreadsheet']: 'fa-file-excel-o',
['application/vnd.oasis.opendocument.presentation']: 'fa-file-powerpoint-o',
['application/mspowerpoint']: 'fa-file-powerpoint-o',
['application/x-zip-compressed']: 'fa-file-archive-o',
['image/jpeg']: 'fa-file-image-o',
['image/png']: 'fa-file-image-o',
['audio/mp3']: 'fa-file-audio-o',
['text/plain']: 'fa-file-text-o'
}
return map[type] || null;
}
export const extToIcon = filename => {
const map = {
['doc']: 'fa-file-word-o',
['docx']: 'fa-file-word-o',
['xls']: 'fa-file-excel-o',
['xlsx']: 'fa-file-excel-o',
['ppt']: 'fa-file-powerpoint-o',
['pdf']: 'fa-file-pdf-o'
}
return map[filename.split('.').pop()] || null;
}
export const getFileIcon = file => {
return typeToIcon(file.type) || extToIcon(file.name) || 'fa-file-o';
}