good_job 2.13.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +53 -1
  3. data/engine/app/assets/good_job/modules/application.js +14 -0
  4. data/engine/app/assets/good_job/modules/charts.js +29 -0
  5. data/engine/app/assets/good_job/modules/checkbox_toggle.js +51 -0
  6. data/engine/app/assets/good_job/modules/document_ready.js +7 -0
  7. data/engine/app/assets/good_job/modules/poller.js +93 -0
  8. data/engine/app/assets/good_job/modules/toasts.js +8 -0
  9. data/engine/app/assets/good_job/scripts.js +3 -0
  10. data/engine/app/assets/{style.css → good_job/style.css} +4 -0
  11. data/engine/app/assets/{vendor → good_job/vendor}/bootstrap/bootstrap.bundle.min.js +0 -0
  12. data/engine/app/assets/{vendor → good_job/vendor}/bootstrap/bootstrap.min.css +0 -0
  13. data/engine/app/assets/{vendor → good_job/vendor}/chartjs/chart.min.js +0 -0
  14. data/engine/app/assets/good_job/vendor/es_module_shims.js +1 -0
  15. data/engine/app/assets/{vendor → good_job/vendor}/rails_ujs.js +0 -0
  16. data/engine/app/controllers/good_job/assets_controller.rb +23 -6
  17. data/engine/app/controllers/good_job/executions_controller.rb +1 -5
  18. data/engine/app/controllers/good_job/jobs_controller.rb +45 -2
  19. data/engine/app/filters/good_job/base_filter.rb +3 -0
  20. data/engine/app/filters/good_job/jobs_filter.rb +5 -2
  21. data/engine/app/helpers/good_job/application_helper.rb +6 -0
  22. data/engine/app/views/good_job/executions/_table.erb +1 -1
  23. data/engine/app/views/good_job/jobs/_table.erb +101 -62
  24. data/engine/app/views/good_job/jobs/index.html.erb +1 -1
  25. data/engine/app/views/good_job/shared/_alert.erb +20 -13
  26. data/engine/app/views/good_job/shared/_navbar.erb +1 -4
  27. data/engine/app/views/layouts/good_job/application.html.erb +11 -8
  28. data/engine/config/locales/en.yml +0 -1
  29. data/engine/config/locales/es.yml +0 -1
  30. data/engine/config/locales/nl.yml +0 -1
  31. data/engine/config/locales/ru.yml +0 -1
  32. data/engine/config/routes.rb +10 -3
  33. data/lib/good_job/active_job_job.rb +9 -7
  34. data/lib/good_job/lockable.rb +10 -0
  35. data/lib/good_job/version.rb +1 -1
  36. metadata +15 -10
  37. data/engine/app/assets/scripts.js +0 -133
  38. data/engine/app/filters/good_job/executions_filter.rb +0 -41
  39. data/engine/app/views/good_job/executions/index.html.erb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c154bb21bc4a390c8e7f488e3a110dace697b660585d67cf66fcc21a1ebbeeb
4
- data.tar.gz: ba8d453f1eb4b9086534710a4bb7e5f29e2e497a1051e3be7aefa21b8c9a3164
3
+ metadata.gz: 6f311db9741be3dc51422a0bc3dd6dc3ec3a63cb2e570a8584d4cd2eaeea2565
4
+ data.tar.gz: 025cb4a2ebc678e3a052edf515d12bfb828dd23ab5d25e71debb9162ff41c34c
5
5
  SHA512:
