feedback.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. var feedbackNode = null
  2. if (!global.p5VendorJs) throw "Missing vendor.js!";
  3. if (!html2canvas) throw "Missing html2canvas!";
  4. var h = global.p5VendorJs.React.createElement;
  5. var ReactDOM = global.p5VendorJs.ReactDOM;
  6. var createReactClass = global.p5VendorJs.createReactClass;
  7. var DBG = DBG || false;
  8. var DBG1 = true;
  9. // echo UI:: h('div', [
  10. // 'style' => "position:fixed; width:20px; height:20px; right:5px; bottom:5px; cursor:pointer; z-index:1041",
  11. // ], [
  12. // UI:: h('i', [
  13. // 'class' => "glyphicon glyphicon-camera",
  14. // 'style' => "color:#666",
  15. // 'onClick' => "p5UI__feedback(event)"
  16. // ])
  17. // ]);
  18. (function () {
  19. var node = document.createElement('div')
  20. node.style.position = 'fixed';
  21. node.style.width = '20px';
  22. node.style.height = '20px';
  23. node.style.right = '5px';
  24. node.style.bottom = '5px';
  25. node.style.cursor = 'pointer';
  26. node.style.zIndex = '1041';
  27. var feedbackBtn = document.createElement('i')
  28. feedbackBtn.style.color = "#666";
  29. feedbackBtn.setAttribute('onClick', "p5UI__feedback(event)");
  30. feedbackBtn.setAttribute('class', "glyphicon glyphicon-camera");
  31. node.appendChild(feedbackBtn);
  32. document.body.appendChild(node);
  33. })();
  34. function p5UI__feedback(event) {
  35. event.stopPropagation()
  36. event.preventDefault()
  37. console.log('DBG:p5UI__feedback', { target: event.target });
  38. if (feedbackNode) hideFeedback();
  39. else {
  40. TODO__getDomToJson();
  41. makeScreenshot().then(function (pngDataUrl) {
  42. showFeedback(pngDataUrl);
  43. }).catch(function (err) {
  44. console.log('Error: ', err);
  45. })
  46. }
  47. }
  48. function showFeedback(pngDataUrl) {
  49. feedbackNode = document.createElement('div')
  50. feedbackNode.style.position = 'absolute';
  51. feedbackNode.style.top = '0px';
  52. feedbackNode.style.left = '0px';
  53. feedbackNode.style.width = '' + document.documentElement.clientWidth + 'px';
  54. var bodyHeight = Math.max(
  55. document.body.scrollHeight, document.body.offsetHeight,
  56. document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight
  57. );
  58. feedbackNode.style.height = '' + bodyHeight + 'px';
  59. feedbackNode.style.zIndex = '2';
  60. feedbackNode.style.backgroundColor = '#eee';
  61. document.body.appendChild(feedbackNode)
  62. ReactDOM.render(
  63. h(p5UI__feedbackBox, {
  64. pngDataUrl: pngDataUrl,
  65. // nameSection: nameSection,
  66. // store: globalGraphStore,
  67. // actions: globalGraphActions,
  68. }),
  69. feedbackNode
  70. );
  71. }
  72. function hideFeedback() {
  73. if (!feedbackNode) return false;
  74. document.body.removeChild(feedbackNode)
  75. feedbackNode = null;
  76. }
  77. function makeScreenshot() {
  78. return new Promise((resolve, reject) => {
  79. var node = document.querySelector('body');
  80. html2canvas(node, {
  81. onrendered: (canvas) => {
  82. let pngUrl = canvas.toDataURL();
  83. resolve(pngUrl);
  84. }
  85. });
  86. });
  87. }
  88. var p5UI__feedbackBox = createReactClass({
  89. sendFeedback: function () {
  90. console.log('TODO: send feedback...');
  91. },
  92. close: function () {
  93. hideFeedback();
  94. },
  95. render: function () {
  96. return h('div', {
  97. style: {
  98. width: '100%',
  99. height: '100%',
  100. }
  101. }, [
  102. h('form', { onSubmit: this.sendFeedback }, [
  103. h('table', {
  104. style: { width: "100%",
  105. backgroundColor: "#eee",
  106. borderBottom: "2px solid #ccc",
  107. }
  108. }, [
  109. h('tr', {}, [
  110. // h('td', { style: { padding: "2px 12px" } }, [
  111. // h('h1', {}, "Test..."),
  112. // ]),
  113. h('td', { style: { padding: "2px 12px", width: "10%" } }, [
  114. h('select', {}, [
  115. h('option', { value: "BUG" }, "Zgłoś błąd"),
  116. h('option', { value: "IDEA" }, "Zaproponuj zmianę/nową funkcjonalność"),
  117. h('option', { value: "DOC" }, "Dokumantacja"),
  118. ]),
  119. ]),
  120. h('td', { style: { padding: "2px 12px", width: "10%" } }, [
  121. h('textarea', { placeholder: "opis..." }),
  122. ]),
  123. h('td', { style: { padding: "2px 12px", width: "10%" } }, [
  124. h('button', { type: "submit" }, "Zapisz"),
  125. ]),
  126. h('td', { style: { padding: "2px 12px", textAlign: "right" } }, [
  127. h('i', { onClick: this.close, className: "glyphicon glyphicon-remove", style: { cursor: "pointer" } }),
  128. ]),
  129. ])
  130. ]),
  131. h('div', {
  132. style: {
  133. padding: "6px",
  134. textAlign: "center",
  135. backgroundColor: "#fff",
  136. }
  137. }, [
  138. h('img', {
  139. src: this.props.pngDataUrl,
  140. style: {
  141. width: '90%',
  142. border: "2px solid #ccc",
  143. }
  144. })
  145. ])
  146. ]),
  147. ]);
  148. }
  149. })
  150. function TODO__getDomToJson() {
  151. // var pageStaticHtml = htmlScreenCaptureJs.capture(htmlScreenCaptureJs.OutputType.STRING);
  152. // console.log('DBG:TODO__getDomToJson', { pageStaticHtml });
  153. // var pageHtml = document.body.innerHTML;
  154. // pageHtml.replace(/<script(.*)<\/script>/g, '')
  155. // console.log('DBG:TODO__getDomToJson', pageHtml);
  156. var staticDomClone = cloneDomToStaticPage(document.body);
  157. var staticPage = {
  158. width: window.document.body.clientWidth,
  159. height: window.document.body.clientHeight,
  160. body:
  161. '<body' + (staticDomClone.hasAttribute('style') ? ' style="' + staticDomClone.getAttribute('style') + '"' : '') + '>' +
  162. staticDomClone.innerHTML +
  163. '</body>',
  164. }
  165. DBG1 && console.log('DBG:TODO__getDomToJson', staticPage);
  166. }
  167. function cloneDomToStaticPage(node) {
  168. var staticClone = node.cloneNode(false);
  169. DBG && console.log('DBG:cloneDomToStaticPage', { type: node.nodeType, name: node.nodeName, node })
  170. cloneChildrensToStatic(staticClone, node, '');
  171. return staticClone;
  172. }
  173. function cloneDomToStaticPage__rec(parentStaticClone, node, path) {
  174. DBG && console.log('DBG:cloneDomToStaticPage__rec', { path, type: node.nodeType, name: node.nodeName, node })
  175. switch (node.nodeType) {
  176. case 1: return cloneDomToStaticPage__rec__tag(parentStaticClone, node, path); // TAG
  177. case 3: return cloneDomToStaticPage__rec__text(parentStaticClone, node, path); // #text
  178. default: return cloneDomToStaticPage__rec__unknown(parentStaticClone, node, path);
  179. }
  180. // for (var child = node.firstChild; child !== null; child = child.nextSibling) {
  181. // DBG && console.log('DBG:cloneDomToStaticPageRec child', { type: child.nodeType, name: child.nodeName, child })
  182. // }
  183. }
  184. function cloneDomToStaticPage__rec__text(parentStaticClone, node, path) {
  185. DBG && console.log('DBG:cloneDomToStaticPage__rec__text', { path, type: node.nodeType, name: node.nodeName, node })
  186. parentStaticClone.appendChild(node.cloneNode(false)); // #text cannot have childrens?
  187. }
  188. function cloneDomToStaticPage__rec__tag(parentStaticClone, node, path) {
  189. DBG && console.log('DBG:cloneDomToStaticPage__rec__tag', { path, type: node.nodeType, name: node.nodeName, node })
  190. switch (node.nodeName) {
  191. case 'SCRIPT': return cloneDomToStaticPage__rec__tag_script(parentStaticClone, node, path + '/script');
  192. case 'LINK': return cloneDomToStaticPage__rec__tag_link(parentStaticClone, node, path + '/link');
  193. case 'BUTTON': return cloneDomToStaticPage__rec__tag_button(parentStaticClone, node, path + '/link');
  194. // TODO: if (clonedNode.classList.contains('glyphicon'))
  195. case 'I': return cloneDomToStaticPage__rec__tag_with_glyphicon(parentStaticClone, node, path + '/i');
  196. case 'SPAN': return cloneDomToStaticPage__rec__tag_with_glyphicon(parentStaticClone, node, path + '/span');
  197. case 'A': return cloneDomToStaticPage__rec__tag_with_glyphicon(parentStaticClone, node, path + '/a');
  198. default: return cloneDomToStaticPage__rec__tag_default(parentStaticClone, node, path + '/' + node.nodeName.toLowerCase());
  199. }
  200. }
  201. function cloneDomToStaticPage__rec__tag_script(parentStaticClone, node, path) {
  202. return false; // skip script tags
  203. }
  204. function cloneDomToStaticPage__rec__tag_link(parentStaticClone, node, path) {
  205. DBG && console.log('DBG:cloneDomToStaticPage__rec__tag_link', { path, type: node.nodeType, name: node.nodeName, node })
  206. var clonedNode = cloneNodeToStatic(node);
  207. parentStaticClone.appendChild(clonedNode);
  208. cloneChildrensToStatic(clonedNode, node, path);
  209. }
  210. function cloneDomToStaticPage__rec__tag_button(parentStaticClone, node, path) {
  211. DBG && console.log('DBG:cloneDomToStaticPage__rec__tag_button', { path, type: node.nodeType, name: node.nodeName, node })
  212. var clonedNode = cloneNodeToStatic(node);
  213. { // fix button height with only glyphicon inside (electron bug)
  214. var btnStyleObj = document.defaultView.getComputedStyle(node)
  215. // clonedNode.style.height = btnStyleObj.height + 'px';
  216. clonedNode.setAttribute('style',
  217. (clonedNode.hasAttribute('style')
  218. ? clonedNode.getAttribute('style') + ';'
  219. : ''
  220. ) + 'height:' + btnStyleObj.height
  221. )
  222. }
  223. parentStaticClone.appendChild(clonedNode);
  224. for (var child = node.firstChild; child !== null; child = child.nextSibling) {
  225. cloneDomToStaticPage__rec(clonedNode, child, path);
  226. }
  227. }
  228. function cloneDomToStaticPage__rec__tag_with_glyphicon(parentStaticClone, node, path) {
  229. DBG && console.log('DBG:cloneDomToStaticPage__rec__tag_with_glyphicon', { path, type: node.nodeType, name: node.nodeName, node })
  230. var clonedNode = cloneNodeToStatic(node);
  231. { // convert glyphicon
  232. if (clonedNode.classList.contains('glyphicon')) {
  233. var styleObj = document.defaultView.getComputedStyle(node);
  234. var width = parseInt(styleObj.width.replace('px', ''));
  235. var height = parseInt(styleObj.height.replace('px', ''));
  236. if (!height) width = height = parseInt(styleObj.fontSize.replace('px', ''));
  237. if (!height) width = height = 12;
  238. DBG && console.log('DBG:glyphicon', { classses: clonedNode.classList, width: styleObj.width, height: styleObj.height, fontSize: styleObj.fontSize });
  239. if (convertBsIconToSvg['search'](clonedNode, width, height)) {
  240. } else if (convertBsIconToSvg['envelope'](clonedNode, width, height)) {
  241. } else if (convertBsIconToSvg['map-marker'](clonedNode, width, height)) {
  242. } else if (convertBsIconToSvg['remove'](clonedNode, width, height)) {
  243. } else if (convertBsIconToSvg['download'](clonedNode, width, height)) {
  244. } else if (convertBsIconToSvg['pencil'](clonedNode, width, height)) {
  245. } else if (convertBsIconToSvg['folder-open'](clonedNode, width, height)) {
  246. } else if (convertBsIconToSvg['plus-sign'](clonedNode, width, height)) {
  247. } else if (convertBsIconToSvg['plus'](clonedNode, width, height)) {
  248. } else if (convertBsIconToSvg['refresh'](clonedNode, width, height)) {
  249. } else if (convertBsIconToSvg['cog'](clonedNode, width, height)) {
  250. } else if (convertBsIconToSvg['question-sign'](clonedNode, width, height)) {
  251. } else if (convertBsIconToSvg['align-left'](clonedNode, width, height)) {
  252. } else if (convertBsIconToSvg['menu-hamburger'](clonedNode, width, height)) {
  253. // triangle-top
  254. // camera
  255. // off
  256. // bell
  257. // calendar
  258. // user
  259. // lock
  260. } else {
  261. DBG1 && console.log('DBG:glyphicon NOT SUPPORTED', { classses: clonedNode.classList, width: styleObj.width, height: styleObj.height, fontSize: styleObj.fontSize });
  262. }
  263. }
  264. }
  265. parentStaticClone.appendChild(clonedNode);
  266. cloneChildrensToStatic(clonedNode, node, path);
  267. }
  268. var convertBsIconToSvg = {};
  269. convertBsIconToSvg['search'] = function(node, width, height) {
  270. return cloneNodeBsIconToSvg(node, width, height, 'search', '<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>');
  271. };
  272. convertBsIconToSvg['envelope'] = function(node, width, height) {
  273. return cloneNodeBsIconToSvg(node, width, height, 'envelope', '<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline>');
  274. };
  275. convertBsIconToSvg['map-marker'] = function (node, width, height) {
  276. return cloneNodeBsIconToSvg(node, width, height, 'map-marker', '<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle>');
  277. };
  278. convertBsIconToSvg['remove'] = function (node, width, height) {
  279. return cloneNodeBsIconToSvg(node, width, height, 'remove', '<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>');
  280. };
  281. convertBsIconToSvg['download'] = function (node, width, height) {
  282. return cloneNodeBsIconToSvg(node, width, height, 'download', '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>');
  283. };
  284. convertBsIconToSvg['pencil'] = function (node, width, height) {
  285. return cloneNodeBsIconToSvg(node, width, height, 'pencil', '<path d="M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34"></path><polygon points="18 2 22 6 12 16 8 16 8 12 18 2"></polygon>');
  286. };
  287. convertBsIconToSvg['folder-open'] = function (node, width, height) {
  288. return cloneNodeBsIconToSvg(node, width, height, 'folder-open', '<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>');
  289. };
  290. convertBsIconToSvg['plus-sign'] = function (node, width, height) {
  291. return cloneNodeBsIconToSvg(node, width, height, 'plus-sign', '<circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line>');
  292. };
  293. convertBsIconToSvg['plus'] = function (node, width, height) {
  294. return cloneNodeBsIconToSvg(node, width, height, 'plus', '<g stroke-width="4" stroke-linecap="butt" stroke-linejoin="miter"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></g>');
  295. };
  296. convertBsIconToSvg['refresh'] = function (node, width, height) {
  297. return cloneNodeBsIconToSvg(node, width, height, 'refresh', '<polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>');
  298. };
  299. convertBsIconToSvg['cog'] = function (node, width, height) {
  300. return cloneNodeBsIconToSvg(node, width, height, 'cog', '<circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>');
  301. };
  302. convertBsIconToSvg['question-sign'] = function (node, width, height) {
  303. return cloneNodeBsIconToSvg(node, width, height, 'question-sign', '<circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12" y2="17"></line>');
  304. };
  305. convertBsIconToSvg['align-left'] = function (node, width, height) {
  306. return cloneNodeBsIconToSvg(node, width, height, 'align-left', '<line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line>');
  307. };
  308. convertBsIconToSvg['menu-hamburger'] = function (node, width, height) {
  309. return cloneNodeBsIconToSvg(node, width, height, 'menu-hamburger', '<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>');
  310. };
  311. function cloneNodeBsIconToSvg(node, width, height, bsIcon, svgContent) {
  312. if (!node.classList.contains('glyphicon-' + bsIcon)) return false;
  313. node.classList.remove('glyphicon-' + bsIcon);
  314. DBG && console.log('DBG:cloneNodeBsIconToSvg', { bsIcon, width, height });
  315. var svgFont = document.createElement('svg');
  316. svgFont.setAttribute('viewBox', "0 0 24 24");
  317. svgFont.setAttribute('height', height);
  318. svgFont.setAttribute('width', width);
  319. svgFont.setAttribute('fill', "none");
  320. svgFont.setAttribute('stroke', "currentColor");
  321. svgFont.setAttribute('stroke-width', "3");
  322. svgFont.setAttribute('stroke-linecap', "round");
  323. svgFont.setAttribute('stroke-linejoin', "round");
  324. node.appendChild(svgFont)
  325. svgFont.innerHTML = svgContent;
  326. return true;
  327. }
  328. function cloneDomToStaticPage__rec__tag_default(parentStaticClone, node, path) {
  329. DBG && console.log('DBG:cloneDomToStaticPage__rec__tag_default', { path, type: node.nodeType, name: node.nodeName, node })
  330. var clonedNode = cloneNodeToStatic(node);
  331. parentStaticClone.appendChild(clonedNode);
  332. cloneChildrensToStatic(clonedNode, node, path);
  333. }
  334. function cloneDomToStaticPage__rec__unknown(parentStaticClone, node, path) {
  335. DBG && console.log('DBG:cloneDomToStaticPage__rec__unknown', { path, type: node.nodeType, name: node.nodeName, node })
  336. }
  337. function cloneChildrensToStatic(targetNode, sourceNode, path) {
  338. for (var child = sourceNode.firstChild; child !== null; child = child.nextSibling) {
  339. cloneDomToStaticPage__rec(targetNode, child, path);
  340. }
  341. }
  342. function cloneNodeToStatic(node) {
  343. var clonedNode = node.cloneNode(false);
  344. if (clonedNode.hasAttribute('onclick')) clonedNode.removeAttribute('onclick');
  345. if (clonedNode.hasAttribute('href')) clonedNode.removeAttribute('href');
  346. // if (clonedNode.hasAttribute('href')) clonedNode.href = clonedNode.href.replace(URL_BASE_PATH, './')
  347. return clonedNode;
  348. }
  349. global.p5UI__feedback = p5UI__feedback;