feat files: Create files and Directories
fix styles.shadows: Follow Material Design's shadow and elevation guide, I like it. 😍
This commit is contained in:
@ -1,15 +1,16 @@
|
||||
import { CREATE_FILE, SHARE_FILE, RENAME_FILE, ACTIVE_FILE, DELETE_FILE } from 'actions/types';
|
||||
|
||||
export function create(path, name) {
|
||||
export function create(path, directory = false) {
|
||||
return {
|
||||
type: CREATE_FILE,
|
||||
path, name
|
||||
path, directory
|
||||
}
|
||||
}
|
||||
|
||||
export function share() {
|
||||
export function share(path) {
|
||||
return {
|
||||
type: SHARE_FILE
|
||||
type: SHARE_FILE,
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,8 @@ import Toolbar from 'components/toolbar';
|
||||
import Menu from 'components/menu';
|
||||
import Dialog from 'components/dialog';
|
||||
import { connect } from 'react-redux';
|
||||
import { hideAll } from 'actions/menu';
|
||||
import { hideAll as hideAllMenus } from 'actions/menu';
|
||||
import { hideAll as hideAllDialogs} from 'actions/dialog';
|
||||
|
||||
import changedir from 'actions/changedir';
|
||||
import store from 'store';
|
||||
@ -21,6 +22,7 @@ let DirectoryMenu = connect(state => state.get('directoryMenu'))(Menu);
|
||||
let RenameDialog = connect(state => state.get('renameDialog'))(Dialog);
|
||||
let DeleteDialog = connect(state => state.get('deleteDialog'))(Dialog);
|
||||
let ErrorDialog = connect(state => state.get('errorDialog'))(Dialog);
|
||||
let CreateDialog = connect(state => state.get('createDialog'))(Dialog);
|
||||
|
||||
export default class Root extends Component {
|
||||
render() {
|
||||
@ -38,13 +40,15 @@ export default class Root extends Component {
|
||||
<RenameDialog />
|
||||
<DeleteDialog />
|
||||
<ErrorDialog />
|
||||
<CreateDialog />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
touchStart(e) {
|
||||
if (!e.target.closest('.menu')) {
|
||||
store.dispatch(hideAll());
|
||||
store.dispatch(hideAllMenus());
|
||||
store.dispatch(hideAllDialogs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { create, share } from 'actions/file';
|
||||
import { toggle as toggleView, refresh } from 'actions/files-view';
|
||||
import { bind } from 'store';
|
||||
import { show as showDialog } from 'actions/dialog';
|
||||
import store, { bind } from 'store';
|
||||
|
||||
export default class Toolbar extends Component {
|
||||
render() {
|
||||
@ -10,7 +10,7 @@ export default class Toolbar extends Component {
|
||||
<button className='icon-plus' onClick={this.newFile} />
|
||||
<button className='icon-view' onClick={bind(toggleView())} />
|
||||
<button className='icon-refresh' onClick={bind(refresh())} />
|
||||
<button className='icon-share' onClick={bind(share())} />
|
||||
<button className='icon-share' onClick={this.share} />
|
||||
<button className='icon-more' onClick={this.showMore} />
|
||||
</div>
|
||||
);
|
||||
@ -21,6 +21,10 @@ export default class Toolbar extends Component {
|
||||
}
|
||||
|
||||
newFile() {
|
||||
|
||||
let cwd = store.getState().get('cwd');
|
||||
let action = showDialog('createDialog', {
|
||||
description: `Enter a name for the new file to be created in ${cwd}`
|
||||
});
|
||||
store.dispatch(action);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,41 @@
|
||||
import React from 'react';
|
||||
import { hide, hideAll } from 'actions/dialog';
|
||||
import { rename, deleteFile } from 'actions/file';
|
||||
import { rename, deleteFile, create } from 'actions/file';
|
||||
import store, { bind } from 'store';
|
||||
|
||||
export default {
|
||||
createDialog: {
|
||||
title: 'Create',
|
||||
description: 'Enter a name for the new file',
|
||||
input: true,
|
||||
buttons: [
|
||||
{
|
||||
text: 'File',
|
||||
action() {
|
||||
let input = React.findDOMNode(this.refs.input);
|
||||
|
||||
let cwd = store.getState().get('cwd');
|
||||
let action = create(cwd + input.value);
|
||||
this.props.dispatch(action);
|
||||
this.props.dispatch(hideAll());
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Directory',
|
||||
action() {
|
||||
let input = React.findDOMNode(this.refs.input);
|
||||
|
||||
let cwd = store.getState().get('cwd');
|
||||
let action = create(cwd + input.value, true);
|
||||
this.props.dispatch(action);
|
||||
this.props.dispatch(hideAll());
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
renameDialog: {
|
||||
title: 'Rename',
|
||||
description: 'Enter your desired new name',
|
||||
description: 'Enter the new name',
|
||||
input: true,
|
||||
buttons: [
|
||||
{
|
||||
|
@ -7,8 +7,13 @@ const entryMenu = {
|
||||
{
|
||||
name: 'Rename',
|
||||
action() {
|
||||
let files = store.getState().get('files');
|
||||
let active = store.getState().get('activeFile');
|
||||
const name = files[active].name;
|
||||
const description = `Are you sure you want to remove ${name}?`;
|
||||
|
||||
store.dispatch(hideAll());
|
||||
store.dispatch(show('renameDialog'));
|
||||
store.dispatch(show('renameDialog', {description}));
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -17,9 +22,9 @@ const entryMenu = {
|
||||
let files = store.getState().get('files');
|
||||
let active = store.getState().get('activeFile');
|
||||
const name = files[active].name;
|
||||
const MSG = `Are you sure you want to remove ${name}?`;
|
||||
const description = `Are you sure you want to remove ${name}?`;
|
||||
store.dispatch(hideAll());
|
||||
store.dispatch(show('deleteDialog', {description: MSG}));
|
||||
store.dispatch(show('deleteDialog', {description}));
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -21,6 +21,7 @@ export default function(state = new Immutable.Map(), action) {
|
||||
directoryMenu: menu(state, action, 'directoryMenu'),
|
||||
renameDialog: dialog(state, action, 'renameDialog'),
|
||||
deleteDialog: dialog(state, action, 'deleteDialog'),
|
||||
errorDialog: dialog(state, action, 'errorDialog')
|
||||
errorDialog: dialog(state, action, 'errorDialog'),
|
||||
createDialog: dialog(state, action, 'createDialog')
|
||||
});
|
||||
}
|
||||
|
@ -1,21 +1,28 @@
|
||||
import { LIST_FILES, RENAME_FILE, DELETE_FILE } from 'actions/types';
|
||||
import { LIST_FILES, RENAME_FILE, DELETE_FILE, CREATE_FILE } from 'actions/types';
|
||||
import { refresh } from 'actions/files-view';
|
||||
import { move, sdcard } from 'api/files';
|
||||
import { move, sdcard, createFile, createDirectory } from 'api/files';
|
||||
import { show } from 'actions/dialog';
|
||||
import store from 'store';
|
||||
import store, { bind } from 'store';
|
||||
import { reportError } from 'utils';
|
||||
|
||||
let boundRefresh = bind(refresh());
|
||||
|
||||
export default function(state = [], action) {
|
||||
if (action.type === LIST_FILES) {
|
||||
return action.files;
|
||||
}
|
||||
|
||||
if (action.type === CREATE_FILE) {
|
||||
let fn = action.directory ? createDirectory : createFile;
|
||||
fn(action.path).then(boundRefresh, reportError);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.type === RENAME_FILE) {
|
||||
let file = state[action.file];
|
||||
|
||||
move(file, (file.path || '') + action.name).then(refresh, err => {
|
||||
let action = show('errorDialog', {description: err.message});
|
||||
store.dispatch(action);
|
||||
});
|
||||
move(file, (file.path || '') + action.name).then(boundRefresh, reportError);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import store from 'store';
|
||||
import { show } from 'actions/dialog';
|
||||
|
||||
export function type(obj) {
|
||||
return Object.prototype.toString.call(obj).slice(8, -1);
|
||||
@ -23,3 +24,8 @@ export function getKey(object = store.getState().toJS(), key) {
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
export function reportError(err) {
|
||||
let action = show('errorDialog', {description: err.message});
|
||||
store.dispatch(action);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
background: white;
|
||||
|
||||
.shadow-bottom;
|
||||
.shadow-16;
|
||||
|
||||
z-index: 3;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
transition: opacity 0.5s ease;
|
||||
|
||||
.shadow-bottom;
|
||||
.shadow-8;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
|
@ -12,7 +12,7 @@ nav {
|
||||
background: @dark;
|
||||
color: white;
|
||||
|
||||
box-shadow: 1px 0 5px @dark-transparent;
|
||||
box-shadow: 3px 0 16px 5px @dark-transparent;
|
||||
z-index: 6;
|
||||
|
||||
transition: left 0.5s ease;
|
||||
|
@ -1,5 +1,9 @@
|
||||
.shadow-bottom {
|
||||
box-shadow: 0 1px 2px @dark-transparent;
|
||||
.shadow-16 {
|
||||
box-shadow: 0 15px 24px 6px @dark-transparent;
|
||||
}
|
||||
|
||||
.shadow-8 {
|
||||
box-shadow: 0 8px 16px 3px @dark-transparent;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
|
Reference in New Issue
Block a user