From 1741c12bea2a4a65850bb5435b6e73ca5c11f462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Mon, 11 Jul 2016 18:57:54 -0300 Subject: [PATCH 01/28] First CardUI commit --- example/config.yml | 2 + example/index.html | 2 +- package.json | 1 + src/components/Cards.js | 11 ++++ src/components/Cards/AlltypeCard.js | 14 +++++ src/components/Cards/MediaCard.js | 16 ++++++ src/components/Cards/UnknownCard.js | 15 +++++ src/components/EntryListing.js | 87 +++++++++++++++++++++++++---- src/components/UI/card/Card.css | 1 + src/components/UI/card/Card.js | 4 +- src/components/stories/Card.js | 56 ++++++++----------- 11 files changed, 162 insertions(+), 47 deletions(-) create mode 100644 src/components/Cards.js create mode 100644 src/components/Cards/AlltypeCard.js create mode 100644 src/components/Cards/MediaCard.js create mode 100644 src/components/Cards/UnknownCard.js diff --git a/example/config.yml b/example/config.yml index 1e549f22..9f45f06d 100644 --- a/example/config.yml +++ b/example/config.yml @@ -17,6 +17,7 @@ collections: # A list of collections the CMS should be able to edit meta: - {label: "Publish Date", name: "date", widget: "datetime", format: "YYYY-MM-DD hh:mma"} - {label: "SEO Description", name: "description", widget: "text"} + card: {type: "media", media: "image", text: "title"} - name: "faq" # Used in routes, ie.: /admin/collections/:slug/edit label: "FAQ" # Used in the UI, ie.: "New Post" @@ -25,6 +26,7 @@ collections: # A list of collections the CMS should be able to edit fields: # The fields each document in this collection have - {label: "Question", name: "title", widget: "string", tagname: "h1"} - {label: "Answer", name: "body", widget: "markdown"} + card: {type: "alltype", text: "title"} - name: "settings" label: "Settings" diff --git a/example/index.html b/example/index.html index ea2ae7f7..1fa10126 100644 --- a/example/index.html +++ b/example/index.html @@ -4,7 +4,7 @@ This is an example - + diff --git a/src/components/Cards/AlltypeCard.js b/src/components/Cards/AlltypeCard.js index 03cc520a..40cfbdcf 100644 --- a/src/components/Cards/AlltypeCard.js +++ b/src/components/Cards/AlltypeCard.js @@ -1,14 +1,82 @@ import React, { PropTypes } from 'react'; import { Card } from '../UI'; +import ScaledLine from './ScaledLine'; -export default function AlltypeCard({ onClick, text }) { - return ( - -

{text}

-
- ); + +export default class AlltypeCard extends React.Component { + + // Based on the Slabtype Algorithm by Erik Loyer + // http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/ + renderInscription(inscription) { + + var idealCharPerLine = 20; + + // segment the text into lines + var words = inscription.split(' '); + var preText, postText, finalText; + var preDiff, postDiff; + var wordIndex = 0; + var lineText = []; + + // while we still have words left, build the next line + while (wordIndex < words.length) { + postText = ''; + + // build two strings (preText and postText) word by word, with one + // string always one word behind the other, until + // the length of one string is less than the ideal number of characters + // per line, while the length of the other is greater than that ideal + while (postText.length < idealCharPerLine) { + preText = postText; + postText += words[wordIndex] + ' '; + wordIndex++; + if (wordIndex >= words.length) { + break; + } + } + + // calculate the character difference between the two strings and the + // ideal number of characters per line + preDiff = idealCharPerLine - preText.length; + postDiff = postText.length - idealCharPerLine; + + // if the smaller string is closer to the length of the ideal than + // the longer string, and doesn’t contain just a single space, then + // use that one for the line + if ((preDiff < postDiff) && (preText.length > 2)) { + finalText = preText; + wordIndex--; + + // otherwise, use the longer string for the line + } else { + finalText = postText; + } + + lineText.push(finalText.substr(0, finalText.length - 1)); + } + return lineText.map(text => ( + + {text} + + )); + } + + render() { + const { onClick, text } = this.props; + return ( + +
{this.renderInscription(text)}
+
+ ); + } } + AlltypeCard.propTypes = { + onClick: PropTypes.func, text: PropTypes.string.isRequired }; + +AlltypeCard.defaultProps = { + onClick: function() {}, +}; diff --git a/src/components/Cards/ScaledLine.js b/src/components/Cards/ScaledLine.js new file mode 100644 index 00000000..5712fa0e --- /dev/null +++ b/src/components/Cards/ScaledLine.js @@ -0,0 +1,45 @@ +import React, { PropTypes } from 'react'; + +export default class ScaledLine extends React.Component { + constructor(props) { + super(props); + this._content = null; + this.state = { + contentWidth: 0, + ratio: 1, + }; + } + + componentDidMount() { + const actualContent = this._content.children[0]; + + this.setState({ + contentWidth: actualContent.offsetWidth, + ratio: this.props.toWidth / actualContent.offsetWidth, + }); + } + + render() { + const { ratio } = this.state; + const { children } = this.props; + + var baseFontSize = 15; + + var styles = { + whiteSpace: 'nowrap', + textAlign: 'center' + }; + styles.fontSize = Math.round((baseFontSize * ratio)*1000)/1000 + + return ( +
this._content = c} style={styles}> + {children} +
+ ) + } +}; + +ScaledLine.propTypes = { + toWidth: PropTypes.number.isRequired, + children: PropTypes.node.isRequired +}; From ea9923e0c85024e475a2b62fb499d26de34d1ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 12 Jul 2016 17:03:39 -0300 Subject: [PATCH 03/28] content Cards refactor --- example/config.yml | 2 +- src/components/Cards.js | 4 ++-- src/components/Cards/ImageCard.js | 22 ++++++++++++++++++++++ src/components/Cards/MediaCard.js | 16 ---------------- src/components/EntryListing.js | 4 ++-- src/containers/CollectionPage.js | 7 ------- 6 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 src/components/Cards/ImageCard.js delete mode 100644 src/components/Cards/MediaCard.js diff --git a/example/config.yml b/example/config.yml index 9f45f06d..a930e59b 100644 --- a/example/config.yml +++ b/example/config.yml @@ -17,7 +17,7 @@ collections: # A list of collections the CMS should be able to edit meta: - {label: "Publish Date", name: "date", widget: "datetime", format: "YYYY-MM-DD hh:mma"} - {label: "SEO Description", name: "description", widget: "text"} - card: {type: "media", media: "image", text: "title"} + card: {type: "image", image: "image", text: "title"} - name: "faq" # Used in routes, ie.: /admin/collections/:slug/edit label: "FAQ" # Used in the UI, ie.: "New Post" diff --git a/src/components/Cards.js b/src/components/Cards.js index ba455280..ab903e2b 100644 --- a/src/components/Cards.js +++ b/src/components/Cards.js @@ -1,10 +1,10 @@ import UnknownCard from './Cards/UnknownCard'; -import MediaCard from './Cards/MediaCard'; +import ImageCard from './Cards/ImageCard'; import AlltypeCard from './Cards/AlltypeCard'; const Cards = { _unknown: UnknownCard, - media: MediaCard, + image: ImageCard, alltype: AlltypeCard }; diff --git a/src/components/Cards/ImageCard.js b/src/components/Cards/ImageCard.js new file mode 100644 index 00000000..001bf391 --- /dev/null +++ b/src/components/Cards/ImageCard.js @@ -0,0 +1,22 @@ +import React, { PropTypes } from 'react'; +import { Card } from '../UI'; + +export default function ImageCard({ onClick, image, text }) { + return ( + + +

