From e05939773ceba52e189c54ad25172a1f20f3cc4f Mon Sep 17 00:00:00 2001 From: Alessandro Sebastiani Date: Sat, 8 Feb 2020 18:53:23 +0100 Subject: [PATCH 1/4] publiccode remote url import in editor --- src/app/components/editor.js | 2 ++ src/app/components/sidebar.js | 33 ++++++++++++++++++++++++--------- src/app/contents/constants.js | 5 +++-- src/app/utils/calls.js | 35 ++++++++++++++++++++++++++++++----- webpack.config.js | 3 ++- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/app/components/editor.js b/src/app/components/editor.js index 170d79a6..e101413a 100644 --- a/src/app/components/editor.js +++ b/src/app/components/editor.js @@ -68,6 +68,7 @@ class Index extends Component { lastGen: null, yamlLoaded: false }; + this.onLoadingRemote = this.props.onLoadingRemote.bind(this); } initBootstrap() { @@ -397,6 +398,7 @@ class Index extends Component { loading, values, allFields, + onLoadingRemote: this.onLoadingRemote, onLoad: this.parseYml.bind(this), onReset: this.reset.bind(this) }; diff --git a/src/app/components/sidebar.js b/src/app/components/sidebar.js index 5b40434b..7911ae5c 100644 --- a/src/app/components/sidebar.js +++ b/src/app/components/sidebar.js @@ -11,7 +11,7 @@ import img_download from "../../asset/img/download.svg"; import img_dots from "../../asset/img/dots.svg"; import img_xx from "../../asset/img/xx.svg"; -import { getRemoteYml } from "../utils/calls"; +import { getRemoteYml, passRemoteURLToValidator } from "../utils/calls"; import { getLabel } from "../contents/data"; function mapStateToProps(state) { @@ -65,9 +65,24 @@ class sidebar extends Component { let yaml = null; try { - yaml = await getRemoteYml(remoteYml); + this.setState({ loading: true }); + this.props.onLoadingRemote(true); + + // trying to get file and process it, cors problem + // yaml = await getRemoteYml(remoteYml); + + // piping url to validator which will returns a fresh + // and validated copy + yaml = await passRemoteURLToValidator(remoteYml); + onLoad(yaml); + + this.setState({ loading: false }); + this.props.onLoadingRemote(false); } catch (error) { + + this.setState({ loading: false }); + this.props.onLoadingRemote(false); console.error(error); alert("error parsing remote yaml"); } @@ -92,7 +107,7 @@ class sidebar extends Component { onReset(); - reader.onload = function() { + reader.onload = function () { let yaml = reader.result; onLoad(yaml); document.getElementById("load_yaml").value = ""; @@ -103,9 +118,9 @@ class sidebar extends Component { download(data) { //has dom - if (!data || data.length == 0){ - return; - } + if (!data || data.length == 0) { + return; + } const blob = new Blob([data], { type: "text/yaml;charset=utf-8;" }); @@ -117,7 +132,7 @@ class sidebar extends Component { tempLink.setAttribute("download", "publiccode.yml"); document.body.appendChild(tempLink); tempLink.click(); - setTimeout(function() { + setTimeout(function () { document.body.removeChild(tempLink); window.URL.revokeObjectURL(blobURL); }, 1000); @@ -199,7 +214,7 @@ class sidebar extends Component { -
+
Paste remote yaml url
this.handleChange(e)} /> -
diff --git a/src/app/contents/constants.js b/src/app/contents/constants.js index f91c298d..6c2e55c9 100644 --- a/src/app/contents/constants.js +++ b/src/app/contents/constants.js @@ -1,9 +1,10 @@ -let {REPOSITORY, ELASTIC_URL, VALIDATOR_URL} = process.env; +let {REPOSITORY, ELASTIC_URL, VALIDATOR_URL, VALIDATOR_REMOTE_URL} = process.env; export const privacyPolicyUrl = `https://developers.italia.it/it/privacy-policy/`; export const repositoryUrl = `https://docs.italia.it/italia/developers-italia/publiccodeyml/it/master/`; export const versionsUrl = `https://api.github.com/repos/${REPOSITORY}/contents/version`; -export const sampleUrl = `https://raw.githubusercontent.com/italia/publiccode.yml/master/docs/it/example/publiccode.minimal.yml`; +export const sampleUrl = `https://raw.githubusercontent.com/italia/pc-web-validator/master/tests/valid.minimal.yml`; export const elasticUrl = ELASTIC_URL || ''; export const validatorUrl = VALIDATOR_URL || ''; +export const validatorRemoteUrl = VALIDATOR_REMOTE_URL || ''; export const APP_FORM = "appForm"; diff --git a/src/app/utils/calls.js b/src/app/utils/calls.js index 791794ae..cb69e7e7 100644 --- a/src/app/utils/calls.js +++ b/src/app/utils/calls.js @@ -1,4 +1,4 @@ -import { validatorUrl } from "../contents/constants"; +import { validatorUrl, validatorRemoteUrl } from "../contents/constants"; export const getReleases = versionsUrl => { return fetch(versionsUrl) @@ -10,9 +10,34 @@ export const getReleases = versionsUrl => { export const getRemoteYml = url => { //return fetch(url).then(res => res.blob()); // return fetch(url).then(res => res.text()); + //it causes cors exception on gitlab domains return fetch(url) - .then(res => res.json()) - .then(data => atob(data.content)); + .then(res => res.text()); +}; + +export const passRemoteURLToValidator = yamlURL => { + const paramsString = "url=" + yamlURL; + // let searchParams = new URLSearchParams(paramsString); + + const myHeaders = new Headers({ + 'Accept': 'application/x-yaml', + 'Content-Type': 'application/x-yaml' + }); + const url = validatorRemoteUrl; + + const myInit = { + method: 'POST', + headers: myHeaders, + mode: 'cors', + cache: 'default', + // body: searchParams // params are sent in query sting url see below in fetch + }; + + if (url == '') + return Promise.reject(new Error('no validator url specified')); + + return fetch(url + '?' + paramsString, myInit) + .then(res => res.text()); }; export const postDataForValidation = data => { @@ -29,8 +54,8 @@ export const postDataForValidation = data => { cache: 'default', body: JSON.stringify(data) }; - - if(url=='') + + if (url == '') return Promise.reject(new Error('no validator url specified')); return fetch(url, myInit); diff --git a/webpack.config.js b/webpack.config.js index bfbab8bd..e34407c5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -31,7 +31,8 @@ module.exports = env => { "process.env": { REPOSITORY: JSON.stringify(process.env.REPOSITORY), ELASTIC_URL: JSON.stringify(process.env.ELASTIC_URL), - VALIDATOR_URL: JSON.stringify(process.env.VALIDATOR_URL) + VALIDATOR_URL: JSON.stringify(process.env.VALIDATOR_URL), + VALIDATOR_REMOTE_URL: JSON.stringify(process.env.VALIDATOR_REMOTE_URL) } }), new HtmlWebpackPlugin({ From 71fc3870fa73617f44d677a32eb871f19596bb21 Mon Sep 17 00:00:00 2001 From: Alessandro Sebastiani Date: Fri, 5 Jun 2020 15:42:54 +0200 Subject: [PATCH 2/4] url query parameter is correctly validated --- src/app/components/editor.js | 25 ++++++++++++++++++++----- src/app/components/sidebar.js | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/app/components/editor.js b/src/app/components/editor.js index e101413a..283b4abd 100644 --- a/src/app/components/editor.js +++ b/src/app/components/editor.js @@ -83,6 +83,20 @@ class Index extends Component { await this.initData(); this.switchLang("it"); this.switchCountry("it"); + + // checks whether url query parameter + // is present in url, if so it will + // passed as prop to Sidebar component + // which will be rerendered validating + // its value. + const search = window.location.search; + const params = new URLSearchParams(search); + const url = params.get('url'); + if (url) { + this.setState({ + remoteYml: url + }); + } } async initData(country = null) { @@ -283,9 +297,9 @@ class Index extends Component { removeEmpty(obj) { // looking forward to replace with bind() const that = this; - Object.keys(obj).forEach(function(key) { + Object.keys(obj).forEach(function (key) { (Object.keys(obj[key]).length === 0 && obj[key].constructor === Object) && delete obj[key] || - (obj[key] && typeof obj[key] === 'object') && that.removeEmpty(obj[key]) + (obj[key] && typeof obj[key] === 'object') && that.removeEmpty(obj[key]) }); return obj; } @@ -310,7 +324,7 @@ class Index extends Component { let { yaml, yamlLoaded } = this.state; let type = "success"; let msg = "Success"; - + //was syncErrors if (form[APP_FORM].submitErrors) { type = "error"; @@ -392,12 +406,13 @@ class Index extends Component { renderSidebar() { //c with state - let { yaml, loading, values, allFields } = this.state; + let { yaml, loading, values, allFields, remoteYml } = this.state; let props = { yaml, loading, values, allFields, + remoteYml, onLoadingRemote: this.onLoadingRemote, onLoad: this.parseYml.bind(this), onReset: this.reset.bind(this) @@ -421,7 +436,7 @@ class Index extends Component { removeLang(lng) { if (!confirm(`Are you sure you want to remove '${lng}'?`)) { - return; + return; } //has state diff --git a/src/app/components/sidebar.js b/src/app/components/sidebar.js index 7911ae5c..6ae91d78 100644 --- a/src/app/components/sidebar.js +++ b/src/app/components/sidebar.js @@ -24,6 +24,7 @@ const mapDispatchToProps = dispatch => { }; }; + @connect( mapStateToProps, mapDispatchToProps @@ -37,6 +38,23 @@ class sidebar extends Component { }; } + componentWillReceiveProps(prevProps) { + const { remoteYml } = prevProps; + const funFake = ({ + preventDefault: () => { } + }) + + if (remoteYml !== this.props.remoteYml) { + console.log("remoteYml:", remoteYml); + this.setState({ + dialog: true, + remoteYml: remoteYml + }, () => { + this.loadRemoteYaml(funFake); + }); + } + } + showDialog(dialog) { this.setState({ dialog }); } From cbfaf6f63f4e4cf291528d67a5e0024828400df9 Mon Sep 17 00:00:00 2001 From: Alessandro Sebastiani Date: Fri, 5 Jun 2020 15:46:40 +0200 Subject: [PATCH 3/4] replace alert with notify --- src/app/components/sidebar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/sidebar.js b/src/app/components/sidebar.js index 6ae91d78..92102b20 100644 --- a/src/app/components/sidebar.js +++ b/src/app/components/sidebar.js @@ -102,7 +102,7 @@ class sidebar extends Component { this.setState({ loading: false }); this.props.onLoadingRemote(false); console.error(error); - alert("error parsing remote yaml"); + this.props.notify({ type: 1, msg: "error parsing remote yaml" }); } } From f5c196fec4e9e307dfe66fb6c55a01ab69352065 Mon Sep 17 00:00:00 2001 From: Alessandro Sebastiani Date: Fri, 5 Jun 2020 15:51:17 +0200 Subject: [PATCH 4/4] cosmetics fix --- src/app/components/sidebar.js | 6 +----- src/app/utils/calls.js | 8 -------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/app/components/sidebar.js b/src/app/components/sidebar.js index 92102b20..cfe3ebf8 100644 --- a/src/app/components/sidebar.js +++ b/src/app/components/sidebar.js @@ -11,7 +11,7 @@ import img_download from "../../asset/img/download.svg"; import img_dots from "../../asset/img/dots.svg"; import img_xx from "../../asset/img/xx.svg"; -import { getRemoteYml, passRemoteURLToValidator } from "../utils/calls"; +import { passRemoteURLToValidator } from "../utils/calls"; import { getLabel } from "../contents/data"; function mapStateToProps(state) { @@ -86,9 +86,6 @@ class sidebar extends Component { this.setState({ loading: true }); this.props.onLoadingRemote(true); - // trying to get file and process it, cors problem - // yaml = await getRemoteYml(remoteYml); - // piping url to validator which will returns a fresh // and validated copy yaml = await passRemoteURLToValidator(remoteYml); @@ -113,7 +110,6 @@ class sidebar extends Component { this.props.notify({ type: 1, msg: "File not found" }); return; } - // let ext = files[0].name.split(".")[1]; let ext = files[0].name.split(/[. ]+/).pop(); if (ext != "yml" && ext != "yaml") { this.props.notify({ type: 1, msg: "File type not supported" }); diff --git a/src/app/utils/calls.js b/src/app/utils/calls.js index cb69e7e7..feb2e6be 100644 --- a/src/app/utils/calls.js +++ b/src/app/utils/calls.js @@ -7,14 +7,6 @@ export const getReleases = versionsUrl => { .then(data => data.map(d => d.name)); }; -export const getRemoteYml = url => { - //return fetch(url).then(res => res.blob()); - // return fetch(url).then(res => res.text()); - //it causes cors exception on gitlab domains - return fetch(url) - .then(res => res.text()); -}; - export const passRemoteURLToValidator = yamlURL => { const paramsString = "url=" + yamlURL; // let searchParams = new URLSearchParams(paramsString);