preview
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
31
src/Components/Icons/Markdown.js
Normal file
31
src/Components/Icons/Markdown.js
Normal 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>
|
||||
);
|
||||
};
|
||||
@@ -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';
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.container {
|
||||
display: flex;
|
||||
padding-top: 48px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
@@ -11,5 +12,5 @@
|
||||
}
|
||||
|
||||
.markdown {
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user