|
@@ -0,0 +1,199 @@
|
|
|
+(function (global, p5VendorJs) {
|
|
|
+ if (!p5VendorJs.React) throw "Missing React"
|
|
|
+ if (!p5VendorJs.ReactDOM) throw "Missing ReactDOM"
|
|
|
+ if (!p5VendorJs.createReactClass) throw "Missing createReactClass"
|
|
|
+
|
|
|
+ var DBG = DBG || 0;
|
|
|
+ var DBG1 = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Loads props.url after mount.
|
|
|
+ * If props.url changed: clear, start loding new url.
|
|
|
+ * If props.url is empty: clear.
|
|
|
+ *
|
|
|
+ * Clear: show props.emptyUrlContent || ''
|
|
|
+ *
|
|
|
+ * @usage:
|
|
|
+ * ReactDOM.render(
|
|
|
+ * h(P5UI__AjaxContent, {
|
|
|
+ * url: '',
|
|
|
+ * }),
|
|
|
+ * document.getElementById(HTML_ID)
|
|
|
+ * )
|
|
|
+ *
|
|
|
+ * props.url: url | null
|
|
|
+ * props.loading: html | null
|
|
|
+ * props.emptyContent: html | null - TODO: show when url is not defined
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ // var React = window.p5VendorJs.React;
|
|
|
+ var createReactClass = window.p5VendorJs.createReactClass;
|
|
|
+ var h = window.p5VendorJs.React.createElement;
|
|
|
+
|
|
|
+ // componentDidMount: function () { console.log('MyWidget::componentDidMount...'); },
|
|
|
+ // componentWillReceiveProps: function (nextProps) { console.log('MyWidget::componentWillReceiveProps(nextProps)...', nextProps); },
|
|
|
+ // shouldComponentUpdate: function (nextProps, nextState) { console.log('MyWidget::shouldComponentUpdate(nextProps, nextState)...', nextProps, nextState); },
|
|
|
+ // componentWillUpdate: function (nextProps, nextState) { console.log('MyWidget::componentWillUpdate(nextProps, nextState)...', nextProps, nextState); },
|
|
|
+ // componentDidUpdate: function (prevProps, prevState) { console.log('MyWidget::componentDidUpdate(prevProps, prevState)...', prevProps, prevState); },
|
|
|
+ // componentWillUnmount: function () { console.log('MyWidget::componentWillUnmount...'); },
|
|
|
+ var P5UI__AjaxContent = createReactClass({
|
|
|
+ _refContentEl: null,
|
|
|
+ setContentElRef: function (el) {
|
|
|
+ this._refContentEl = el;
|
|
|
+ },
|
|
|
+ getInitialState: function () {
|
|
|
+ return {
|
|
|
+ isLoading: false,
|
|
|
+ postData: null, // if method = 'POST'
|
|
|
+ response_type: null,
|
|
|
+ response_msg: null,
|
|
|
+ response_body: null,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ componentDidMount() {
|
|
|
+ if (this.props.url) this._fetchContent();
|
|
|
+ },
|
|
|
+ componentDidUpdate(prevProps, prevState) {
|
|
|
+ if (prevProps.url !== this.props.url) {
|
|
|
+ this._fetchContent();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ _fetchContent: function () {
|
|
|
+ this.setState({
|
|
|
+ isLoading: true
|
|
|
+ });
|
|
|
+ // var _setState = this.setState.bind(this);
|
|
|
+ var _handleFetchResponseSuccess = this._handleFetchResponseSuccess.bind(this);
|
|
|
+ var _handleFetchResponseFail = this._handleFetchResponseFail.bind(this);
|
|
|
+ var _handleFetchResponseJson = this._handleFetchResponseJson.bind(this);
|
|
|
+ window.fetch(this.props.url,
|
|
|
+ (!this.props.postData)
|
|
|
+ ? {
|
|
|
+ method: 'GET',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ credentials: 'same-origin',
|
|
|
+ }
|
|
|
+ : {
|
|
|
+ method: 'POST',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ credentials: 'same-origin',
|
|
|
+ body: this.props.postData, // JSON.stringify(this.props.postData)
|
|
|
+ }
|
|
|
+ ).then(function (response) {
|
|
|
+ DBG1 && console.log("DBG:response", {
|
|
|
+ status: response.status,
|
|
|
+ response: response
|
|
|
+ });
|
|
|
+ response.text()
|
|
|
+ .then(response.ok ? _handleFetchResponseSuccess : _handleFetchResponseFail)
|
|
|
+ .catch(function (err) {
|
|
|
+ _handleFetchResponseJson({
|
|
|
+ response_type: 'error',
|
|
|
+ response_msg: "" + err,
|
|
|
+ response_body: null,
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }).then(function (data) {
|
|
|
+ DBG1 && console.warn("DBG:response data", { data });
|
|
|
+ }).catch(function (err) {
|
|
|
+ DBG1 && console.log("Response Error #2:")
|
|
|
+ DBG1 && console.error(err)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ _handleFetchResponseFail: function (responseText) {
|
|
|
+ DBG1 && console.warn("DBG:response fail responseText", { responseText });
|
|
|
+ if (!responseText) throw "Error";
|
|
|
+ this._handleFetchResponseText(false, responseText)
|
|
|
+ },
|
|
|
+
|
|
|
+ _handleFetchResponseSuccess: function (responseText) {
|
|
|
+ DBG1 && console.warn("DBG:response success responseText", { responseText });
|
|
|
+ this._handleFetchResponseText(true, responseText)
|
|
|
+ },
|
|
|
+
|
|
|
+ _handleFetchResponseText: function (isOk, responseText) {
|
|
|
+ DBG1 && console.warn("DBG:response _handleFetchResponseText", { isOk, responseText });
|
|
|
+ if ('{' !== responseText.substr(0, 1)) throw "Response Parse Error: Expected json.";
|
|
|
+ try {
|
|
|
+ var jsonResponse = JSON.parse(responseText);
|
|
|
+ if (!jsonResponse.msg) throw "Response Parse Error: Expected json with msg.";
|
|
|
+ if (!isOk) throw jsonResponse.msg; // TODO: throw or just show alert for user
|
|
|
+
|
|
|
+ this._handleFetchResponseJson(jsonResponse)
|
|
|
+ } catch (err) {
|
|
|
+ throw "Response Parse Error: " + err;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ _handleFetchResponseJson: function (jsonResponse) {
|
|
|
+ DBG1 && console.warn("DBG:response _handleFetchResponseJson", { jsonResponse });
|
|
|
+ this.setState({
|
|
|
+ isLoading: false,
|
|
|
+ response_type: jsonResponse.type,
|
|
|
+ response_msg: jsonResponse.msg,
|
|
|
+ response_body: jsonResponse.body,
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ shouldComponentUpdate: function (nextProps, nextState) {
|
|
|
+ DBG1 && console.warn("DBG:response shouldComponentUpdate", {
|
|
|
+ props: this.props, nextProps,
|
|
|
+ state: this.state, nextState,
|
|
|
+ });
|
|
|
+ if (!this.state.isLoading && nextState.isLoading) {
|
|
|
+ doShowLoading(this.props, this._refContentEl);
|
|
|
+ }
|
|
|
+ if (!nextState.isLoading && nextState.response_type) {
|
|
|
+ doParseResponseBody(nextState.response_type, nextState.response_msg, nextState.response_body, this._refContentEl);
|
|
|
+ }
|
|
|
+ return false; // render only once!
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ DBG1 && console.log('DBG:render (TODO: render only once!)', { options: this.state.options });
|
|
|
+
|
|
|
+ return h('div', {
|
|
|
+ ref: this.setContentElRef,
|
|
|
+ // dangerouslySetInnerHTML: { __html: this.renderContentHtml() }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ function doParseResponseBody(type, msg, body, rootNode) {
|
|
|
+ switch (type) {
|
|
|
+ case 'error': return doNotify('error', (msg || "Wystąpił błąd"), rootNode);
|
|
|
+ case 'success': return doShowContent(body, rootNode);
|
|
|
+ default: return doNotify('warning', msg, rootNode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function doShowLoading(props, rootNode) {
|
|
|
+ DBG1 && console.log('DBG:doShowLoading', { rootNode });
|
|
|
+ if (!rootNode) return;
|
|
|
+ rootNode.innerHTML = props.loading || '<p>Loading ...</p>';
|
|
|
+ // DBG && rootNode.innerHTML += "\n" + '<pre>' + "props: " + JSON.stringify(props, null, 4) + '</pre>';
|
|
|
+ }
|
|
|
+ function doShowContent(body, rootNode) {
|
|
|
+ DBG1 && console.log('DBG:doShowContent', { rootNode });
|
|
|
+ if (!rootNode) return;
|
|
|
+ if (body.reactNode) return p5UI__buildDom(body.reactNode, rootNode);
|
|
|
+ if (body.html) return doShowHtmlContent(body.html, rootNode);
|
|
|
+ if (typeof body === 'string' || body instanceof String) return doShowHtmlContent(body, rootNode);
|
|
|
+ else {
|
|
|
+ // TODO: if DBG
|
|
|
+ rootNode.innerHTML = '<pre>' + JSON.stringify(body, null, 4) + '</pre>';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function doShowHtmlContent(htmlContent, node) {
|
|
|
+ node.innerHTML = htmlContent;
|
|
|
+ }
|
|
|
+ function doNotify(type, msg, rootNode) {
|
|
|
+ // TODO: if (NOTIFY_USER_MODE) // 'inline' | 'notify'
|
|
|
+ type = ('error' == type) ? 'danger' : type;
|
|
|
+ rootNode.innerHTML = '<div class="alert alert-' + type + '" style="margin-bottom:0">' + msg + '</div>';
|
|
|
+ }
|
|
|
+
|
|
|
+ global.P5UI__AjaxContent = P5UI__AjaxContent;
|
|
|
+})(window, window.p5VendorJs);
|