ChangeOwner.php.view.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. var DBG = DBG || false;
  2. var DBG1 = true;
  3. if (!HTML_ID) throw "Missing HTML_ID"
  4. if (!URL_BASE) throw "Missing URL_BASE"
  5. if (!URL_SEARCH_TABLE_LIST) throw "Missing URL_SEARCH_TABLE_LIST"
  6. if (!URL_SEARCH_USER_LIST) throw "Missing URL_SEARCH_USER_LIST"
  7. if (!URL_FETCH_INFO) throw "Missing URL_FETCH_INFO"
  8. if (!CHANGE_OWNER_POST_TASK_NAME) throw "Missing CHANGE_OWNER_POST_TASK_NAME"
  9. var SELECTED_TABLE_ID = SELECTED_TABLE_ID || null
  10. var SELECTED_TABLE_INFO = SELECTED_TABLE_INFO || null
  11. var SELECTED_FROM_OWNER_ID = SELECTED_FROM_OWNER_ID || null
  12. var SELECTED_FROM_OWNER_INFO = SELECTED_FROM_OWNER_INFO || null
  13. var SELECTED_TO_OWNER_ID = SELECTED_TO_OWNER_ID || null
  14. var SELECTED_TO_OWNER_INFO = SELECTED_TO_OWNER_INFO || null
  15. if (!global.fetch) throw "Missing fetch";
  16. if (!global.p5VendorJs) throw "Missing p5VendorJs";
  17. if (!global.p5VendorJs.Typeahead) throw "Missing Typeahead";
  18. if (!global.p5VendorJs.AsyncTypeahead) throw "Missing AsyncTypeahead";
  19. var createReactClass = global.p5VendorJs.createReactClass;
  20. var h = global.p5VendorJs.React.createElement;
  21. var React = global.p5VendorJs.React;
  22. var ReactDOM = global.p5VendorJs.ReactDOM;
  23. var Redux = global.p5VendorJs.Redux;
  24. var ReduxThunk = global.p5VendorJs.ReduxThunk;
  25. var createStoreWithThunkMiddleware = Redux.applyMiddleware(ReduxThunk)(Redux.createStore); // TODO: to vendor.js
  26. var Typeahead = global.p5VendorJs.Typeahead;
  27. var AsyncTypeahead = window.p5VendorJs.AsyncTypeahead;
  28. function makeJsonRequest(url, props) {
  29. return global.fetch(url, {
  30. method: 'POST',
  31. header: { 'contentType': 'applications/json' },
  32. credentials: 'same-origin',
  33. body: JSON.stringify(props.body)
  34. })
  35. .then(function (response) {
  36. return response.text();
  37. })
  38. .then(function (responseText) {
  39. try {
  40. return JSON.parse(responseText);
  41. } catch (e) {
  42. throw responseText;
  43. }
  44. })
  45. .then(function (result) {
  46. DBG1 && console.log('DBG:makeJsonRequest: result', result);
  47. if (result.type == 'success') {
  48. return result.body;
  49. }
  50. })
  51. }
  52. function filterByLabelHelper(listItem, node) { // previous: filterByHelper
  53. // DBG && console.log("DBG:filterByLabelHelper", { listItem, node })
  54. var query = (node && node.text) ? node.text : '';
  55. var label = listItem.label.toLowerCase();
  56. var words = (
  57. (query.indexOf(' ') > 0) ? query.split(' ') : [ query ]
  58. ).map(function (word) { return word.trim().replace(/^[0]+/g, '').toLowerCase(); })
  59. .filter(function (word) { return word.length > 2; });
  60. var foundWords = words.filter(function (word) {
  61. return (label.indexOf(word) > -1);
  62. })
  63. return (foundWords.length === words.length);
  64. }
  65. function filterByAllHelper(listItem, node) {
  66. // DBG && console.log("DBG:filterByAllHelper", { listItem, node })
  67. var query = (node && node.text) ? node.text : '';
  68. var label = listItem.label.toLowerCase();
  69. var id = listItem.id.toLowerCase();
  70. var words = (
  71. (query.indexOf(' ') > 0) ? query.split(' ') : [ query ]
  72. ).map(function (word) { return word.trim().replace(/^[0]+/g, '').toLowerCase(); })
  73. .filter(function (word) { return word.length > 2; });
  74. var foundWords = words.filter(function (word) {
  75. return (label.indexOf(word) > -1 || id.indexOf(word) > -1);
  76. })
  77. return (foundWords.length === words.length);
  78. }
  79. var p5UI__ChangeOwner_SearchTableWidget = createReactClass({
  80. getInitialState: function () {
  81. return {
  82. isSearching: false,
  83. options: this.props.selected || [],
  84. }
  85. },
  86. handleSearch: function (query) {
  87. this.setState({ isSearching: true });
  88. var _setState = this.setState.bind(this);
  89. makeJsonRequest(URL_SEARCH_TABLE_LIST, {
  90. body: {
  91. query: query,
  92. }
  93. })
  94. .then(function (responseBody) {
  95. var items = (responseBody && responseBody.items && responseBody.items.length) ? responseBody.items : []
  96. if (!items.length) p5UI__notifyAjaxCallback({ type: 'warning', msg: "Brak danych pasujących do kryteriów wyszukiwania" });
  97. DBG1 && console.log('items fetched:', items);
  98. _setState({ isSearching: false, options: items });
  99. })
  100. .catch(function (error) {
  101. DBG1 && console.log('request failed', error);
  102. })
  103. },
  104. render: function () {
  105. DBG1 && console.log("DBG:ChangeOwner:SearchTable:render", { props: this.props, state: this.state });
  106. return h('div', {}, [
  107. h(AsyncTypeahead, {
  108. isLoading: this.state.isSearching,
  109. allowNew: false,
  110. multiple: false,
  111. options: this.state.options || [],
  112. selected: this.props.selected || [],
  113. labelKey: "label",
  114. emptyLabel: "Brak danych pasujących do kryteriów wyszukiwania",
  115. searchText: "Wyszukiwanie...",
  116. // labelKey: function (option) {
  117. // return [
  118. // option.nazwa.replace('"', ''),
  119. // option.nip,
  120. // option.krs,
  121. // option.regon,
  122. // option.S_miejscowosc,
  123. // ].join(' ')
  124. // },
  125. minLength: 3,
  126. onSearch: this.handleSearch,
  127. placeholder: "Wyszukaj...",
  128. autoFocus: false,
  129. filterBy: filterByLabelHelper,
  130. renderMenuItemChildren: function (option, props) {
  131. return h(p5UI__ChangeOwner_SearchTableItem, { key: option.id, data: option });
  132. },
  133. onChange: this.props.onChange,
  134. })
  135. ])
  136. }
  137. });
  138. var p5UI__ChangeOwner_SearchTableItem = createReactClass({
  139. // this.props: { key: option.ID, baza: selectedBaza, data: option }
  140. render: function () {
  141. return h('div', {}, [
  142. h('em', {}, "[" + this.props.data.id + "]"),
  143. " ",
  144. this.props.data.label,
  145. ]);
  146. }
  147. });
  148. var p5UI__ChangeOwner_SearchUserWidget = createReactClass({
  149. getInitialState: function () {
  150. return {
  151. isSearching: false,
  152. options: (this.props.selected && this.props.selected.length > 0) ? this.props.selected : [],
  153. }
  154. },
  155. handleSearch: function (query) {
  156. this.setState({ isSearching: true });
  157. var _setState = this.setState.bind(this);
  158. makeJsonRequest(URL_SEARCH_USER_LIST, {
  159. body: {
  160. id_table: this.props.id_table,
  161. query: query,
  162. }
  163. })
  164. .then(function (responseBody) {
  165. var items = (responseBody && responseBody.items && responseBody.items.length) ? responseBody.items : []
  166. if (!items.length) p5UI__notifyAjaxCallback({ type: 'warning', msg: "Brak danych pasujących do kryteriów wyszukiwania" });
  167. DBG1 && console.log('items fetched:', items);
  168. _setState({ isSearching: false, options: items });
  169. })
  170. .catch(function (error) {
  171. DBG1 && console.log('request failed', error);
  172. })
  173. },
  174. render: function () {
  175. DBG1 && console.log("DBG:ChangeOwner:SearchUser:render", { props: this.props, state: this.state });
  176. return h('div', {}, [
  177. h(AsyncTypeahead, {
  178. isLoading: this.state.isSearching,
  179. allowNew: false,
  180. multiple: false,
  181. options: this.state.options,
  182. selected: this.props.selected || [],
  183. labelKey: "label",
  184. emptyLabel: "Brak danych pasujących do kryteriów wyszukiwania",
  185. searchText: "Wyszukiwanie...",
  186. // labelKey: function (option) {
  187. // return [
  188. // option.nazwa.replace('"', ''),
  189. // option.nip,
  190. // option.krs,
  191. // option.regon,
  192. // option.S_miejscowosc,
  193. // ].join(' ')
  194. // },
  195. minLength: 3,
  196. onSearch: this.handleSearch,
  197. placeholder: "Wyszukaj...",
  198. autoFocus: false,
  199. filterBy: filterByAllHelper,
  200. renderMenuItemChildren: function (option, props) {
  201. return h(p5UI__ChangeOwner_SearchUserItem, { key: option.id, data: option });
  202. },
  203. onChange: this.props.onChange,
  204. })
  205. ])
  206. }
  207. });
  208. var p5UI__ChangeOwner_SearchUserItem = createReactClass({
  209. // this.props: { key: option.ID, baza: selectedBaza, data: option }
  210. render: function () {
  211. return h('div', {}, [
  212. h('em', {}, "[" + this.props.data.id + "]"),
  213. " ",
  214. this.props.data.label,
  215. ]);
  216. }
  217. });
  218. var p5UI__ChangeOwnerWidget = createReactClass({
  219. getInitialState: function () {
  220. return {
  221. selectedTableID: SELECTED_TABLE_ID,
  222. selectedFromOwnerLogin: SELECTED_FROM_OWNER_ID,
  223. selectedToOwnerLogin: SELECTED_TO_OWNER_ID,
  224. selectedTableInfo: SELECTED_TABLE_INFO,
  225. selectedFromOwnerInfo: SELECTED_FROM_OWNER_INFO,
  226. selectedToOwnerInfo: SELECTED_TO_OWNER_INFO,
  227. isSearchingInfo: false,
  228. info: null,
  229. }
  230. },
  231. componentDidMount: function () {
  232. if (this.state.selectedTableID > 0) {
  233. this.fetchInfo()
  234. }
  235. },
  236. makeUrl: function (args) {
  237. var queryArgs = Object.assign({
  238. id_table: this.state.selectedTableID,
  239. id_from: this.state.selectedFromOwnerLogin,
  240. id_to: this.state.selectedToOwnerLogin,
  241. }, args);
  242. return [ URL_BASE ].concat(
  243. Object.keys(queryArgs).reduce(function (ret, argName) {
  244. if (!queryArgs[argName]) return ret;
  245. ret.push(argName + '=' + queryArgs[argName])
  246. return ret;
  247. }, [])
  248. ).join("&")
  249. },
  250. handleChangeTableID: function (selected) {
  251. DBG1 && console.log("DBG:ChangeOwner:handleChangeTableID", { selected })
  252. var tableID = (selected.length > 0) ? selected[0].id : ''
  253. this.setState({
  254. selectedTableID: tableID,
  255. selectedTableInfo: (selected.length > 0) ? [ selected[0] ] : null,
  256. })
  257. if (global.history && global.history.pushState) history.pushState({}, global.document.title, this.makeUrl({ id_table: tableID }));
  258. },
  259. handleChangeFromOwnerID: function (selected) {
  260. DBG1 && console.log("DBG:ChangeOwner:handleChangeFromOwnerID", { selected })
  261. var fromLogin = (selected.length > 0) ? selected[0].id : ''
  262. // if (global.history && global.history.pushState) history.pushState({}, global.document.title, this.makeUrl({ id_from: fromLogin }));
  263. this.setState({
  264. selectedFromOwnerLogin: fromLogin,
  265. selectedFromOwnerInfo: (selected.length > 0) ? [ selected[0] ] : null,
  266. }, (function () {
  267. if (global.history && global.history.pushState) history.pushState({}, global.document.title, this.makeUrl());
  268. this.fetchInfo()
  269. }).bind(this))
  270. },
  271. handleChangeToOwnerID: function (selected) {
  272. DBG1 && console.log("DBG:ChangeOwner:handleChangeToOwnerID", { selected })
  273. var toLogin = (selected.length > 0) ? selected[0].id : ''
  274. this.setState({
  275. selectedToOwnerLogin: toLogin,
  276. selectedToOwnerInfo: (selected.length > 0) ? [ selected[0] ] : null,
  277. }, (function () {
  278. if (global.history && global.history.pushState) history.pushState({}, global.document.title, this.makeUrl());
  279. this.fetchInfo()
  280. }).bind(this))
  281. },
  282. fetchInfo: function () {
  283. DBG1 && console.log("TODO:ChangeOwner:fetchInfo", { state: this.state })
  284. // TODO: fetch info if id_table, and id_from, optional id_to
  285. // TODO: handle race condition, skip old responses
  286. this.setState({ isSearchingInfo: true });
  287. var _setState = this.setState.bind(this);
  288. makeJsonRequest(URL_FETCH_INFO, {
  289. body: {
  290. id_table: this.state.selectedTableID,
  291. id_from: this.state.selectedFromOwnerLogin,
  292. id_to: this.state.selectedToOwnerLogin,
  293. }
  294. })
  295. .then(function (info) {
  296. // if (!info.length) p5UI__notifyAjaxCallback({ type: 'warning', msg: "Brak danych pasujących do kryteriów wyszukiwania" });
  297. DBG1 && console.log('DBG:ChangeOwner:handleChangeTableID info fetched:', info);
  298. _setState({ isSearchingInfo: false, info: info });
  299. })
  300. .catch(function (error) {
  301. DBG1 && console.log('DBG:ChangeOwner:handleChangeTableID request failed', error);
  302. })
  303. },
  304. renderInfo: function () {
  305. if (!this.state.info) return null;
  306. if (!this.state.selectedTableID) return null;
  307. if (!this.state.selectedFromOwnerLogin) return null;
  308. if (!this.state.selectedToOwnerLogin) return null;
  309. if (this.state.info && this.state.info.error_missing_owner_field) {
  310. return h('div', { className: "alert alert-danger" }, "Brak pola Osoba odpowiedzialana w wybranej tabeli");
  311. }
  312. if (this.state.info && this.state.info.errors && this.state.info.errors.length) {
  313. return h('div', {}, this.state.info.errors.map(function (err) {
  314. return h('div', { className: "alert alert-danger" }, err);
  315. }));
  316. }
  317. // "fromInfo": {
  318. // "id": "wolczynskit",
  319. // "name": "Tomasz Wólczyński",
  320. // "type": "Pracownik",
  321. // "status": "NORMAL",
  322. // "total": "1793"
  323. // },
  324. // "toInfo": {
  325. // "id": "michal.podejko",
  326. // "name": "Michał Podejko",
  327. // "type": "Pracownik",
  328. // "status": "NORMAL",
  329. // "total": "5940"
  330. // },
  331. var fromInfo = this.state.info.fromInfo
  332. var toInfo = this.state.info.toInfo
  333. var totalToUpdate = fromInfo.total || 0
  334. return h('div', {}, [
  335. h('table', { style: { width: "100%" } }, [
  336. h('tbody', {}, [
  337. h('tr', {}, [
  338. h('td', { style: { width: "5%" } }, ""),
  339. h('td', { style: { width: "40%" } }, [
  340. (fromInfo) ? this.renderOwnerInfo(fromInfo) : h('div', { className: "alert alert-warning" }, "Brak danych"),
  341. ]),
  342. h('td', {}, ""),
  343. h('td', { style: { width: "40%" } }, [
  344. (toInfo) ? this.renderOwnerInfo(toInfo) : h('div', { className: "alert alert-warning" }, "Brak danych"),
  345. ]),
  346. ])
  347. ])
  348. ]),
  349. (totalToUpdate)
  350. ? h('form', { method: "post", style: { textAlign: "center" } }, [
  351. h('input', { type: "hidden", name: "id_table", value: this.state.selectedTableID }),
  352. h('input', { type: "hidden", name: "id_from", value: this.state.selectedFromOwnerLogin }),
  353. h('input', { type: "hidden", name: "id_to", value: this.state.selectedToOwnerLogin }),
  354. h('input', { type: "hidden", name: "_postTask", value: CHANGE_OWNER_POST_TASK_NAME }),
  355. h('button', { className: "btn btn-lg btn-primary" }, "Zmień " + totalToUpdate + " rekordów"),
  356. ])
  357. : null
  358. ,
  359. // h('pre', {}, [
  360. // JSON.stringify(this.state.info, null, "\t")
  361. // ]),
  362. ]);
  363. },
  364. renderOwnerInfo: function (userInfo) {
  365. return h('div', {}, [
  366. h('p', {}, [
  367. h('em', {}, "[" + userInfo.id + "]"),
  368. " ",
  369. h('span', {}, userInfo.name),
  370. h('br'),
  371. h('span', {}, "Status: " + userInfo.status),
  372. h('br'),
  373. h('span', {}, "Typ: " + userInfo.type),
  374. ]),
  375. h('p', {}, [
  376. h('span', {}, "Odnaleziono " + userInfo.total + " rekordów"),
  377. ]),
  378. ]);
  379. },
  380. render: function () {
  381. DBG1 && console.log("DBG:ChangeOwner:render", { props: this.props, state: this.state });
  382. return h('form', { method: "get", style: { fontSize: "14px", lineHeight: "2em" } }, [
  383. h('input', { type: "hidden", name: "_route", value: "UrlAction_ChangeOwner" }),
  384. h('input', { type: "hidden", name: "id_table", value: this.state.selectedTableID }),
  385. h('input', { type: "hidden", name: "id_from", value: this.state.selectedFromOwnerLogin }),
  386. h('input', { type: "hidden", name: "id_to", value: this.state.selectedToOwnerLogin }),
  387. h('table', { style: { width: "100%", margin: "12px 0" } }, [
  388. h('tbody', {}, [
  389. h('tr', {}, [
  390. h('td', { style: { width: "5%" } }, [
  391. "Tabela: ",
  392. ]),
  393. h('td', {}, [
  394. h(p5UI__ChangeOwner_SearchTableWidget, {
  395. selected: this.state.selectedTableInfo,
  396. onChange: this.handleChangeTableID,
  397. })
  398. ]),
  399. h('td', {}, [
  400. h('a', {
  401. 'title': "Usuń zaznaczenie",
  402. 'href': URL_BASE,
  403. 'class': "btn btn-link",
  404. }, "usuń"),
  405. ]),
  406. ]),
  407. ]),
  408. ]),
  409. (this.state.selectedTableID > 0 && this.state.selectedTableInfo.length > 0) && h(React.Fragment, {}, [
  410. h('p', {}, [
  411. "Zmień osobę odpowiedzialną w tabeli ",
  412. h('em', {}, "[" + this.state.selectedTableID + "]"),
  413. " " + this.state.selectedTableInfo[0].label
  414. ]),
  415. h('table', { style: { width: "100%", margin: "12px 0" } }, [
  416. h('tbody', {}, [
  417. h('tr', {}, [
  418. h('td', { style: { width: "5%", textAlign: "right", paddingRight: "3px" } }, [
  419. "z: ",
  420. ]),
  421. h('td', { style: { width: "40%" } }, [
  422. h(p5UI__ChangeOwner_SearchUserWidget, {
  423. id_table: this.state.selectedTableID,
  424. selected: this.state.selectedFromOwnerInfo,
  425. onChange: this.handleChangeFromOwnerID,
  426. })
  427. ]),
  428. h('td', {}, ""),
  429. h('td', { style: { width: "5%", textAlign: "right", paddingRight: "3px" } }, [
  430. "na: ",
  431. ]),
  432. h('td', { style: { width: "40%" } }, [
  433. h(p5UI__ChangeOwner_SearchUserWidget, {
  434. id_table: this.state.selectedTableID,
  435. selected: this.state.selectedToOwnerInfo,
  436. onChange: this.handleChangeToOwnerID,
  437. })
  438. ]),
  439. ]),
  440. ]),
  441. ]),
  442. (this.state.isSearchingInfo)
  443. ? h('div', {}, [
  444. "Pobieranie informacji ..."
  445. ])
  446. : this.renderInfo()
  447. ,
  448. ]),
  449. ]);
  450. }
  451. })
  452. ReactDOM.render(
  453. h(p5UI__ChangeOwnerWidget, {
  454. // store: createStoreWithThunkMiddleware(NetworkGraph.store),
  455. // storeActions: NetworkGraph.createActions(),
  456. }),
  457. document.getElementById(HTML_ID)
  458. );