mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-03 13:11:46 +08:00
improvement (UI): make the UI more engaging and "modern"
This commit is contained in:
@ -2,32 +2,28 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Input, Button, Modal, NgIf } from './';
|
||||
import './prompt.scss';
|
||||
import "./alert.scss";
|
||||
|
||||
export class Alert extends React.Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
modal_appear: false
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit(e){
|
||||
e.preventDefault();
|
||||
this.props.onConfirm();
|
||||
this.setState({modal_appear: false});
|
||||
e && e.preventDefault && e.preventDefault();
|
||||
this.props.onConfirm && this.props.onConfirm();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isActive={this.state.modal_appear} onQuit={this.onSubmit.bind(this)}>
|
||||
<Modal isActive={this.props.appear} onQuit={this.onSubmit.bind(this)}>
|
||||
<div className="component_alert">
|
||||
<p>
|
||||
<p className="modal-message">
|
||||
{this.props.message}
|
||||
</p>
|
||||
<form id="key_manager" onSubmit={this.onSubmit.bind(this)}>
|
||||
<form onSubmit={this.onSubmit.bind(this)}>
|
||||
<div className="buttons">
|
||||
<Button type="submit" onClick={this.onSubmit.bind(this)}>OK</Button>
|
||||
<Button type="submit" theme="secondary" onClick={this.onSubmit.bind(this)}>OK</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -37,6 +33,7 @@ export class Alert extends React.Component {
|
||||
}
|
||||
|
||||
Alert.propTypes = {
|
||||
appear: PropTypes.bool.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
onConfirm: PropTypes.func
|
||||
};
|
||||
|
||||
3
client/components/alert.scss
Normal file
3
client/components/alert.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.component_modal > div{
|
||||
padding: 20px 20px 0 20px;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Link } from 'react-router-dom';
|
||||
import { NgIf, Icon, EventEmitter, EventReceiver } from './';
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
|
||||
|
||||
import './breadcrumb.scss';
|
||||
|
||||
export class BreadCrumb extends React.Component {
|
||||
constructor(props){
|
||||
@ -26,7 +29,7 @@ export class BreadCrumb extends React.Component {
|
||||
if(index === paths.length - 1){
|
||||
return {full: null, label: label};
|
||||
}else{
|
||||
return {full: sub_path+'/', label: label}
|
||||
return {full: sub_path+'/', label: label};
|
||||
}
|
||||
});
|
||||
return paths;
|
||||
@ -35,19 +38,21 @@ export class BreadCrumb extends React.Component {
|
||||
render(Element) {
|
||||
const Path = Element? Element : PathElement;
|
||||
return (
|
||||
<div>
|
||||
<div className="component_breadcrumb">
|
||||
<BreadCrumbContainer className={this.props.className+' no-select'}>
|
||||
<Logout />
|
||||
<ReactCSSTransitionGroup transitionName="breadcrumb" transitionLeave={true} transitionEnter={true} transitionLeaveTimeout={500} transitionEnterTimeout={500} transitionAppear={false}>
|
||||
{
|
||||
this.state.path.map((path, index) => {
|
||||
return (
|
||||
<span key={index}>
|
||||
<span key={"breadcrumb_"+index}>
|
||||
<Path path={path} isLast={this.state.path.length === index + 1} needSaving={this.props.needSaving} />
|
||||
<Separator isLast={this.state.path.length === index + 1} />
|
||||
</span>
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
</ReactCSSTransitionGroup>
|
||||
</BreadCrumbContainer>
|
||||
</div>
|
||||
);
|
||||
@ -77,7 +82,7 @@ const Logout = (props) => {
|
||||
display: 'inline-block',
|
||||
padding: '5px 0px 5px 5px',
|
||||
margin: '0 0px'
|
||||
}
|
||||
};
|
||||
return (
|
||||
<li style={style}>
|
||||
<Link to="/logout">
|
||||
@ -176,6 +181,6 @@ export class PathElement extends PathElementWrapper {
|
||||
<div style={{display: 'inline-block', color: this.props.isLast? '#6f6f6f' : 'inherit'}}>
|
||||
<PathElementWrapper highlight={highlight} {...this.props} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
.component_breadcrumb{
|
||||
.breadcrumb-leave{
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
.breadcrumb-leave.breadcrumb-leave-active{
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
transition: all 0.15s ease-out;
|
||||
}
|
||||
|
||||
.breadcrumb-enter{
|
||||
transform: translateX(10px);
|
||||
opacity: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
.breadcrumb-enter.breadcrumb-enter-active{
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
right: 0;
|
||||
background: rgba(0,0,0,0.7);
|
||||
box-shadow: 1px 2px 10px rgba(0,0,0,0.2);
|
||||
z-index: 1000;
|
||||
|
||||
> div{
|
||||
background: white;
|
||||
@ -16,6 +17,40 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.component_prompt, .component_alert{
|
||||
> p{
|
||||
font-size: 1.1em;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
.modal-error-message{
|
||||
color: var(--error);
|
||||
}
|
||||
.buttons{
|
||||
display: flex;
|
||||
[type="submit"]{
|
||||
border-radius: 10px 0 0;
|
||||
}
|
||||
> button{
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.component_prompt .buttons{
|
||||
margin: 15px -20px;
|
||||
> p{
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.component_alert .buttons{
|
||||
margin: 25px -20px 15px -20px;
|
||||
> p{
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* ENTERING TRANSITION */
|
||||
// background
|
||||
|
||||
@ -2,41 +2,48 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Input, Button, Modal, NgIf } from './';
|
||||
import './prompt.scss';
|
||||
|
||||
export class Prompt extends React.Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
modal_appear: false,
|
||||
error: ''
|
||||
error: this.props.error,
|
||||
value: ''
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
onCancel(should_clear){
|
||||
this.setState({modal_appear: false});
|
||||
if(this.props.onCancel) this.props.onCancel();
|
||||
}
|
||||
|
||||
onSubmit(e){
|
||||
e && e.preventDefault && e.preventDefault();
|
||||
if(this.props.onSubmit) this.props.onSubmit(this.state.value);
|
||||
}
|
||||
|
||||
onInputChange(value){
|
||||
this.setState({value: value});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isActive={this.state.modal_appear} onQuit={this.onCancel.bind(this)}>
|
||||
<Modal isActive={this.props.appear} onQuit={this.onCancel.bind(this)}>
|
||||
<div className="component_prompt">
|
||||
<p className="message">
|
||||
<p className="modal-message">
|
||||
{this.props.message}
|
||||
</p>
|
||||
<form onSubmit={this.onSubmit.bind(this)}>
|
||||
<Input autoFocus={true} value={this.state.key} type={this.props.type || 'text'} onChange={this.onKeyChange.bind(this)} autoComplete="new-password" />
|
||||
<Input autoFocus={true} value={this.state.value} type={this.props.type || 'text'} autoComplete="new-password" onChange={(e) => this.onInputChange(e.target.value)} />
|
||||
|
||||
<div className="error">{this.props.error} </div>
|
||||
<div className="modal-error-message">{this.state.error} </div>
|
||||
|
||||
<div className="buttons">
|
||||
<Button type="button" onClick={this.onCancel.bind(this)}>CANCEL</Button>
|
||||
@ -50,8 +57,10 @@ 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,6 +8,7 @@ import { ForkMe, RememberMe, Credentials, Form } from './connectpage/';
|
||||
import { invalidate } from '../helpers/';
|
||||
import config from '../../config.js';
|
||||
|
||||
import { Alert, Prompt } from '../components/';
|
||||
|
||||
export class ConnectPage extends React.Component {
|
||||
constructor(props){
|
||||
@ -101,7 +102,6 @@ export class ConnectPage extends React.Component {
|
||||
<NgIf cond={this.state.loading === true}>
|
||||
<Loader/>
|
||||
</NgIf>
|
||||
|
||||
<NgIf cond={this.state.loading === false}>
|
||||
<ReactCSSTransitionGroup transitionName="form" transitionLeave={false} transitionEnter={false} transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<Form credentials={this.state.credentials}
|
||||
|
||||
@ -2,9 +2,8 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
|
||||
|
||||
import { Input, Button, NgIf, Modal } from '../../components/';
|
||||
import { Prompt } from '../../components/';
|
||||
import { encrypt, decrypt, memory } from '../../helpers/';
|
||||
import './credentials.scss';
|
||||
|
||||
export class Credentials extends React.Component {
|
||||
constructor(props){
|
||||
@ -13,7 +12,7 @@ export class Credentials extends React.Component {
|
||||
this.state = {
|
||||
modal_appear: key ? false : this.props.remember_me,
|
||||
key: key || '',
|
||||
message: null,
|
||||
message: '',
|
||||
error: null
|
||||
};
|
||||
// we use a clojure for the "key" because we want to persist it in memory
|
||||
@ -38,7 +37,7 @@ export class Credentials extends React.Component {
|
||||
|
||||
componentDidMount(){
|
||||
this.init();
|
||||
if(this.state.key) this.onSubmit();
|
||||
if(this.state.key) this.onSubmit(this.state.key);
|
||||
}
|
||||
|
||||
init(){
|
||||
@ -57,24 +56,19 @@ export class Credentials extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onKeyChange(e){
|
||||
this.setState({key: e.target.value});
|
||||
memory.set('credentials_key', e.target.value);
|
||||
}
|
||||
|
||||
onCancel(should_clear){
|
||||
memory.set('credentials_key', '');
|
||||
this.setState({modal_appear: false, key: ''});
|
||||
}
|
||||
|
||||
onSubmit(e){
|
||||
e && e.preventDefault();
|
||||
onSubmit(key){
|
||||
this.setState({key: key});
|
||||
memory.set('credentials_key', key);
|
||||
/*
|
||||
* 2 differents use cases:
|
||||
* - a user is creating a new master password
|
||||
* - a user want to unlock existing credentials
|
||||
*/
|
||||
const key = memory.get('credentials_key');
|
||||
if(key !== ''){
|
||||
let raw = window.localStorage.getItem('credentials');
|
||||
if(raw){
|
||||
@ -97,23 +91,14 @@ export class Credentials extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isActive={this.state.modal_appear} onQuit={this.onCancel.bind(this)}>
|
||||
<div className="component_password">
|
||||
<p>
|
||||
{this.state.message}
|
||||
</p>
|
||||
<form id="key_manager" onSubmit={this.onSubmit.bind(this)}>
|
||||
<Input autoFocus={true} value={this.state.key} type="password" onChange={this.onKeyChange.bind(this)} autoComplete="new-password" />
|
||||
|
||||
<div key={this.state.error} className="error">{this.state.error} </div>
|
||||
|
||||
<div className="buttons">
|
||||
<Button type="button" onClick={this.onCancel.bind(this)}>CANCEL</Button>
|
||||
<Button type="submit" theme="secondary">OK</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</Modal>
|
||||
<Prompt
|
||||
type="password"
|
||||
appear={this.state.modal_appear}
|
||||
error={this.state.error}
|
||||
message={this.state.message}
|
||||
onCancel={this.onCancel.bind(this)}
|
||||
onSubmit={this.onSubmit.bind(this)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
.component_password{
|
||||
> p{
|
||||
text-align: center;
|
||||
font-size: 1.1em;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
.error{
|
||||
color: var(--error);
|
||||
}
|
||||
.buttons{
|
||||
display: flex;
|
||||
margin: 15px -20px;
|
||||
[type="submit"]{
|
||||
border-radius: 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* APPEAR TRANSITION */
|
||||
.form-appear{ opacity: 0;}
|
||||
.form-appear.form-appear-active{
|
||||
opacity: 1;
|
||||
transition: opacity 0.1s ease;
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* ENTER TRANSITION */
|
||||
.form-enter{ opacity: 0;}
|
||||
.form-enter.form-enter-active{
|
||||
opacity: 1;
|
||||
transition: opacity 0.1s ease;
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* LEAVE TRANSITION */
|
||||
.form-leave{ opacity: 1;}
|
||||
.form-leave.form-enter-active{
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s ease-out;
|
||||
}
|
||||
@ -20,11 +20,12 @@ export class Form extends React.Component {
|
||||
advanced_git: false,
|
||||
dummy: true
|
||||
};
|
||||
this.rerender = this.rerender.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.publishState(this.props.credentials);
|
||||
window.addEventListener('resize', this.rerender.bind(this));
|
||||
window.addEventListener('resize', this.rerender);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props){
|
||||
@ -34,7 +35,7 @@ export class Form extends React.Component {
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
window.removeEventListener('resize', this.rerender.bind(this));
|
||||
window.removeEventListener('resize', this.rerender);
|
||||
}
|
||||
|
||||
publishState(_credentials){
|
||||
|
||||
@ -97,7 +97,6 @@ export class FilesPage extends React.Component {
|
||||
return Files.rm(file, type);
|
||||
}
|
||||
|
||||
|
||||
onUpload(path, files){
|
||||
const createFilesInUI = (_files) => {
|
||||
const newfiles = _files.map((file) => {
|
||||
|
||||
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { DragSource, DropTarget } from 'react-dnd';
|
||||
|
||||
import './existingthing.scss';
|
||||
import { Card, NgIf, Icon, EventEmitter} from '../../components/';
|
||||
import { Card, NgIf, Icon, EventEmitter, Prompt } from '../../components/';
|
||||
import { pathBuilder } from '../../helpers/';
|
||||
|
||||
const fileSource = {
|
||||
@ -93,7 +93,9 @@ export class ExistingThing extends React.Component {
|
||||
message: null,
|
||||
icon: props.file.type,
|
||||
filename: props.file.name,
|
||||
request_delete: false
|
||||
delete_request: false,
|
||||
delete_message: "Confirm by tapping \""+this._confirm_delete_text()+"\"",
|
||||
delete_error: ''
|
||||
};
|
||||
}
|
||||
|
||||
@ -132,13 +134,11 @@ export class ExistingThing extends React.Component {
|
||||
}
|
||||
|
||||
onDeleteRequest(filename){
|
||||
let toConfirm = this.props.file.name.length > 16? this.props.file.name.substring(0, 10).toLowerCase() : this.props.file.name;
|
||||
let answer = prompt('Confirm by tapping "'+toConfirm+'"');
|
||||
console.log(answer);
|
||||
this.setState({delete_request: true});
|
||||
}
|
||||
onDeleteConfirm(filename, toConfirm, answer){
|
||||
if(answer === toConfirm){
|
||||
this.setState({icon: 'loading'});
|
||||
onDeleteConfirm(answer){
|
||||
if(answer === this._confirm_delete_text()){
|
||||
this.setState({icon: 'loading', delete_request: false});
|
||||
this.props.emit(
|
||||
'file.delete',
|
||||
pathBuilder(this.props.path, this.props.file.name),
|
||||
@ -149,8 +149,16 @@ export class ExistingThing extends React.Component {
|
||||
if(err && err.code === 'CANCELLED'){ return; }
|
||||
this.setState({icon: 'error', message: err.message});
|
||||
});
|
||||
}else{
|
||||
this.setState({delete_error: "Doesn't match"});
|
||||
}
|
||||
}
|
||||
onDeleteCancel(){
|
||||
this.setState({delete_request: false});
|
||||
}
|
||||
_confirm_delete_text(){
|
||||
return this.props.file.name.length > 16? this.props.file.name.substring(0, 10).toLowerCase() : this.props.file.name;
|
||||
}
|
||||
|
||||
|
||||
render(highlight){
|
||||
@ -182,14 +190,11 @@ export class ExistingThing extends React.Component {
|
||||
<Message message={this.state.message} />
|
||||
</Card>
|
||||
</NgIf>
|
||||
<NgIf cond={this.state.request_delete}>
|
||||
|
||||
</NgIf>
|
||||
<Prompt appear={this.state.delete_request} error={this.state.delete_error} message={this.state.delete_message} onCancel={this.onDeleteCancel.bind(this)} onSubmit={this.onDeleteConfirm.bind(this)}/>
|
||||
</div>
|
||||
)));
|
||||
}
|
||||
}
|
||||
// <Prompt message="" onCancel={() => {}} onConfirm={this.onDeleteConfirm.bind(this, this.state.filename, 'test')} />
|
||||
ExistingThing.PropTypes = {
|
||||
connectDragSource: PropTypes.func.isRequired,
|
||||
isDragging: PropTypes.bool.isRequired,
|
||||
@ -268,7 +273,7 @@ const DateTime = (props) => {
|
||||
function padding(number){
|
||||
let str = String(number),
|
||||
pad = "00";
|
||||
return pad.substring(0, pad.length - str.length) + str
|
||||
return pad.substring(0, pad.length - str.length) + str;
|
||||
}
|
||||
if(timestamp){
|
||||
let t = new Date(timestamp);
|
||||
@ -298,7 +303,7 @@ const FileSize = (props) => {
|
||||
}else if(bytes < 1099511627776){
|
||||
return Math.round(bytes/(1024*1024*1024)*10)/10+'GB';
|
||||
}else{
|
||||
return Math.round(bytes/(1024*1024*1024*1024))+'TB'
|
||||
return Math.round(bytes/(1024*1024*1024*1024))+'TB';
|
||||
}
|
||||
}
|
||||
const style = {color: '#6f6f6f', fontSize: '0.85em'};
|
||||
@ -307,7 +312,7 @@ const FileSize = (props) => {
|
||||
<NgIf cond={props.type === 'file'} style={{display: 'inline-block'}}>
|
||||
<span style={style}>({displaySize(props.size)})</span>
|
||||
</NgIf>
|
||||
)
|
||||
);
|
||||
}
|
||||
const Message = (props) => {
|
||||
const style = {color: 'rgba(0,0,0,0.4)', fontSize: '0.9em', paddingLeft: '10px', display: 'inline'};
|
||||
@ -315,5 +320,5 @@ const Message = (props) => {
|
||||
<NgIf cond={props.message !== null} style={style}>
|
||||
- {props.message}
|
||||
</NgIf>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
|
||||
import { DropTarget } from 'react-dnd';
|
||||
import Path from 'path';
|
||||
|
||||
import "./filesystem.scss";
|
||||
import { Container, NgIf } from '../../components/';
|
||||
import { NewThing } from './newthing';
|
||||
import { ExistingThing } from './existingthing';
|
||||
@ -86,13 +88,14 @@ export class FileSystem extends React.Component {
|
||||
|
||||
render() {
|
||||
return this.props.connectDropFile(
|
||||
<div style={{height: '100%'}}>
|
||||
<Container style={{height: '100%'}}>
|
||||
<div className="component_filesystem">
|
||||
<Container>
|
||||
<NewThing path={this.props.path} sort={this.state.sort} onSortUpdate={(value) => {this.setState({sort: value})}} accessRight={this.state.access_right}></NewThing>
|
||||
<NgIf cond={this.props.fileIsOver}>
|
||||
<FileZone path={this.props.path} />
|
||||
</NgIf>
|
||||
<NgIf cond={this.props.files.length > 0} style={{clear: 'both', paddingBottom: '15px'}}>
|
||||
<NgIf className="list" cond={this.props.files.length > 0}>
|
||||
<ReactCSSTransitionGroup transitionName="filelist-item" transitionLeave={false} transitionEnter={false} transitionAppear={true} transitionAppearTimeout={200}>
|
||||
{
|
||||
this.sort(this.props.files, this.state.sort).map((file, index) => {
|
||||
if(file.type === 'directory' || file.type === 'file' || file.type === 'link' || file.type === 'bucket'){
|
||||
@ -100,8 +103,9 @@ export class FileSystem extends React.Component {
|
||||
}
|
||||
})
|
||||
}
|
||||
</ReactCSSTransitionGroup>
|
||||
</NgIf>
|
||||
<NgIf cond={this.props.files.length === 0 && !this.state.creating} style={{fontSize: '25px', textAlign: 'center', fontWeight: '100', marginTop: '50px'}}>
|
||||
<NgIf className="error" cond={this.props.files.length === 0 && !this.state.creating}>
|
||||
There is nothing here
|
||||
</NgIf>
|
||||
</Container>
|
||||
|
||||
27
client/pages/filespage/filesystem.scss
Normal file
27
client/pages/filespage/filesystem.scss
Normal file
@ -0,0 +1,27 @@
|
||||
.filelist-item-appear{
|
||||
opacity: 0;
|
||||
transform: translateY(5px);
|
||||
}
|
||||
.filelist-item-appear.filelist-item-appear-active{
|
||||
transition: all 0.2s ease-out;
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.component_filesystem{
|
||||
height: 100%;
|
||||
> div{
|
||||
height: 100%;
|
||||
.list{
|
||||
clear: both;
|
||||
padding-bottom: 150px;
|
||||
}
|
||||
|
||||
.error{
|
||||
font-size: 25px;
|
||||
text-align: center;
|
||||
font-weight: 100;
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
height: 100%;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll { -webkit-overflow-scrolling: touch; }
|
||||
|
||||
/* SEARCH */
|
||||
.CodeMirror-dialog {
|
||||
@ -38,20 +38,26 @@
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll { -webkit-overflow-scrolling: touch; }
|
||||
|
||||
/* Highlight Theme */
|
||||
.cm-s-default .cm-header {color: #3E7AA6; font-size: 1.15em;}
|
||||
.cm-s-default .cm-keyword {color: #3E7AA6;}
|
||||
.cm-s-default .cm-header.cm-org-level-star{color: #6f6f6f; position: relative; top: 2px;}
|
||||
.cm-s-default .cm-header.cm-org-todo{color: #FF8355;}
|
||||
.cm-s-default .cm-header.cm-org-done{color: #3BB27C;}
|
||||
.cm-s-default .cm-link{color: #555!important;}
|
||||
.cm-s-default .cm-url{color: #555!important;}
|
||||
|
||||
|
||||
.cm-s-default .cm-keyword {color: #3E7AA6;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-comment {color: #6f6f6f;}
|
||||
.cm-s-default .cm-string, .cm-s-default .cm-string-2{ color: #c41a16; }
|
||||
.cm-s-default .cm-def { color: rgb(68, 85, 136); }
|
||||
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
|
||||
.CodeMirror-foldmarker{
|
||||
padding-left: 5px;
|
||||
color: #6f6f6f;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user