From ebb955f1a765923ddbfd73abe9c5d3814d2820f1 Mon Sep 17 00:00:00 2001 From: Mikhail Eremin Date: Mon, 27 Jul 2020 20:28:45 +0200 Subject: [PATCH] Pre-config for header, endpoint and smdUrl. Also, ErrorBoundaries added, Backward compatibility with auto init by using #json-rpc-root selector in html --- README.md | 19 +++- dist/app.css | 2 +- dist/app.js | 4 +- dist/index.html | 12 ++- package.json | 4 +- src/assets/html/index.dev.html | 10 ++- src/assets/html/index.html | 8 +- src/components/Application/index.jsx | 98 +++++++++++---------- src/components/CrashScreen/CrashScreen.scss | 4 + src/components/CrashScreen/index.jsx | 32 +++++++ src/components/ErrorBoundary/index.jsx | 28 ++++++ src/components/Project/index.jsx | 23 +++-- src/containers/CrashScreen/index.js | 12 +++ src/containers/Project/actionTypes.js | 1 + src/containers/Project/actions.js | 5 ++ src/containers/Project/saga.js | 9 +- src/helpers/session.js | 13 ++- src/index.jsx | 50 +++++++++-- webpack/webpack.dev.js | 2 +- webpack/webpack.prod.js | 2 +- yarn.lock | 8 +- 21 files changed, 265 insertions(+), 81 deletions(-) create mode 100644 src/components/CrashScreen/CrashScreen.scss create mode 100644 src/components/CrashScreen/index.jsx create mode 100644 src/components/ErrorBoundary/index.jsx create mode 100644 src/containers/CrashScreen/index.js diff --git a/README.md b/README.md index 52d32d5..cb0eb9c 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,23 @@ SMD Box is UI for human-readable displaying of JSON-RPC SMD schemas from remote url, allowing you to call RPC methods live, view and log results. ## Getting started +Smdbox script exposes it's initialization to window.smdbox variable. Call window.smdbox() to initialize smdbox with default options, which are: +```javascript +const defaultOptions = { + endpoint: null, // api endpoint url + smdUrl: null, // smd scheme url + headers: {}, // headers added to each request smdbox makes + selector: '#json-rpc-root', // element to which smdbox is inserted +}; +``` +You can override any of this options to pre-fill project options. -* Run: +For backward-compatibility with previous versions there's a possibility to initialize smdbox without any calls - just leave this block in html (no options can be passed to init this way): +```html +
+``` + +* Build: * `yarn run dev` — watches the project with continuous rebuild at localhost:4500 * `yarn run prod` — builds minified project for production * `yarn run dist` — same as 'prod', but assets are made without hash (e.g. for deploys from github) @@ -14,4 +29,4 @@ SMD Box is UI for human-readable displaying of JSON-RPC SMD schemas from remote When project is set up you're able to choose methods from list at left sidebar, view method's description, it's input and output params, and run selected method on remote server to see results. -History of successfull calls and their input/output are shown in "History" window (click History at top navigation). +History of successfull calls and their input/output are shown in "History" window (click History at top navigation). diff --git a/dist/app.css b/dist/app.css index 0522b7f..c6d0a59 100644 --- a/dist/app.css +++ b/dist/app.css @@ -1 +1 @@ -.app-create-project__header{margin-bottom:20px}.app-create-project__step-header{margin-bottom:10px}.app-create-project .btn+.btn,.app-create-project__loading{margin-left:10px}.app-create-project__loading i{animation:rotate 1s linear infinite;font-size:20px}.sb-method-description .tab-content{padding-top:10px}.sb-method-description .required-icon{color:#5cb85c;display:block;text-align:center}.sb-form-from-schema button[type=submit]{width:100%}.sb-form-from-schema label.control-label{font-weight:500}.sb-raw-json-editor textarea{width:100%;min-height:400px;resize:vertical}.sb-raw-json-editor button[type=submit]{width:100%}.sb-json-viewer__clipboard-button{margin-left:10px;display:inline-block}.sb-json-viewer__textarea{width:100%;max-width:100%;resize:vertical;min-height:300px}.sb-method-invoker__result{padding:10px;border:1px solid #ddd}.sb-method-invoker__loading{margin:0 auto;text-align:center}.sb-method-invoker__loading i{animation:rotate 1s linear infinite;font-size:30px}.sb-method-invoker__content{margin-bottom:20px}.sb-method-invoker .tab-content{padding-top:10px}@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.sb-method-viewer h3 .btn{margin-left:5px}.sb-application .navbar{margin-bottom:0}.sb-application__content-column{height:calc(100vh - 51px);overflow:auto;padding-top:15px;padding-bottom:15px}.form-inline .form-group:not(:last-child){margin-right:10px}.navbar{min-height:50px}.navbar .navbar-brand{height:auto}.navbar .navbar-brand,.navbar .navbar-nav li>a{padding-top:13px;padding-bottom:13px} \ No newline at end of file +.sb-crashscreen{text-align:center;padding:80px}.app-create-project__header{margin-bottom:20px}.app-create-project__step-header{margin-bottom:10px}.app-create-project .btn+.btn,.app-create-project__loading{margin-left:10px}.app-create-project__loading i{animation:rotate 1s linear infinite;font-size:20px}.sb-method-description .tab-content{padding-top:10px}.sb-method-description .required-icon{color:#5cb85c;display:block;text-align:center}.sb-form-from-schema button[type=submit]{width:100%}.sb-form-from-schema label.control-label{font-weight:500}.sb-raw-json-editor textarea{width:100%;min-height:400px;resize:vertical}.sb-raw-json-editor button[type=submit]{width:100%}.sb-json-viewer__clipboard-button{margin-left:10px;display:inline-block}.sb-json-viewer__textarea{width:100%;max-width:100%;resize:vertical;min-height:300px}.sb-method-invoker__result{padding:10px;border:1px solid #ddd}.sb-method-invoker__loading{margin:0 auto;text-align:center}.sb-method-invoker__loading i{animation:rotate 1s linear infinite;font-size:30px}.sb-method-invoker__content{margin-bottom:20px}.sb-method-invoker .tab-content{padding-top:10px}@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.sb-method-viewer h3 .btn{margin-left:5px}.sb-application .navbar{margin-bottom:0}.sb-application__content-column{height:calc(100vh - 51px);overflow:auto;padding-top:15px;padding-bottom:15px}.form-inline .form-group:not(:last-child){margin-right:10px}.navbar{min-height:50px}.navbar .navbar-brand{height:auto}.navbar .navbar-brand,.navbar .navbar-nav li>a{padding-top:13px;padding-bottom:13px} \ No newline at end of file diff --git a/dist/app.js b/dist/app.js index 2f32a53..0e8740d 100644 --- a/dist/app.js +++ b/dist/app.js @@ -12,7 +12,7 @@ e.exports=function(e){return null!=e&&null!=e.constructor&&"function"==typeof e. !function(){"use strict";function o(){for(var e=[],t=0;t1?arguments[1]:void 0,o),u=a>2?arguments[2]:void 0,i=void 0===u?o:n(u,o);i>l;)t[l++]=e;return t}},"./node_modules/core-js/library/modules/_array-from-iterable.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_for-of.js");e.exports=function(e,t){var o=[];return r(e,!1,o.push,o,t),o}},"./node_modules/core-js/library/modules/_array-includes.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_to-iobject.js"),n=o("./node_modules/core-js/library/modules/_to-length.js"),s=o("./node_modules/core-js/library/modules/_to-absolute-index.js");e.exports=function(e){return function(t,o,a){var l,u=r(t),i=n(u.length),d=s(a,i);if(e&&o!=o){for(;i>d;)if((l=u[d++])!=l)return!0}else for(;i>d;d++)if((e||d in u)&&u[d]===o)return e||d||0;return!e&&-1}}},"./node_modules/core-js/library/modules/_array-methods.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_ctx.js"),n=o("./node_modules/core-js/library/modules/_iobject.js"),s=o("./node_modules/core-js/library/modules/_to-object.js"),a=o("./node_modules/core-js/library/modules/_to-length.js"),l=o("./node_modules/core-js/library/modules/_array-species-create.js");e.exports=function(e,t){var o=1==e,u=2==e,i=3==e,d=4==e,c=6==e,f=5==e||c,m=t||l;return function(t,l,p){for(var h,j,b=s(t),_=n(b),v=r(l,p,3),y=a(_.length),g=0,x=o?m(t,y):u?m(t,0):void 0;y>g;g++)if((f||g in _)&&(h=_[g],j=v(h,g,b),e))if(o)x[g]=j;else if(j)switch(e){case 3:return!0;case 5:return h;case 6:return g;case 2:x.push(h)}else if(d)return!1;return c?-1:i||d?d:x}}},"./node_modules/core-js/library/modules/_array-species-constructor.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_is-object.js"),n=o("./node_modules/core-js/library/modules/_is-array.js"),s=o("./node_modules/core-js/library/modules/_wks.js")("species");e.exports=function(e){var t;return n(e)&&(t=e.constructor,"function"!=typeof t||t!==Array&&!n(t.prototype)||(t=void 0),r(t)&&null===(t=t[s])&&(t=void 0)),void 0===t?Array:t}},"./node_modules/core-js/library/modules/_array-species-create.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_array-species-constructor.js");e.exports=function(e,t){return new(r(e))(t)}},"./node_modules/core-js/library/modules/_classof.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_cof.js"),n=o("./node_modules/core-js/library/modules/_wks.js")("toStringTag"),s="Arguments"==r(function(){return arguments}()),a=function(e,t){try{return e[t]}catch(e){}};e.exports=function(e){var t,o,l;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(o=a(t=Object(e),n))?o:s?r(t):"Object"==(l=r(t))&&"function"==typeof t.callee?"Arguments":l}},"./node_modules/core-js/library/modules/_cof.js":function(e,t){var o={}.toString;e.exports=function(e){return o.call(e).slice(8,-1)}},"./node_modules/core-js/library/modules/_collection-strong.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_object-dp.js").f,n=o("./node_modules/core-js/library/modules/_object-create.js"),s=o("./node_modules/core-js/library/modules/_redefine-all.js"),a=o("./node_modules/core-js/library/modules/_ctx.js"),l=o("./node_modules/core-js/library/modules/_an-instance.js"),u=o("./node_modules/core-js/library/modules/_for-of.js"),i=o("./node_modules/core-js/library/modules/_iter-define.js"),d=o("./node_modules/core-js/library/modules/_iter-step.js"),c=o("./node_modules/core-js/library/modules/_set-species.js"),f=o("./node_modules/core-js/library/modules/_descriptors.js"),m=o("./node_modules/core-js/library/modules/_meta.js").fastKey,p=o("./node_modules/core-js/library/modules/_validate-collection.js"),h=f?"_s":"size",j=function(e,t){var o,r=m(t);if("F"!==r)return e._i[r];for(o=e._f;o;o=o.n)if(o.k==t)return o};e.exports={getConstructor:function(e,t,o,i){var d=e(function(e,r){l(e,d,t,"_i"),e._t=t,e._i=n(null),e._f=void 0,e._l=void 0,e[h]=0,void 0!=r&&u(r,o,e[i],e)});return s(d.prototype,{clear:function(){for(var e=p(this,t),o=e._i,r=e._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete o[r.i];e._f=e._l=void 0,e[h]=0},delete:function(e){var o=p(this,t),r=j(o,e);if(r){var n=r.n,s=r.p;delete o._i[r.i],r.r=!0,s&&(s.n=n),n&&(n.p=s),o._f==r&&(o._f=n),o._l==r&&(o._l=s),o[h]--}return!!r},forEach:function(e){p(this,t);for(var o,r=a(e,arguments.length>1?arguments[1]:void 0,3);o=o?o.n:this._f;)for(r(o.v,o.k,this);o&&o.r;)o=o.p},has:function(e){return!!j(p(this,t),e)}}),f&&r(d.prototype,"size",{get:function(){return p(this,t)[h]}}),d},def:function(e,t,o){var r,n,s=j(e,t);return s?s.v=o:(e._l=s={i:n=m(t,!0),k:t,v:o,p:r=e._l,n:void 0,r:!1},e._f||(e._f=s),r&&(r.n=s),e[h]++,"F"!==n&&(e._i[n]=s)),e},getEntry:j,setStrong:function(e,t,o){i(e,t,function(e,o){this._t=p(e,t),this._k=o,this._l=void 0},function(){for(var e=this,t=e._k,o=e._l;o&&o.r;)o=o.p;return e._t&&(e._l=o=o?o.n:e._t._f)?"keys"==t?d(0,o.k):"values"==t?d(0,o.v):d(0,[o.k,o.v]):(e._t=void 0,d(1))},o?"entries":"values",!o,!0),c(t)}}},"./node_modules/core-js/library/modules/_collection-to-json.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_classof.js"),n=o("./node_modules/core-js/library/modules/_array-from-iterable.js");e.exports=function(e){return function(){if(r(this)!=e)throw TypeError(e+"#toJSON isn't generic");return n(this)}}},"./node_modules/core-js/library/modules/_collection-weak.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_redefine-all.js"),n=o("./node_modules/core-js/library/modules/_meta.js").getWeak,s=o("./node_modules/core-js/library/modules/_an-object.js"),a=o("./node_modules/core-js/library/modules/_is-object.js"),l=o("./node_modules/core-js/library/modules/_an-instance.js"),u=o("./node_modules/core-js/library/modules/_for-of.js"),i=o("./node_modules/core-js/library/modules/_array-methods.js"),d=o("./node_modules/core-js/library/modules/_has.js"),c=o("./node_modules/core-js/library/modules/_validate-collection.js"),f=i(5),m=i(6),p=0,h=function(e){return e._l||(e._l=new j)},j=function(){this.a=[]},b=function(e,t){return f(e.a,function(e){return e[0]===t})};j.prototype={get:function(e){var t=b(this,e);if(t)return t[1]},has:function(e){return!!b(this,e)},set:function(e,t){var o=b(this,e);o?o[1]=t:this.a.push([e,t])},delete:function(e){var t=m(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,o,s){var i=e(function(e,r){l(e,i,t,"_i"),e._t=t,e._i=p++,e._l=void 0,void 0!=r&&u(r,o,e[s],e)});return r(i.prototype,{delete:function(e){if(!a(e))return!1;var o=n(e);return!0===o?h(c(this,t)).delete(e):o&&d(o,this._i)&&delete o[this._i]},has:function(e){if(!a(e))return!1;var o=n(e);return!0===o?h(c(this,t)).has(e):o&&d(o,this._i)}}),i},def:function(e,t,o){var r=n(s(t),!0);return!0===r?h(e).set(t,o):r[e._i]=o,e},ufstore:h}},"./node_modules/core-js/library/modules/_collection.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_global.js"),n=o("./node_modules/core-js/library/modules/_export.js"),s=o("./node_modules/core-js/library/modules/_meta.js"),a=o("./node_modules/core-js/library/modules/_fails.js"),l=o("./node_modules/core-js/library/modules/_hide.js"),u=o("./node_modules/core-js/library/modules/_redefine-all.js"),i=o("./node_modules/core-js/library/modules/_for-of.js"),d=o("./node_modules/core-js/library/modules/_an-instance.js"),c=o("./node_modules/core-js/library/modules/_is-object.js"),f=o("./node_modules/core-js/library/modules/_set-to-string-tag.js"),m=o("./node_modules/core-js/library/modules/_object-dp.js").f,p=o("./node_modules/core-js/library/modules/_array-methods.js")(0),h=o("./node_modules/core-js/library/modules/_descriptors.js");e.exports=function(e,t,o,j,b,_){var v=r[e],y=v,g=b?"set":"add",x=y&&y.prototype,E={};return h&&"function"==typeof y&&(_||x.forEach&&!a(function(){(new y).entries().next()}))?(y=t(function(t,o){d(t,y,e,"_c"),t._c=new v,void 0!=o&&i(o,b,t[g],t)}),p("add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON".split(","),function(e){var t="add"==e||"set"==e;e in x&&(!_||"clear"!=e)&&l(y.prototype,e,function(o,r){if(d(this,y,e),!t&&_&&!c(o))return"get"==e&&void 0;var n=this._c[e](0===o?0:o,r);return t?this:n})}),_||m(y.prototype,"size",{get:function(){return this._c.size}})):(y=j.getConstructor(t,e,b,g),u(y.prototype,o),s.NEED=!0),f(y,e),E[e]=y,n(n.G+n.W+n.F,E),_||j.setStrong(y,e,b),y}},"./node_modules/core-js/library/modules/_core.js":function(e,t){var o=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=o)},"./node_modules/core-js/library/modules/_create-property.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_object-dp.js"),n=o("./node_modules/core-js/library/modules/_property-desc.js");e.exports=function(e,t,o){t in e?r.f(e,t,n(0,o)):e[t]=o}},"./node_modules/core-js/library/modules/_ctx.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_a-function.js");e.exports=function(e,t,o){if(r(e),void 0===t)return e;switch(o){case 1:return function(o){return e.call(t,o)};case 2:return function(o,r){return e.call(t,o,r)};case 3:return function(o,r,n){return e.call(t,o,r,n)}}return function(){return e.apply(t,arguments)}}},"./node_modules/core-js/library/modules/_defined.js":function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},"./node_modules/core-js/library/modules/_descriptors.js":function(e,t,o){e.exports=!o("./node_modules/core-js/library/modules/_fails.js")(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},"./node_modules/core-js/library/modules/_dom-create.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_is-object.js"),n=o("./node_modules/core-js/library/modules/_global.js").document,s=r(n)&&r(n.createElement);e.exports=function(e){return s?n.createElement(e):{}}},"./node_modules/core-js/library/modules/_enum-bug-keys.js":function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},"./node_modules/core-js/library/modules/_enum-keys.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_object-keys.js"),n=o("./node_modules/core-js/library/modules/_object-gops.js"),s=o("./node_modules/core-js/library/modules/_object-pie.js");e.exports=function(e){var t=r(e),o=n.f;if(o)for(var a,l=o(e),u=s.f,i=0;l.length>i;)u.call(e,a=l[i++])&&t.push(a);return t}},"./node_modules/core-js/library/modules/_export.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_global.js"),n=o("./node_modules/core-js/library/modules/_core.js"),s=o("./node_modules/core-js/library/modules/_ctx.js"),a=o("./node_modules/core-js/library/modules/_hide.js"),l=o("./node_modules/core-js/library/modules/_has.js"),u=function(e,t,o){var i,d,c,f=e&u.F,m=e&u.G,p=e&u.S,h=e&u.P,j=e&u.B,b=e&u.W,_=m?n:n[t]||(n[t]={}),v=_.prototype,y=m?r:p?r[t]:(r[t]||{}).prototype;m&&(o=t);for(i in o)(d=!f&&y&&void 0!==y[i])&&l(_,i)||(c=d?y[i]:o[i],_[i]=m&&"function"!=typeof y[i]?o[i]:j&&d?s(c,r):b&&y[i]==c?function(e){var t=function(t,o,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,o)}return new e(t,o,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(c):h&&"function"==typeof c?s(Function.call,c):c,h&&((_.virtual||(_.virtual={}))[i]=c,e&u.R&&v&&!v[i]&&a(v,i,c)))};u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},"./node_modules/core-js/library/modules/_fails.js":function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},"./node_modules/core-js/library/modules/_for-of.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_ctx.js"),n=o("./node_modules/core-js/library/modules/_iter-call.js"),s=o("./node_modules/core-js/library/modules/_is-array-iter.js"),a=o("./node_modules/core-js/library/modules/_an-object.js"),l=o("./node_modules/core-js/library/modules/_to-length.js"),u=o("./node_modules/core-js/library/modules/core.get-iterator-method.js"),i={},d={},t=e.exports=function(e,t,o,c,f){var m,p,h,j,b=f?function(){return e}:u(e),_=r(o,c,t?2:1),v=0;if("function"!=typeof b)throw TypeError(e+" is not iterable!");if(s(b)){for(m=l(e.length);m>v;v++)if((j=t?_(a(p=e[v])[0],p[1]):_(e[v]))===i||j===d)return j}else for(h=b.call(e);!(p=h.next()).done;)if((j=n(h,_,p.value,t))===i||j===d)return j};t.BREAK=i,t.RETURN=d},"./node_modules/core-js/library/modules/_global.js":function(e,t){var o=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=o)},"./node_modules/core-js/library/modules/_has.js":function(e,t){var o={}.hasOwnProperty;e.exports=function(e,t){return o.call(e,t)}},"./node_modules/core-js/library/modules/_hide.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_object-dp.js"),n=o("./node_modules/core-js/library/modules/_property-desc.js");e.exports=o("./node_modules/core-js/library/modules/_descriptors.js")?function(e,t,o){return r.f(e,t,n(1,o))}:function(e,t,o){return e[t]=o,e}},"./node_modules/core-js/library/modules/_html.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_global.js").document;e.exports=r&&r.documentElement},"./node_modules/core-js/library/modules/_ie8-dom-define.js":function(e,t,o){e.exports=!o("./node_modules/core-js/library/modules/_descriptors.js")&&!o("./node_modules/core-js/library/modules/_fails.js")(function(){return 7!=Object.defineProperty(o("./node_modules/core-js/library/modules/_dom-create.js")("div"),"a",{get:function(){return 7}}).a})},"./node_modules/core-js/library/modules/_invoke.js":function(e,t){e.exports=function(e,t,o){var r=void 0===o;switch(t.length){case 0:return r?e():e.call(o);case 1:return r?e(t[0]):e.call(o,t[0]);case 2:return r?e(t[0],t[1]):e.call(o,t[0],t[1]);case 3:return r?e(t[0],t[1],t[2]):e.call(o,t[0],t[1],t[2]);case 4:return r?e(t[0],t[1],t[2],t[3]):e.call(o,t[0],t[1],t[2],t[3])}return e.apply(o,t)}},"./node_modules/core-js/library/modules/_iobject.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_cof.js");e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==r(e)?e.split(""):Object(e)}},"./node_modules/core-js/library/modules/_is-array-iter.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_iterators.js"),n=o("./node_modules/core-js/library/modules/_wks.js")("iterator"),s=Array.prototype;e.exports=function(e){return void 0!==e&&(r.Array===e||s[n]===e)}},"./node_modules/core-js/library/modules/_is-array.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_cof.js");e.exports=Array.isArray||function(e){return"Array"==r(e)}},"./node_modules/core-js/library/modules/_is-integer.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_is-object.js"),n=Math.floor;e.exports=function(e){return!r(e)&&isFinite(e)&&n(e)===e}},"./node_modules/core-js/library/modules/_is-object.js":function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},"./node_modules/core-js/library/modules/_iter-call.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_an-object.js");e.exports=function(e,t,o,n){try{return n?t(r(o)[0],o[1]):t(o)}catch(t){var s=e.return;throw void 0!==s&&r(s.call(e)),t}}},"./node_modules/core-js/library/modules/_iter-create.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_object-create.js"),n=o("./node_modules/core-js/library/modules/_property-desc.js"),s=o("./node_modules/core-js/library/modules/_set-to-string-tag.js"),a={};o("./node_modules/core-js/library/modules/_hide.js")(a,o("./node_modules/core-js/library/modules/_wks.js")("iterator"),function(){return this}),e.exports=function(e,t,o){e.prototype=r(a,{next:n(1,o)}),s(e,t+" Iterator")}},"./node_modules/core-js/library/modules/_iter-define.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_library.js"),n=o("./node_modules/core-js/library/modules/_export.js"),s=o("./node_modules/core-js/library/modules/_redefine.js"),a=o("./node_modules/core-js/library/modules/_hide.js"),l=o("./node_modules/core-js/library/modules/_iterators.js"),u=o("./node_modules/core-js/library/modules/_iter-create.js"),i=o("./node_modules/core-js/library/modules/_set-to-string-tag.js"),d=o("./node_modules/core-js/library/modules/_object-gpo.js"),c=o("./node_modules/core-js/library/modules/_wks.js")("iterator"),f=!([].keys&&"next"in[].keys()),m=function(){return this};e.exports=function(e,t,o,p,h,j,b){u(o,t,p);var _,v,y,g=function(e){if(!f&&e in O)return O[e];switch(e){case"keys":case"values":return function(){return new o(this,e)}}return function(){return new o(this,e)}},x=t+" Iterator",E="values"==h,w=!1,O=e.prototype,S=O[c]||O["@@iterator"]||h&&O[h],C=S||g(h),P=h?E?g("entries"):C:void 0,k="Array"==t?O.entries||S:S;if(k&&(y=d(k.call(new e)))!==Object.prototype&&y.next&&(i(y,x,!0),r||"function"==typeof y[c]||a(y,c,m)),E&&S&&"values"!==S.name&&(w=!0,C=function(){return S.call(this)}),r&&!b||!f&&!w&&O[c]||a(O,c,C),l[t]=C,l[x]=m,h)if(_={values:E?C:g("values"),keys:j?C:g("keys"),entries:P},b)for(v in _)v in O||s(O,v,_[v]);else n(n.P+n.F*(f||w),t,_);return _}},"./node_modules/core-js/library/modules/_iter-detect.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_wks.js")("iterator"),n=!1;try{var s=[7][r]();s.return=function(){n=!0},Array.from(s,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!n)return!1;var o=!1;try{var s=[7],a=s[r]();a.next=function(){return{done:o=!0}},s[r]=function(){return a},e(s)}catch(e){}return o}},"./node_modules/core-js/library/modules/_iter-step.js":function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},"./node_modules/core-js/library/modules/_iterators.js":function(e,t){e.exports={}},"./node_modules/core-js/library/modules/_library.js":function(e,t){e.exports=!0},"./node_modules/core-js/library/modules/_meta.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_uid.js")("meta"),n=o("./node_modules/core-js/library/modules/_is-object.js"),s=o("./node_modules/core-js/library/modules/_has.js"),a=o("./node_modules/core-js/library/modules/_object-dp.js").f,l=0,u=Object.isExtensible||function(){return!0},i=!o("./node_modules/core-js/library/modules/_fails.js")(function(){return u(Object.preventExtensions({}))}),d=function(e){a(e,r,{value:{i:"O"+ ++l,w:{}}})},c=function(e,t){if(!n(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!s(e,r)){if(!u(e))return"F";if(!t)return"E";d(e)}return e[r].i},f=function(e,t){if(!s(e,r)){if(!u(e))return!0;if(!t)return!1;d(e)}return e[r].w},m=function(e){return i&&p.NEED&&u(e)&&!s(e,r)&&d(e),e},p=e.exports={KEY:r,NEED:!1,fastKey:c,getWeak:f,onFreeze:m}},"./node_modules/core-js/library/modules/_microtask.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_global.js"),n=o("./node_modules/core-js/library/modules/_task.js").set,s=r.MutationObserver||r.WebKitMutationObserver,a=r.process,l=r.Promise,u="process"==o("./node_modules/core-js/library/modules/_cof.js")(a);e.exports=function(){var e,t,o,i=function(){var r,n;for(u&&(r=a.domain)&&r.exit();e;){n=e.fn,e=e.next;try{n()}catch(r){throw e?o():t=void 0,r}}t=void 0,r&&r.enter()};if(u)o=function(){a.nextTick(i)};else if(!s||r.navigator&&r.navigator.standalone)if(l&&l.resolve){var d=l.resolve(void 0);o=function(){d.then(i)}}else o=function(){n.call(r,i)};else{var c=!0,f=document.createTextNode("");new s(i).observe(f,{characterData:!0}),o=function(){f.data=c=!c}}return function(r){var n={fn:r,next:void 0};t&&(t.next=n),e||(e=n,o()),t=n}}},"./node_modules/core-js/library/modules/_new-promise-capability.js":function(e,t,o){"use strict";function r(e){var t,o;this.promise=new e(function(e,r){if(void 0!==t||void 0!==o)throw TypeError("Bad Promise constructor");t=e,o=r}),this.resolve=n(t),this.reject=n(o)}var n=o("./node_modules/core-js/library/modules/_a-function.js");e.exports.f=function(e){return new r(e)}},"./node_modules/core-js/library/modules/_object-assign.js":function(e,t,o){"use strict";var r=o("./node_modules/core-js/library/modules/_descriptors.js"),n=o("./node_modules/core-js/library/modules/_object-keys.js"),s=o("./node_modules/core-js/library/modules/_object-gops.js"),a=o("./node_modules/core-js/library/modules/_object-pie.js"),l=o("./node_modules/core-js/library/modules/_to-object.js"),u=o("./node_modules/core-js/library/modules/_iobject.js"),i=Object.assign;e.exports=!i||o("./node_modules/core-js/library/modules/_fails.js")(function(){var e={},t={},o=Symbol(),r="abcdefghijklmnopqrst";return e[o]=7,r.split("").forEach(function(e){t[e]=e}),7!=i({},e)[o]||Object.keys(i({},t)).join("")!=r})?function(e,t){for(var o=l(e),i=arguments.length,d=1,c=s.f,f=a.f;i>d;)for(var m,p=u(arguments[d++]),h=c?n(p).concat(c(p)):n(p),j=h.length,b=0;j>b;)m=h[b++],r&&!f.call(p,m)||(o[m]=p[m]);return o}:i},"./node_modules/core-js/library/modules/_object-create.js":function(e,t,o){var r=o("./node_modules/core-js/library/modules/_an-object.js"),n=o("./node_modules/core-js/library/modules/_object-dps.js"),s=o("./node_modules/core-js/library/modules/_enum-bug-keys.js"),a=o("./node_modules/core-js/library/modules/_shared-key.js")("IE_PROTO"),l=function(){},u=function(){var e,t=o("./node_modules/core-js/library/modules/_dom-create.js")("iframe"),r=s.length;for(t.style.display="none",o("./node_modules/core-js/library/modules/_html.js").appendChild(t),t.src="javascript:",e=t.contentWindow.document,e.open(),e.write(" -
- + +
+ + diff --git a/package.json b/package.json index 79c23d8..d686f40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smdbox", - "version": "1.0.2", + "version": "1.0.3", "main": "src/index.jsx", "repository": "https://gitlab.semrush.net/m.eremin/smdbox", "author": "Semrush", @@ -22,7 +22,7 @@ "axios": "0.18.1", "bem-cl": "1.0.2", "copy-to-clipboard": "3.0.6", - "lodash": "4.17.4", + "lodash": "4.17.19", "prop-types": "15.6.0", "react": "16.12.0", "react-bootstrap": "0.33.1", diff --git a/src/assets/html/index.dev.html b/src/assets/html/index.dev.html index 4f6e276..c65c8d6 100644 --- a/src/assets/html/index.dev.html +++ b/src/assets/html/index.dev.html @@ -7,6 +7,14 @@ -
+ +
+ diff --git a/src/assets/html/index.html b/src/assets/html/index.html index 446a32c..a742ce6 100644 --- a/src/assets/html/index.html +++ b/src/assets/html/index.html @@ -7,6 +7,12 @@ -
+ +
+ diff --git a/src/components/Application/index.jsx b/src/components/Application/index.jsx index 7cc8355..6255941 100644 --- a/src/components/Application/index.jsx +++ b/src/components/Application/index.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import bemCl from 'bem-cl'; - +import ErrorBoundary from 'components/ErrorBoundary'; import Project from 'containers/Project'; import MethodViewer from 'containers/MethodViewer'; import History from 'containers/History'; @@ -39,55 +39,57 @@ class Application extends React.Component { render() { return ( -
- - { - !this.props.isProjectCreated ? - - - : - - - - - - - - - - - - Project settings - - - - - + + { + !this.props.isProjectCreated ? + + + : + + + + + + + + + + + + Project settings + + + + + - - - Request history - - - - - - - } -
+ + + Request history + + + + + + + } + + ); } } diff --git a/src/components/CrashScreen/CrashScreen.scss b/src/components/CrashScreen/CrashScreen.scss new file mode 100644 index 0000000..8dc8b6a --- /dev/null +++ b/src/components/CrashScreen/CrashScreen.scss @@ -0,0 +1,4 @@ +.sb-crashscreen { + text-align: center; + padding: 80px; +} diff --git a/src/components/CrashScreen/index.jsx b/src/components/CrashScreen/index.jsx new file mode 100644 index 0000000..19e59ad --- /dev/null +++ b/src/components/CrashScreen/index.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button } from 'react-bootstrap'; +import bemCl from 'bem-cl'; +import './CrashScreen.scss'; +const b = bemCl('sb-crashscreen'); + +class CrashScreen extends React.Component { + static propTypes = { + clearProject: PropTypes.func.isRequired, + } + onReset = () => { + this.props.clearProject(); + } + render() { + return ( +
+

OOPS! Everything crashed

+

No one knows why

+

Fortunately, you have this magic button

+

+
+ +

+
+ ); + } +} + +export default CrashScreen; diff --git a/src/components/ErrorBoundary/index.jsx b/src/components/ErrorBoundary/index.jsx new file mode 100644 index 0000000..b4d8bb6 --- /dev/null +++ b/src/components/ErrorBoundary/index.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import CrashScreen from 'containers/CrashScreen'; + +class ErrorBoundary extends React.Component { + constructor(props) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError() { + return { hasError: true }; + } + + componentDidCatch(error, errorInfo) { + console.error(error, errorInfo); + } + + render() { + if (this.state.hasError) { + // Можно отрендерить запасной UI произвольного вида + return ; + } + + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/src/components/Project/index.jsx b/src/components/Project/index.jsx index aac47fe..77921e9 100644 --- a/src/components/Project/index.jsx +++ b/src/components/Project/index.jsx @@ -45,17 +45,26 @@ class Project extends React.Component { this.state = { endpoint: this.props.endpoint || '', + smdUrl: this.props.smdUrl || '', headers: map(this.props.headers, (value = '', key = '') => ({ key, value })) }; this.fetchSmd = debounce(this.fetchSmd.bind(this), 800); + + // if endpoint is set initially - preload scheme + if (this.state.endpoint !== '' && !props.created) { + this.fetchSmd(this.state.smdUrl); + } } - componentWillReceiveProps({ endpoint }) { + componentWillReceiveProps({ endpoint, smdUrl }) { if (endpoint !== this.props.endpoint) { this.setState({ endpoint }); } + if (smdUrl !== this.props.smdUrl) { + this.setState({ smdUrl }); + } } fetchSmd(url, isRefresh = false) { @@ -66,6 +75,7 @@ class Project extends React.Component { e.preventDefault(); this.props.create({ endpoint: this.state.endpoint, + smdUrl: this.state.smdUrl, headers: reduce(this.state.headers, (res, header) => { if (header.key && header.value) { res[header.key] = header.value; } return res; @@ -98,7 +108,9 @@ class Project extends React.Component { } handleChangeUrl = (e) => { - this.fetchSmd(e.nativeEvent.target.value); + this.setState({ smdUrl: e.nativeEvent.target.value }, () => { + this.fetchSmd(this.state.smdUrl); + }); } handleChangeHeaderName = (index, value) => { @@ -134,13 +146,14 @@ class Project extends React.Component { { mode !== modes.SETTINGS &&

SMD scheme * - { - this.props.fetchingSchema && - } + { + this.props.fetchingSchema && + }

diff --git a/src/containers/CrashScreen/index.js b/src/containers/CrashScreen/index.js new file mode 100644 index 0000000..0c31ac6 --- /dev/null +++ b/src/containers/CrashScreen/index.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import CrashScreen from 'components/CrashScreen'; +import { clearProjectWithDbReset as clearProject } from '../Project/actions'; + +export default connect( + () => ({ + + }), + { + clearProject, + } +)(CrashScreen); diff --git a/src/containers/Project/actionTypes.js b/src/containers/Project/actionTypes.js index 6dfd01c..9b84037 100644 --- a/src/containers/Project/actionTypes.js +++ b/src/containers/Project/actionTypes.js @@ -4,6 +4,7 @@ export const FETCH_SUCCESS = 'PROJECT/FETCH_SUCCESS'; export const FETCH_REQUEST = 'PROJECT/FETCH_REQUEST'; export const FETCH_ERROR = 'PROJECT/FETCH_ERROR'; export const CLEAR = 'PROJECT/CLEAR'; +export const CLEAR_WITH_DB = 'PROJECT/CLEAR_WITH_DB'; export const SAVE_TO_HISTORY = 'PROJECT/SAVE_TO_HISTORY'; export const OPEN_SETTINGS = 'PROJECT/OPEN_SETTINGS'; export const CLOSE_SETTINGS = 'PROJECT/CLOSE_SETTINGS'; diff --git a/src/containers/Project/actions.js b/src/containers/Project/actions.js index 3568b45..5bc9e85 100644 --- a/src/containers/Project/actions.js +++ b/src/containers/Project/actions.js @@ -21,6 +21,11 @@ export function clearProject() { }; } +export function clearProjectWithDbReset() { + return { + type: ACTION_TYPES.CLEAR_WITH_DB + }; +} export function openSettings() { return { diff --git a/src/containers/Project/saga.js b/src/containers/Project/saga.js index f43e17b..997ca71 100644 --- a/src/containers/Project/saga.js +++ b/src/containers/Project/saga.js @@ -2,10 +2,11 @@ import axios from 'axios'; import { call, put, takeEvery } from 'redux-saga/effects'; import * as ACTION_TYPES from './actionTypes'; import * as ProjectActions from './actions'; +import { clearStorage } from '../../helpers/session'; function* onFetch({ url, isRefresh }) { try { - yield put({ type: ACTION_TYPES.FETCH_REQUEST}) + yield put({ type: ACTION_TYPES.FETCH_REQUEST }); const smdScheme = yield call(() => { return axios.get(url); }); @@ -19,8 +20,14 @@ function* onFetch({ url, isRefresh }) { } } +function* onClear() { + clearStorage(); + yield put(ProjectActions.clearProject()); +} + export default function* createProjectSaga() { yield [ takeEvery(ACTION_TYPES.FETCH, onFetch), + takeEvery(ACTION_TYPES.CLEAR_WITH_DB, onClear), ]; } diff --git a/src/helpers/session.js b/src/helpers/session.js index 5922d8e..22f7283 100644 --- a/src/helpers/session.js +++ b/src/helpers/session.js @@ -31,7 +31,7 @@ export const get = (f) => { if (typeof (request.result) === 'object') { f(request.result); } else { - f(false); + f({}); } }; }); @@ -54,7 +54,7 @@ export const syncStore = (store) => { requestAnimationFrame(() => { // remove formData from store const stateData = cloneDeep(store.getState()); - + // hotfix - react-json-schema cannot restore object values. Do not save formData if (stateData.selectedMethod && stateData.selectedMethod.formData && @@ -65,3 +65,12 @@ export const syncStore = (store) => { }); }); }; + +export const clearStorage = () => { + connectDB((db) => { + const request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(storageKey); + request.onsuccess = function () { + window.location.reload(); + }; + }); +}; diff --git a/src/index.jsx b/src/index.jsx index 2082a81..fa554ef 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,13 +1,23 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; +import merge from 'lodash/merge'; import Application from 'containers/Application'; import { get as getStore } from 'helpers/session'; import configureStore from './configureStore'; import './styles/main.scss'; -const rootNode = document.querySelector('#json-rpc-root'); +const autoInitSelector = '#json-rpc-root'; + +const defaultOptions = { + endpoint: null, + smdUrl: null, + headers: {}, + selector: '#smdbox-root', +}; + +let rootNode; const renderApp = (App, store) => render( @@ -17,15 +27,41 @@ const renderApp = (App, store) => rootNode ); -getStore((storeData) => { - const store = configureStore(storeData || {}); - renderApp(Application, store); -}); - - if (module.hot) { module.hot.accept(['containers/Application'], () => { const NextApp = require('containers/Application').default; renderApp(NextApp); }); } + + +const init = (opts = {}) => { + const options = { + ...defaultOptions, + ...opts + }; + + const { smdUrl, endpoint, selector, headers } = options; + if (selector) { + rootNode = document.querySelector(selector); + } + + getStore((storeData = {}) => { + // set preconfigured smdUrl, endpoint and headers from config + merge(storeData, { project: { smdUrl, endpoint, headers } }); + const store = configureStore(storeData); + renderApp(Application, store); + }); +}; + +// try to auto init without calls (backward compatibilty) +document.addEventListener('DOMContentLoaded', () => { + if (document.querySelector(autoInitSelector)) { + init({ selector: autoInitSelector }); + } +}); + +window.smdbox = init; + +export default init; + diff --git a/webpack/webpack.dev.js b/webpack/webpack.dev.js index d885e89..af683b8 100644 --- a/webpack/webpack.dev.js +++ b/webpack/webpack.dev.js @@ -74,7 +74,7 @@ const webpackConfig = { filename: 'index.html', template: `${APP_FOLDER}/assets/html/index.dev.html`, minify: false, - inject: 'body', + inject: 'head', }), new AutoDllPlugin({ inject: true, diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 6e57efd..2be6f27 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -83,7 +83,7 @@ const webpackConfigWidget = { filename: 'index.html', template: `${APP_FOLDER}/assets/html/index.html`, minify: false, - inject: 'body', + inject: 'head', }), new webpack.ContextReplacementPlugin(/moment[\/\\]locale/, /en|ru/), // eslint-disable-line no-useless-escape, max-len new webpack.DefinePlugin({ diff --git a/yarn.lock b/yarn.lock index e0d8fb6..33ef8be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4834,10 +4834,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= +lodash@4.17.19: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== lodash@^4.0.0, lodash@^4.16.4, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1, lodash@~4.17.10: version "4.17.15"