var DBG = DBG || 0; var DBG1 = true; var EXECUTE_NEXT_ACTION_LIMIT = 1000; var EXECUTE_NEXT_ACTION_INTERVAL = 100; if (!HTML_ID) throw "Missing HTML_ID"; if (!TOTAL) throw "Missing TOTAL"; if (!EXECUTE_SINGLE_TASK_URL) throw "Missing EXECUTE_SINGLE_TASK_URL"; if (!global.p5VendorJs) throw "Missing vendor.js"; var ALLOW_FORCE_UPDATE = ALLOW_FORCE_UPDATE || false; var FORCE_UPDATE_POST_DATA = FORCE_UPDATE_POST_DATA || []; var createReactClass = global.p5VendorJs.createReactClass; var h = global.p5VendorJs.React.createElement; var ReactDOM = global.p5VendorJs.ReactDOM; // var AsyncTypeahead = window.p5VendorJs.AsyncTypeahead; // responseBody: // - percentDone // - totalToUpdate // - total // - totalDone var sendRequest = (function () { // uses: EXECUTE_SINGLE_TASK_URL var _versionSent = 1; var _versionReceived = 0; return function () {// return function (limit, page, sorted, filtered) { // var filterTableProps = { // limit: limit || REQUEST_DATA_LIMIT, // page: page || 0, // sorted: sorted || [], // filtered: filtered || [], // }; _versionSent++; var this_version = _versionSent; return global.fetch(EXECUTE_SINGLE_TASK_URL, { header: { 'contentType': 'applications/json' }, credentials: 'same-origin', method: 'GET', // body: JSON.stringify(filterTableProps), // POST }).then(function (result) { if (this_version < _versionReceived) throw "Skipped response: already received newer version."; return result.json() }).then(function (data) { DBG && console.log("DBG:EXECUTE_SINGLE_TASK_URL:Data", { data }) _versionReceived = this_version; // DBG && console.log("DBG:sendRequest:afterReceived", { _versionSent, _versionReceived, _lastPropsJson, this_version, this_lastPropsJson }); return data.body; // body: { rows: [], total: int } }) } })(); var P5UI__WindykacjaStatusUpdate = createReactClass({ getInitialState: function () { return { errorMsg: '', loading: false, version: 0, responseBody: null, execLimit: EXECUTE_NEXT_ACTION_LIMIT, execCounter: 0, execAgain: true, } }, componentDidMount: function () { this.runUpdateStatus(); }, runAgainIfNotDone: function () { if (!this.state.execAgain) return; if (this.state.responseBody && 100 === this.state.responseBody.percentDone && 0 === this.state.responseBody.totalToUpdate) { return; } if (this.state.execCounter > this.state.execLimit) { this.setState({ errorMsg: "Osiągnięto limit wywołań funkcji", }) return; } var _runUpdateStatus = this.runUpdateStatus.bind(this); setTimeout(_runUpdateStatus, EXECUTE_NEXT_ACTION_INTERVAL) }, runUpdateStatus: function () { DBG && console.log('DBG:runUpdateStatus', {}); this.setState({ loading: true }); var _runAgainIfNotDone = this.runAgainIfNotDone.bind(this); var _setState = this.setState.bind(this); var _version = this.state.version + 1; // TODO: handle race condition sendRequest().then(responseBody => { _setState({ responseBody: responseBody, version: _version, loading: false, execCounter: this.state.execCounter + 1, }, _runAgainIfNotDone); }).catch(function (e) { if ("Skipped request" === ('' + e).substr(0, "Skipped request".length)) { console.log("DBG:sendRequest:Skipped", e) _setState({ loading: false, }, ); return; } console.log("Error:sendRequest", e) _setState({ loading: false, errorMsg: '' + e, }); }); }, handleClickRestart: function (event) { event.preventDefault() location.reload() }, handleClickForceRestart: function (event) { event.preventDefault() }, handleClickPause: function (event) { event.preventDefault() this.setState({ execAgain: false }) }, handleClickPlay: function (event) { event.preventDefault() this.setState({ execAgain: true }) this.runUpdateStatus(); }, render: function () { DBG && console.log('DBG:render', { state: this.state }); var isDone = (this.state.responseBody && 100 === this.state.responseBody.percentDone && 0 === this.state.responseBody.totalToUpdate); var percent = (this.state.responseBody) ? Math.round(this.state.responseBody.percentDone, 2) : 0; var panelClass = (percent < 100) ? "warning" : "success"; if (this.state.errorMsg) panelClass = "danger"; var iconPause = h('i', { className: "glyphicon glyphicon-pause" }); var iconPlay = h('i', { className: "glyphicon glyphicon-play" }); return h('div', { p5_node_id: 'p5-windykacja-status-update-widget' }, [ h('div', { className: "panel panel-" + panelClass }, [ h('div', { className: "panel-heading" }, [ ]), h('div', { className: "panel-body", style: { paddingBottom: "0" } }, [ h('p', {}, [ "Aktaulizacja statusu " + this.props.total + " rekordów ", " ", (!isDone) ? ( (this.state.execAgain) ? h('button', { className: "btn btn-xs btn-default", onClick: this.handleClickPause }, [ iconPause, "Zatrzymaj" ]) : h('button', { className: "btn btn-xs btn-default", onClick: this.handleClickPlay }, [ iconPlay, "Uruchom ponownie" ]) ) : '', ]), h('div', { className: "progress" }, [ h('div', { className: "progress-bar", role: "progressbar", ariaValuenow: percent, ariaValuemin: "0", ariaValuemax: "100", style: { width: "" + percent + "%" }, }, [ "" + percent + "%" ]), ]), (this.state.responseBody) ? h('p', {}, "Wykonano " + this.state.responseBody.totalDone + " z " + this.state.responseBody.total) : '', (this.state.errorMsg) ? h('div', { className: "alert alert-danger" }, [ this.state.errorMsg, " ", h('button', { className: "btn btn-primary", onClick: this.handleClickRestart }, "Uruchom ponownie") ]) : "", (isDone && !this.state.errorMsg && this.props.allowForceUpdate) ? h('div', { style: { float: "right" } }, [ h(P5UI__PostButton, { data: this.props.forceUpdatePostData, className: "btn btn-xs btn-warning", label: "Wymuś ponowne uruchomienie" }) ]) : '', ]), ]), ]); } }); var P5UI__PostButton = function (props) { // @props: { label: string, data: { key: value, ... } } return h('form', { 'style' : { display : "inline" }, method: "POST" }, [ h('div', {}, Object.keys(props.data).map(function (key) { return h('input', { type: "hidden", name: key, value: props.data[key] }); })), h('button', { className: props.className || "btn btn-primary", type: "submit" }, props.label) ]); } ReactDOM.render( h(P5UI__WindykacjaStatusUpdate, { total: TOTAL, allowForceUpdate: ALLOW_FORCE_UPDATE, forceUpdatePostData: FORCE_UPDATE_POST_DATA, }), document.getElementById(HTML_ID) )