From b0f03a51ec0cfde460d456c0ab50a272d1d264aa Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Sat, 20 May 2017 12:16:19 +0100 Subject: [PATCH 1/2] Allow more ES6 features Now you can (and will be forced to, by eslint!) use: - function shorthand - let instead of var - string template instead of concatenation --- src/js/query/results.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/query/results.jsx b/src/js/query/results.jsx index 7b2775f..dc037f5 100644 --- a/src/js/query/results.jsx +++ b/src/js/query/results.jsx @@ -113,11 +113,11 @@ const Results = React.createClass({ }, getCopyLink() { - return (this.canCopyResults()) ?
  • Copy To Clipboard
  • : null + return (this.canCopyResults()) ? Copy to clipboard : null }, render() { - new Clipboard("a.site-link[data-clipboard-action='copy']") + new Clipboard("pre a") return (
    From 4c795514eca6ee51d764970ecbbad67760c4670b Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Sun, 21 May 2017 10:04:10 +0100 Subject: [PATCH 2/2] Implement Material UI Uses Google Material Design components to give a more flexible design system with a extensible tool palette. --- package.json | 3 + src/css/app.css | 293 ++---------------------------- src/index.html | 2 +- src/js/components/code.jsx | 8 +- src/js/components/inset.jsx | 26 +++ src/js/components/layout.jsx | 45 +++++ src/js/components/space-after.jsx | 16 ++ src/js/home/index.jsx | 67 ++++--- src/js/home/paste.jsx | 15 +- src/js/home/upload.jsx | 30 ++- src/js/home/url.jsx | 31 +++- src/js/index.jsx | 19 +- src/js/main.jsx | 23 ++- src/js/query/controls.jsx | 83 ++++----- src/js/query/filter-row.jsx | 85 ++++++--- src/js/query/filters.jsx | 57 +++--- src/js/query/grouping-control.jsx | 68 ++++--- src/js/query/index.jsx | 99 ++++++---- src/js/query/removeable.jsx | 28 +++ src/js/query/results.jsx | 149 +++++++++------ src/js/query/schema-edit-row.jsx | 33 ++-- src/js/query/schema-edit.jsx | 58 ++++-- src/js/query/sorting-control.jsx | 57 +++--- src/js/query/summary.jsx | 37 +++- 24 files changed, 684 insertions(+), 648 deletions(-) create mode 100644 src/js/components/inset.jsx create mode 100644 src/js/components/layout.jsx create mode 100644 src/js/components/space-after.jsx create mode 100644 src/js/query/removeable.jsx diff --git a/package.json b/package.json index b785c7d..110d256 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,15 @@ "date-fns": "^1.28.1", "flat": "^2.0.1", "flux": "^2.1.1", + "material-ui": "^0.18.1", + "normalize.css": "^7.0.0", "prop-types": "^15.5.10", "query-string": "^4.3.2", "ramda": "^0.23.0", "react": "^15.0.1", "react-dom": "^15.0.1", "react-syntax-highlighter": "^5.6.0", + "react-tap-event-plugin": "^2.0.1", "uuid": "^3.0.1" }, "devDependencies": { diff --git a/src/css/app.css b/src/css/app.css index a9819f2..7a1b0f1 100644 --- a/src/css/app.css +++ b/src/css/app.css @@ -1,296 +1,35 @@ -* { - box-sizing: border-box; -} - -html { - font-family: sans-serif; - font-size: 10px; -} - body { - margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; color: #333; - background-color: #fff; -} - -p > code { - background: #eee; - border: 1px solid #ccc; - border-radius: 3px; - padding: 0 4px; - color: darkred; -} - -pre { - margin: 0 0 10px; - border: 1px solid #ccc; - border-radius: 3px; -} - -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; - width: 760px; -} - -.header { - display: flex; -} - -.header h1 { - width: 50%; - margin-bottom: 0; -} - -.header h1 a { - text-decoration: none; - color: #000; - cursor: pointer; -} - -.header span { - text-align: right; - width: 50%; - margin-top: 5px; - font-size: 12px; -} - -a { - color: #337ab7; - text-decoration: none; - background-color: transparent; -} - -a:active, -a:hover { - outline: 0; -} - -a:hover { - color: #23527c; - text-decoration: underline; -} - -a.site-link { - cursor: pointer; + line-height: 1.4; } -table { - border-spacing: 0; - border-collapse: collapse; - background-color: transparent; -} - -td, -th { - padding: 0; -} - -th { - text-align: left; -} - -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} - -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} - -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} - -.table > thead:first-child > tr:first-child > th { - border-top: 0; -} -.table-striped > tbody > tr:nth-of-type(odd) { - background-color: #f9f9f9; +p { + margin-bottom: 1em; + margin-top: 0; } textarea { - width: 730px; - height: 350px; -} - -ul.side-options { - display: flex; - flex-direction: row; - list-style-type: none; - padding: 0; - margin: 15px 0; -} - -ul.side-options.right { - justify-content: flex-end; -} - -ul.side-options li { - margin-right: 15px; -} - -ul.side-options li.active { - font-weight: bold; -} - -ul.side-options li:last-of-type { - margin-right: 0; + font-size: 13px; + font-family: monospace, monospace; + color: #333; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; } -.checkbox-label { - margin-right: 10px; - cursor: pointer; +pre { + border: 1px solid #ccc; + border-radius: 4px; + font-size: 13px; } /* Home */ - -.home-cont .drag-drop-area { - width: 730px; +.drag-drop-area { + width: 100%; height: 200px; border: 3px dashed #AAA; display: flex; justify-content: center; align-items: center; } - -/* Filters */ - -.filters { - margin: 10px 0 15px 0; -} - -.filters tbody tr.inactive { - background: #cccccc; - opacity: 0.6; -} - -.filter-controls { - display: flex; - align-items: flex-start; -} - -.filter-controls select { - width: 170px; - margin-right: 10px; -} - -.filter-controls .inputs { - flex: 1; - display: flex; - flex-direction: column; -} - -.filter-controls input { - width: 150px; - margin-bottom: 5px; -} - -.filter-controls.number input { - width: 100px; -} - -.filter-controls input:last-of-type { - margin-bottom: 0; -} - -/* Controls */ - -.input-control { - display: flex; - align-items: flex-start; - margin-bottom: 5px; -} - -.input-control label { - width: 100px; -} - -.input-control .body { - flex: 1; - display: flex; - flex-direction: column; -} - -.input-control .body .grouping, -.input-control .body .sorter { - line-height: 22px; -} - -.input-control .body .grouping a, -.input-control .body .sorter a { - margin-left: 30px; -} - -.input-control select { - min-width: 100px; - margin-right: 10px; -} - -/* Results */ - -.results-options { - display: flex; - justify-content: space-between; -} - -/* Summary */ - -h3.summary { - margin-bottom: 0; -} - -.summary-stats { - display: flex; - flex-direction: row; - align-items: flex-start; - flex-wrap: wrap; - flex-flow: row wrap; - align-content: flex-end; -} - -.summary-stats p { - width: 200px; - margin-bottom: 0; -} - -/* From Url */ - -.from-url-cont { - height: 300px; - display: flex; - justify-content: center; - flex-direction: column; -} - -.from-url-cont p { - text-align: center; -} - -/* From Url */ - -.schema-edit-cont .rows { - display: flex; - align-items: flex-start; -} - -.schema-edit-cont .rows pre { - flex-basis: 20%; - flex-grow: 1; - margin-left: 15px; -} diff --git a/src/index.html b/src/index.html index 39be152..2df75c0 100644 --- a/src/index.html +++ b/src/index.html @@ -23,7 +23,7 @@ {% endif %} -
    +
    diff --git a/src/js/components/code.jsx b/src/js/components/code.jsx index c2971e0..3582a33 100644 --- a/src/js/components/code.jsx +++ b/src/js/components/code.jsx @@ -8,12 +8,18 @@ const resultsStyle = require("react-syntax-highlighter/dist/styles/github").defa SLH.registerLanguage("json", language) function Code(props) { - return ( + return ( {props.children} ) } Code.propTypes = { + inline: PropTypes.bool, children: PropTypes.node.isRequired, language: PropTypes.oneOf(["json"]), } diff --git a/src/js/components/inset.jsx b/src/js/components/inset.jsx new file mode 100644 index 0000000..cd013dd --- /dev/null +++ b/src/js/components/inset.jsx @@ -0,0 +1,26 @@ +const React = require("react") +const PropTypes = require("prop-types") + +const SIZE = 16 + +function Inset({children, horizontal, vertical}) { + return
    {children}
    +} + +Inset.defaultProps = { + horizontal: true, + vertical: true, +} + +Inset.propTypes = { + children: PropTypes.node.isRequired, + horizontal: PropTypes.bool.isRequired, + vertical: PropTypes.bool.isRequired, +} + +module.exports = Inset diff --git a/src/js/components/layout.jsx b/src/js/components/layout.jsx new file mode 100644 index 0000000..4b4745d --- /dev/null +++ b/src/js/components/layout.jsx @@ -0,0 +1,45 @@ +const React = require("react") +const PropTypes = require("prop-types") + +const {default: Card} = require("material-ui/Card") + +function Layout({left, right}) { + return ( +
    +
    + {left} +
    +
    + {right} +
    +
    + ) +} + +Layout.propTypes = { + left: PropTypes.node.isRequired, + right: PropTypes.node.isRequired, +} + +module.exports = Layout diff --git a/src/js/components/space-after.jsx b/src/js/components/space-after.jsx new file mode 100644 index 0000000..6ec0715 --- /dev/null +++ b/src/js/components/space-after.jsx @@ -0,0 +1,16 @@ +const React = require("react") +const PropTypes = require("prop-types") + +const style = { + marginBottom: 16, +} + +function SpaceAfter({children}) { + return
    {children}
    +} + +SpaceAfter.propTypes = { + children: PropTypes.node.isRequired, +} + +module.exports = SpaceAfter diff --git a/src/js/home/index.jsx b/src/js/home/index.jsx index 0dff4b5..41b635a 100644 --- a/src/js/home/index.jsx +++ b/src/js/home/index.jsx @@ -1,10 +1,14 @@ const React = require("react") const PropTypes = require("prop-types") -const classNames = require("classnames") const validator = require("../services/validator") const schemaGenerator = require("../services/schema-generator") +const {CardText, CardTitle} = require("material-ui/Card") +const {default: Tabs, Tab} = require("material-ui/Tabs") + +const Layout = require("../components/layout") + const Paste = require("./paste") const Upload = require("./upload") const Url = require("./url") @@ -56,41 +60,34 @@ const Home = React.createClass({ this.props.actionCreator.saveJson("schema", schemaGenerator.generate(json[0])) }, - getPasteComponent() { - if (this.state.selectedTab !== "paste") return null - return - }, - - getUploadComponent() { - if (this.state.selectedTab !== "upload") return null - return - }, - - getUrlComponent() { - if (this.state.selectedTab !== "url") return null - return - }, - render() { - const pasteActive = classNames({active: this.state.selectedTab === "paste"}) - const uploadActive = classNames({active: this.state.selectedTab === "upload"}) - const urlActive = classNames({active: this.state.selectedTab === "url"}) - - return ( -
    -

    Online JSON Querying Tool. Query your JSON with ease.

    -

    Takes a JSON array and allows you to add multiple filters, groupings and sorting to manipulate the data in many ways. Use the inputs below to supply your data. We do not do anything with your data!

    -
    - - {this.getPasteComponent()} - {this.getUploadComponent()} - {this.getUrlComponent()} -
    - ) + return ( + + +

    Takes a JSON array and allows you to add multiple filters, groupings and sorting to manipulate the data in many ways.

    +

    Use the inputs on the right to supply your data.

    +

    We do not do anything with your data!

    +
    +
    } + + right = { + + + + + + + + + + + + } + />) }, }) diff --git a/src/js/home/paste.jsx b/src/js/home/paste.jsx index 458fd6b..2a7833f 100644 --- a/src/js/home/paste.jsx +++ b/src/js/home/paste.jsx @@ -3,6 +3,11 @@ const PropTypes = require("prop-types") const testData = require("../../test-data.json") +const Inset = require("../components/inset") +const SpaceAfter = require("../components/space-after") + +const {default: RaisedButton} = require("material-ui/RaisedButton") + const Paste = React.createClass({ displayName: "Paste", @@ -28,10 +33,12 @@ const Paste = React.createClass({ render() { return ( -
    -