From 69a665373f26a4934fd13bdd58a6e51b0ee73efc Mon Sep 17 00:00:00 2001 From: jirik Date: Thu, 12 Jan 2017 18:27:44 +0100 Subject: [PATCH] Export to Gist anonymously, related to maputnik/editor#3 --- package.json | 1 + src/components/Toolbar.jsx | 13 ++- src/components/modals/ExportModal.jsx | 152 ++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/components/modals/ExportModal.jsx diff --git a/package.json b/package.json index 974e385..ac7e880 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "codemirror": "^5.18.2", "color": "^1.0.3", "file-saver": "^1.3.2", + "github-api": "^3.0.0", "lodash.capitalize": "^4.2.1", "lodash.clonedeep": "^4.5.0", "lodash.isequal": "^4.4.0", diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index 1898783..fc14638 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -18,6 +18,7 @@ import InspectionIcon from 'react-icons/lib/md/find-in-page' import logoImage from '../img/maputnik.png' import SettingsModal from './modals/SettingsModal' +import ExportModal from './modals/ExportModal' import SourcesModal from './modals/SourcesModal' import OpenModal from './modals/OpenModal' @@ -68,6 +69,7 @@ export default class Toolbar extends React.Component { sources: false, open: false, add: false, + export: false, } } } @@ -96,6 +98,12 @@ export default class Toolbar extends React.Component { isOpen={this.state.isOpen.settings} onOpenToggle={this.toggleModal.bind(this, 'settings')} /> + Open - {this.downloadButton()} + + + Export + Sources diff --git a/src/components/modals/ExportModal.jsx b/src/components/modals/ExportModal.jsx new file mode 100644 index 0000000..89547c2 --- /dev/null +++ b/src/components/modals/ExportModal.jsx @@ -0,0 +1,152 @@ +import React from 'react' + +import GlSpec from 'mapbox-gl-style-spec/reference/latest.js' +import InputBlock from '../inputs/InputBlock' +import StringInput from '../inputs/StringInput' +import SelectInput from '../inputs/SelectInput' +import Button from '../Button' +import Modal from './Modal' +import MdFileDownload from 'react-icons/lib/md/file-download' +import formatStyle from 'mapbox-gl-style-spec/lib/format' +import GitHub from 'github-api' + + +class Gist extends React.Component { + static propTypes = { + mapStyle: React.PropTypes.object.isRequired, + } + + constructor(props) { + super(props); + this.state = {} + } + + onSave() { + this.setState({ + saving: true + }); + const mapStyleStr = formatStyle(this.props.mapStyle); + const styleTitle = this.props.mapStyle.name || 'Style'; + const htmlStr = ` + + + + + + `+styleTitle+` Preview + + + + + +
+ + + +` + const gh = new GitHub(); + let gist = gh.getGist(); // not a gist yet + gist.create({ + public: true, + description: styleTitle + 'Preview', + files: { + "style.json": { + content: mapStyleStr + }, + "index.html": { + content: htmlStr + } + } + }).then(function({data}) { + return gist.read(); + }).then(function({data}) { + this.setState({ + latestGist: data + }); + }.bind(this)); + } + + renderLatestGist() { + const gist = this.state.latestGist; + const saving = this.state.saving; + if(gist) { + const user = gist.user || 'anonymous'; + return

+ Latest saved gist:{' '} + Preview,{' '} + Source +

+ } else if(saving) { + return

Saving...

+ } + } + + render() { + return
+ + {this.renderLatestGist()} +
+ } +} + + + +class ExportModal extends React.Component { + static propTypes = { + mapStyle: React.PropTypes.object.isRequired, + isOpen: React.PropTypes.bool.isRequired, + onOpenToggle: React.PropTypes.func.isRequired, + // Current style is requested for download + onStyleDownload: React.PropTypes.func.isRequired, + } + + constructor(props) { + super(props); + } + + onStyleDownload() { + const blob = new Blob([formatStyle(mapStyle)], {type: "application/json;charset=utf-8"}); + saveAs(blob, mapStyle.id + ".json"); + } + + render() { + return + +
+

Download Style

+

+ Download a JSON style to your computer. +

+ +
+ +
+

Save style

+ +
+
+ } +} + +export default ExportModal