6
- metadata.gz: f4344deb0fb76ad2ed78b1d0898aa7521fbab371c08ec6b59f2fd5dec4283723fc3cfe11d8af3acd891d7d6a44c586869c31e1f0106de6ca0ec09da1eee9e345
7
- data.tar.gz: bfb185dc98b9cc33e4562b6b641f179a32d57dcedd92622ca2334e79566f4d6876d55771425a5760e9bb14f06bee6ddad37067f97df887659c12acb1f25d34fc
6
+ metadata.gz: 4ef6d3f5d653481e1307f1c1f50371471fc7387f64b987d856d2b7bdf104b24d435060d9cb2d4d11fcc81e0808fecd564faf7ee2cc52c10c9c910626990818a9
7
+ data.tar.gz: 7c414de9a084fb505e8ff7306af76dfe026fce8427462c8c9bb051a82be2a80219685af1c4c37ec220c86f1dbd10c23f1651f611883348018224d9e62286467d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## [v2.14.0](https://github.com/bensheldon/good_job/tree/v2.14.0) (2022-04-26)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.13.2...v2.14.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Add mass update operations for jobs to Dashboard [\#578](https://github.com/bensheldon/good_job/pull/578) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Closed issues:**
12
+
13
+ - Allow "mass"-actions through Dashboard \(e.g. retry all\) [\#446](https://github.com/bensheldon/good_job/issues/446)
14
+
15
+ **Merged pull requests:**
16
+
17
+ - Track down incompatibility/race condition between JRuby and RSpec mocks in tests [\#581](https://github.com/bensheldon/good_job/pull/581) ([bensheldon](https://github.com/bensheldon))
18
+
19
+ ## [v2.13.2](https://github.com/bensheldon/good_job/tree/v2.13.2) (2022-04-25)
20
+
21
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.13.1...v2.13.2)
22
+
23
+ **Fixed bugs:**
24
+
25
+ - Namespaces assets per Rails docs [\#580](https://github.com/bensheldon/good_job/pull/580) ([kylekthompson](https://github.com/kylekthompson))
26
+
27
+ ## [v2.13.1](https://github.com/bensheldon/good_job/tree/v2.13.1) (2022-04-22)
28
+
29
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.13.0...v2.13.1)
30
+
31
+ **Implemented enhancements:**
32
+
33
+ - Dashboard: Use toasts to show notices and alerts [\#577](https://github.com/bensheldon/good_job/pull/577) ([bkeepers](https://github.com/bkeepers))
34
+ - Remove executions from the dashboard [\#576](https://github.com/bensheldon/good_job/pull/576) ([bkeepers](https://github.com/bkeepers))
35
+
36
+ **Fixed bugs:**
37
+
38
+ - `ActionMailer::MailDeliveryJob` executing twice [\#329](https://github.com/bensheldon/good_job/issues/329)
39
+ - Email job breaks dashboard [\#313](https://github.com/bensheldon/good_job/issues/313)
40
+
41
+ **Closed issues:**
42
+
43
+ - Possible encryption feature? [\#561](https://github.com/bensheldon/good_job/issues/561)
44
+ - Inconsistencies in configuration settings [\#380](https://github.com/bensheldon/good_job/issues/380)
45
+ - Lockable should accept an explicit keys on class methods too [\#341](https://github.com/bensheldon/good_job/issues/341)
46
+ - Run Scheduler\#cache\_warm on global thread pool instead of Scheduler's thread pool [\#286](https://github.com/bensheldon/good_job/issues/286)
47
+
48
+ **Merged pull requests:**
49
+
50
+ - Use javascript importmaps for Dashboard [\#574](https://github.com/bensheldon/good_job/pull/574) ([bensheldon](https://github.com/bensheldon))
51
+
3
52
  ## [v2.13.0](https://github.com/bensheldon/good_job/tree/v2.13.0) (2022-04-19)
4
53
 
5
54
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.12.2...v2.13.0)
@@ -20,10 +69,13 @@
20
69
 
21
70
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.12.1...v2.12.2)
22
71
 
72
+ **Fixed bugs:**
73
+
74
+ - Un-deprecate Adapter's `execution_mode` argument [\#567](https://github.com/bensheldon/good_job/pull/567) ([bensheldon](https://github.com/bensheldon))
75
+
23
76
  **Merged pull requests:**
24
77
 
25
78
  - Dashboard: added NL translations [\#568](https://github.com/bensheldon/good_job/pull/568) ([eelcoj](https://github.com/eelcoj))
26
- - Un-deprecate Adapter's `execution_mode` argument [\#567](https://github.com/bensheldon/good_job/pull/567) ([bensheldon](https://github.com/bensheldon))
27
79
 
28
80
  ## [v2.12.1](https://github.com/bensheldon/good_job/tree/v2.12.1) (2022-04-18)
29
81
 
@@ -0,0 +1,14 @@
1
+ /*jshint esversion: 6, strict: false */
2
+
3
+ import renderCharts from "charts";
4
+ import checkboxToggle from "checkbox_toggle";
5
+ import documentReady from "document_ready";
6
+ import showToasts from "toasts";
7
+ import Poller from "poller";
8
+
9
+ documentReady(function() {
10
+ renderCharts();
11
+ showToasts();
12
+ checkboxToggle();
13
+ Poller.start();
14
+ });
@@ -0,0 +1,29 @@
1
+ function renderCharts(animate) {
2
+ const charts = document.querySelectorAll('.chart');
3
+
4
+ for (let i = 0; i < charts.length; i++) {
5
+ const chartEl = charts[i];
6
+ const chartData = JSON.parse(chartEl.dataset.json);
7
+
8
+ const ctx = chartEl.getContext('2d');
9
+ const chart = new Chart(ctx, {
10
+ type: 'line',
11
+ data: {
12
+ labels: chartData.labels,
13
+ datasets: chartData.datasets
14
+ },
15
+ options: {
16
+ animation: animate,
17
+ responsive: true,
18
+ maintainAspectRatio: false,
19
+ scales: {
20
+ y: {
21
+ beginAtZero: true
22
+ }
23
+ }
24
+ }
25
+ });
26
+ }
27
+ }
28
+
29
+ export { renderCharts as default };
@@ -0,0 +1,51 @@
1
+ /*jshint esversion: 6, strict: false */
2
+
3
+ // How to use:
4
+ //<form data-checkbox-toggle="{key}">
5
+ // <input type="checkbox" data-checkbox-toggle-all="{key}" />
6
+ //
7
+ // <input type="checkbox" data-checkbox-toggle-each="{key}" />
8
+ // <input type="checkbox" data-checkbox-toggle-each="{key}" />
9
+ // ...
10
+
11
+ export default function checkboxToggle() {
12
+ document.querySelectorAll("form[data-checkbox-toggle]").forEach(function (form) {
13
+ const keyName = form.dataset.checkboxToggle;
14
+ const checkboxToggle = form.querySelector(`input[type=checkbox][data-checkbox-toggle-all=${keyName}]`);
15
+ const checkboxes = form.querySelectorAll(`input[type=checkbox][data-checkbox-toggle-each=${keyName}]`);
16
+ const showables = form.querySelectorAll(`[data-checkbox-toggle-show=${keyName}]`);
17
+
18
+ // Check or uncheck all checkboxes
19
+ checkboxToggle.addEventListener("change", function (event) {
20
+ checkboxes.forEach(function (checkbox) {
21
+ checkbox.checked = checkboxToggle.checked;
22
+ });
23
+
24
+ showables.forEach(function (showable) {
25
+ showable.classList.toggle("d-none", !checkboxToggle.checked);
26
+ showable.disabled = ! checkboxToggle.checked;
27
+ });
28
+ });
29
+
30
+ // check or uncheck the "all" checkbox when all checkboxes are checked or unchecked
31
+ form.addEventListener("change", function (event) {
32
+ if (!event.target.matches(`input[type=checkbox][data-checkbox-toggle-each=${keyName}]`)) {
33
+ return;
34
+ }
35
+ const checkedCount = Array.from(checkboxes).filter(function (checkbox) {
36
+ return checkbox.checked;
37
+ }).length;
38
+
39
+ const allChecked = checkedCount === checkboxes.length;
40
+ const indeterminateChecked = !allChecked && checkedCount > 0;
41
+
42
+ checkboxToggle.checked = allChecked;
43
+ checkboxToggle.indeterminate = indeterminateChecked;
44
+
45
+ showables.forEach(function (showable) {
46
+ showable.classList.toggle("d-none", !allChecked);
47
+ showable.disabled = !allChecked;
48
+ });
49
+ });
50
+ });
51
+ }
@@ -0,0 +1,7 @@
1
+ export default function documentReady(callback) {
2
+ if (document.readyState !== "loading") {
3
+ callback();
4
+ } else {
5
+ document.addEventListener("DOMContentLoaded", callback);
6
+ }
7
+ }
@@ -0,0 +1,93 @@
1
+ /*jshint esversion: 6, strict: false */
2
+ import renderCharts from "charts";
3
+
4
+ // NOTE: this file is a bit disorganized. Please do not use it as a template for how to organize a JS module.
5
+
6
+ const DEFAULT_POLL_INTERVAL_SECONDS = 30;
7
+ const MINIMUM_POLL_INTERVAL = 1000;
8
+
9
+ function getStorage(key) {
10
+ const value = localStorage.getItem('good_job-' + key);
11
+
12
+ if (value === 'true') {
13
+ return true;
14
+ } else if (value === 'false') {
15
+ return false;
16
+ } else {
17
+ return value;
18
+ }
19
+ }
20
+
21
+ function setStorage(key, value) {
22
+ localStorage.setItem('good_job-' + key, value);
23
+ }
24
+
25
+ function updatePageContent(newContent) {
26
+ const domParser = new DOMParser();
27
+ const parsedDOM = domParser.parseFromString(newContent, "text/html");
28
+
29
+ const newElements = parsedDOM.querySelectorAll('[data-gj-poll-replace]');
30
+
31
+ for (let i = 0; i < newElements.length; i++) {
32
+ const newEl = newElements[i];
33
+ const oldEl = document.getElementById(newEl.id);
34
+
35
+ if (oldEl) {
36
+ oldEl.replaceWith(newEl);
37
+ }
38
+ }
39
+
40
+ renderCharts(false);
41
+ }
42
+
43
+ function refreshPage() {
44
+ fetch(window.location.href)
45
+ .then(resp => resp.text())
46
+ .then(updatePageContent);
47
+ }
48
+
49
+ const Poller = {
50
+ start: () => {
51
+ Poller.updateSettings();
52
+ Poller.pollUpdates();
53
+
54
+ const checkbox = document.querySelector('input[name="toggle-poll"]');
55
+ checkbox.addEventListener('change', Poller.togglePoll)
56
+ },
57
+
58
+ togglePoll: (event) => {
59
+ Poller.pollEnabled = event.currentTarget.checked;
60
+ setStorage('pollEnabled', Poller.pollEnabled);
61
+ },
62
+
63
+ updateSettings: () => {
64
+ const queryString = window.location.search;
65
+ const urlParams = new URLSearchParams(queryString);
66
+
67
+ if (urlParams.has('poll')) {
68
+ const parsedInterval = (parseInt(urlParams.get('poll')) || DEFAULT_POLL_INTERVAL_SECONDS) * 1000;
69
+ Poller.pollInterval = Math.max(parsedInterval, MINIMUM_POLL_INTERVAL);
70
+ setStorage('pollInterval', Poller.pollInterval);
71
+
72
+ Poller.pollEnabled = true;
73
+ } else {
74
+ Poller.pollInterval = getStorage('pollInterval') || (DEFAULT_POLL_INTERVAL_SECONDS * 1000);
75
+ Poller.pollEnabled = getStorage('pollEnabled') || false;
76
+ }
77
+
78
+ document.getElementById('toggle-poll').checked = Poller.pollEnabled;
79
+ },
80
+
81
+ pollUpdates: () => {
82
+ setTimeout(() => {
83
+ if (Poller.pollEnabled === true) {
84
+ refreshPage();
85
+ Poller.pollUpdates();
86
+ } else {
87
+ Poller.pollUpdates();
88
+ }
89
+ }, Poller.pollInterval);
90
+ },
91
+ };
92
+
93
+ export { Poller as default };
@@ -0,0 +1,8 @@
1
+ export default function showToasts() {
2
+ const toasts = document.querySelectorAll('.toast');
3
+
4
+ for (let i = 0; i < toasts.length; i++) {
5
+ var toast = new bootstrap.Toast(toasts[i])
6
+ toast.show()
7
+ }
8
+ }
@@ -0,0 +1,3 @@
1
+ /*jshint esversion: 6, strict: false */
2
+
3
+ import "application"; // ./modules/good_job/application.js
@@ -30,3 +30,7 @@
30
30
  position:relative;
31
31
  left:calc(-1 * (100vw - 100%)/2);
32
32
  }
33
+
34
+ .toast-container {
35
+ z-index: 1;
36
+ }
@@ -0,0 +1 @@
1
+ (function(){const noop=()=>{};const e=document.querySelector("script[type=esms-options]");const t=e?JSON.parse(e.innerHTML):{};Object.assign(t,self.esmsInitOptions||{});let r=!!t.shimMode;const s=globalHook(r&&t.onimport);const a=globalHook(r&&t.resolve);let n=t.fetch?globalHook(t.fetch):fetch;const i=t.meta?globalHook(shimModule&&t.meta):noop;const c=t.skip?new RegExp(t.skip):null;let f=t.nonce;const te=t.mapOverrides;if(!f){const e=document.querySelector("script[nonce]");e&&(f=e.nonce||e.getAttribute("nonce"))}const re=globalHook(t.onerror||noop);const se=t.onpolyfill?globalHook(t.onpolyfill):()=>console.log("%c^^ Module TypeError above is polyfilled and can be ignored ^^","font-weight:900;color:#391");const{revokeBlobURLs:ae,noLoadEventRetriggers:ne,enforceIntegrity:ie}=t;function globalHook(e){return"string"===typeof e?self[e]:e}const oe=Array.isArray(t.polyfillEnable)?t.polyfillEnable:[];const ce=oe.includes("css-modules");const le=oe.includes("json-modules");function setShimMode(){r=true}const fe=!navigator.userAgentData&&!!navigator.userAgent.match(/Edge\/\d+\.\d+/);const ue=document.baseURI;function createBlob(e,t="text/javascript"){return URL.createObjectURL(new Blob([e],{type:t}))}const eoop=e=>setTimeout((()=>{throw e}));const throwError=e=>{(window.reportError||window.safari&&console.error||eoop)(e),void re(e)};function fromParent(e){return e?` imported from ${e}`:""}const de=/\\/g;function isURL(e){if(-1===e.indexOf(":"))return false;try{new URL(e);return true}catch(e){return false}}function resolveUrl(e,t){return resolveIfNotPlainOrUrl(e,t)||(isURL(e)?e:resolveIfNotPlainOrUrl("./"+e,t))}function resolveIfNotPlainOrUrl(e,t){const r=t.indexOf("?",-1===t.indexOf("#")?t.indexOf("#"):t.length);-1!==r&&(t=t.slice(0,r));-1!==e.indexOf("\\")&&(e=e.replace(de,"/"));if("/"===e[0]&&"/"===e[1])return t.slice(0,t.indexOf(":")+1)+e;if("."===e[0]&&("/"===e[1]||"."===e[1]&&("/"===e[2]||2===e.length&&(e+="/"))||1===e.length&&(e+="/"))||"/"===e[0]){const r=t.slice(0,t.indexOf(":")+1);let s;if("/"===t[r.length+1])if("file:"!==r){s=t.slice(r.length+2);s=s.slice(s.indexOf("/")+1)}else s=t.slice(8);else s=t.slice(r.length+("/"===t[r.length]));if("/"===e[0])return t.slice(0,t.length-s.length-1)+e;const a=s.slice(0,s.lastIndexOf("/")+1)+e;const n=[];let i=-1;for(let e=0;e<a.length;e++)if(-1===i){if("."===a[e]){if("."===a[e+1]&&("/"===a[e+2]||e+2===a.length)){n.pop();e+=2;continue}if("/"===a[e+1]||e+1===a.length){e+=1;continue}}while("/"===a[e])e++;i=e}else if("/"===a[e]){n.push(a.slice(i,e+1));i=-1}-1!==i&&n.push(a.slice(i));return t.slice(0,t.length-s.length)+n.join("")}}function resolveAndComposeImportMap(e,t,r){const s={imports:Object.assign({},r.imports),scopes:Object.assign({},r.scopes)};e.imports&&resolveAndComposePackages(e.imports,s.imports,t,r);if(e.scopes)for(let a in e.scopes){const n=resolveUrl(a,t);resolveAndComposePackages(e.scopes[a],s.scopes[n]||(s.scopes[n]={}),t,r)}return s}function getMatch(e,t){if(t[e])return e;let r=e.length;do{const s=e.slice(0,r+1);if(s in t)return s}while(-1!==(r=e.lastIndexOf("/",r-1)))}function applyPackages(e,t){const r=getMatch(e,t);if(r){const s=t[r];if(null===s)return;return s+e.slice(r.length)}}function resolveImportMap(e,t,r){let s=r&&getMatch(r,e.scopes);while(s){const r=applyPackages(t,e.scopes[s]);if(r)return r;s=getMatch(s.slice(0,s.lastIndexOf("/")),e.scopes)}return applyPackages(t,e.imports)||-1!==t.indexOf(":")&&t}function resolveAndComposePackages(e,t,s,a){for(let n in e){const i=resolveIfNotPlainOrUrl(n,s)||n;if((!r||!te)&&t[i]&&t[i]!==e[i])throw Error(`Rejected map override "${i}" from ${t[i]} to ${e[i]}.`);let c=e[n];if("string"!==typeof c)continue;const f=resolveImportMap(a,resolveIfNotPlainOrUrl(c,s)||c,s);f?t[i]=f:console.warn(`Mapping "${n}" -> "${e[n]}" does not resolve`)}}let pe;window.addEventListener("error",(e=>pe=e));function dynamicImportScript(e,{errUrl:t=e}={}){pe=void 0;const r=createBlob(`import*as m from'${e}';self._esmsi=m`);const s=Object.assign(document.createElement("script"),{type:"module",src:r});s.setAttribute("nonce",f);s.setAttribute("noshim","");const a=new Promise(((e,a)=>{s.addEventListener("error",cb);s.addEventListener("load",cb);function cb(n){document.head.removeChild(s);if(self._esmsi){e(self._esmsi,ue);self._esmsi=void 0}else{a(!(n instanceof Event)&&n||pe&&pe.error||new Error(`Error loading or executing the graph of ${t} (check the console for ${r}).`));pe=void 0}}}));document.head.appendChild(s);return a}let be=dynamicImportScript;const he=dynamicImportScript(createBlob("export default u=>import(u)")).then((e=>{e&&(be=e.default);return!!e}),noop);let ke=false;let me=false;let we=false;let ge=false;let ve=false;const ye=Promise.resolve(he).then((e=>{if(e){ve=true;return Promise.all([be(createBlob("import.meta")).then((()=>we=true),noop),ce&&be(createBlob('import"data:text/css,{}"assert{type:"css"}')).then((()=>me=true),noop),le&&be(createBlob('import"data:text/json,{}"assert{type:"json"}')).then((()=>ke=true),noop),new Promise((e=>{self._$s=r=>{document.head.removeChild(t);r&&(ge=true);delete self._$s;e()};const t=document.createElement("iframe");t.style.display="none";t.srcdoc=`<script type=importmap nonce="${f}">{"imports":{"x":"data:text/javascript,"}}<\/script><script nonce="${f}">import('x').then(()=>1,()=>0).then(v=>parent._$s(v))<\/script>`;document.head.appendChild(t)}))])}}));let Se,$e,Le,Oe=2<<19;const Ce=1===new Uint8Array(new Uint16Array([1]).buffer)[0]?function(e,t){const r=e.length;let s=0;for(;s<r;)t[s]=e.charCodeAt(s++)}:function(e,t){const r=e.length;let s=0;for(;s<r;){const r=e.charCodeAt(s);t[s++]=(255&r)<<8|r>>>8}},Ae="xportmportlassetafromssertvoyiedeleinstantyreturdebuggeawaithrwhileforifcatcfinallels";let Ue,Ie,Me;function parse(e,t="@"){Ue=e,Ie=t;const r=2*Ue.length+(2<<18);if(r>Oe||!Se){for(;r>Oe;)Oe*=2;$e=new ArrayBuffer(Oe),Ce(Ae,new Uint16Array($e,16,85)),Se=function(e,t,r){"use asm";var s=new e.Int8Array(r),a=new e.Int16Array(r),n=new e.Int32Array(r),i=new e.Uint8Array(r),c=new e.Uint16Array(r),f=992;function b(e){e=e|0;var t=0,r=0,i=0,te=0,re=0,se=0,ae=0;ae=f;f=f+11520|0;re=ae+2048|0;s[763]=1;a[377]=0;a[378]=0;a[379]=0;a[380]=-1;n[57]=n[2];s[764]=0;n[56]=0;s[762]=0;n[58]=ae+10496;n[59]=ae+2304;n[60]=ae;s[765]=0;e=(n[3]|0)+-2|0;n[61]=e;t=e+(n[54]<<1)|0;n[62]=t;e:while(1){r=e+2|0;n[61]=r;if(e>>>0>=t>>>0){te=18;break}t:do{switch(a[r>>1]|0){case 9:case 10:case 11:case 12:case 13:case 32:break;case 101:{if((((a[379]|0)==0?D(r)|0:0)?(m(e+4|0,16,10)|0)==0:0)?(k(),(s[763]|0)==0):0){te=9;break e}else te=17;break}case 105:{if(D(r)|0?(m(e+4|0,26,10)|0)==0:0){l();te=17}else te=17;break}case 59:{te=17;break}case 47:switch(a[e+4>>1]|0){case 47:{j();break t}case 42:{y(1);break t}default:{te=16;break e}}default:{te=16;break e}}}while(0);if((te|0)==17){te=0;n[57]=n[61]}e=n[61]|0;t=n[62]|0}if((te|0)==9){e=n[61]|0;n[57]=e;te=19}else if((te|0)==16){s[763]=0;n[61]=e;te=19}else if((te|0)==18)if(!(s[762]|0)){e=r;te=19}else e=0;do{if((te|0)==19){e:while(1){t=e+2|0;n[61]=t;i=t;if(e>>>0>=(n[62]|0)>>>0){te=75;break}t:do{switch(a[t>>1]|0){case 9:case 10:case 11:case 12:case 13:case 32:break;case 101:{if(((a[379]|0)==0?D(t)|0:0)?(m(e+4|0,16,10)|0)==0:0){k();te=74}else te=74;break}case 105:{if(D(t)|0?(m(e+4|0,26,10)|0)==0:0){l();te=74}else te=74;break}case 99:{if((D(t)|0?(m(e+4|0,36,8)|0)==0:0)?M(a[e+12>>1]|0)|0:0){s[765]=1;te=74}else te=74;break}case 40:{r=n[57]|0;i=n[59]|0;te=a[379]|0;a[379]=te+1<<16>>16;n[i+((te&65535)<<2)>>2]=r;te=74;break}case 41:{t=a[379]|0;if(!(t<<16>>16)){te=36;break e}t=t+-1<<16>>16;a[379]=t;r=a[378]|0;if(r<<16>>16!=0?(se=n[(n[60]|0)+((r&65535)+-1<<2)>>2]|0,(n[se+20>>2]|0)==(n[(n[59]|0)+((t&65535)<<2)>>2]|0)):0){t=se+4|0;if(!(n[t>>2]|0))n[t>>2]=i;n[se+12>>2]=e+4;a[378]=r+-1<<16>>16;te=74}else te=74;break}case 123:{te=n[57]|0;i=n[51]|0;e=te;do{if((a[te>>1]|0)==41&(i|0)!=0?(n[i+4>>2]|0)==(te|0):0){t=n[52]|0;n[51]=t;if(!t){n[47]=0;break}else{n[t+28>>2]=0;break}}}while(0);r=a[379]|0;te=r&65535;s[re+te>>0]=s[765]|0;s[765]=0;i=n[59]|0;a[379]=r+1<<16>>16;n[i+(te<<2)>>2]=e;te=74;break}case 125:{e=a[379]|0;if(!(e<<16>>16)){te=49;break e}r=e+-1<<16>>16;a[379]=r;t=a[380]|0;if(e<<16>>16!=t<<16>>16)if(t<<16>>16!=-1&(r&65535)<(t&65535)){te=53;break e}else{te=74;break t}else{i=n[58]|0;te=(a[377]|0)+-1<<16>>16;a[377]=te;a[380]=a[i+((te&65535)<<1)>>1]|0;h();te=74;break t}}case 39:{d(39);te=74;break}case 34:{d(34);te=74;break}case 47:switch(a[e+4>>1]|0){case 47:{j();break t}case 42:{y(1);break t}default:{t=n[57]|0;r=a[t>>1]|0;r:do{if(!(U(r)|0)){switch(r<<16>>16){case 41:if(q(n[(n[59]|0)+(c[379]<<2)>>2]|0)|0){te=71;break r}else{te=68;break r}case 125:break;default:{te=68;break r}}e=c[379]|0;if(!(p(n[(n[59]|0)+(e<<2)>>2]|0)|0)?(s[re+e>>0]|0)==0:0)te=68;else te=71}else switch(r<<16>>16){case 46:if(((a[t+-2>>1]|0)+-48&65535)<10){te=68;break r}else{te=71;break r}case 43:if((a[t+-2>>1]|0)==43){te=68;break r}else{te=71;break r}case 45:if((a[t+-2>>1]|0)==45){te=68;break r}else{te=71;break r}default:{te=71;break r}}}while(0);r:do{if((te|0)==68){te=0;if(!(o(t)|0)){switch(r<<16>>16){case 0:{te=71;break r}case 47:break;default:{e=1;break r}}if(!(s[764]|0))e=1;else te=71}else te=71}}while(0);if((te|0)==71){g();e=0}s[764]=e;te=74;break t}}case 96:{h();te=74;break}default:te=74}}while(0);if((te|0)==74){te=0;n[57]=n[61]}e=n[61]|0}if((te|0)==36){L();e=0;break}else if((te|0)==49){L();e=0;break}else if((te|0)==53){L();e=0;break}else if((te|0)==75){e=(a[380]|0)==-1&(a[379]|0)==0&(s[762]|0)==0&(a[378]|0)==0;break}}}while(0);f=ae;return e|0}function k(){var e=0,t=0,r=0,i=0,c=0,f=0;c=n[61]|0;f=c+12|0;n[61]=f;t=w(1)|0;e=n[61]|0;if(!((e|0)==(f|0)?!(I(t)|0):0))i=3;e:do{if((i|0)==3){t:do{switch(t<<16>>16){case 100:{B(e,e+14|0);break e}case 97:{n[61]=e+10;w(1)|0;e=n[61]|0;i=6;break}case 102:{i=6;break}case 99:{if((m(e+2|0,36,8)|0)==0?(r=e+10|0,$(a[r>>1]|0)|0):0){n[61]=r;c=w(1)|0;f=n[61]|0;E(c)|0;B(f,n[61]|0);n[61]=(n[61]|0)+-2;break e}e=e+4|0;n[61]=e;i=13;break}case 108:case 118:{i=13;break}case 123:{n[61]=e+2;e=w(1)|0;r=n[61]|0;while(1){if(N(e)|0){d(e);e=(n[61]|0)+2|0;n[61]=e}else{E(e)|0;e=n[61]|0}w(1)|0;e=C(r,e)|0;if(e<<16>>16==44){n[61]=(n[61]|0)+2;e=w(1)|0}t=r;r=n[61]|0;if(e<<16>>16==125){i=32;break}if((r|0)==(t|0)){i=29;break}if(r>>>0>(n[62]|0)>>>0){i=31;break}}if((i|0)==29){L();break e}else if((i|0)==31){L();break e}else if((i|0)==32){n[61]=r+2;i=34;break t}break}case 42:{n[61]=e+2;w(1)|0;i=n[61]|0;C(i,i)|0;i=34;break}default:{}}}while(0);if((i|0)==6){n[61]=e+16;e=w(1)|0;if(e<<16>>16==42){n[61]=(n[61]|0)+2;e=w(1)|0}f=n[61]|0;E(e)|0;B(f,n[61]|0);n[61]=(n[61]|0)+-2;break}else if((i|0)==13){e=e+4|0;n[61]=e;s[763]=0;t:while(1){n[61]=e+2;f=w(1)|0;e=n[61]|0;switch((E(f)|0)<<16>>16){case 91:case 123:{i=15;break t}default:{}}t=n[61]|0;if((t|0)==(e|0))break e;B(e,t);switch((w(1)|0)<<16>>16){case 61:{i=19;break t}case 44:break;default:{i=20;break t}}e=n[61]|0}if((i|0)==15){n[61]=(n[61]|0)+-2;break}else if((i|0)==19){n[61]=(n[61]|0)+-2;break}else if((i|0)==20){n[61]=(n[61]|0)+-2;break}}else if((i|0)==34)t=w(1)|0;e=n[61]|0;if(t<<16>>16==102?(m(e+2|0,52,6)|0)==0:0){n[61]=e+8;u(c,w(1)|0);break}n[61]=e+-2}}while(0);return}function l(){var e=0,t=0,r=0,i=0,c=0;c=n[61]|0;t=c+12|0;n[61]=t;e:do{switch((w(1)|0)<<16>>16){case 40:{e=n[61]|0;t=n[59]|0;r=a[379]|0;a[379]=r+1<<16>>16;n[t+((r&65535)<<2)>>2]=e;if((a[n[57]>>1]|0)!=46){e=n[61]|0;n[61]=e+2;r=w(1)|0;v(c,n[61]|0,0,e);e=n[51]|0;t=n[60]|0;c=a[378]|0;a[378]=c+1<<16>>16;n[t+((c&65535)<<2)>>2]=e;switch(r<<16>>16){case 39:{d(39);break}case 34:{d(34);break}default:{n[61]=(n[61]|0)+-2;break e}}e=(n[61]|0)+2|0;n[61]=e;switch((w(1)|0)<<16>>16){case 44:{n[61]=(n[61]|0)+2;w(1)|0;r=n[51]|0;n[r+4>>2]=e;c=n[61]|0;n[r+16>>2]=c;s[r+24>>0]=1;n[61]=c+-2;break e}case 41:{a[379]=(a[379]|0)+-1<<16>>16;c=n[51]|0;n[c+4>>2]=e;n[c+12>>2]=(n[61]|0)+2;s[c+24>>0]=1;a[378]=(a[378]|0)+-1<<16>>16;break e}default:{n[61]=(n[61]|0)+-2;break e}}}break}case 46:{n[61]=(n[61]|0)+2;if(((w(1)|0)<<16>>16==109?(e=n[61]|0,(m(e+2|0,44,6)|0)==0):0)?(a[n[57]>>1]|0)!=46:0)v(c,c,e+8|0,2);break}case 42:case 39:case 34:{i=16;break}case 123:{e=n[61]|0;if(a[379]|0){n[61]=e+-2;break e}while(1){if(e>>>0>=(n[62]|0)>>>0)break;e=w(1)|0;if(!(N(e)|0)){if(e<<16>>16==125){i=31;break}}else d(e);e=(n[61]|0)+2|0;n[61]=e}if((i|0)==31)n[61]=(n[61]|0)+2;w(1)|0;e=n[61]|0;if(m(e,50,8)|0){L();break e}n[61]=e+8;e=w(1)|0;if(N(e)|0){u(c,e);break e}else{L();break e}}default:if((n[61]|0)!=(t|0))i=16}}while(0);do{if((i|0)==16){if(a[379]|0){n[61]=(n[61]|0)+-2;break}e=n[62]|0;t=n[61]|0;while(1){if(t>>>0>=e>>>0){i=23;break}r=a[t>>1]|0;if(N(r)|0){i=21;break}i=t+2|0;n[61]=i;t=i}if((i|0)==21){u(c,r);break}else if((i|0)==23){L();break}}}while(0);return}function u(e,t){e=e|0;t=t|0;var r=0,s=0;r=(n[61]|0)+2|0;switch(t<<16>>16){case 39:{d(39);s=5;break}case 34:{d(34);s=5;break}default:L()}do{if((s|0)==5){v(e,r,n[61]|0,1);n[61]=(n[61]|0)+2;s=(w(0)|0)<<16>>16==97;t=n[61]|0;if(s?(m(t+2|0,58,10)|0)==0:0){n[61]=t+12;if((w(1)|0)<<16>>16!=123){n[61]=t;break}e=n[61]|0;r=e;e:while(1){n[61]=r+2;r=w(1)|0;switch(r<<16>>16){case 39:{d(39);n[61]=(n[61]|0)+2;r=w(1)|0;break}case 34:{d(34);n[61]=(n[61]|0)+2;r=w(1)|0;break}default:r=E(r)|0}if(r<<16>>16!=58){s=16;break}n[61]=(n[61]|0)+2;switch((w(1)|0)<<16>>16){case 39:{d(39);break}case 34:{d(34);break}default:{s=20;break e}}n[61]=(n[61]|0)+2;switch((w(1)|0)<<16>>16){case 125:{s=25;break e}case 44:break;default:{s=24;break e}}n[61]=(n[61]|0)+2;if((w(1)|0)<<16>>16==125){s=25;break}r=n[61]|0}if((s|0)==16){n[61]=t;break}else if((s|0)==20){n[61]=t;break}else if((s|0)==24){n[61]=t;break}else if((s|0)==25){s=n[51]|0;n[s+16>>2]=e;n[s+12>>2]=(n[61]|0)+2;break}}n[61]=t+-2}}while(0);return}function o(e){e=e|0;e:do{switch(a[e>>1]|0){case 100:switch(a[e+-2>>1]|0){case 105:{e=S(e+-4|0,68,2)|0;break e}case 108:{e=S(e+-4|0,72,3)|0;break e}default:{e=0;break e}}case 101:{switch(a[e+-2>>1]|0){case 115:break;case 116:{e=S(e+-4|0,78,4)|0;break e}default:{e=0;break e}}switch(a[e+-4>>1]|0){case 108:{e=O(e+-6|0,101)|0;break e}case 97:{e=O(e+-6|0,99)|0;break e}default:{e=0;break e}}}case 102:{if((a[e+-2>>1]|0)==111?(a[e+-4>>1]|0)==101:0)switch(a[e+-6>>1]|0){case 99:{e=S(e+-8|0,86,6)|0;break e}case 112:{e=S(e+-8|0,98,2)|0;break e}default:{e=0;break e}}else e=0;break}case 110:{e=e+-2|0;if(O(e,105)|0)e=1;else e=S(e,102,5)|0;break}case 111:{e=O(e+-2|0,100)|0;break}case 114:{e=S(e+-2|0,112,7)|0;break}case 116:{e=S(e+-2|0,126,4)|0;break}case 119:switch(a[e+-2>>1]|0){case 101:{e=O(e+-4|0,110)|0;break e}case 111:{e=S(e+-4|0,134,3)|0;break e}default:{e=0;break e}}default:e=0}}while(0);return e|0}function h(){var e=0,t=0,r=0;t=n[62]|0;r=n[61]|0;e:while(1){e=r+2|0;if(r>>>0>=t>>>0){t=8;break}switch(a[e>>1]|0){case 96:{t=9;break e}case 36:{if((a[r+4>>1]|0)==123){t=6;break e}break}case 92:{e=r+4|0;break}default:{}}r=e}if((t|0)==6){n[61]=r+4;e=a[380]|0;t=n[58]|0;r=a[377]|0;a[377]=r+1<<16>>16;a[t+((r&65535)<<1)>>1]=e;r=(a[379]|0)+1<<16>>16;a[379]=r;a[380]=r}else if((t|0)==8){n[61]=e;L()}else if((t|0)==9)n[61]=e;return}function w(e){e=e|0;var t=0,r=0,s=0;r=n[61]|0;e:do{t=a[r>>1]|0;t:do{if(t<<16>>16!=47)if(e)if(M(t)|0)break;else break e;else if(z(t)|0)break;else break e;else switch(a[r+2>>1]|0){case 47:{j();break t}case 42:{y(e);break t}default:{t=47;break e}}}while(0);s=n[61]|0;r=s+2|0;n[61]=r}while(s>>>0<(n[62]|0)>>>0);return t|0}function d(e){e=e|0;var t=0,r=0,s=0,i=0;i=n[62]|0;t=n[61]|0;while(1){s=t+2|0;if(t>>>0>=i>>>0){t=9;break}r=a[s>>1]|0;if(r<<16>>16==e<<16>>16){t=10;break}if(r<<16>>16==92){r=t+4|0;if((a[r>>1]|0)==13){t=t+6|0;t=(a[t>>1]|0)==10?t:r}else t=r}else if(T(r)|0){t=9;break}else t=s}if((t|0)==9){n[61]=s;L()}else if((t|0)==10)n[61]=s;return}function v(e,t,r,a){e=e|0;t=t|0;r=r|0;a=a|0;var i=0,c=0;i=n[55]|0;n[55]=i+32;c=n[51]|0;n[((c|0)==0?188:c+28|0)>>2]=i;n[52]=c;n[51]=i;n[i+8>>2]=e;if(2==(a|0))e=r;else e=1==(a|0)?r+2|0:0;n[i+12>>2]=e;n[i>>2]=t;n[i+4>>2]=r;n[i+16>>2]=0;n[i+20>>2]=a;s[i+24>>0]=1==(a|0)&1;n[i+28>>2]=0;return}function A(){var e=0,t=0,r=0;r=n[62]|0;t=n[61]|0;e:while(1){e=t+2|0;if(t>>>0>=r>>>0){t=6;break}switch(a[e>>1]|0){case 13:case 10:{t=6;break e}case 93:{t=7;break e}case 92:{e=t+4|0;break}default:{}}t=e}if((t|0)==6){n[61]=e;L();e=0}else if((t|0)==7){n[61]=e;e=93}return e|0}function C(e,t){e=e|0;t=t|0;var r=0,s=0;r=n[61]|0;s=a[r>>1]|0;if(s<<16>>16==97){n[61]=r+4;r=w(1)|0;e=n[61]|0;if(N(r)|0){d(r);t=(n[61]|0)+2|0;n[61]=t}else{E(r)|0;t=n[61]|0}s=w(1)|0;r=n[61]|0}if((r|0)!=(e|0))B(e,t);return s|0}function g(){var e=0,t=0,r=0;e:while(1){e=n[61]|0;t=e+2|0;n[61]=t;if(e>>>0>=(n[62]|0)>>>0){r=7;break}switch(a[t>>1]|0){case 13:case 10:{r=7;break e}case 47:break e;case 91:{A()|0;break}case 92:{n[61]=e+4;break}default:{}}}if((r|0)==7)L();return}function p(e){e=e|0;switch(a[e>>1]|0){case 62:{e=(a[e+-2>>1]|0)==61;break}case 41:case 59:{e=1;break}case 104:{e=S(e+-2|0,160,4)|0;break}case 121:{e=S(e+-2|0,168,6)|0;break}case 101:{e=S(e+-2|0,180,3)|0;break}default:e=0}return e|0}function y(e){e=e|0;var t=0,r=0,s=0,i=0,c=0;i=(n[61]|0)+2|0;n[61]=i;r=n[62]|0;while(1){t=i+2|0;if(i>>>0>=r>>>0)break;s=a[t>>1]|0;if(!e?T(s)|0:0)break;if(s<<16>>16==42?(a[i+4>>1]|0)==47:0){c=8;break}i=t}if((c|0)==8){n[61]=t;t=i+4|0}n[61]=t;return}function m(e,t,r){e=e|0;t=t|0;r=r|0;var a=0,n=0;e:do{if(!r)e=0;else{while(1){a=s[e>>0]|0;n=s[t>>0]|0;if(a<<24>>24!=n<<24>>24)break;r=r+-1|0;if(!r){e=0;break e}else{e=e+1|0;t=t+1|0}}e=(a&255)-(n&255)|0}}while(0);return e|0}function I(e){e=e|0;e:do{switch(e<<16>>16){case 38:case 37:case 33:{e=1;break}default:if((e&-8)<<16>>16==40|(e+-58&65535)<6)e=1;else{switch(e<<16>>16){case 91:case 93:case 94:{e=1;break e}default:{}}e=(e+-123&65535)<4}}}while(0);return e|0}function U(e){e=e|0;e:do{switch(e<<16>>16){case 38:case 37:case 33:break;default:if(!((e+-58&65535)<6|(e+-40&65535)<7&e<<16>>16!=41)){switch(e<<16>>16){case 91:case 94:break e;default:{}}return e<<16>>16!=125&(e+-123&65535)<4|0}}}while(0);return 1}function x(e){e=e|0;var t=0,r=0,s=0,i=0;r=f;f=f+16|0;s=r;n[s>>2]=0;n[54]=e;t=n[3]|0;i=t+(e<<1)|0;e=i+2|0;a[i>>1]=0;n[s>>2]=e;n[55]=e;n[47]=0;n[51]=0;n[49]=0;n[48]=0;n[53]=0;n[50]=0;f=r;return t|0}function S(e,t,r){e=e|0;t=t|0;r=r|0;var s=0,i=0;s=e+(0-r<<1)|0;i=s+2|0;e=n[3]|0;if(i>>>0>=e>>>0?(m(i,t,r<<1)|0)==0:0)if((i|0)==(e|0))e=1;else e=$(a[s>>1]|0)|0;else e=0;return e|0}function O(e,t){e=e|0;t=t|0;var r=0;r=n[3]|0;if(r>>>0<=e>>>0?(a[e>>1]|0)==t<<16>>16:0)if((r|0)==(e|0))r=1;else r=$(a[e+-2>>1]|0)|0;else r=0;return r|0}function $(e){e=e|0;e:do{if((e+-9&65535)<5)e=1;else{switch(e<<16>>16){case 32:case 160:{e=1;break e}default:{}}e=e<<16>>16!=46&(I(e)|0)}}while(0);return e|0}function j(){var e=0,t=0,r=0;e=n[62]|0;r=n[61]|0;e:while(1){t=r+2|0;if(r>>>0>=e>>>0)break;switch(a[t>>1]|0){case 13:case 10:break e;default:r=t}}n[61]=t;return}function B(e,t){e=e|0;t=t|0;var r=0,s=0;r=n[55]|0;n[55]=r+12;s=n[53]|0;n[((s|0)==0?192:s+8|0)>>2]=r;n[53]=r;n[r>>2]=e;n[r+4>>2]=t;n[r+8>>2]=0;return}function E(e){e=e|0;while(1){if(M(e)|0)break;if(I(e)|0)break;e=(n[61]|0)+2|0;n[61]=e;e=a[e>>1]|0;if(!(e<<16>>16)){e=0;break}}return e|0}function P(){var e=0;e=n[(n[49]|0)+20>>2]|0;switch(e|0){case 1:{e=-1;break}case 2:{e=-2;break}default:e=e-(n[3]|0)>>1}return e|0}function q(e){e=e|0;if(!(S(e,140,5)|0)?!(S(e,150,3)|0):0)e=S(e,156,2)|0;else e=1;return e|0}function z(e){e=e|0;switch(e<<16>>16){case 160:case 32:case 12:case 11:case 9:{e=1;break}default:e=0}return e|0}function D(e){e=e|0;if((n[3]|0)==(e|0))e=1;else e=$(a[e+-2>>1]|0)|0;return e|0}function F(){var e=0;e=n[(n[49]|0)+12>>2]|0;if(!e)e=-1;else e=e-(n[3]|0)>>1;return e|0}function G(){var e=0;e=n[(n[49]|0)+16>>2]|0;if(!e)e=-1;else e=e-(n[3]|0)>>1;return e|0}function H(){var e=0;e=n[(n[49]|0)+4>>2]|0;if(!e)e=-1;else e=e-(n[3]|0)>>1;return e|0}function J(){var e=0;e=n[49]|0;e=n[((e|0)==0?188:e+28|0)>>2]|0;n[49]=e;return(e|0)!=0|0}function K(){var e=0;e=n[50]|0;e=n[((e|0)==0?192:e+8|0)>>2]|0;n[50]=e;return(e|0)!=0|0}function L(){s[762]=1;n[56]=(n[61]|0)-(n[3]|0)>>1;n[61]=(n[62]|0)+2;return}function M(e){e=e|0;return(e|128)<<16>>16==160|(e+-9&65535)<5|0}function N(e){e=e|0;return e<<16>>16==39|e<<16>>16==34|0}function Q(){return(n[(n[49]|0)+8>>2]|0)-(n[3]|0)>>1|0}function R(){return(n[(n[50]|0)+4>>2]|0)-(n[3]|0)>>1|0}function T(e){e=e|0;return e<<16>>16==13|e<<16>>16==10|0}function V(){return(n[n[49]>>2]|0)-(n[3]|0)>>1|0}function W(){return(n[n[50]>>2]|0)-(n[3]|0)>>1|0}function X(){return i[(n[49]|0)+24>>0]|0|0}function Y(e){e=e|0;n[3]=e;return}function Z(){return(s[763]|0)!=0|0}function _(){return n[56]|0}function ee(e){e=e|0;f=e+992+15&-16;return 992}return{su:ee,ai:G,e:_,ee:R,es:W,f:Z,id:P,ie:H,ip:X,is:V,p:b,re:K,ri:J,sa:x,se:F,ses:Y,ss:Q}}("undefined"!=typeof self?self:global,{},$e),Le=Se.su(Oe-(2<<17))}const s=Ue.length+1;Se.ses(Le),Se.sa(s-1),Ce(Ue,new Uint16Array($e,Le,s)),Se.p()||(Me=Se.e(),o());const a=[],n=[];for(;Se.ri();){const e=Se.is(),t=Se.ie(),r=Se.ai(),s=Se.id(),n=Se.ss(),i=Se.se();let c;Se.ip()&&(c=b(-1===s?e:e+1,Ue.charCodeAt(-1===s?e-1:e))),a.push({n:c,s:e,e:t,ss:n,se:i,d:s,a:r})}for(;Se.re();){const e=Se.es(),t=Ue.charCodeAt(e);n.push(34===t||39===t?b(e+1,t):Ue.slice(Se.es(),Se.ee()))}return[a,n,!!Se.f()]}function b(e,t){Me=e;let r="",s=Me;for(;;){Me>=Ue.length&&o();const e=Ue.charCodeAt(Me);if(e===t)break;92===e?(r+=Ue.slice(s,Me),r+=k(),s=Me):(8232===e||8233===e||u(e)&&o(),++Me)}return r+=Ue.slice(s,Me++),r}function k(){let e=Ue.charCodeAt(++Me);switch(++Me,e){case 110:return"\n";case 114:return"\r";case 120:return String.fromCharCode(l(2));case 117:return function(){let e;123===Ue.charCodeAt(Me)?(++Me,e=l(Ue.indexOf("}",Me)-Me),++Me,e>1114111&&o()):e=l(4);return e<=65535?String.fromCharCode(e):(e-=65536,String.fromCharCode(55296+(e>>10),56320+(1023&e)))}();case 116:return"\t";case 98:return"\b";case 118:return"\v";case 102:return"\f";case 13:10===Ue.charCodeAt(Me)&&++Me;case 10:return"";case 56:case 57:o();default:if(e>=48&&e<=55){let t=Ue.substr(Me-1,3).match(/^[0-7]+/)[0],r=parseInt(t,8);return r>255&&(t=t.slice(0,-1),r=parseInt(t,8)),Me+=t.length-1,e=Ue.charCodeAt(Me),"0"===t&&56!==e&&57!==e||o(),String.fromCharCode(r)}return u(e)?"":String.fromCharCode(e)}}function l(e){const t=Me;let r=0,s=0;for(let t=0;t<e;++t,++Me){let e,a=Ue.charCodeAt(Me);if(95!==a){if(a>=97)e=a-97+10;else if(a>=65)e=a-65+10;else{if(!(a>=48&&a<=57))break;e=a-48}if(e>=16)break;s=a,r=16*r+e}else 95!==s&&0!==t||o(),s=a}return 95!==s&&Me-t===e||o(),r}function u(e){return 13===e||10===e}function o(){throw Object.assign(Error(`Parse error ${Ie}:${Ue.slice(0,Me).split("\n").length}:${Me-Ue.lastIndexOf("\n",Me-1)}`),{idx:Me})}async function _resolve(e,t){const r=resolveIfNotPlainOrUrl(e,t);return{r:resolveImportMap(Ee,r||e,t)||throwUnresolved(e,t),b:!r&&!isURL(e)}}const Pe=a?async(e,t)=>{let r=a(e,t,defaultResolve);r&&r.then&&(r=await r);return r?{r:r,b:!resolveIfNotPlainOrUrl(e,t)&&!isURL(e)}:_resolve(e,t)}:_resolve;async function importShim(e,...t){let a=t[t.length-1];"string"!==typeof a&&(a=ue);await Ne;s&&await s(e,"string"!==typeof t[1]?t[1]:{},a);if(Te||r||!Re){processImportMaps();r||(Te=false)}await _e;return topLevelLoad((await Pe(e,a)).r,{credentials:"same-origin"})}self.importShim=importShim;function defaultResolve(e,t){return resolveImportMap(Ee,resolveIfNotPlainOrUrl(e,t)||e,t)||throwUnresolved(e,t)}function throwUnresolved(e,t){throw Error(`Unable to resolve specifier '${e}'${fromParent(t)}`)}const resolveSync=(e,t=ue)=>{t=`${t}`;const r=a&&a(e,t,defaultResolve);return r&&!r.then?r:defaultResolve(e,t)};function metaResolve(e,t=this.url){return resolveSync(e,t)}importShim.resolve=resolveSync;importShim.getImportMap=()=>JSON.parse(JSON.stringify(Ee));const xe=importShim._r={};async function loadAll(e,t){if(!e.b&&!t[e.u]){t[e.u]=1;await e.L;await Promise.all(e.d.map((e=>loadAll(e,t))));e.n||(e.n=e.d.some((e=>e.n)))}}let Ee={imports:{},scopes:{}};let je=false;let Re;const Ne=ye.then((()=>{if(!r)if(document.querySelectorAll("script[type=module-shim],script[type=importmap-shim],link[rel=modulepreload-shim]").length)setShimMode();else{let e=false;for(const t of document.querySelectorAll("script[type=module],script[type=importmap]"))if(e){if("importmap"===t.type){je=true;break}}else"module"===t.type&&(e=true)}Re=true!==t.polyfillEnable&&ve&&we&&ge&&(!le||ke)&&(!ce||me)&&!je&&true;if(!r&&Re);else{new MutationObserver((e=>{for(const t of e)if("childList"===t.type)for(const e of t.addedNodes)if("SCRIPT"===e.tagName){e.type===(r?"module-shim":"module")&&processScript(e);e.type===(r?"importmap-shim":"importmap")&&processImportMap(e)}else"LINK"===e.tagName&&e.rel===(r?"modulepreload-shim":"modulepreload")&&processPreload(e)})).observe(document,{childList:true,subtree:true});processImportMaps();processScriptsAndPreloads()}}));let _e=Ne;let Be=true;let Te=true;async function topLevelLoad(e,t,a,n,i){r||(Te=false);await _e;s&&await s(id,"string"!==typeof args[1]?args[1]:{},parentUrl);if(!r&&Re){if(n)return null;await i;return be(a?createBlob(a):e,{errUrl:e||a})}const c=getOrCreateLoad(e,t,null,a);const f={};await loadAll(c,f);Fe=void 0;resolveDeps(c,f);await i;if(a&&!r&&!c.n&&true){const e=await be(createBlob(a),{errUrl:a});ae&&revokeObjectURLs(Object.keys(f));return e}if(Be&&!r&&c.n&&n){se();Be=false}const te=await be(r||c.n||!n?c.b:c.u,{errUrl:c.u});c.s&&(await be(c.s)).u$_(te);ae&&revokeObjectURLs(Object.keys(f));return te}function revokeObjectURLs(e){let t=0;const r=e.length;const s=self.requestIdleCallback?self.requestIdleCallback:self.requestAnimationFrame;s(cleanup);function cleanup(){const a=100*t;if(!(a>r)){for(const t of e.slice(a,a+100)){const e=xe[t];e&&URL.revokeObjectURL(e.b)}t++;s(cleanup)}}}function urlJsString(e){return`'${e.replace(/'/g,"\\'")}'`}let Fe;function resolveDeps(e,t){if(e.b||!t[e.u])return;t[e.u]=0;for(const c of e.d)resolveDeps(c,t);const[r]=e.a;const s=e.S;let a=fe&&Fe?`import '${Fe}';`:"";if(r.length){let f=0,te=0,re=[];function pushStringTo(t){while(re[re.length-1]<t){const t=re.pop();a+=`${s.slice(f,t)}, ${urlJsString(e.r)}`;f=t}a+=s.slice(f,t);f=t}for(const{s:se,ss:ae,se:ne,d:ie}of r)if(-1===ie){let oe=e.d[te++],ce=oe.b,le=!ce;le&&((ce=oe.s)||(ce=oe.s=createBlob(`export function u$_(m){${oe.a[1].map((e=>"default"===e?"d$_=m.default":`${e}=m.${e}`)).join(",")}}${oe.a[1].map((e=>"default"===e?"let d$_;export{d$_ as default}":`export let ${e}`)).join(";")}\n//# sourceURL=${oe.r}?cycle`)));pushStringTo(se-1);a+=`/*${s.slice(se-1,ne)}*/${urlJsString(ce)}`;if(!le&&oe.s){a+=`;import*as m$_${te} from'${oe.b}';import{u$_ as u$_${te}}from'${oe.s}';u$_${te}(m$_${te})`;oe.s=void 0}f=ne}else if(-2===ie){e.m={url:e.r,resolve:metaResolve};i(e.m,e.u);pushStringTo(se);a+=`importShim._r[${urlJsString(e.u)}].m`;f=ne}else{pushStringTo(ae+6);a+="Shim(";re.push(ne-1);f=se}pushStringTo(s.length)}else a+=s;let n=false;a=a.replace(He,((t,r,s)=>(n=!r,t.replace(s,(()=>new URL(s,e.r))))));n||(a+="\n//# sourceURL="+e.r);e.b=Fe=createBlob(a);e.S=void 0}const He=/\n\/\/# source(Mapping)?URL=([^\n]+)\s*((;|\/\/[^#][^\n]*)\s*)*$/;const qe=/^(text|application)\/(x-)?javascript(;|$)/;const De=/^(text|application)\/json(;|$)/;const Je=/^(text|application)\/css(;|$)/;const Ke=/url\(\s*(?:(["'])((?:\\.|[^\n\\"'])+)\1|((?:\\.|[^\s,"'()\\])+))\s*\)/g;let ze=[];let Ge=0;function pushFetchPool(){if(++Ge>100)return new Promise((e=>ze.push(e)))}function popFetchPool(){Ge--;ze.length&&ze.shift()()}async function doFetch(e,t,r){if(ie&&!t.integrity)throw Error(`No integrity for ${e}${fromParent(r)}.`);const s=pushFetchPool();s&&await s;try{var a=await n(e,t)}catch(t){t.message=`Unable to fetch ${e}${fromParent(r)} - see network log for details.\n`+t.message;throw t}finally{popFetchPool()}if(!a.ok)throw Error(`${a.status} ${a.statusText} ${a.url}${fromParent(r)}`);return a}async function fetchModule(e,t,r){const s=await doFetch(e,t,r);const a=s.headers.get("content-type");if(qe.test(a))return{r:s.url,s:await s.text(),t:"js"};if(De.test(a))return{r:s.url,s:`export default ${await s.text()}`,t:"json"};if(Je.test(a))return{r:s.url,s:`var s=new CSSStyleSheet();s.replaceSync(${JSON.stringify((await s.text()).replace(Ke,((t,r="",s,a)=>`url(${r}${resolveUrl(s||a,e)}${r})`)))});export default s;`,t:"css"};throw Error(`Unsupported Content-Type "${a}" loading ${e}${fromParent(r)}. Modules must be served with a valid MIME type like application/javascript.`)}function getOrCreateLoad(e,t,s,a){let n=xe[e];if(n&&!a)return n;n={u:e,r:a?e:void 0,f:void 0,S:void 0,L:void 0,a:void 0,d:void 0,b:void 0,s:void 0,n:false,t:null,m:null};if(xe[e]){let e=0;while(xe[n.u+ ++e]);n.u+=e}xe[n.u]=n;n.f=(async()=>{if(!a){let i;({r:n.r,s:a,t:i}=await(Xe[e]||fetchModule(e,t,s)));if(i&&!r){if("css"===i&&!ce||"json"===i&&!le)throw Error(`${i}-modules require <script type="esms-options">{ "polyfillEnable": ["${i}-modules"] }<\/script>`);("css"===i&&!me||"json"===i&&!ke)&&(n.n=true)}}try{n.a=parse(a,n.u)}catch(e){throwError(e);n.a=[[],[],false]}n.S=a;return n})();n.L=n.f.then((async()=>{let e=t;n.d=(await Promise.all(n.a[0].map((async({n:t,d:r})=>{(r>=0&&!ve||2===r&&!we)&&(n.n=true);if(-1!==r||!t)return;const{r:s,b:a}=await Pe(t,n.r||n.u);!a||ge&&!je||(n.n=true);if(c&&c.test(s))return{b:s};e.integrity&&(e=Object.assign({},e,{integrity:void 0}));return getOrCreateLoad(s,e,n.r).f})))).filter((e=>e))}));return n}function processScriptsAndPreloads(){for(const e of document.querySelectorAll(r?"script[type=module-shim]":"script[type=module]"))processScript(e);for(const e of document.querySelectorAll(r?"link[rel=modulepreload-shim]":"link[rel=modulepreload]"))processPreload(e)}function processImportMaps(){for(const e of document.querySelectorAll(r?'script[type="importmap-shim"]':'script[type="importmap"]'))processImportMap(e)}function getFetchOpts(e){const t={};e.integrity&&(t.integrity=e.integrity);e.referrerpolicy&&(t.referrerPolicy=e.referrerpolicy);"use-credentials"===e.crossorigin?t.credentials="include":"anonymous"===e.crossorigin?t.credentials="omit":t.credentials="same-origin";return t}let Qe=Promise.resolve();let Ve=1;function domContentLoadedCheck(){0!==--Ve||ne||document.dispatchEvent(new Event("DOMContentLoaded"))}document.addEventListener("DOMContentLoaded",(async()=>{await Ne;domContentLoadedCheck();if(r||!Re){processImportMaps();processScriptsAndPreloads()}}));let We=1;"complete"===document.readyState?readyStateCompleteCheck():document.addEventListener("readystatechange",(async()=>{processImportMaps();await Ne;readyStateCompleteCheck()}));function readyStateCompleteCheck(){0!==--We||ne||document.dispatchEvent(new Event("readystatechange"))}function processImportMap(e){if(!e.ep&&(e.src||e.innerHTML)){e.ep=true;if(e.src){if(!r)return;je=true}if(Te){_e=_e.then((async()=>{Ee=resolveAndComposeImportMap(e.src?await(await doFetch(e.src,getFetchOpts(e))).json():JSON.parse(e.innerHTML),e.src||ue,Ee)})).catch(throwError);r||(Te=false)}}}function processScript(e){if(e.ep)return;if(null!==e.getAttribute("noshim"))return;if(!e.src&&!e.innerHTML)return;e.ep=true;const t=We>0;const s=Ve>0;t&&We++;s&&Ve++;const a=null===e.getAttribute("async")&&t;const n=topLevelLoad(e.src||ue,getFetchOpts(e),!e.src&&e.innerHTML,!r,a&&Qe).catch(throwError);a&&(Qe=n.then(readyStateCompleteCheck));s&&n.then(domContentLoadedCheck)}const Xe={};function processPreload(e){if(!e.ep){e.ep=true;Xe[e.href]||(Xe[e.href]=fetchModule(e.href,getFetchOpts(e)))}}})();
@@ -3,32 +3,49 @@ module GoodJob
3
3
  class AssetsController < ActionController::Base # rubocop:disable Rails/ApplicationController
4
4
  skip_before_action :verify_authenticity_token, raise: false
5
5
 
6
+ def self.js_modules
7
+ @_js_modules ||= GoodJob::Engine.root.join("app", "assets", "good_job", "modules").children.select(&:file?).each_with_object({}) do |file, modules|
8
+ key = File.basename(file.basename.to_s, ".js").to_sym
9
+ modules[key] = file
10
+ end
11
+ end
12
+
6
13
  before_action do
7
14
  expires_in 1.year, public: true
8
15
  end
9
16
 
17
+ def es_module_shims_js
18
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "vendor", "es_module_shims.js")
19
+ end
20
+
10
21
  def bootstrap_css
11
- render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap.min.css")
22
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "vendor", "bootstrap", "bootstrap.min.css")
12
23
  end
13
24
 
14
25
  def bootstrap_js
15
- render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap.bundle.min.js")
26
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "vendor", "bootstrap", "bootstrap.bundle.min.js")
16
27
  end
17
28
 
18
29
  def chartjs_js
19
- render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartjs", "chart.min.js")
30
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "vendor", "chartjs", "chart.min.js")
20
31
  end
21
32
 
22
33
  def rails_ujs_js
23
- render file: GoodJob::Engine.root.join("app", "assets", "vendor", "rails_ujs.js")
34
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "vendor", "rails_ujs.js")
24
35
  end
25
36
 
26
37
  def scripts_js
27
- render file: GoodJob::Engine.root.join("app", "assets", "scripts.js")
38
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "scripts.js")
28
39
  end
29
40
 
30
41
  def style_css
31
- render file: GoodJob::Engine.root.join("app", "assets", "style.css")
42
+ render file: GoodJob::Engine.root.join("app", "assets", "good_job", "style.css")
43
+ end
44
+
45
+ def modules_js
46
+ module_name = params[:module].to_sym
47
+ module_file = self.class.js_modules.fetch(module_name) { raise ActionController::RoutingError, 'Not Found' }
48
+ render file: module_file
32
49
  end
33
50
  end
34
51
  end
@@ -1,14 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  class ExecutionsController < GoodJob::ApplicationController
4
- def index
5
- @filter = ExecutionsFilter.new(params)
6
- end
7
-
8
4
  def destroy
9
5
  deleted_count = GoodJob::Execution.where(id: params[:id]).delete_all
10
6
  message = deleted_count.positive? ? { notice: "Job execution deleted" } : { alert: "Job execution not deleted" }
11
- redirect_back fallback_location: root_path, **message
7
+ redirect_back fallback_location: jobs_path, **message
12
8
  end
13
9
  end
14
10
  end
@@ -1,6 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  class JobsController < GoodJob::ApplicationController
4
+ DISCARD_MESSAGE = "Discarded through dashboard"
5
+
6
+ ACTIONS = {
7
+ discard: "discarded",
8
+ reschedule: "rescheduled",
9
+ retry: "retried",
10
+ }.freeze
11
+
4
12
  rescue_from GoodJob::ActiveJobJob::AdapterNotGoodJobError,
5
13
  GoodJob::ActiveJobJob::ActionForStateMismatchError,
6
14
  with: :redirect_on_error
@@ -9,15 +17,50 @@ module GoodJob
9
17
  @filter = JobsFilter.new(params)
10
18
  end
11
19
 
20
+ def mass_update
21
+ mass_action = params.fetch(:mass_action, "").to_sym
22
+ raise ActionController::BadRequest, "#{mass_action} is not a valid mass action" unless mass_action.in?(ACTIONS.keys)
23
+
24
+ jobs = if params[:all_job_ids]
25
+ ActiveJobJob.all
26
+ else
27
+ job_ids = params.fetch(:job_ids, [])
28
+ ActiveJobJob.where(active_job_id: job_ids)
29
+ end
30
+
31
+ processed_jobs = jobs.map do |job|
32
+ case mass_action
33
+ when :discard
34
+ job.discard_job(DISCARD_MESSAGE)
35
+ when :reschedule
36
+ job.reschedule_job
37
+ when :retry
38
+ job.retry_job
39
+ end
40
+
41
+ job
42
+ rescue GoodJob::ActiveJobJob::ActionForStateMismatchError
43
+ nil
44
+ end.compact
45
+
46
+ notice = if processed_jobs.any?
47
+ "Successfully #{ACTIONS[mass_action]} #{processed_jobs.count} #{'job'.pluralize(processed_jobs.count)}"
48
+ else
49
+ "No jobs were #{ACTIONS[mass_action]}"
50
+ end
51
+
52
+ redirect_to jobs_path, notice: notice
53
+ end
54
+
12
55
  def show
13
56
  @executions = GoodJob::Execution.active_job_id(params[:id])
14
57
  .order(Arel.sql("COALESCE(scheduled_at, created_at) DESC"))
15
- redirect_to root_path, alert: "Executions for Active Job #{params[:id]} not found" if @executions.empty?
58
+ redirect_to jobs_path, alert: "Executions for Active Job #{params[:id]} not found" if @executions.empty?
16
59
  end
17
60
 
18
61
  def discard
19
62
  @job = ActiveJobJob.find(params[:id])
20
- @job.discard_job("Discarded through dashboard")
63
+ @job.discard_job(DISCARD_MESSAGE)
21
64
  redirect_back(fallback_location: jobs_path, notice: "Job has been discarded")
22
65
  end
23
66
 
@@ -54,6 +54,9 @@ module GoodJob
54
54
  raise NotImplementedError
55
55
  end
56
56
 
57
+ # def filtered_query_count
58
+ delegate :count, to: :filtered_query, prefix: true
59
+
57
60
  private
58
61
 
59
62
  def default_base_query
@@ -13,8 +13,7 @@ module GoodJob
13
13
  end
14
14
 
15
15
  def filtered_query
16
- query = base_query.includes(:executions)
17
- .joins_advisory_locks.select("#{GoodJob::ActiveJobJob.table_name}.*", 'pg_locks.locktype AS locktype')
16
+ query = base_query.includes(:executions).includes_advisory_locks
18
17
 
19
18
  query = query.job_class(params[:job_class]) if params[:job_class].present?
20
19
  query = query.where(queue_name: params[:queue_name]) if params[:queue_name].present?
@@ -40,6 +39,10 @@ module GoodJob
40
39
  query
41
40
  end
42
41
 
42
+ def filtered_query_count
43
+ filtered_query.unscope(:select).count
44
+ end
45
+
43
46
  private
44
47
 
45
48
  def default_base_query
@@ -20,5 +20,11 @@ module GoodJob
20
20
 
21
21
  content_tag :span, status.to_s, class: classes
22
22
  end
23
+
24
+ def render_icon(name)
25
+ # workaround to render svg icons without all of the log messages
26
+ partial = lookup_context.find_template("good_job/shared/icons/#{name}", [], true)
27
+ partial.render(self, {})
28
+ end
23
29
  end
24
30
  end
@@ -46,7 +46,7 @@
46
46
  </td>
47
47
  <td>
48
48
  <%= button_to execution_path(execution.id), method: :delete, class: "btn btn-sm btn-outline-danger", title: "Delete execution", data: { confirm: "Confirm delete" } do %>
49
- <%= render "good_job/shared/icons/trash" %>
49
+ <%= render_icon "trash" %>
50
50
  <% end %>
51
51
  </td>
52
52
  </tr>