{text}

+
+ ); +} + +ImageCard.propTypes = { + image: PropTypes.string.isRequired, + + onClick: PropTypes.func, + text: PropTypes.string.isRequired +}; + +ImageCard.defaultProps = { + onClick: function() {}, +}; diff --git a/src/components/Cards/MediaCard.js b/src/components/Cards/MediaCard.js deleted file mode 100644 index fbb10e49..00000000 --- a/src/components/Cards/MediaCard.js +++ /dev/null @@ -1,16 +0,0 @@ -import React, { PropTypes } from 'react'; -import { Card } from '../UI'; - -export default function MediaCard({ onClick, media, text }) { - return ( - - -

{text}

-
- ); -} - -MediaCard.propTypes = { - media: PropTypes.string.isRequired, - text: PropTypes.string.isRequired -}; diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index d45378ea..beed5b30 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -58,7 +58,7 @@ export default class EntryListing extends React.Component { collection: collection, onClick: browserHistory.push.bind(this, link), text: entry.getIn(['data', collection.getIn(['card', 'text'])]), - media: entry.getIn(['data', collection.getIn(['card', 'media'])]), + image: entry.getIn(['data', collection.getIn(['card', 'image'])]), }); } @@ -67,7 +67,7 @@ export default class EntryListing extends React.Component { const name = collection.get('name'); return
-

Listing entries!

+

Listing {name}

this._entries = c}> {entries.map((entry) => { const path = `/collections/${name}/entries/${entry.get('slug')}`; diff --git a/src/containers/CollectionPage.js b/src/containers/CollectionPage.js index 8d8b12b4..d7e43ea9 100644 --- a/src/containers/CollectionPage.js +++ b/src/containers/CollectionPage.js @@ -30,13 +30,6 @@ class DashboardPage extends React.Component { return

Dashboard

-
- {collections.map((collection) => ( -
- {collection.get('name')} -
- )).toArray()} -
{entries ? : 'Loading entries...'}
From 7dcd8c3d64f827415c982e4a597d12be1b61a9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 12 Jul 2016 17:25:26 -0300 Subject: [PATCH 04/28] On card image loaded, redistribute cards --- src/components/Cards/ImageCard.js | 49 ++++++++++++++++++++++++++----- src/components/EntryListing.js | 1 + 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/components/Cards/ImageCard.js b/src/components/Cards/ImageCard.js index 001bf391..265f8bdc 100644 --- a/src/components/Cards/ImageCard.js +++ b/src/components/Cards/ImageCard.js @@ -1,22 +1,55 @@ import React, { PropTypes } from 'react'; import { Card } from '../UI'; -export default function ImageCard({ onClick, image, text }) { - return ( - - -

{text}

-
- ); +export default class ImageCard extends React.Component { + constructor(props) { + super(props); + this._image = null; + this.fetchImage = this.fetchImage.bind(this); + } + + componentDidMount() { + this._image = new Image(); + if (this.props.image) { + this.fetchImage(this.props.image); + } + } + + componentWillReceiveProps(nextProps) { + if (this.props.image !== nextProps.image) { + this.fetchImage(nextProps.image); + } + } + + componentWillUnmount() { + this._image.onload = null; + this._image = null; + } + + fetchImage(src) { + this._image.onload = this.props.onImageLoaded; + this._image.src = src; + } + + render() { + const { onClick, image, text } = this.props; + return ( + + +

{text}

+
+ ); + } } ImageCard.propTypes = { image: PropTypes.string.isRequired, - onClick: PropTypes.func, + onImageLoaded: PropTypes.func, text: PropTypes.string.isRequired }; ImageCard.defaultProps = { onClick: function() {}, + onImageLoaded: function() {} }; diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index beed5b30..41908a22 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -57,6 +57,7 @@ export default class EntryListing extends React.Component { key: entry.get('slug'), collection: collection, onClick: browserHistory.push.bind(this, link), + onImageLoaded: () => this.bricksInstance.pack(), text: entry.getIn(['data', collection.getIn(['card', 'text'])]), image: entry.getIn(['data', collection.getIn(['card', 'image'])]), }); From ec85b95ef97e35821da8645a7788fdf1138aa5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 12 Jul 2016 18:10:26 -0300 Subject: [PATCH 05/28] css refinments --- example/index.html | 4 ++-- src/components/Cards/AlltypeCard.js | 2 +- src/components/Cards/ScaledLine.js | 9 ++++----- src/components/UI/theme.css | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/example/index.html b/example/index.html index 368e0f91..9142ebcc 100644 --- a/example/index.html +++ b/example/index.html @@ -47,7 +47,7 @@ var slug = dateString + "-post-number-" + i + ".md"; window.repoFiles._posts[slug] = { - content: "---\ntitle: \"This is post #" + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# The post is number " + i + "\n\nAnd this is yet another identical post body" + content: "---\ntitle: \"This is post # " + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# The post is number " + i + "\n\nAnd this is yet another identical post body" } } @@ -59,7 +59,7 @@ var slug = dateString + "-faq-number-" + i + ".md"; window.repoFiles._faqs[slug] = { - content: "---\ntitle: \"This a FAQ item #" + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# Loren ipsum dolor sit amet" + content: "---\ntitle: \"This FAQ item # " + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# Loren ipsum dolor sit amet" } } diff --git a/src/components/Cards/AlltypeCard.js b/src/components/Cards/AlltypeCard.js index 40cfbdcf..8076f3e2 100644 --- a/src/components/Cards/AlltypeCard.js +++ b/src/components/Cards/AlltypeCard.js @@ -9,7 +9,7 @@ export default class AlltypeCard extends React.Component { // http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/ renderInscription(inscription) { - var idealCharPerLine = 20; + var idealCharPerLine = 22; // segment the text into lines var words = inscription.split(' '); diff --git a/src/components/Cards/ScaledLine.js b/src/components/Cards/ScaledLine.js index 5712fa0e..182c80d1 100644 --- a/src/components/Cards/ScaledLine.js +++ b/src/components/Cards/ScaledLine.js @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react'; +import styles from './ScaledLine.css'; export default class ScaledLine extends React.Component { constructor(props) { @@ -25,14 +26,12 @@ export default class ScaledLine extends React.Component { var baseFontSize = 15; - var styles = { - whiteSpace: 'nowrap', - textAlign: 'center' + var inlineStyles = { }; - styles.fontSize = Math.round((baseFontSize * ratio)*1000)/1000 + inlineStyles.fontSize = Math.round((baseFontSize * ratio)*1000)/1000 return ( -
this._content = c} style={styles}> +
this._content = c} style={inlineStyles} className={styles.root}> {children}
) diff --git a/src/components/UI/theme.css b/src/components/UI/theme.css index e39e702b..41aac294 100644 --- a/src/components/UI/theme.css +++ b/src/components/UI/theme.css @@ -12,7 +12,6 @@ } .container { - margin: 10px; color: var(--defaultColor); background-color: var(--backgroundColor); } From e50fbfdeeb8ed677e53307917bf71c0e286c2702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 12 Jul 2016 18:11:42 -0300 Subject: [PATCH 06/28] moved out scaled line css --- src/components/Cards/ScaledLine.css | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/components/Cards/ScaledLine.css diff --git a/src/components/Cards/ScaledLine.css b/src/components/Cards/ScaledLine.css new file mode 100644 index 00000000..45375896 --- /dev/null +++ b/src/components/Cards/ScaledLine.css @@ -0,0 +1,5 @@ +.root { + white-space: nowrap; + text-align: center; + font-weight: 500; +} From 893533961fb548392a82b810e25e41850a68a3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Wed, 13 Jul 2016 11:37:00 -0300 Subject: [PATCH 07/28] refinments on alltype card --- example/index.html | 2 +- .../Cards/{ScaledLine.css => AlltypeCard.css} | 2 +- src/components/Cards/AlltypeCard.js | 17 ++++++++--------- src/components/Cards/ScaledLine.js | 19 +++++++------------ 4 files changed, 17 insertions(+), 23 deletions(-) rename src/components/Cards/{ScaledLine.css => AlltypeCard.css} (81%) diff --git a/example/index.html b/example/index.html index 9142ebcc..341eebd4 100644 --- a/example/index.html +++ b/example/index.html @@ -20,7 +20,7 @@ "what-is-jam-stack.md": { content: "---\ntitle: What is the “JAM Stack”?\ndate: 2015-11-02T00:00.000Z\n---\n\n# The JAM stack is a new way of building websites and apps that are fast, secure and simple to work with.\n\nJAM stands for JavaScript, APIs and Markup. It's the fastest growing new stack for building websites and apps: no more servers, host all your front-end on a CDN and use APIs for any moving parts.\n\n" }, - "sll-support.md": { + "cache-invalidation.md": { content: "---\ntitle: What about Cache Invalidation?\ndate: 2015-11-02T00:00.000Z\n---\n\n# Netlify handles cache invalidation automatically\n\nWhen your changes go live, they go live.\n\nNo waiting for cache purges, no cumbersome varnish setup, no API calls to clean your distribution. Netlify handles cache purges within an average of 250ms from your deploy!\n\n" }, "continuous-deployment.md": { diff --git a/src/components/Cards/ScaledLine.css b/src/components/Cards/AlltypeCard.css similarity index 81% rename from src/components/Cards/ScaledLine.css rename to src/components/Cards/AlltypeCard.css index 45375896..f0e04a3c 100644 --- a/src/components/Cards/ScaledLine.css +++ b/src/components/Cards/AlltypeCard.css @@ -1,4 +1,4 @@ -.root { +.cardContent { white-space: nowrap; text-align: center; font-weight: 500; diff --git a/src/components/Cards/AlltypeCard.js b/src/components/Cards/AlltypeCard.js index 8076f3e2..7e3c98b3 100644 --- a/src/components/Cards/AlltypeCard.js +++ b/src/components/Cards/AlltypeCard.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import { Card } from '../UI'; import ScaledLine from './ScaledLine'; - +import styles from './AlltypeCard.css'; export default class AlltypeCard extends React.Component { @@ -9,14 +9,14 @@ export default class AlltypeCard extends React.Component { // http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/ renderInscription(inscription) { - var idealCharPerLine = 22; + const idealCharPerLine = 22; // segment the text into lines - var words = inscription.split(' '); - var preText, postText, finalText; - var preDiff, postDiff; - var wordIndex = 0; - var lineText = []; + const words = inscription.split(' '); + let preText, postText, finalText; + let preDiff, postDiff; + let wordIndex = 0; + const lineText = []; // while we still have words left, build the next line while (wordIndex < words.length) { @@ -65,13 +65,12 @@ export default class AlltypeCard extends React.Component { const { onClick, text } = this.props; return ( -
{this.renderInscription(text)}
+
{this.renderInscription(text)}
); } } - AlltypeCard.propTypes = { onClick: PropTypes.func, text: PropTypes.string.isRequired diff --git a/src/components/Cards/ScaledLine.js b/src/components/Cards/ScaledLine.js index 182c80d1..be274a6d 100644 --- a/src/components/Cards/ScaledLine.js +++ b/src/components/Cards/ScaledLine.js @@ -1,12 +1,10 @@ import React, { PropTypes } from 'react'; -import styles from './ScaledLine.css'; export default class ScaledLine extends React.Component { constructor(props) { super(props); this._content = null; this.state = { - contentWidth: 0, ratio: 1, }; } @@ -15,7 +13,6 @@ export default class ScaledLine extends React.Component { const actualContent = this._content.children[0]; this.setState({ - contentWidth: actualContent.offsetWidth, ratio: this.props.toWidth / actualContent.offsetWidth, }); } @@ -24,21 +21,19 @@ export default class ScaledLine extends React.Component { const { ratio } = this.state; const { children } = this.props; - var baseFontSize = 15; - - var inlineStyles = { + const styles = { + fontSize: ratio.toFixed(3) + 'em' }; - inlineStyles.fontSize = Math.round((baseFontSize * ratio)*1000)/1000 return ( -
this._content = c} style={inlineStyles} className={styles.root}> +
this._content = c} style={styles}> {children}
- ) + ); } -}; +} ScaledLine.propTypes = { - toWidth: PropTypes.number.isRequired, - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired, + toWidth: PropTypes.number.isRequired }; From 350f9a12b7bf947a281b05e3c2c3504ac175d149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Wed, 13 Jul 2016 17:19:26 -0300 Subject: [PATCH 08/28] typo --- src/components/Widgets.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/Widgets.js b/src/components/Widgets.js index 9ffc220d..0a86b6b7 100644 --- a/src/components/Widgets.js +++ b/src/components/Widgets.js @@ -1,11 +1,11 @@ -import UnknownControl from './widgets/UnknownControl'; -import UnknownPreview from './widgets/UnknownPreview'; -import StringControl from './widgets/StringControl'; -import StringPreview from './widgets/StringPreview'; -import MarkdownControl from './widgets/MarkdownControl'; -import MarkdownPreview from './widgets/MarkdownPreview'; -import ImageControl from './widgets/ImageControl'; -import ImagePreview from './widgets/ImagePreview'; +import UnknownControl from './Widgets/UnknownControl'; +import UnknownPreview from './Widgets/UnknownPreview'; +import StringControl from './Widgets/StringControl'; +import StringPreview from './Widgets/StringPreview'; +import MarkdownControl from './Widgets/MarkdownControl'; +import MarkdownPreview from './Widgets/MarkdownPreview'; +import ImageControl from './Widgets/ImageControl'; +import ImagePreview from './Widgets/ImagePreview'; const Widgets = { From 9e213c3b9ffdba03964042607d4283a149e1db61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Wed, 13 Jul 2016 17:19:59 -0300 Subject: [PATCH 09/28] added key --- src/components/Cards/AlltypeCard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Cards/AlltypeCard.js b/src/components/Cards/AlltypeCard.js index 7e3c98b3..07956790 100644 --- a/src/components/Cards/AlltypeCard.js +++ b/src/components/Cards/AlltypeCard.js @@ -55,7 +55,7 @@ export default class AlltypeCard extends React.Component { lineText.push(finalText.substr(0, finalText.length - 1)); } return lineText.map(text => ( - + {text} )); From f4b44c56611e8182aa28a7eb63d9c03282dfe674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Wed, 13 Jul 2016 17:20:41 -0300 Subject: [PATCH 10/28] layout adjustments --- src/components/EntryListing.js | 2 +- src/containers/CollectionPage.js | 5 +---- src/containers/FindBar.css | 1 + src/index.css | 5 ----- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index 41908a22..0a08f48a 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -68,7 +68,7 @@ export default class EntryListing extends React.Component { const name = collection.get('name'); return
-

Listing {name}

+

Listing {name}

this._entries = c}> {entries.map((entry) => { const path = `/collections/${name}/entries/${entry.get('slug')}`; diff --git a/src/containers/CollectionPage.js b/src/containers/CollectionPage.js index d7e43ea9..bc119da5 100644 --- a/src/containers/CollectionPage.js +++ b/src/containers/CollectionPage.js @@ -29,10 +29,7 @@ class DashboardPage extends React.Component { } return
-

Dashboard

-
- {entries ? : 'Loading entries...'} -
+ {entries ? : 'Loading entries...'}
; } } diff --git a/src/containers/FindBar.css b/src/containers/FindBar.css index e19a35da..c520bfbb 100644 --- a/src/containers/FindBar.css +++ b/src/containers/FindBar.css @@ -10,6 +10,7 @@ position: relative; background-color: var(--backgroundColor); padding: 1px 0; + margin-bottom: 50px; } .inputArea { diff --git a/src/index.css b/src/index.css index ee57887e..d1c6f90d 100644 --- a/src/index.css +++ b/src/index.css @@ -15,8 +15,3 @@ body { :global #root, :global #root > * { height: 100%; } - -h1, h2, h3, h4, h5, h6, p, blockquote, figure, dl, ol, ul { - margin: 0; - padding: 0; -} From 2746d91e39d8b04878b9cbfb048246c78679ad65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Wed, 13 Jul 2016 19:32:41 -0300 Subject: [PATCH 11/28] style update --- src/components/Cards/ImageCard.js | 2 +- src/components/UI/theme.css | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Cards/ImageCard.js b/src/components/Cards/ImageCard.js index 265f8bdc..9dbe971d 100644 --- a/src/components/Cards/ImageCard.js +++ b/src/components/Cards/ImageCard.js @@ -36,7 +36,7 @@ export default class ImageCard extends React.Component { return ( -

{text}

+

{text}

); } diff --git a/src/components/UI/theme.css b/src/components/UI/theme.css index 41aac294..b8add9c7 100644 --- a/src/components/UI/theme.css +++ b/src/components/UI/theme.css @@ -1,7 +1,7 @@ :root { --defaultColor: #333; --backgroundColor: #fff; - --shadowColor: rgba(0, 0, 0, 0.25); + --shadowColor: rgba(0, 0, 0, 0.117647); --successColor: #1c7; --warningColor: #fa0; --errorColor: #f52; @@ -17,9 +17,9 @@ } .rounded { - border-radius: 6px; + border-radius: 2px; } .depth { - box-shadow: 0px 1px 2px 0px var(--shadowColor); + box-shadow: var(--shadowColor) 0px 1px 6px, var(--shadowColor) 0px 1px 4px; } From 5d6eec28bb4e45293f38f3748fe01233c17dee7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Thu, 14 Jul 2016 17:17:18 -0300 Subject: [PATCH 12/28] Layout refinments --- src/components/Cards/ImageCard.css | 13 +++++++++ src/components/Cards/ImageCard.js | 9 ++++--- src/components/EntryListing.js | 13 ++++----- src/containers/App.css | 43 ++++++++++++++++++++++++++++++ src/containers/App.js | 19 ++++++++----- src/containers/FindBar.css | 3 +-- src/index.css | 16 +++++++++++ 7 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 src/components/Cards/ImageCard.css create mode 100644 src/containers/App.css diff --git a/src/components/Cards/ImageCard.css b/src/components/Cards/ImageCard.css new file mode 100644 index 00000000..398cfdda --- /dev/null +++ b/src/components/Cards/ImageCard.css @@ -0,0 +1,13 @@ +.root { + cursor: pointer; +} + +.root h1 { + font-weight: 500; + font-size: 18px; +} + +.root h2 { + font-weight: 400; + font-size: 16px; +} diff --git a/src/components/Cards/ImageCard.js b/src/components/Cards/ImageCard.js index 9dbe971d..1d09aa16 100644 --- a/src/components/Cards/ImageCard.js +++ b/src/components/Cards/ImageCard.js @@ -1,5 +1,6 @@ import React, { PropTypes } from 'react'; import { Card } from '../UI'; +import styles from './ImageCard.css' export default class ImageCard extends React.Component { constructor(props) { @@ -34,16 +35,16 @@ export default class ImageCard extends React.Component { render() { const { onClick, image, text } = this.props; return ( - - -

{text}

+ + {image ? : null} +

{text}

); } } ImageCard.propTypes = { - image: PropTypes.string.isRequired, + image: PropTypes.string, onClick: PropTypes.func, onImageLoaded: PropTypes.func, text: PropTypes.string.isRequired diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index 0a08f48a..130f1cd2 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -12,12 +12,13 @@ export default class EntryListing extends React.Component { this.bricksConfig = { packed: 'data-packed', sizes: [ - { columns: 2, gutter: 15 }, - { mq: '780px', columns: 3, gutter: 15 }, - { mq: '1035px', columns: 4, gutter: 15 }, - { mq: '1290px', columns: 5, gutter: 15 }, - { mq: '1545px', columns: 6, gutter: 15 }, - { mq: '1800px', columns: 7, gutter: 15 }, + { columns: 1, gutter: 15 }, + { mq: '495px', columns: 2, gutter: 15 }, + { mq: '750px', columns: 3, gutter: 15 }, + { mq: '1005px', columns: 4, gutter: 15 }, + { mq: '1260px', columns: 5, gutter: 15 }, + { mq: '1515px', columns: 6, gutter: 15 }, + { mq: '1770px', columns: 7, gutter: 15 }, ] }; } diff --git a/src/containers/App.css b/src/containers/App.css new file mode 100644 index 00000000..ad6bef11 --- /dev/null +++ b/src/containers/App.css @@ -0,0 +1,43 @@ +.alignable { + margin: 0px auto; +} + +@media (max-width: 749px) and (min-width: 495px) { + .alignable { + width: 495px; + } +} + +@media (max-width: 1004px) and (min-width: 750px) { + .alignable { + width: 750px; + } +} + +@media (max-width: 1259px) and (min-width: 1005px) { + .alignable { + width: 1005px; + } +} + +@media (max-width: 1514px) and (min-width: 1260px) { + .alignable { + width: 1260px; + } +} + +@media (max-width: 1769px) and (min-width: 1515px) { + .alignable { + width: 1515px; + } +} + +@media (min-width: 1770px) { + .alignable { + width: 1770px; + } +} + +.main { + padding-top: 60px; +} diff --git a/src/containers/App.js b/src/containers/App.js index 290a6d4a..2e0a00ef 100644 --- a/src/containers/App.js +++ b/src/containers/App.js @@ -5,6 +5,7 @@ import { loginUser } from '../actions/auth'; import { currentBackend } from '../backends/backend'; import { LIST_POSTS, LIST_FAQ, HELP, MORE_COMMANDS } from '../actions/findbar'; import FindBar from './FindBar'; +import styles from './App.css'; class App extends React.Component { componentDidMount() { @@ -70,12 +71,18 @@ class App extends React.Component { return (
- - {children} +
+
+ +
+
+
+ {children} +
); } diff --git a/src/containers/FindBar.css b/src/containers/FindBar.css index c520bfbb..5f31c520 100644 --- a/src/containers/FindBar.css +++ b/src/containers/FindBar.css @@ -10,9 +10,8 @@ position: relative; background-color: var(--backgroundColor); padding: 1px 0; - margin-bottom: 50px; + margin: 4px auto; } - .inputArea { display: table; width: calc(100% - 10px); diff --git a/src/index.css b/src/index.css index d1c6f90d..7d136634 100644 --- a/src/index.css +++ b/src/index.css @@ -2,6 +2,7 @@ html { box-sizing: border-box; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; + margin: 0; } *, *:before, *:after { box-sizing: inherit; @@ -10,8 +11,23 @@ html { body { font-family: 'Roboto', sans-serif; height: 100%; + background-color: #fafafa; + margin: 0; +} + +header { + background-color: #fff; + box-shadow: 0 1px 2px 0 rgba(0,0,0,0.22); + height: 54px; + position: fixed; + width: 100%; + z-index: 999; } :global #root, :global #root > * { height: 100%; } + +h1, h2, h3, h4, h5, h6 { + margin: 0; +} From e3643217dea1233c40408eed9da0210247cf3625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Fri, 15 Jul 2016 15:05:04 -0300 Subject: [PATCH 13/28] setting base href support for router --- package.json | 4 ++-- src/actions/findbar.js | 9 ++++----- src/components/EntryListing.js | 6 +++--- src/index.js | 11 +++++++++-- src/routes/routes.js | 19 ------------------- src/routing/history.js | 15 +++++++++++++++ src/routing/routes.js | 17 +++++++++++++++++ src/store/configureStore.js | 7 +++---- 8 files changed, 53 insertions(+), 35 deletions(-) delete mode 100644 src/routes/routes.js create mode 100644 src/routing/history.js create mode 100644 src/routing/routes.js diff --git a/package.json b/package.json index fae8a986..defae628 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "react-lazy-load": "^3.0.3", "react-pure-render": "^1.0.2", "react-redux": "^4.4.0", - "react-router": "^2.0.0", - "react-router-redux": "^3.0.0", + "react-router": "^2.5.1", + "react-router-redux": "^4.0.5", "redux": "^3.3.1", "redux-thunk": "^1.0.3", "style-loader": "^0.13.0", diff --git a/src/actions/findbar.js b/src/actions/findbar.js index b231b46f..77053ada 100644 --- a/src/actions/findbar.js +++ b/src/actions/findbar.js @@ -1,4 +1,4 @@ -import { browserHistory } from 'react-router'; +import history from '../routing/history'; import { SEARCH } from '../containers/FindBar'; export const RUN_COMMAND = 'RUN_COMMAND'; @@ -10,21 +10,20 @@ export function run(commandName, payload) { return { type: RUN_COMMAND, command: commandName, payload }; } - export function runCommand(commandName, payload) { return (dispatch, getState) => { switch (commandName) { case LIST_POSTS: - browserHistory.push('/collections/posts'); + history.push('/collections/posts'); break; case LIST_FAQ: - browserHistory.push('/collections/faq'); + history.push('/collections/faq'); break; case HELP: window.alert('Find Bar Help (PLACEHOLDER)\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit.'); break; case SEARCH: - browserHistory.push('/search'); + history.push('/search'); break; } dispatch(run(commandName, payload)); diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index 130f1cd2..712c0c08 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -1,7 +1,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Bricks from 'bricks.js' -import { browserHistory } from 'react-router'; +import Bricks from 'bricks.js'; +import history from '../routing/history'; import Cards from './Cards'; export default class EntryListing extends React.Component { @@ -57,7 +57,7 @@ export default class EntryListing extends React.Component { return React.createElement(card, { key: entry.get('slug'), collection: collection, - onClick: browserHistory.push.bind(this, link), + onClick: history.push.bind(this, link), onImageLoaded: () => this.bricksInstance.pack(), text: entry.getIn(['data', collection.getIn(['card', 'text'])]), image: entry.getIn(['data', collection.getIn(['card', 'image'])]), diff --git a/src/index.js b/src/index.js index 40da4d74..79fea2e0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,10 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; +import { Router } from 'react-router'; import configureStore from './store/configureStore'; -import Routes from './routes/routes'; +import routes from './routing/routes'; +import history, { syncHistory } from './routing/history'; import 'file?name=index.html!../example/index.html'; import './index.css'; @@ -12,8 +14,13 @@ const el = document.createElement('div'); el.id = 'root'; document.body.appendChild(el); +// Create an enhanced history that syncs navigation events with the store +syncHistory(store); + render(( - + + {routes} + ), el); diff --git a/src/routes/routes.js b/src/routes/routes.js deleted file mode 100644 index 50a798d6..00000000 --- a/src/routes/routes.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { Router, Route, IndexRoute, browserHistory } from 'react-router'; -import App from '../containers/App'; -import CollectionPage from '../containers/CollectionPage'; -import EntryPage from '../containers/EntryPage'; -import SearchPage from '../containers/SearchPage'; -import NotFoundPage from '../containers/NotFoundPage'; - -export default () => ( - - - - - - - - - -); diff --git a/src/routing/history.js b/src/routing/history.js new file mode 100644 index 00000000..12a7b087 --- /dev/null +++ b/src/routing/history.js @@ -0,0 +1,15 @@ +import { createHistory } from 'history'; +import { useRouterHistory } from 'react-router'; +import { syncHistoryWithStore } from 'react-router-redux'; + +const base = document.querySelector('base'); +let history = useRouterHistory(createHistory)({ + basename: base && base.href || '' +}); + +const syncHistory = (store) => { + history = syncHistoryWithStore(history, store); +}; + +export { syncHistory }; +export default history; diff --git a/src/routing/routes.js b/src/routing/routes.js new file mode 100644 index 00000000..39f1bf81 --- /dev/null +++ b/src/routing/routes.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { Route, IndexRoute } from 'react-router'; +import App from '../containers/App'; +import CollectionPage from '../containers/CollectionPage'; +import EntryPage from '../containers/EntryPage'; +import SearchPage from '../containers/SearchPage'; +import NotFoundPage from '../containers/NotFoundPage'; + +export default ( + + + + + + + +); diff --git a/src/store/configureStore.js b/src/store/configureStore.js index 3107dba0..d7552c00 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,16 +1,15 @@ import { createStore, applyMiddleware, combineReducers, compose } from 'redux'; import thunkMiddleware from 'redux-thunk'; -import { browserHistory } from 'react-router'; -import { syncHistory, routeReducer } from 'react-router-redux'; +import { routerReducer } from 'react-router-redux'; import reducers from '../reducers'; const reducer = combineReducers({ ...reducers, - router: routeReducer + routing: routerReducer }); const createStoreWithMiddleware = compose( - applyMiddleware(thunkMiddleware, syncHistory(browserHistory)), + applyMiddleware(thunkMiddleware), window.devToolsExtension ? window.devToolsExtension() : (f) => f )(createStore); From b991b1af2665d6ec820060f4f861ce2dd0ce2196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Fri, 15 Jul 2016 16:16:33 -0300 Subject: [PATCH 14/28] basepath config as singleton --- src/actions/config.js | 3 ++- src/routing/basePath.js | 10 ++++++++++ src/routing/history.js | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/routing/basePath.js diff --git a/src/actions/config.js b/src/actions/config.js index c0148f3e..14c51e34 100644 --- a/src/actions/config.js +++ b/src/actions/config.js @@ -2,6 +2,7 @@ import yaml from 'js-yaml'; import { currentBackend } from '../backends/backend'; import { authenticate } from '../actions/auth'; import * as MediaProxy from '../valueObjects/MediaProxy'; +import basePath from '../routing/basePath'; export const CONFIG_REQUEST = 'CONFIG_REQUEST'; export const CONFIG_SUCCESS = 'CONFIG_SUCCESS'; @@ -43,7 +44,7 @@ export function loadConfig(config) { return (dispatch, getState) => { dispatch(configLoading()); - fetch('/config.yml').then((response) => { + fetch(`${basePath}/config.yml`).then((response) => { if (response.status !== 200) { throw `Failed to load config.yml (${response.status})`; } diff --git a/src/routing/basePath.js b/src/routing/basePath.js new file mode 100644 index 00000000..d00abe17 --- /dev/null +++ b/src/routing/basePath.js @@ -0,0 +1,10 @@ +const base = document.querySelector('base'); + +let basePath; +if (base && base.href) { + basePath = base.attributes.getNamedItem('href').value; +} else { + basePath = ''; +} + +export default basePath; diff --git a/src/routing/history.js b/src/routing/history.js index 12a7b087..4825aba1 100644 --- a/src/routing/history.js +++ b/src/routing/history.js @@ -1,10 +1,10 @@ import { createHistory } from 'history'; import { useRouterHistory } from 'react-router'; import { syncHistoryWithStore } from 'react-router-redux'; +import basePath from './basePath'; -const base = document.querySelector('base'); let history = useRouterHistory(createHistory)({ - basename: base && base.href || '' + basename: basePath }); const syncHistory = (store) => { From 8fdb46f0854608086bb05fe3f2a6cc9fe0556823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Mon, 18 Jul 2016 15:07:45 -0300 Subject: [PATCH 15/28] extracting css file --- example/index.html | 2 ++ package.json | 1 + webpack.config.js | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/example/index.html b/example/index.html index 341eebd4..8710f979 100644 --- a/example/index.html +++ b/example/index.html @@ -6,6 +6,7 @@ This is an example + + diff --git a/package.json b/package.json index defae628..a23ad57d 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "eslint-loader": "^1.2.1", "eslint-plugin-react": "^5.1.1", "exports-loader": "^0.6.3", + "extract-text-webpack-plugin": "^1.0.1", "express": "^4.13.4", "file-loader": "^0.8.5", "immutable": "^3.7.6", diff --git a/webpack.config.js b/webpack.config.js index 66e20d7e..b312cf01 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,6 @@ /* global module, __dirname, require */ var webpack = require('webpack'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); var path = require('path'); module.exports = { @@ -12,7 +13,7 @@ module.exports = { { test: /\.json$/, loader: 'json-loader' }, { test: /\.css$/, - loader: 'style!css?modules&importLoaders=1!postcss' + loader: ExtractTextPlugin.extract("style", "css?modules&importLoaders=1!postcss"), }, { loader: 'babel', @@ -33,6 +34,7 @@ module.exports = { ], plugins: [ + new ExtractTextPlugin('cms.css', { allChunks: true }), new webpack.ProvidePlugin({ 'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch' }) From f7fb01e3cbc827f55367d3c1c9a7670c3d7a6675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Mon, 18 Jul 2016 15:07:59 -0300 Subject: [PATCH 16/28] refinments --- src/actions/media.js | 4 ++-- src/containers/CollectionPage.js | 1 - src/index.js | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/actions/media.js b/src/actions/media.js index 88f822ff..a45e6f64 100644 --- a/src/actions/media.js +++ b/src/actions/media.js @@ -2,9 +2,9 @@ export const ADD_MEDIA = 'ADD_MEDIA'; export const REMOVE_MEDIA = 'REMOVE_MEDIA'; export function addMedia(mediaProxy) { - return {type: ADD_MEDIA, payload: mediaProxy}; + return { type: ADD_MEDIA, payload: mediaProxy }; } export function removeMedia(uri) { - return {type: REMOVE_MEDIA, payload: uri}; + return { type: REMOVE_MEDIA, payload: uri }; } diff --git a/src/containers/CollectionPage.js b/src/containers/CollectionPage.js index bc119da5..8c10703e 100644 --- a/src/containers/CollectionPage.js +++ b/src/containers/CollectionPage.js @@ -1,6 +1,5 @@ import React, { PropTypes } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { Link } from 'react-router'; import { connect } from 'react-redux'; import { loadEntries } from '../actions/entries'; import { selectEntries } from '../reducers'; diff --git a/src/index.js b/src/index.js index 79fea2e0..508b38f0 100644 --- a/src/index.js +++ b/src/index.js @@ -10,13 +10,13 @@ import './index.css'; const store = configureStore(); +// Create an enhanced history that syncs navigation events with the store +syncHistory(store); + const el = document.createElement('div'); el.id = 'root'; document.body.appendChild(el); -// Create an enhanced history that syncs navigation events with the store -syncHistory(store); - render(( From 2277a9c479bc6e8551e9fee4cff18a3cc6e1e016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Mon, 18 Jul 2016 16:09:35 -0300 Subject: [PATCH 17/28] bugfix: request cannot be bound to repo url --- src/backends/github/implementation.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backends/github/implementation.js b/src/backends/github/implementation.js index 96790bd6..d9bd08af 100644 --- a/src/backends/github/implementation.js +++ b/src/backends/github/implementation.js @@ -8,7 +8,7 @@ class API { this.token = token; this.repo = repo; this.branch = branch; - this.baseURL = API_ROOT + `/repos/${this.repo}`; + this.repoURL = `/repos/${this.repo}`; } user() { @@ -20,9 +20,9 @@ class API { return cache.then((cached) => { if (cached) { return cached; } - return this.request(`/contents/${path}`, { - headers: {Accept: 'application/vnd.github.VERSION.raw'}, - data: {ref: this.branch}, + return this.request(`${this.repoURL}/contents/${path}`, { + headers: { Accept: 'application/vnd.github.VERSION.raw' }, + data: { ref: this.branch }, cache: false }).then((result) => { if (sha) { @@ -35,8 +35,8 @@ class API { } listFiles(path) { - return this.request(`/contents/${path}`, { - data: {ref: this.branch} + return this.request(`${this.repoURL}/contents/${path}`, { + data: { ref: this.branch } }); } @@ -60,7 +60,7 @@ class API { request(path, options = {}) { const headers = this.requestHeaders(options.headers || {}); - return fetch(this.baseURL + path, {...options, headers: headers}).then((response) => { + return fetch(API_ROOT + path, { ...options, headers: headers }).then((response) => { if (response.headers.get('Content-Type').match(/json/)) { return this.parseJsonResponse(response); } From 6f0f13ad405ceb32521eefd9ba2821f2a0f571e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 19 Jul 2016 17:10:07 -0300 Subject: [PATCH 18/28] refine font import --- example/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/index.html b/example/index.html index 8710f979..2d910b39 100644 --- a/example/index.html +++ b/example/index.html @@ -5,7 +5,7 @@ This is an example - +