beautify (code): improve code + fixes

This commit is contained in:
Mickael KERJEAN 2018-04-05 04:49:55 +10:00
parent d88c845a06
commit 50749a1b6c
13 changed files with 144 additions and 103 deletions

View file

@ -10,11 +10,11 @@ export { Loader } from './loader';
export { Error } from './error';
export { Fab } from './fab';
export { Icon } from './icon';
export { Notification } from './notification';
export { Uploader } from './uploader';
export { Bundle } from './bundle';
export { Modal } from './modal';
export { Prompt } from './prompt';
export { ModalPrompt } from './prompt';
export { Notification } from './notification';
export { Alert } from './alert';
export { Audio } from './audio';
export { Video } from './video';

View file

@ -2,49 +2,51 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Input, Button, Modal, NgIf } from './';
import { prompt } from '../helpers/';
export class Prompt extends React.Component {
export class ModalPrompt extends React.Component {
constructor(props){
super(props);
this.state = {
error: this.props.error,
value: ''
appear: false
};
if(this.props.error) window.setTimeout(() => this.setState({error: ''}), 2000);
}
componentWillReceiveProps(props){
if(props.error !== this.state.error){
this.setState({error: props.error});
window.setTimeout(() => this.setState({error: ''}), 2000);
}
componentDidMount(){
prompt.subscribe((text, okCallback, cancelCallback, type) => {
console.log("REQUEST FOR PROMPT");
this.setState({
appear: true,
error: null,
type: type || 'text',
text: text || '',
fns: {ok: okCallback, cancel: cancelCallback}
});
});
}
onCancel(should_clear){
if(this.props.onCancel) this.props.onCancel();
onCancel(){
this.setState({appear: false});
this.state.fns.cancelCallback();
}
onSubmit(e){
e && e.preventDefault && e.preventDefault();
if(this.props.onSubmit) this.props.onSubmit(this.state.value);
}
onInputChange(value){
this.setState({value: value});
this.state.fns.okCallback(this.state.value)
.then(() => this.setState({appear: false}))
.catch((message) => this.setState({error: message}));
}
render() {
return (
<Modal isActive={this.props.appear} onQuit={this.onCancel.bind(this)}>
<Modal isActive={this.state.appear} onQuit={this.onCancel.bind(this)}>
<div className="component_prompt">
<p className="modal-message">
{this.props.message}
{this.state.text}
</p>
<form onSubmit={this.onSubmit.bind(this)}>
<Input autoFocus={true} value={this.state.value} type={this.props.type || 'text'} autoComplete="new-password" onChange={(e) => this.onInputChange(e.target.value)} />
<Input autoFocus={true} value={this.state.value} type={this.state.type} autoComplete="new-password" onChange={(e) => this.setState({value: e.target.value})} />
<div className="modal-error-message">{this.state.error}&nbsp;</div>
<div className="buttons">
<Button type="button" onClick={this.onCancel.bind(this)}>CANCEL</Button>
<Button type="submit" theme="secondary" onClick={this.onSubmit.bind(this)}>OK</Button>
@ -55,12 +57,3 @@ export class Prompt extends React.Component {
);
}
}
Prompt.propTypes = {
appear: PropTypes.bool.isRequired,
type: PropTypes.string,
message: PropTypes.string.isRequired,
error: PropTypes.string,
onCancel: PropTypes.func,
onConfirm: PropTypes.func
};

8
client/helpers/dom.js Normal file
View file

@ -0,0 +1,8 @@
export function screenHeight(){
const $breadcrumb = document.querySelector(".breadcrumb");
let size = document.body.clientHeight;
if($breadcrumb){
size -= $breadcrumb.clientHeight;
}
return size;
}

View file

@ -8,3 +8,5 @@ export { pathBuilder, basename, dirname } from './path';
export { memory } from './memory';
export { prepare } from './navigate';
export { invalidate, http_get, http_post, http_delete } from './ajax';
export { screenHeight } from './dom';
export { prompt } from './prompt';

20
client/helpers/prompt.js Normal file
View file

@ -0,0 +1,20 @@
import { Observable } from 'rxjs/Observable';
const Prompt = function (){
let obs = null;
return {
emit: function(text, okCallback, cancelCallbck, type){
console.log(obs);
obs.emit(text, okCallback, cancelcallBack, type);
},
subscribe: function(){
console.log("> SUBSCRIBE")
return new Observable((_obs) => {
console.log(_obs);
obs = _obs;
});
}
}
}
export const prompt = new Prompt();

View file

@ -8,7 +8,7 @@ import { ForkMe, RememberMe, Credentials, Form } from './connectpage/';
import { cache } from '../helpers/';
import config from '../../config_client';
import { Alert, Prompt } from '../components/';
import { Alert } from '../components/';
export class ConnectPage extends React.Component {
constructor(props){

View file

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import { Prompt } from '../../components/';
import { ModalPrompt } from '../../components/';
import { encrypt, decrypt, memory } from '../../helpers/';
export class Credentials extends React.Component {
@ -91,7 +91,7 @@ export class Credentials extends React.Component {
render() {
return (
<Prompt
<ModalPrompt
type="password"
appear={this.state.modal_appear}
error={this.state.error}

View file

@ -7,7 +7,7 @@ import Path from 'path';
import './filespage.scss';
import { Files } from '../model/';
import { NgIf, Loader, Error, Uploader, EventReceiver } from '../components/';
import { debounce, goToFiles, goToViewer, event } from '../helpers/';
import { debounce, goToFiles, goToViewer, event, screenHeight } from '../helpers/';
import { BreadCrumb, FileSystem } from './filespage/';
@EventReceiver
@ -18,7 +18,7 @@ export class FilesPage extends React.Component {
this.state = {
path: props.match.url.replace('/files', '') || '/',
files: [],
loading: false,
loading: true,
error: false,
height: null
};
@ -29,23 +29,21 @@ export class FilesPage extends React.Component {
}
componentDidMount(){
this.onPathUpdate(this.state.path, 'directory');
this.onRefresh(this.state.path, 'directory');
// subscriptions
this.props.subscribe('file.select', this.onPathUpdate.bind(this));
this.props.subscribe('file.upload', this.onUpload.bind(this));
this.props.subscribe('file.create', this.onCreate.bind(this));
this.props.subscribe('file.rename', this.onRename.bind(this));
this.props.subscribe('file.delete', this.onDelete.bind(this));
this.props.subscribe('file.refresh', this.onRefresh.bind(this));
this.resetHeight();
this.hideError();
this.resetHeight();
window.addEventListener("resize", this.resetHeight);
}
componentWillUnmount() {
this.props.unsubscribe('file.select');
this.props.unsubscribe('file.upload');
this.props.unsubscribe('file.create');
this.props.unsubscribe('file.rename');
@ -112,8 +110,7 @@ export class FilesPage extends React.Component {
name: file.name,
type: 'file',
size: file.size,
icon: 'loading',
virtual: true
icon: 'loading'
};
});
const files = JSON.parse(JSON.stringify(this.state.files));
@ -204,17 +201,15 @@ export class FilesPage extends React.Component {
<div className="component_page_filespage">
<BreadCrumb className="breadcrumb" path={this.state.path} />
<div style={{height: this.state.height+'px'}} className="scroll-y">
<NgIf className="container" cond={!this.state.loading}>
<NgIf className="container" cond={this.state.loading === false}>
<FileSystem path={this.state.path} files={this.state.files} />
<Uploader path={this.state.path} />
</NgIf>
<NgIf cond={this.state.loading}>
<NgIf cond={this.state.error === false}>
<Loader/>
</NgIf>
<NgIf className="error" cond={this.state.error !== false} onClick={this.componentDidMount.bind(this)}>
<NgIf cond={!!this.state.error} className="error" onClick={this.componentDidMount.bind(this)}>
<Error err={this.state.error}/>
</NgIf>
<NgIf cond={this.state.loading && !this.state.error}>
<Loader/>
</NgIf>
</div>
</div>

View file

@ -81,19 +81,12 @@ export class ExistingThing extends React.Component {
hover: null,
message: null,
filename: props.file.name,
delete_request: false,
delete_message: "Confirm by tapping \""+this._confirm_delete_text()+"\"",
delete_error: ''
is_renaming: false
};
}
onSelect(){
if(this.state.icon !== 'loading' && this.state.icon !== 'error'){
this.props.emit(
'file.select',
pathBuilder(this.props.path, this.props.file.name, this.props.file.type),
this.props.file.type
);
}
}
@ -108,8 +101,28 @@ export class ExistingThing extends React.Component {
}
}
onRenameRequest(){
this.setState({is_renaming: !this.state.is_renaming});
}
onDeleteRequest(filename){
this.setState({delete_request: true});
console.log(prompt);
prompt.emit(
"Confirm by tapping \""+this._confirm_delete_text()+"\"",
(answer) => { // click on ok
if(answer === this._confirm_delete_text()){
this.setState({icon: 'loading'});
this.props.emit(
'file.delete',
pathBuilder(this.props.path, this.props.file.name),
this.props.file.type
);
return Promise.resolve();
}else{
return Promise.reject("Doesn't match");
}
},
() => { /* click on cancel */ });
}
onDeleteConfirm(answer){
if(answer === this._confirm_delete_text()){
@ -137,9 +150,6 @@ export class ExistingThing extends React.Component {
if(this.props.isDragging) {
className += "is-dragging ";
}
if(this.state.hover === true){
className += "mouse-is-hover ";
}
if((this.props.fileIsOver && this.props.canDropFile) || (this.props.nativeFileIsOver && this.props.canDropNativeFile)) {
className += "file-is-hover ";
}
@ -170,57 +180,32 @@ ExistingThing.PropTypes = {
canDropNativeFile: PropTypes.bool.isRequired
}
class Updater extends React.Component {
class Filename extends React.Component {
constructor(props){
super(props);
this.state = {
editing: null
filename: props.filename
};
}
onRename(e){
e.preventDefault();
this.props.onRename(this.state.editing);
this.setState({editing: null});
}
onDelete(e){
e.stopPropagation();
this.props.onDelete();
this.props.onRename(this.state.filename);
}
onRenameRequest(e){
e.stopPropagation();
if(this.state.editing === null){
this.setState({editing: this.props.filename});
}else{
this.setState({editing: null});
}
}
preventSelect(e){
e.stopPropagation();
e.preventDefault();
}
render(){
return (
<span className="component_updater">
<NgIf className="action" cond={this.props.show}>
<NgIf cond={this.props.can_move} type="inline">
<Icon name="edit" onClick={this.onRenameRequest.bind(this)} className="component_updater--icon" />
</NgIf>
<NgIf cond={this.props.can_delete !== false} type="inline">
<Icon name="delete" onClick={this.onDelete.bind(this)} className="component_updater--icon"/>
</NgIf>
</NgIf>
<Icon className="component_updater--icon" name={this.props.icon} />
<span className="component_filename">
<span className="file-details">
<NgIf cond={this.state.editing === null} type='inline'>{this.props.filename}</NgIf>
<NgIf cond={this.state.editing !== null} type='inline'>
<NgIf cond={this.props.is_renaming === false} type='inline'>{this.state.filename}</NgIf>
<NgIf cond={this.props.is_renaming === true} type='inline'>
<form onClick={this.preventSelect} onSubmit={this.onRename.bind(this)}>
<input value={this.state.editing} onChange={(e) => this.setState({editing: e.target.value})} autoFocus />
<input value={this.state.filename} onChange={(e) => this.setState({filename: e.target.value})} autoFocus />
</form>
</NgIf>
</span>
@ -229,6 +214,30 @@ class Updater extends React.Component {
}
}
const ActionButton = (props) => {
const onRename = (e) => {
console.log(props);
e.preventDefault();
props.onClickRename();
};
const onDelete = (e) => {
e.preventDefault();
props.onClickDelete();
};
return (
<div className="component_action">
<NgIf cond={props.can_move === true} type="inline">
<Icon name="edit" onClick={onRename} className="component_updater--icon" />
</NgIf>
<NgIf cond={props.can_delete === true} type="inline">
<Icon name="delete" onClick={onDelete} className="component_updater--icon"/>
</NgIf>
</div>
);
}
const DateTime = (props) => {
function displayTime(timestamp){
function padding(number){

View file

@ -1,6 +1,6 @@
export { HomePage } from './homepage';
export { ConnectPage } from './connectpage';
export { LogoutPage } from './logout';
export { NotFoundPage } from './notfound';
export { NotFoundPage } from './notfoundpage';
export { FilesPage } from './filespage';
export { ViewerPage } from './viewerpage';

View file

@ -3,7 +3,7 @@ import Path from 'path';
import { Files } from '../model/';
import { BreadCrumb, Bundle, NgIf, Loader, Error, Container, EventReceiver, EventEmitter } from '../components/';
import { debounce, opener } from '../helpers/';
import { debounce, opener, screenHeight } from '../helpers/';
import { AudioPlayer, FileDownloader, ImageViewer, PDFViewer } from './viewerpage/';
const VideoPlayer = (props) => (
@ -29,9 +29,11 @@ export class ViewerPage extends React.Component {
needSaving: false,
isSaving: false,
loading: true,
error: false
error: false,
height: 0
};
this.props.subscribe('file.select', this.onPathUpdate.bind(this));
this.resetHeight = debounce(this.resetHeight.bind(this), 100);
}
componentWillMount(){
@ -48,6 +50,7 @@ export class ViewerPage extends React.Component {
if(err && err.code === 'CANCELLED'){ return; }
if(err.code === 'BINARY_FILE'){
Files.url(this.state.path).then((url) => {
console.log(this.state.path);
this.setState({data: url, loading: false, opener: 'download'});
}).catch(err => {
this.setState({error: err});
@ -68,8 +71,13 @@ export class ViewerPage extends React.Component {
componentWillUnmount() {
this.props.unsubscribe('file.select');
window.removeEventListener("resize", this.resetHeight);
}
componentDidMount(){
this.resetHeight();
window.addEventListener("resize", this.resetHeight);
}
save(file){
this.setState({isSaving: true});
@ -97,12 +105,18 @@ export class ViewerPage extends React.Component {
this.setState({needSaving: bool});
}
resetHeight(){
this.setState({
height: screenHeight()
});
}
render() {
let style = {height: '100%'};
let style = {height: '100%'}; // {{height: this.state.height+'px'}}
return (
<div style={style}>
<BreadCrumb needSaving={this.state.needSaving} className="breadcrumb" path={this.state.path} />
<div style={style}>
<div style={{height: this.state.height+'px'}}>
<NgIf cond={this.state.loading === false} style={style}>
<NgIf cond={this.state.opener === 'editor'} style={style}>
<IDE needSaving={this.needSaving.bind(this)}

View file

@ -39,7 +39,6 @@
font-size: 70%;
}
/* Highlight Theme */
.cm-s-default .cm-header {color: #3E7AA6; font-size: 1.15em;}
.cm-s-default .cm-keyword {color: #3E7AA6;}

View file

@ -2,7 +2,7 @@ import React from 'react';
import { BrowserRouter, Route, IndexRoute, Switch } from 'react-router-dom';
import { NotFoundPage, ConnectPage, HomePage, LogoutPage, FilesPage, ViewerPage } from './pages/';
import { Bundle, URL_HOME, URL_FILES, URL_VIEWER, URL_LOGIN, URL_LOGOUT } from './helpers/';
import { Audio, Video } from './components/';
import { ModalPrompt, Audio, Video } from './components/';
export default class AppRouter extends React.Component {
render() {
@ -20,6 +20,7 @@ export default class AppRouter extends React.Component {
</Switch>
</div>
</BrowserRouter>
<ModalPrompt />
</div>
);
}