This commit is contained in:
Jori Lallo
2016-03-10 22:54:47 -08:00
parent f6456a3817
commit 7225c01924
11 changed files with 121 additions and 39 deletions

View File

@@ -57,7 +57,7 @@
"react-redux": "^4.4.0",
"react-router": "^2.0.0",
"redux": "^3.3.1",
"redux-storage": "^3.0.0",
"redux-storage": "^4.0.0",
"redux-storage-engine-localstorage": "^1.0.0",
"sass-loader": "^3.1.2",
"style-loader": "^0.13.0",

View File

@@ -1,5 +1,7 @@
import React from 'react';
import MarkdownIcon from '../../Components/Icons/Markdown';
import styles from './Header.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
@@ -7,23 +9,26 @@ const cx = classNames.bind(styles);
const Header = ({
activeEditors,
toggleEditors,
addRevision,
}) => {
return (
<div className={ styles.header }>
<div className={ styles.headerItem }><i>Beautiful</i> Atlas</div>
<div className={ cx('headerItem', 'editorToggle') }>
<span
<div
className={ cx('headerItem', 'editorToggle') }
style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}
>
<div
onClick={toggleEditors.bind(this, 'MARKDOWN')}
className={ activeEditors.includes('MARKDOWN') ? styles.active : '' }
>Markdown</span>
<span
>
<MarkdownIcon style={{ width: '32px', height: '20px', color: '#fff' }} />
</div>
<div
onClick={toggleEditors.bind(this, 'TEXT')}
className={ activeEditors.includes('TEXT') ? styles.active : '' }
>Text</span>
</div>
<div className={ cx('headerItem', 'sidebar') }>
<span onClick={addRevision.bind(this, (new Date()).toISOString())}>Save</span>
>
<span className={ styles.textIcon }>Aa</span>
</div>
</div>
</div>
);
@@ -32,7 +37,6 @@ const Header = ({
Header.propTypes = {
activeEditors: React.PropTypes.array.isRequired,
toggleEditors: React.PropTypes.func.isRequired,
addRevision: React.PropTypes.func.isRequired,
};
export default Header;

View File

@@ -2,6 +2,9 @@
display: flex;
width: 100%;
height: 42px;
position: fixed;
z-index: 9999;
justify-content: space-between;
background-color: #111;
@@ -29,26 +32,29 @@
}
}
.editorToggle {
span {
margin-right: 12px;
cursor: pointer;
.editorToggle div {
margin-right: 12px;
cursor: pointer;
opacity: 0.4;
color: #fff;
&:last-child {
margin-right: 0;
}
&.active {
opacity: 1;
}
&:first-child {
margin-top: 2px;
margin-right: 15px;
}
&:last-child {
margin-top: -2px;
}
}
.sidebar {
span {
margin-right: 12px;
cursor: pointer;
}
}
.textIcon {
font-family: Times, serif;
font-size: 20px;
.active {
text-decoration: underline;
text-decoration-color: #fff;
}
}

View File

@@ -0,0 +1,31 @@
import React from 'react';
export default ({ style = {}, className }) => {
return (
<span className={className}>
<svg
xmlns="http://www.w3.org/2000/svg"
width={ style.width || 208 }
height={ style.height || 128 }
viewBox="0 0 208 128"
color={ style.color }
>
<rect
width="198"
height="118"
x="5"
y="5"
ry="10"
stroke="currentColor"
strokeWidth="10"
fill="none"
fillOpacity="0"
/>
<path
d="M30 98v-68h20l20 25 20-25h20v68h-20v-39l-20 25-20-25v39zM155 98l-30-33h20v-35h20v35h20z"
fill="currentColor"
/>
</svg>
</span>
);
};

View File

@@ -1,6 +1,7 @@
import React from 'react';
import Codemirror from 'react-codemirror';
import 'codemirror/mode/gfm/gfm';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/addon/edit/continuelist';
import styles from './MarkdownEditor.scss';

View File

@@ -1,4 +1,13 @@
.container {
width: 70%;
margin: 48px auto;
font-weight: 400;
font-size: 1em;
line-height: 1.5em;
margin: 0 auto;
padding: 2em 3em;
max-width: 50em;
}
@media all and (max-width: 2000px) and (min-width: 960px) {
.container {font-size: 1.1em}
}

View File

@@ -11,10 +11,11 @@
@import url(https://fonts.googleapis.com/css?family=Cousine:400,700,700italic,400italic);
.cm-s-atlas.CodeMirror {
background: #fcfcfc;
background: #ffffff;
color: #202020;
font-family: 'Cousine', 'Monaco', monospace;
font-weight: 300;
height: auto;
}
.cm-s-atlas div.CodeMirror-selected {
background: #90CAF9;

View File

@@ -1,5 +1,17 @@
.container {
font-weight: 400;
font-size: 1em;
line-height: 1.5em;
margin: 0 auto;
padding: 2em 3em;
max-width: 50em;
}
.editor {
outline: none;
margin: 0 0 20px 0;
padding: 0 0 20px 0;
}
@media all and (max-width: 2000px) and (min-width: 960px) {
.container {font-size: 1.1em}
}

View File

@@ -12,11 +12,12 @@ import {
const activeEditors = (state = [ActiveEditors.MARKDOWN, ActiveEditors.TEXT], action) => {
switch (action.type) {
case TOGGLE_EDITORS: {
// TODO: A rewrite would be nice
const newState = _.xor(state, [action.toggledEditor]);
if (newState.length > 0) {
return newState;
} else {
return [action.toggledEditor];
return _.xor([ActiveEditors.MARKDOWN, ActiveEditors.TEXT], [action.toggledEditor]);
}
}
default:
@@ -37,15 +38,28 @@ const historySidebar = (state = { visible: false }, action) => {
}
};
const text = (state = { text: '', revisions: [] }, action) => {
const textDefaultState = {
text: '',
revisions: [],
unsavedChanges: false,
};
const text = (state = textDefaultState, action) => {
const lastRevision = _.last(state.revisions);
switch (action.type) {
case UPDATE_TEXT:
case UPDATE_TEXT: {
let unsavedChanges = false;
if (lastRevision && lastRevision.text !== state.text) {
unsavedChanges = true;
}
return {
...state,
unsavedChanges,
text: action.text,
};
}
case ADD_REVISION: {
const lastRevision = _.last(state.revisions);
// Create new revision if it differs from the previous one
if (!lastRevision || lastRevision.text !== state.text) {
const lastId = lastRevision ? lastRevision.id : 0;
@@ -59,6 +73,7 @@ const text = (state = { text: '', revisions: [] }, action) => {
created_at: action.createdAt,
},
],
unsavedChanges: false,
};
} else {
return state;

View File

@@ -19,6 +19,7 @@ class App extends Component {
activeEditors: React.PropTypes.array.isRequired,
toggleEditors: React.PropTypes.func.isRequired,
addRevision: React.PropTypes.func.isRequired,
unsavedChanges: React.PropTypes.bool.isRequired,
}
state = {
@@ -47,6 +48,7 @@ class App extends Component {
activeEditors={this.props.activeEditors}
toggleEditors={this.props.toggleEditors}
addRevision={this.props.addRevision}
unsavedChanges={this.props.unsavedChanges}
/>
<div className={ styles.content }>
{ this.props.children }
@@ -59,7 +61,7 @@ class App extends Component {
const mapStateToProps = (state) => {
return {
activeEditors: state.activeEditors,
showHistorySidebar: state.historySidebar.visible,
unsavedChanges: state.text.unsavedChanges,
};
};

View File

@@ -1,5 +1,6 @@
.container {
display: flex;
padding-top: 48px;
}
.panel {
@@ -11,5 +12,5 @@
}
.markdown {
background-color: #fbfbfb;
}
background-color: #ffffff;
}