Initial Commit Rework

This commit is contained in:
Qstick 2017-09-03 22:20:56 -04:00
parent 74a4cc048c
commit 95051cbd63
2483 changed files with 101351 additions and 111396 deletions

View file

@ -0,0 +1,5 @@
.modal {
composes: modal from 'Components/Modal/Modal.css';
height: 600px;
}

View file

@ -0,0 +1,39 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Modal from 'Components/Modal/Modal';
import FileBrowserModalContentConnector from './FileBrowserModalContentConnector';
import styles from './FileBrowserModal.css';
class FileBrowserModal extends Component {
//
// Render
render() {
const {
isOpen,
onModalClose,
...otherProps
} = this.props;
return (
<Modal
className={styles.modal}
isOpen={isOpen}
onModalClose={onModalClose}
>
<FileBrowserModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
</Modal>
);
}
}
FileBrowserModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default FileBrowserModal;

View file

@ -0,0 +1,16 @@
.modalBody {
composes: modalBody from 'Components/Modal/ModalBody.css';
display: flex;
flex-direction: column;
}
.pathInput {
composes: pathInputWrapper from 'Components/Form/PathInput.css';
flex: 0 0 auto;
}
.scroller {
margin-top: 20px;
}

View file

@ -0,0 +1,213 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { scrollDirections } from 'Helpers/Props';
import Button from 'Components/Link/Button';
import Scroller from 'Components/Scroller/Scroller';
import ModalContent from 'Components/Modal/ModalContent';
import ModalHeader from 'Components/Modal/ModalHeader';
import ModalBody from 'Components/Modal/ModalBody';
import ModalFooter from 'Components/Modal/ModalFooter';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import PathInput from 'Components/Form/PathInput';
import FileBrowserRow from './FileBrowserRow';
import styles from './FileBrowserModalContent.css';
const columns = [
{
name: 'type',
label: 'Type',
isVisible: true
},
{
name: 'name',
label: 'Name',
isVisible: true
}
];
class FileBrowserModalContent extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this._scrollerNode = null;
this.state = {
isFileBrowserModalOpen: false,
currentPath: props.value
};
}
componentDidUpdate(prevProps) {
const {
currentPath
} = this.props;
if (currentPath !== this.state.currentPath) {
this.setState({ currentPath });
this._scrollerNode.scrollTop = 0;
}
}
//
// Control
setScrollerRef = (ref) => {
if (ref) {
this._scrollerNode = ReactDOM.findDOMNode(ref);
} else {
this._scrollerNode = null;
}
}
//
// Listeners
onPathInputChange = ({ value }) => {
this.setState({ currentPath: value });
}
onRowPress = (path) => {
this.props.onFetchPaths(path);
}
onOkPress = () => {
this.props.onChange({
name: this.props.name,
value: this.state.currentPath
});
this.props.onClearPaths();
this.props.onModalClose();
}
//
// Render
render() {
const {
parent,
directories,
files,
onModalClose,
...otherProps
} = this.props;
const emptyParent = parent === '';
return (
<ModalContent
onModalClose={onModalClose}
>
<ModalHeader>
File Browser
</ModalHeader>
<ModalBody
className={styles.modalBody}
scrollDirection={scrollDirections.NONE}
>
<PathInput
className={styles.pathInput}
placeholder="Start typing or select a path below"
hasFileBrowser={false}
{...otherProps}
value={this.state.currentPath}
onChange={this.onPathInputChange}
/>
<Scroller
ref={this.setScrollerRef}
className={styles.scroller}
>
<Table columns={columns}>
<TableBody>
{
emptyParent &&
<FileBrowserRow
type="computer"
name="My Computer"
path={parent}
onPress={this.onRowPress}
/>
}
{
!emptyParent && parent &&
<FileBrowserRow
type="parent"
name="..."
path={parent}
onPress={this.onRowPress}
/>
}
{
directories.map((directory) => {
return (
<FileBrowserRow
key={directory.path}
type={directory.type}
name={directory.name}
path={directory.path}
onPress={this.onRowPress}
/>
);
})
}
{
files.map((file) => {
return (
<FileBrowserRow
key={file.path}
type={file.type}
name={file.name}
path={file.path}
onPress={this.onRowPress}
/>
);
})
}
</TableBody>
</Table>
</Scroller>
</ModalBody>
<ModalFooter>
<Button
onPress={onModalClose}
>
Cancel
</Button>
<Button
onPress={this.onOkPress}
>
Ok
</Button>
</ModalFooter>
</ModalContent>
);
}
}
FileBrowserModalContent.propTypes = {
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
parent: PropTypes.string,
currentPath: PropTypes.string.isRequired,
directories: PropTypes.arrayOf(PropTypes.object).isRequired,
files: PropTypes.arrayOf(PropTypes.object).isRequired,
onFetchPaths: PropTypes.func.isRequired,
onClearPaths: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default FileBrowserModalContent;

View file

@ -0,0 +1,86 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { fetchPaths, clearPaths } from 'Store/Actions/pathActions';
import FileBrowserModalContent from './FileBrowserModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.paths,
(paths) => {
const {
parent,
currentPath,
directories,
files
} = paths;
const filteredPaths = _.filter([...directories, ...files], ({ path }) => {
return path.toLowerCase().startsWith(currentPath.toLowerCase());
});
return {
parent,
currentPath,
directories,
files,
paths: filteredPaths
};
}
);
}
const mapDispatchToProps = {
fetchPaths,
clearPaths
};
class FileBrowserModalContentConnector extends Component {
// Lifecycle
componentDidMount() {
this.props.fetchPaths({ path: this.props.value });
}
//
// Listeners
onFetchPaths = (path) => {
this.props.fetchPaths({ path });
}
onClearPaths = () => {
// this.props.clearPaths();
}
onModalClose = () => {
this.props.clearPaths();
this.props.onModalClose();
}
//
// Render
render() {
return (
<FileBrowserModalContent
onFetchPaths={this.onFetchPaths}
onClearPaths={this.onClearPaths}
{...this.props}
onModalClose={this.onModalClose}
/>
);
}
}
FileBrowserModalContentConnector.propTypes = {
value: PropTypes.string,
fetchPaths: PropTypes.func.isRequired,
clearPaths: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(FileBrowserModalContentConnector);

View file

@ -0,0 +1,5 @@
.type {
composes: cell from 'Components/Table/Cells/TableRowCell.css';
width: 32px;
}

View file

@ -0,0 +1,62 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { icons } from 'Helpers/Props';
import Icon from 'Components/Icon';
import TableRowButton from 'Components/Table/TableRowButton';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import styles from './FileBrowserRow.css';
function getIconName(type) {
switch (type) {
case 'computer':
return icons.COMPUTER;
case 'drive':
return icons.DRIVE;
case 'file':
return icons.FILE;
case 'parent':
return icons.PARENT;
default:
return icons.FOLDER;
}
}
class FileBrowserRow extends Component {
//
// Listeners
onPress = () => {
this.props.onPress(this.props.path);
}
//
// Render
render() {
const {
type,
name
} = this.props;
return (
<TableRowButton onPress={this.onPress}>
<TableRowCell className={styles.type}>
<Icon name={getIconName(type)} />
</TableRowCell>
<TableRowCell>{name}</TableRowCell>
</TableRowButton>
);
}
}
FileBrowserRow.propTypes = {
type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
onPress: PropTypes.func.isRequired
};
export default FileBrowserRow;