From 341a0ae81ff78239c30b194cfdd03a59b1716e16 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 24 Mar 2020 12:59:11 +0200 Subject: [PATCH 01/86] add empty readme --- readme.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 00000000..e69de29b From ec5035286f5c165535c5bada11921eadf4fb046d Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Mon, 23 Mar 2020 16:16:24 +0200 Subject: [PATCH 02/86] fix look in admin --- rt_dashboard/contrib/django/templates/rt_dashboard_admin.html | 2 +- rt_dashboard/static/css/main.css | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rt_dashboard/contrib/django/templates/rt_dashboard_admin.html b/rt_dashboard/contrib/django/templates/rt_dashboard_admin.html index 92678fd3..c6455bde 100644 --- a/rt_dashboard/contrib/django/templates/rt_dashboard_admin.html +++ b/rt_dashboard/contrib/django/templates/rt_dashboard_admin.html @@ -3,7 +3,7 @@ {% block content %} + + + ` + // eslint-disable-next-line no-undef + class HowtoTabs extends HTMLElement { + constructor () { + super() + + this._onSlotChange = this._onSlotChange.bind(this) + + this.attachShadow({ mode: 'open' }) + this.shadowRoot.appendChild(template.content.cloneNode(true)) + + this._tabSlot = this.shadowRoot.querySelector('slot[name=tab]') + this._panelSlot = this.shadowRoot.querySelector('slot[name=panel]') + + this._tabSlot.addEventListener('slotchange', this._onSlotChange) + this._panelSlot.addEventListener('slotchange', this._onSlotChange) + } + + connectedCallback () { + this.addEventListener('keydown', this._onKeyDown) + this.addEventListener('click', this._onClick) + + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'tablist') + } + + Promise.all([ + customElements.whenDefined('howto-tab'), + customElements.whenDefined('howto-panel'), + ]).then(_ => this._linkPanels()) + } + + disconnectedCallback () { + this.removeEventListener('keydown', this._onKeyDown) + this.removeEventListener('click', this._onClick) + } + + _onSlotChange () { + this._linkPanels() + } + + _linkPanels () { + const tabs = this._allTabs() + + tabs.forEach(tab => { + const panel = tab.nextElementSibling + if (!panel) { + return + } + + if (panel.tagName.toLowerCase() !== 'howto-panel') { + console.error(`Tab #${tab.id} is not a sibling of a `) + return + } + + tab.setAttribute('aria-controls', panel.id) + panel.setAttribute('aria-labelledby', tab.id) + }) + + const selectedTab = + tabs.find(tab => tab.selected) || tabs[0] + + this._selectTab(selectedTab) + } + + _allPanels () { + return Array.from(this.querySelectorAll('howto-panel')) + } + + _allTabs () { + return Array.from(this.querySelectorAll('howto-tab')) + } + + _panelForTab (tab) { + const panelId = tab.getAttribute('aria-controls') + return this.querySelector(`#${panelId}`) + } + + _prevTab () { + const tabs = this._allTabs() + const newIdx = tabs.findIndex(tab => tab.selected) - 1 + return tabs[(newIdx + tabs.length) % tabs.length] + } + + _firstTab () { + const tabs = this._allTabs() + return tabs[0] + } + + _lastTab () { + const tabs = this._allTabs() + return tabs[tabs.length - 1] + } + + _nextTab () { + const tabs = this._allTabs() + const newIdx = tabs.findIndex(tab => tab.selected) + 1 + return tabs[newIdx % tabs.length] + } + + reset () { + const tabs = this._allTabs() + const panels = this._allPanels() + + tabs.forEach(tab => { tab.selected = false }) + panels.forEach(panel => { panel.hidden = true }) + } + + _selectTab (newTab) { + if (!newTab) { + return + } + // Deselect all tabs and hide all panels. + this.reset() + + // Get the panel that the `newTab` is associated with. + const newPanel = this._panelForTab(newTab) + // If that panel doesn’t exist, abort. + if (!newPanel) { + throw new Error(`No panel with id ${newTab.id}`) + } + newTab.selected = true + newPanel.hidden = false + newTab.focus() + } + + _onKeyDown (event) { + // If the keypress did not originate from a tab element itself, + // it was a keypress inside the a panel or on empty space. Nothing to do. + if (event.target.getAttribute('role') !== 'tab') { + return + } + // Don’t handle modifier shortcuts typically used by assistive technology. + if (event.altKey) { + return + } + + // The switch-case will determine which tab should be marked as active + // depending on the key that was pressed. + let newTab + switch (event.keyCode) { + case KEYCODE.LEFT: + case KEYCODE.UP: + newTab = this._prevTab() + break + + case KEYCODE.RIGHT: + case KEYCODE.DOWN: + newTab = this._nextTab() + break + + case KEYCODE.HOME: + newTab = this._firstTab() + break + + case KEYCODE.END: + newTab = this._lastTab() + break + // Any other key press is ignored and passed back to the browser. + default: + return + } + + // The browser might have some native functionality bound to the arrow + // keys, home or end. The element calls `preventDefault()` to prevent the + // browser from taking any actions. + event.preventDefault() + // Select the new tab, that has been determined in the switch-case. + this._selectTab(newTab) + } + + _onClick (event) { + // If the click was not targeted on a tab element itself, + // it was a click inside the a panel or on empty space. Nothing to do. + if (event.target.getAttribute('role') !== 'tab') { + return + } + // If it was on a tab element, though, select that tab. + this._selectTab(event.target) + } + } + customElements.define('howto-tabs', HowtoTabs) + + // `howtoTabCounter` counts the number of `` instances created. The + // number is used to generated new, unique IDs. + let howtoTabCounter = 0 + const header = document.createElement('li') + const tabShadowRoot = header.attachShadow({ mode: 'open' }) + tabShadowRoot.innerHTML = '' + class HowtoTab extends HTMLElement { + static get observedAttributes() { + return ['selected'] + } + + constructor() { + super() + this.innerHTML = tabShadowRoot.content.cloneNode(true) + } + + connectedCallback () { + // If this is executed, JavaScript is working and the element + // changes its role to `tab`. + const template = document.getElementById('one-dialog'); + const node = document.importNode(template.content, true); + this.appendChild(node); + + this.attachShadow( { mode: 'open' } ) + .innerHTML = '' + + this.setAttribute('role', 'tab') + if (!this.id) { + this.id = `howto-tab-generated-${howtoTabCounter++}` + } + + // Set a well-defined initial state. + this.setAttribute('aria-selected', 'false') + this.setAttribute('tabindex', -1) + this._upgradeProperty('selected') + } + + _upgradeProperty (prop) { + if (this.hasOwnProperty(prop)) { + let value = this[prop] + delete this[prop] + this[prop] = value + } + } + + attributeChangedCallback () { + const value = this.hasAttribute('selected') + this.setAttribute('aria-selected', value) + this.setAttribute('tabindex', value ? 0 : -1) + } + + set selected (value) { + value = Boolean(value) + if (value) { + this.setAttribute('selected', '') + } else { + this.removeAttribute('selected') + } + } + + get selected () { + return this.hasAttribute('selected') + } + } + customElements.define('howto-tab', HowtoTab) + + let howtoPanelCounter = 0 + /** + * `HowtoPanel` is a panel for a `` tab panel. + */ + class HowtoPanel extends HTMLElement { + constructor() { + super() + } + + connectedCallback() { + this.setAttribute('role', 'tabpanel') + if (!this.id) + this.id = `howto-panel-generated-${howtoPanelCounter++}` + } + } + customElements.define('howto-panel', HowtoPanel) +})() diff --git a/rt_dashboard/javascript/styles/main.scss b/rt_dashboard/javascript/styles/main.scss index 9997c62b..e599633b 100644 --- a/rt_dashboard/javascript/styles/main.scss +++ b/rt_dashboard/javascript/styles/main.scss @@ -11,6 +11,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; background: white; margin-top: 0; width: 100%; + max-width: 100%; } #content { diff --git a/rt_dashboard/static/index.html b/rt_dashboard/static/index.html index 992795dc..fe03839a 100644 --- a/rt_dashboard/static/index.html +++ b/rt_dashboard/static/index.html @@ -7,186 +7,11 @@ RQ dashboard - + -
- - -
-
-
- -

Queues

-

This list below contains all the registered queues with the number of tasks currently - in the queue. Select a queue from above to view all tasks currently pending on the queue.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QueueTasks
Loading...
- - [failed] - 0
- - [finished] - 0
- - [running] - 0
-
-
- -
-
- -

Workers

- - -

- - No workers registered!

- - - - - - - - - - - - - - - - - - - - - -
StateWorkerQueues
Loading...
v-yf.2193default, low_prio_queue
- - - -
-
-
- -
-
-
- -

Tasks on {{ queue.name }} -

-

- - - - - Delete - - - This list below contains all the registered tasks on queue - {{ queue.name }}, sorted by age - - (newest on top). - - -

- - - - - - - - - - - - - - -
NameAgeActions
Loading...
- - - - - - - - - - - - - - - -
-
-
-
+ diff --git a/webpack.config.js b/webpack.config.js index ef7e08e3..cd5cf518 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -51,7 +51,7 @@ module.exports = { target: 'web', devServer: { proxy: { - '/api': 'http://localhost:3000' + '/admin': 'https://172.16.0.5/admin/' }, contentBase: path.join(__dirname, 'rt_dashboard/static'), historyApiFallback: true, From 5eb6b0ac7d4df1416d2245651e980c2612a7a8ae Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Wed, 25 Mar 2020 16:44:02 +0200 Subject: [PATCH 19/86] remove unused component --- .../javascript/src/components/tabs.js | 292 ------------------ 1 file changed, 292 deletions(-) delete mode 100644 rt_dashboard/javascript/src/components/tabs.js diff --git a/rt_dashboard/javascript/src/components/tabs.js b/rt_dashboard/javascript/src/components/tabs.js deleted file mode 100644 index 362fc1a4..00000000 --- a/rt_dashboard/javascript/src/components/tabs.js +++ /dev/null @@ -1,292 +0,0 @@ -(function() { - /** - * Define key codes to help with handling keyboard events. - */ - const KEYCODE = { - DOWN: 40, - LEFT: 37, - RIGHT: 39, - UP: 38, - HOME: 36, - END: 35, - } - - const template = document.createElement('template') - template.innerHTML = ` - - - - ` - // eslint-disable-next-line no-undef - class HowtoTabs extends HTMLElement { - constructor () { - super() - - this._onSlotChange = this._onSlotChange.bind(this) - - this.attachShadow({ mode: 'open' }) - this.shadowRoot.appendChild(template.content.cloneNode(true)) - - this._tabSlot = this.shadowRoot.querySelector('slot[name=tab]') - this._panelSlot = this.shadowRoot.querySelector('slot[name=panel]') - - this._tabSlot.addEventListener('slotchange', this._onSlotChange) - this._panelSlot.addEventListener('slotchange', this._onSlotChange) - } - - connectedCallback () { - this.addEventListener('keydown', this._onKeyDown) - this.addEventListener('click', this._onClick) - - if (!this.hasAttribute('role')) { - this.setAttribute('role', 'tablist') - } - - Promise.all([ - customElements.whenDefined('howto-tab'), - customElements.whenDefined('howto-panel'), - ]).then(_ => this._linkPanels()) - } - - disconnectedCallback () { - this.removeEventListener('keydown', this._onKeyDown) - this.removeEventListener('click', this._onClick) - } - - _onSlotChange () { - this._linkPanels() - } - - _linkPanels () { - const tabs = this._allTabs() - - tabs.forEach(tab => { - const panel = tab.nextElementSibling - if (!panel) { - return - } - - if (panel.tagName.toLowerCase() !== 'howto-panel') { - console.error(`Tab #${tab.id} is not a sibling of a `) - return - } - - tab.setAttribute('aria-controls', panel.id) - panel.setAttribute('aria-labelledby', tab.id) - }) - - const selectedTab = - tabs.find(tab => tab.selected) || tabs[0] - - this._selectTab(selectedTab) - } - - _allPanels () { - return Array.from(this.querySelectorAll('howto-panel')) - } - - _allTabs () { - return Array.from(this.querySelectorAll('howto-tab')) - } - - _panelForTab (tab) { - const panelId = tab.getAttribute('aria-controls') - return this.querySelector(`#${panelId}`) - } - - _prevTab () { - const tabs = this._allTabs() - const newIdx = tabs.findIndex(tab => tab.selected) - 1 - return tabs[(newIdx + tabs.length) % tabs.length] - } - - _firstTab () { - const tabs = this._allTabs() - return tabs[0] - } - - _lastTab () { - const tabs = this._allTabs() - return tabs[tabs.length - 1] - } - - _nextTab () { - const tabs = this._allTabs() - const newIdx = tabs.findIndex(tab => tab.selected) + 1 - return tabs[newIdx % tabs.length] - } - - reset () { - const tabs = this._allTabs() - const panels = this._allPanels() - - tabs.forEach(tab => { tab.selected = false }) - panels.forEach(panel => { panel.hidden = true }) - } - - _selectTab (newTab) { - if (!newTab) { - return - } - // Deselect all tabs and hide all panels. - this.reset() - - // Get the panel that the `newTab` is associated with. - const newPanel = this._panelForTab(newTab) - // If that panel doesn’t exist, abort. - if (!newPanel) { - throw new Error(`No panel with id ${newTab.id}`) - } - newTab.selected = true - newPanel.hidden = false - newTab.focus() - } - - _onKeyDown (event) { - // If the keypress did not originate from a tab element itself, - // it was a keypress inside the a panel or on empty space. Nothing to do. - if (event.target.getAttribute('role') !== 'tab') { - return - } - // Don’t handle modifier shortcuts typically used by assistive technology. - if (event.altKey) { - return - } - - // The switch-case will determine which tab should be marked as active - // depending on the key that was pressed. - let newTab - switch (event.keyCode) { - case KEYCODE.LEFT: - case KEYCODE.UP: - newTab = this._prevTab() - break - - case KEYCODE.RIGHT: - case KEYCODE.DOWN: - newTab = this._nextTab() - break - - case KEYCODE.HOME: - newTab = this._firstTab() - break - - case KEYCODE.END: - newTab = this._lastTab() - break - // Any other key press is ignored and passed back to the browser. - default: - return - } - - // The browser might have some native functionality bound to the arrow - // keys, home or end. The element calls `preventDefault()` to prevent the - // browser from taking any actions. - event.preventDefault() - // Select the new tab, that has been determined in the switch-case. - this._selectTab(newTab) - } - - _onClick (event) { - // If the click was not targeted on a tab element itself, - // it was a click inside the a panel or on empty space. Nothing to do. - if (event.target.getAttribute('role') !== 'tab') { - return - } - // If it was on a tab element, though, select that tab. - this._selectTab(event.target) - } - } - customElements.define('howto-tabs', HowtoTabs) - - // `howtoTabCounter` counts the number of `` instances created. The - // number is used to generated new, unique IDs. - let howtoTabCounter = 0 - const header = document.createElement('li') - const tabShadowRoot = header.attachShadow({ mode: 'open' }) - tabShadowRoot.innerHTML = '' - class HowtoTab extends HTMLElement { - static get observedAttributes() { - return ['selected'] - } - - constructor() { - super() - this.innerHTML = tabShadowRoot.content.cloneNode(true) - } - - connectedCallback () { - // If this is executed, JavaScript is working and the element - // changes its role to `tab`. - const template = document.getElementById('one-dialog'); - const node = document.importNode(template.content, true); - this.appendChild(node); - - this.attachShadow( { mode: 'open' } ) - .innerHTML = '' - - this.setAttribute('role', 'tab') - if (!this.id) { - this.id = `howto-tab-generated-${howtoTabCounter++}` - } - - // Set a well-defined initial state. - this.setAttribute('aria-selected', 'false') - this.setAttribute('tabindex', -1) - this._upgradeProperty('selected') - } - - _upgradeProperty (prop) { - if (this.hasOwnProperty(prop)) { - let value = this[prop] - delete this[prop] - this[prop] = value - } - } - - attributeChangedCallback () { - const value = this.hasAttribute('selected') - this.setAttribute('aria-selected', value) - this.setAttribute('tabindex', value ? 0 : -1) - } - - set selected (value) { - value = Boolean(value) - if (value) { - this.setAttribute('selected', '') - } else { - this.removeAttribute('selected') - } - } - - get selected () { - return this.hasAttribute('selected') - } - } - customElements.define('howto-tab', HowtoTab) - - let howtoPanelCounter = 0 - /** - * `HowtoPanel` is a panel for a `` tab panel. - */ - class HowtoPanel extends HTMLElement { - constructor() { - super() - } - - connectedCallback() { - this.setAttribute('role', 'tabpanel') - if (!this.id) - this.id = `howto-panel-generated-${howtoPanelCounter++}` - } - } - customElements.define('howto-panel', HowtoPanel) -})() From 5f8b91ae74f3b6a804d804da37c73d2e1a582299 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 26 Mar 2020 13:19:03 +0200 Subject: [PATCH 20/86] Place components in folders and add implementation --- package.json | 1 + rt_dashboard/javascript/app.js | 17 +- .../dashboard.html} | 64 +------- .../src/components/dashboard/dashboard.js | 29 ++++ .../src/components/layout/layout.html | 10 ++ .../src/components/{ => layout}/layout.js | 20 ++- .../src/components/queues/queues.html | 20 +++ .../src/components/queues/queues.js | 78 +++++++++ rt_dashboard/javascript/src/utils/dom.js | 11 ++ webpack.config.js | 16 ++ yarn.lock | 148 +++++++++++++++++- 11 files changed, 331 insertions(+), 83 deletions(-) rename rt_dashboard/javascript/src/components/{dashboard.js => dashboard/dashboard.html} (66%) create mode 100644 rt_dashboard/javascript/src/components/dashboard/dashboard.js create mode 100644 rt_dashboard/javascript/src/components/layout/layout.html rename rt_dashboard/javascript/src/components/{ => layout}/layout.js (66%) create mode 100644 rt_dashboard/javascript/src/components/queues/queues.html create mode 100644 rt_dashboard/javascript/src/components/queues/queues.js create mode 100644 rt_dashboard/javascript/src/utils/dom.js diff --git a/package.json b/package.json index d7072b8f..1122ffd7 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", "file-loader": "^6.0.0", + "html-loader": "^1.0.0", "jquery": "^3.4.1", "mini-css-extract-plugin": "^0.9.0", "node-sass": "^4.13.1", diff --git a/rt_dashboard/javascript/app.js b/rt_dashboard/javascript/app.js index 04096b5d..9eb024b4 100644 --- a/rt_dashboard/javascript/app.js +++ b/rt_dashboard/javascript/app.js @@ -1,9 +1,10 @@ import './styles/main.scss' import 'bootstrap/dist/js/bootstrap.min.js' import $ from 'jquery' -import './src/components/layout' -import './src/components/dashboard' +import './src/components/layout/layout' +import './src/components/dashboard/dashboard' import './src/components/history' +import './src/components/queues/queues' const DOCUMENT_SCRIPT_NAME = 'app.js' const API_URL_PARAM_NAME = 'apiUrl' @@ -30,7 +31,7 @@ const getApiUrl = () => { return getParams(DOCUMENT_SCRIPT_NAME)[API_URL_PARAM_NAME] } -var url_for = function (name, param) { +var urlFor = function (name, param) { var url = getApiUrl() if (name === 'queues') { url += 'queues.json' @@ -42,21 +43,21 @@ var url_for = function (name, param) { return url } -var url_for_jobs = function (param, page) { +var urlForJobs = function (param, page) { var url = getApiUrl() + 'jobs/' + encodeURIComponent(param) + '/' + page + '.json' return url } var api = { getQueues: function (cb) { - $.getJSON(url_for('queues'), function (data) { + $.getJSON(urlFor('queues'), function (data) { var queues = data.queues cb(queues) }) }, - getJobs: function (queue_name, page, cb) { - $.getJSON(url_for_jobs(queue_name, page), function (data) { + getJobs: function (queueName, page, cb) { + $.getJSON(urlForJobs(queueName, page), function (data) { var jobs = data.jobs var pagination = data.pagination cb(jobs, pagination) @@ -64,7 +65,7 @@ var api = { }, getWorkers: function (cb) { - $.getJSON(url_for('workers'), function (data) { + $.getJSON(urlFor('workers'), function (data) { var workers = data.workers cb(workers) }) diff --git a/rt_dashboard/javascript/src/components/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.html similarity index 66% rename from rt_dashboard/javascript/src/components/dashboard.js rename to rt_dashboard/javascript/src/components/dashboard/dashboard.html index 257ef511..eb2d6836 100644 --- a/rt_dashboard/javascript/src/components/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.html @@ -1,52 +1,7 @@ -const html = `
-
- -

Queues

-

This list below contains all the registered queues with the number of tasks currently - in the queue. Select a queue from above to view all tasks currently pending on the queue.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QueueTasks
Loading...
- - [failed] - 0
- - [finished] - 0
- - [running] - 0
-
+
@@ -94,8 +49,8 @@

Workers

- -

Tasks on {{ queue.name }} + +

Tasks on {{ queue.name }}

@@ -168,16 +123,3 @@

Tasks on

-` - -class Dashboard extends HTMLElement { - constructor () { - super() - const template = document.createElement('template') - template.innerHTML = html - - this.attachShadow({ mode: 'open' }) - this.shadowRoot.appendChild(template.content.cloneNode(true)) - } -} -customElements.define('dashboard-component', Dashboard) diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js new file mode 100644 index 00000000..2e98e6be --- /dev/null +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -0,0 +1,29 @@ +import html from './dashboard.html' + +class Dashboard extends HTMLElement { + constructor () { + super() + const template = document.createElement('template') + template.innerHTML = html + + this.attachShadow({ mode: 'open' }) + this.shadowRoot.appendChild(template.content.cloneNode(true)) + + this.selectedQueueChange = this.selectedQueueChange.bind(this) + } + + connectedCallback () { + const queuesComponent = this.shadowRoot.querySelector('queues-component') + queuesComponent.addEventListener('selectedQueueChange', this.selectedQueueChange) + } + + disconnectedCallback () { + this.removeEventListener('selectedQueueChange', this.selectedQueueChange) + } + + selectedQueueChange (event) { + const { detail: { queueName } } = event + console.log(queueName) + } +} +window.customElements.define('dashboard-component', Dashboard) diff --git a/rt_dashboard/javascript/src/components/layout/layout.html b/rt_dashboard/javascript/src/components/layout/layout.html new file mode 100644 index 00000000..23edc5dc --- /dev/null +++ b/rt_dashboard/javascript/src/components/layout/layout.html @@ -0,0 +1,10 @@ + +
+ + + +
diff --git a/rt_dashboard/javascript/src/components/layout.js b/rt_dashboard/javascript/src/components/layout/layout.js similarity index 66% rename from rt_dashboard/javascript/src/components/layout.js rename to rt_dashboard/javascript/src/components/layout/layout.js index d50f0459..c6bd73b0 100644 --- a/rt_dashboard/javascript/src/components/layout.js +++ b/rt_dashboard/javascript/src/components/layout/layout.js @@ -1,13 +1,5 @@ -const html = ` - -
- - - -
` +import html from './layout.html' + const DASHBOARD = 'dashboard-component' const HISTORY = 'history-component' @@ -37,6 +29,12 @@ class LayoutWrapper extends HTMLElement { }) } + disconnectedCallback () { + this.navLinks.forEach(link => { + link.removeEventListener('click', this.tabClicked) + }) + } + tabClicked (e) { const { target: activeLink } = e this.navLinks.forEach(l => { l.classList.remove('active') }) @@ -45,4 +43,4 @@ class LayoutWrapper extends HTMLElement { this.panels.find(p => p.tagName.toLowerCase() === activeLink.name).hidden = false } } -customElements.define('layout-wrapper', LayoutWrapper) +window.customElements.define('layout-wrapper', LayoutWrapper) diff --git a/rt_dashboard/javascript/src/components/queues/queues.html b/rt_dashboard/javascript/src/components/queues/queues.html new file mode 100644 index 00000000..8bc56ced --- /dev/null +++ b/rt_dashboard/javascript/src/components/queues/queues.html @@ -0,0 +1,20 @@ + +
+

Queues

+

This list below contains all the registered queues with the number of tasks currently + in the queue. Select a queue from above to view all tasks currently pending on the queue.

+ + + + + + + + + + + + + +
QueueTasks
Loading...
+
diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js new file mode 100644 index 00000000..85c0c305 --- /dev/null +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -0,0 +1,78 @@ +import html from './queues.html' +import { appendElement } from '../../utils/dom' + +const rowTemplate = ` + + + + [failed] + + 0 + +` + +class Queues extends HTMLElement { + constructor () { + super() + const template = document.createElement('template') + template.innerHTML = html + + this.attachShadow({ mode: 'open' }) + this.shadowRoot.appendChild(template.content.cloneNode(true)) + + this.onQueueClicked = this.onQueueClicked.bind(this) + } + + connectedCallback () { + this.queuesLinks = [] + Array.from(this.shadowRoot.querySelectorAll('td a')).forEach(link => { + this.queuesLinks.push(link) + link.addEventListener('click', this.onQueueClicked) + }) + + setTimeout(() => { + const tbody = this.shadowRoot.querySelector('tbody') + Array.from(tbody.childNodes).forEach((el) => { + tbody.removeChild(el) + }) + + const row = appendElement('tr', tbody) + row.setAttribute('data-role', 'queue') + + const td = appendElement('td', row) + appendElement('i', td, 'fas fa-inbox') + + const name = 'test' + const count = 0 + const link = appendElement('a', td, null, `[${name}]`) + link.setAttribute('name', name) + link.setAttribute('href', `/admin/rt_dashboard/inner/%5B${name}%5D`) + + appendElement('td', row, 'narrow', count) + + Array.from(this.shadowRoot.querySelectorAll('td a')).forEach(link => { + this.queuesLinks.push(link) + link.addEventListener('click', this.onQueueClicked) + }) + }, 1000) + } + + disconnectedCallback () { + this.queuesLinks.forEach(link => { + link.removeEventListener('click', this.onQueueClicked) + }) + } + + onQueueClicked (e) { + const { target: selectedQueue } = e + this.dispatchEvent( + new CustomEvent('selectedQueueChange', { + detail: { queueName: selectedQueue.name }, + bubbles: true + }) + ) + e.preventDefault() + return false + } +} +window.customElements.define('queues-component', Queues) diff --git a/rt_dashboard/javascript/src/utils/dom.js b/rt_dashboard/javascript/src/utils/dom.js new file mode 100644 index 00000000..9623fa6c --- /dev/null +++ b/rt_dashboard/javascript/src/utils/dom.js @@ -0,0 +1,11 @@ + +export const appendElement = (tag, parent, classes = '', innerHtml = null) => { + const element = document.createElement(tag) + if (classes) { + classes.split(' ').filter(c => c && c.length > 0) + .forEach((className) => element.classList.add(className)) + } + element.innerHTML = innerHtml + parent.appendChild(element) + return element +} diff --git a/webpack.config.js b/webpack.config.js index cd5cf518..6d77560b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,6 +21,22 @@ module.exports = { presets: ['@babel/preset-env', '@babel/preset-react'] } }, + { + test: /\.html$/i, + loader: 'html-loader', + options: { + attributes: { + list: [{ + tag: 'link', + attribute: 'href', + type: 'src', + filter: (tag, attribute, attributes) => { + return false + } + }] + } + } + }, { test: /\.s[ac]ss$/i, use: [ diff --git a/yarn.lock b/yarn.lock index 4444e61a..36f1a347 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1615,6 +1615,14 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" + integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== + dependencies: + pascal-case "^3.1.1" + tslib "^1.10.0" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -1730,6 +1738,13 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-css@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" + integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== + dependencies: + source-map "~0.6.0" + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -1837,6 +1852,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2265,11 +2285,48 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-serializer@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domhandler@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" + integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw== + dependencies: + domelementtype "^2.0.1" + +domutils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.0.0.tgz#15b8278e37bfa8468d157478c58c367718133c08" + integrity sha512-n5SelJ1axbO636c2yUtOGia/IcJtVtlhQbFiVDBZHKV5ReJO1ViX7sFEemtuyoAnBxk5meNSYgA8V4s0271efg== + dependencies: + dom-serializer "^0.2.1" + domelementtype "^2.0.1" + domhandler "^3.0.0" + +dot-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" + integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -2361,6 +2418,11 @@ enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -3260,6 +3322,11 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -3296,6 +3363,40 @@ html-entities@^1.2.1: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= +html-loader@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.0.0.tgz#40000ff27bfb4fbf087d37f8438cae0b1d8b53b1" + integrity sha512-acPyjP9Mo05jEbe/oejXu5gFwtKWdFewPoaVa47VCnHmRbR43jtdx/kPhPEbCBm2qWtIn+a8uTJAW4Ocnn4olw== + dependencies: + html-minifier-terser "^5.0.4" + htmlparser2 "^4.1.0" + loader-utils "^2.0.0" + parse-srcset "^1.0.2" + schema-utils "^2.6.5" + +html-minifier-terser@^5.0.4: + version "5.0.5" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.0.5.tgz#8f12f639789f04faa9f5cf2ff9b9f65607f21f8b" + integrity sha512-cBSFFghQh/uHcfSiL42KxxIRMF7A144+3E44xdlctIjxEmkEfCvouxNyFH2wysXk1fCGBPwtcr3hDWlGTfkDew== + dependencies: + camel-case "^4.1.1" + clean-css "^4.2.3" + commander "^4.1.1" + he "^1.2.0" + param-case "^3.0.3" + relateurl "^0.2.7" + terser "^4.6.3" + +htmlparser2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -4071,6 +4172,13 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== + dependencies: + tslib "^1.10.0" + lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -4399,6 +4507,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== + dependencies: + lower-case "^2.0.1" + tslib "^1.10.0" + node-forge@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" @@ -4785,6 +4901,14 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" +param-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" + integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== + dependencies: + dot-case "^3.0.3" + tslib "^1.10.0" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4824,11 +4948,24 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" + integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -5370,6 +5507,11 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5852,7 +5994,7 @@ source-map@^0.5.0, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -6192,7 +6334,7 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.1.2: +terser@^4.1.2, terser@^4.6.3: version "4.6.7" resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.7.tgz#478d7f9394ec1907f0e488c5f6a6a9a2bad55e72" integrity sha512-fmr7M1f7DBly5cX2+rFDvmGBAaaZyPrHYK4mMdHEDAdNTqXSZgSOfqsfGq2HqPGT/1V0foZZuCZFx8CHKgAk3g== @@ -6298,7 +6440,7 @@ trim-newlines@^1.0.0: dependencies: glob "^7.1.2" -tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.9.0: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== From 68614fa89e37f942b9815981874c2edcfa425569 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 26 Mar 2020 13:45:59 +0200 Subject: [PATCH 21/86] Address comments --- rt_dashboard/javascript/app.js | 3 +- .../src/components/dashboard/dashboard.html | 39 +----------------- .../src/components/dashboard/dashboard.js | 7 +--- .../src/components/queues/queues.js | 7 +--- .../rt-dashboard.html} | 0 .../rt-dashboard.js} | 13 +++--- .../src/components/workers/workers.html | 40 +++++++++++++++++++ .../src/components/workers/workers.js | 31 ++++++++++++++ rt_dashboard/javascript/src/utils/dom.js | 8 ++++ 9 files changed, 91 insertions(+), 57 deletions(-) rename rt_dashboard/javascript/src/components/{layout/layout.html => rt-dashboard/rt-dashboard.html} (100%) rename rt_dashboard/javascript/src/components/{layout/layout.js => rt-dashboard/rt-dashboard.js} (74%) create mode 100644 rt_dashboard/javascript/src/components/workers/workers.html create mode 100644 rt_dashboard/javascript/src/components/workers/workers.js diff --git a/rt_dashboard/javascript/app.js b/rt_dashboard/javascript/app.js index 9eb024b4..cda41297 100644 --- a/rt_dashboard/javascript/app.js +++ b/rt_dashboard/javascript/app.js @@ -1,10 +1,11 @@ import './styles/main.scss' import 'bootstrap/dist/js/bootstrap.min.js' import $ from 'jquery' -import './src/components/layout/layout' +import './src/components/rt-dashboard/rt-dashboard' import './src/components/dashboard/dashboard' import './src/components/history' import './src/components/queues/queues' +import './src/components/workers/workers' const DOCUMENT_SCRIPT_NAME = 'app.js' const API_URL_PARAM_NAME = 'apiUrl' diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.html b/rt_dashboard/javascript/src/components/dashboard/dashboard.html index eb2d6836..89cfd63d 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.html +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.html @@ -5,44 +5,7 @@
-
- -

Workers

- - -

- - No workers registered!

- - - - - - - - - - - - - - - - - - - - - -
StateWorkerQueues
Loading...
v-yf.2193default, low_prio_queue
- - - -
+
diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js index 2e98e6be..f5ed885f 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -1,13 +1,10 @@ import html from './dashboard.html' +import { loadTemplate } from '../../utils/dom' class Dashboard extends HTMLElement { constructor () { super() - const template = document.createElement('template') - template.innerHTML = html - - this.attachShadow({ mode: 'open' }) - this.shadowRoot.appendChild(template.content.cloneNode(true)) + loadTemplate(this, html) this.selectedQueueChange = this.selectedQueueChange.bind(this) } diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index 85c0c305..8518ae48 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -1,5 +1,5 @@ import html from './queues.html' -import { appendElement } from '../../utils/dom' +import { appendElement, loadTemplate } from '../../utils/dom' const rowTemplate = ` @@ -14,11 +14,8 @@ const rowTemplate = ` class Queues extends HTMLElement { constructor () { super() - const template = document.createElement('template') - template.innerHTML = html - this.attachShadow({ mode: 'open' }) - this.shadowRoot.appendChild(template.content.cloneNode(true)) + loadTemplate(this, html) this.onQueueClicked = this.onQueueClicked.bind(this) } diff --git a/rt_dashboard/javascript/src/components/layout/layout.html b/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html similarity index 100% rename from rt_dashboard/javascript/src/components/layout/layout.html rename to rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html diff --git a/rt_dashboard/javascript/src/components/layout/layout.js b/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.js similarity index 74% rename from rt_dashboard/javascript/src/components/layout/layout.js rename to rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.js index c6bd73b0..12aa5161 100644 --- a/rt_dashboard/javascript/src/components/layout/layout.js +++ b/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.js @@ -1,16 +1,13 @@ -import html from './layout.html' +import html from './rt-dashboard.html' +import { loadTemplate } from '../../utils/dom' const DASHBOARD = 'dashboard-component' const HISTORY = 'history-component' -class LayoutWrapper extends HTMLElement { +class RtDashboard extends HTMLElement { constructor () { super() - const template = document.createElement('template') - template.innerHTML = html - - this.attachShadow({ mode: 'open' }) - this.shadowRoot.appendChild(template.content.cloneNode(true)) + loadTemplate(this, html) this.tabClicked = this.tabClicked.bind(this) } @@ -43,4 +40,4 @@ class LayoutWrapper extends HTMLElement { this.panels.find(p => p.tagName.toLowerCase() === activeLink.name).hidden = false } } -window.customElements.define('layout-wrapper', LayoutWrapper) +window.customElements.define('rt-dashboard', RtDashboard) diff --git a/rt_dashboard/javascript/src/components/workers/workers.html b/rt_dashboard/javascript/src/components/workers/workers.html new file mode 100644 index 00000000..5cdfbbba --- /dev/null +++ b/rt_dashboard/javascript/src/components/workers/workers.html @@ -0,0 +1,40 @@ + +
+ +

Workers

+ + +

+ + No workers registered! +

+ + + + + + + + + + + + + + + + + + + + + +
StateWorkerQueues
Loading...
v-yf.2193default, low_prio_queue
+ + + +
diff --git a/rt_dashboard/javascript/src/components/workers/workers.js b/rt_dashboard/javascript/src/components/workers/workers.js new file mode 100644 index 00000000..8586edf7 --- /dev/null +++ b/rt_dashboard/javascript/src/components/workers/workers.js @@ -0,0 +1,31 @@ +import html from './workers.html' +import { loadTemplate } from '../../utils/dom' + +class Workers extends HTMLElement { + constructor () { + super() + loadTemplate(this, html) + + this.onWorkersBtnClick = this.onWorkersBtnClick.bind(this) + } + + connectedCallback () { + const btn = this.shadowRoot.querySelector('button#workers-btn') + btn.addEventListener('click', this.onWorkersBtnClick) + } + + disconnectedCallback () { + this.removeEventListener('click', this.onWorkersBtnClick) + } + + onWorkersBtnClick (event) { + const workersTable = this.shadowRoot.querySelector('#workers') + const isHidden = workersTable.getAttribute('hidden') + if (isHidden) { + workersTable.removeAttribute('hidden') + } else { + workersTable.setAttribute('hidden', true) + } + } +} +window.customElements.define('workers-component', Workers) diff --git a/rt_dashboard/javascript/src/utils/dom.js b/rt_dashboard/javascript/src/utils/dom.js index 9623fa6c..e2d9cd22 100644 --- a/rt_dashboard/javascript/src/utils/dom.js +++ b/rt_dashboard/javascript/src/utils/dom.js @@ -9,3 +9,11 @@ export const appendElement = (tag, parent, classes = '', innerHtml = null) => { parent.appendChild(element) return element } + +export const loadTemplate = (element, html) => { + const template = document.createElement('template') + template.innerHTML = html + + element.attachShadow({ mode: 'open' }) + element.shadowRoot.appendChild(template.content.cloneNode(true)) +} From 67f67091b32e7b042fc8d8504b9cac8c8efd7357 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 26 Mar 2020 13:46:28 +0200 Subject: [PATCH 22/86] update template --- rt_dashboard/static/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rt_dashboard/static/index.html b/rt_dashboard/static/index.html index fe03839a..7d02fa59 100644 --- a/rt_dashboard/static/index.html +++ b/rt_dashboard/static/index.html @@ -11,7 +11,7 @@ - + From 0c8dd04f72576bf9c7922c33c923498a5a7a4cfb Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 26 Mar 2020 16:04:48 +0200 Subject: [PATCH 23/86] Worker and Queue functionalities --- rt_dashboard/javascript/app.js | 71 ------------------- rt_dashboard/javascript/src/api.js | 70 ++++++++++++++++++ .../src/components/queues/queues.js | 56 ++++++--------- .../src/components/workers/workers.html | 7 -- .../src/components/workers/workers.js | 35 ++++++++- rt_dashboard/javascript/src/utils/dom.js | 19 +++++ webpack.config.js | 23 ++++++ 7 files changed, 169 insertions(+), 112 deletions(-) create mode 100644 rt_dashboard/javascript/src/api.js diff --git a/rt_dashboard/javascript/app.js b/rt_dashboard/javascript/app.js index cda41297..625396b0 100644 --- a/rt_dashboard/javascript/app.js +++ b/rt_dashboard/javascript/app.js @@ -1,78 +1,7 @@ import './styles/main.scss' import 'bootstrap/dist/js/bootstrap.min.js' -import $ from 'jquery' import './src/components/rt-dashboard/rt-dashboard' import './src/components/dashboard/dashboard' import './src/components/history' import './src/components/queues/queues' import './src/components/workers/workers' - -const DOCUMENT_SCRIPT_NAME = 'app.js' -const API_URL_PARAM_NAME = 'apiUrl' - -function getParams (scriptName) { - var scripts = document.getElementsByTagName('script') - - for (var i = 0; i < scripts.length; i++) { - if (scripts[i].src.indexOf('/' + scriptName) > -1) { - var pa = scripts[i].src.split('?').pop().split('&') - var p = {} - for (var j = 0; j < pa.length; j++) { - var kv = pa[j].split('=') - p[kv[0]] = kv[1] - } - return p - } - } - - return {} -} - -const getApiUrl = () => { - return getParams(DOCUMENT_SCRIPT_NAME)[API_URL_PARAM_NAME] -} - -var urlFor = function (name, param) { - var url = getApiUrl() - if (name === 'queues') { - url += 'queues.json' - } else if (name === 'workers') { - url += 'workers.json' - } else if (name === 'cancel_job') { - url += 'job/' + encodeURIComponent(param) + '/cancel' - } - return url -} - -var urlForJobs = function (param, page) { - var url = getApiUrl() + 'jobs/' + encodeURIComponent(param) + '/' + page + '.json' - return url -} - -var api = { - getQueues: function (cb) { - $.getJSON(urlFor('queues'), function (data) { - var queues = data.queues - cb(queues) - }) - }, - - getJobs: function (queueName, page, cb) { - $.getJSON(urlForJobs(queueName, page), function (data) { - var jobs = data.jobs - var pagination = data.pagination - cb(jobs, pagination) - }) - }, - - getWorkers: function (cb) { - $.getJSON(urlFor('workers'), function (data) { - var workers = data.workers - cb(workers) - }) - } -} - -api.getQueues((data) => { - console.log(data) -}) diff --git a/rt_dashboard/javascript/src/api.js b/rt_dashboard/javascript/src/api.js new file mode 100644 index 00000000..ac73ec37 --- /dev/null +++ b/rt_dashboard/javascript/src/api.js @@ -0,0 +1,70 @@ +import $ from 'jquery' + +const DOCUMENT_SCRIPT_NAME = 'app.js' +const API_URL_PARAM_NAME = 'apiUrl' + +const requestErrorHandler = error => { + console.error(error) + alert('Error with network request') +} + +export const getParams = (scriptName) => { + var scripts = document.getElementsByTagName('script') + + for (var i = 0; i < scripts.length; i++) { + if (scripts[i].src.indexOf('/' + scriptName) > -1) { + var pa = scripts[i].src.split('?').pop().split('&') + var p = {} + for (var j = 0; j < pa.length; j++) { + var kv = pa[j].split('=') + p[kv[0]] = kv[1] + } + return p + } + } + + return {} +} + +export const getApiUrl = () => { + return getParams(DOCUMENT_SCRIPT_NAME)[API_URL_PARAM_NAME] +} + +export const urlFor = (name, param) => { + var url = getApiUrl() + if (name === 'queues') { + url += 'queues.json' + } else if (name === 'workers') { + url += 'workers.json' + } else if (name === 'cancel_job') { + url += 'job/' + encodeURIComponent(param) + '/cancel' + } + return url +} + +export const urlForJobs = (param, page) => { + var url = getApiUrl() + 'jobs/' + encodeURIComponent(param) + '/' + page + '.json' + return url +} + +export const getQueues = (cb) => { + $.getJSON(urlFor('queues'), (data) => { + var queues = data.queues + cb(queues) + }).fail(requestErrorHandler) +} + +export const getJobs = (queueName, page, cb) => { + $.getJSON(urlForJobs(queueName, page), (data) => { + var jobs = data.jobs + var pagination = data.pagination + cb(jobs, pagination) + }).fail(requestErrorHandler) +} + +export const getWorkers = (cb) => { + $.getJSON(urlFor('workers'), (data) => { + var workers = data.workers + cb(workers) + }).fail(requestErrorHandler) +} diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index 8518ae48..a8ca1e4f 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -1,15 +1,6 @@ import html from './queues.html' -import { appendElement, loadTemplate } from '../../utils/dom' - -const rowTemplate = ` - - - - [failed] - - 0 - -` +import { appendElement, loadTemplate, mapDataToElements, appendNoDataRow } from '../../utils/dom' +import { getQueues } from '../../api' class Queues extends HTMLElement { constructor () { @@ -22,36 +13,21 @@ class Queues extends HTMLElement { connectedCallback () { this.queuesLinks = [] - Array.from(this.shadowRoot.querySelectorAll('td a')).forEach(link => { - this.queuesLinks.push(link) - link.addEventListener('click', this.onQueueClicked) - }) - setTimeout(() => { + getQueues((data) => { const tbody = this.shadowRoot.querySelector('tbody') - Array.from(tbody.childNodes).forEach((el) => { - tbody.removeChild(el) - }) - - const row = appendElement('tr', tbody) - row.setAttribute('data-role', 'queue') - - const td = appendElement('td', row) - appendElement('i', td, 'fas fa-inbox') - - const name = 'test' - const count = 0 - const link = appendElement('a', td, null, `[${name}]`) - link.setAttribute('name', name) - link.setAttribute('href', `/admin/rt_dashboard/inner/%5B${name}%5D`) - appendElement('td', row, 'narrow', count) + if (!data || data.length <= 0) { + appendNoDataRow(tbody, 'No queues.', 2) + return + } + mapDataToElements(tbody, data, this.fillRow) Array.from(this.shadowRoot.querySelectorAll('td a')).forEach(link => { this.queuesLinks.push(link) link.addEventListener('click', this.onQueueClicked) }) - }, 1000) + }) } disconnectedCallback () { @@ -60,6 +36,20 @@ class Queues extends HTMLElement { }) } + fillRow (parent, { name, url, count }) { + const row = appendElement('tr', parent) + row.setAttribute('data-role', 'queue') + + const td = appendElement('td', row) + appendElement('i', td, 'fas fa-inbox') + + const link = appendElement('a', td, null, name) + link.setAttribute('name', name) + link.setAttribute('href', url) + + appendElement('td', row, 'narrow', count) + } + onQueueClicked (e) { const { target: selectedQueue } = e this.dispatchEvent( diff --git a/rt_dashboard/javascript/src/components/workers/workers.html b/rt_dashboard/javascript/src/components/workers/workers.html index 5cdfbbba..eadd5a99 100644 --- a/rt_dashboard/javascript/src/components/workers/workers.html +++ b/rt_dashboard/javascript/src/components/workers/workers.html @@ -22,13 +22,6 @@

Workers

Loading... - - - - v-yf.2193 - default, low_prio_queue - - - - - - - - - - - - - - - -
+
+
+
diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js index bb73afd8..b1f558c4 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -20,7 +20,9 @@ export default class Dashboard extends HTMLElement { } selectedQueueChange (event) { - const { detail: { queueName } } = event - console.log(queueName) + const { detail: { queueName, count } } = event + const tasksComponent = this.shadowRoot.querySelector('tasks-component') + tasksComponent.setAttribute('queue', queueName) + tasksComponent.setAttribute('count', count) } } diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index a4d5775d..442ce674 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -27,6 +27,8 @@ export default class Queues extends HTMLElement { this.queuesLinks.push(link) link.addEventListener('click', this.onQueueClicked) }) + const [first] = data + this.sendChangedEvent(first.name, first.count) }) } @@ -43,8 +45,9 @@ export default class Queues extends HTMLElement { const td = appendElement('td', row) appendElement('i', td, 'fas fa-inbox') - const link = appendElement('a', td, null, name) + const link = appendElement('a', td, 'ml-1', name) link.setAttribute('name', name) + link.setAttribute('data-count', count) link.setAttribute('href', url) appendElement('td', row, 'narrow', count) @@ -52,13 +55,20 @@ export default class Queues extends HTMLElement { onQueueClicked (e) { const { target: selectedQueue } = e - this.dispatchEvent( - new CustomEvent('selectedQueueChange', { - detail: { queueName: selectedQueue.name }, - bubbles: true, - }), + this.sendChangedEvent( + selectedQueue.name, + selectedQueue.getAttribute('data-count') ) e.preventDefault() return false } + + sendChangedEvent (queueName, count) { + this.dispatchEvent( + new CustomEvent('selectedQueueChange', { + detail: { queueName, count }, + bubbles: true + }) + ) + } } diff --git a/rt_dashboard/javascript/src/components/tasks/index.js b/rt_dashboard/javascript/src/components/tasks/index.js new file mode 100644 index 00000000..255a8a47 --- /dev/null +++ b/rt_dashboard/javascript/src/components/tasks/index.js @@ -0,0 +1,3 @@ +import Tasks from './tasks' + +window.customElements.define('tasks-component', Tasks) diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.html b/rt_dashboard/javascript/src/components/tasks/tasks.html new file mode 100644 index 00000000..bd4d084b --- /dev/null +++ b/rt_dashboard/javascript/src/components/tasks/tasks.html @@ -0,0 +1,76 @@ + +
+ +

+ Tasks on +

+

+ + + + + + This list below contains all the registered tasks on queue + {{ queue.name }}, sorted by age + + (newest on top). + + +

+ + + + + + + + + + + + + + +
NameAgeActions
Loading...
+ + + + + + + + + + + + + + + +
diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js new file mode 100644 index 00000000..47ac3147 --- /dev/null +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -0,0 +1,135 @@ +import { Date, Number } from 'sugar' +import html from './tasks.html' +import { + loadTemplate, + appendElement, + appendNoDataRow, + mapDataToElements +} from '../../utils/dom' +import { getJobs, cancelJob } from '../../api' + +export default class Tasks extends HTMLElement { + static get observedAttributes () { + return ['queue', 'count'] + } + + constructor () { + super() + loadTemplate(this.attachShadow({ mode: 'open' }), html) + + this.mapToRow = this.mapToRow.bind(this) + } + + connectedCallback () { + + } + + disconnectedCallback () { + + } + + attributeChangedCallback () { + const queue = this.getAttribute('queue') + const count = this.getAttribute('count') + const queueName = this.shadowRoot.querySelector('h1 strong') + queueName.innerHTML = queue + const queueNameSubTitle = this.shadowRoot.querySelector('p.intro strong') + queueNameSubTitle.innerHTML = queue + this.toggleEmptyBtns(queue, count) + this.loadQueueTasks(queue) + } + + toggleEmptyBtns (queue, count) { + const emptyBtn = this.shadowRoot.querySelector('p.intro #empty-btn') + const deleteBtn = this.shadowRoot.querySelector('p.intro #delete-btn') + emptyBtn.hidden = true + deleteBtn.hidden = true + if (count > 0) { + emptyBtn.hidden = false + } else if (!queue.startsWith('[')) { + deleteBtn.hidden = false + } + } + + loadQueueTasks (queue) { + this.cancelLinks = this.cancelLinks || [] + this.cancelLinks.forEach(link => { + link.removeEventListener('click', this.onQueueClicked) + }) + + getJobs(queue, 1, (jobs, pagination) => { + const tbody = this.shadowRoot.querySelector('tbody') + + if (!jobs || jobs.length <= 0) { + appendNoDataRow(tbody, 'No jobs.', 3) + return + } + + mapDataToElements(tbody, jobs, this.mapToRow) + + Array.from(this.shadowRoot.querySelectorAll('td a')).forEach(link => { + this.cancelLinks.push(link) + link.addEventListener('click', this.onCancelClicked) + }) + }) + } + + onCancelClicked (e) { + const { target: cancelTaskBtn } = e + cancelJob(cancelTaskBtn.getAttribute('data-jobid')) + e.preventDefault() + } + + mapToRow (parent, { + id, + description, + origin, + worker, + status, + error_message: error, + enqueued_at: enqueued, + started_at: started, + ended_at: ended + }) { + const row = appendElement('tr', parent) + row.setAttribute('data-role', 'job') + row.setAttribute('data-job-id', id) + + const td = appendElement('td', row) + appendElement('i', td, 'fas fa-file') + appendElement('span', td, 'description ml-1', description) + + if (this.getAttribute('queue').startsWith('[')) { + let originInfo = ` from ${origin}` + if (worker) { + originInfo += ` running on ${worker}` + } + appendElement('span', td, 'origin', originInfo) + } + + appendElement('div', td, 'job_id d-block', id) + + if (status === 'running') { + appendElement('span', td, 'end_date', `Enqueued ${Date(enqueued).relative()}`) + } else if (status === 'failed') { + appendElement('span', td, 'end_date', + `Enqueued ${Date(enqueued).relative()}, failed ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) + appendElement('pre', td, 'exc_info', `
${error}
`) + } else if (status === 'finished') { + appendElement('span', td, 'end_date', + `Enqueued ${Date(enqueued).relative()}, finished ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) + } + + const col2 = appendElement('td', row) + if (status === 'running') { + appendElement('span', col2, 'creation_date', `${Number(new Date().getTime() - started).duration()}`) + } else { + appendElement('span', col2, 'creation_date', `${Date(ended ?? enqueued).relative()}`) + } + + const col3 = appendElement('td', row, 'actions narrow') + const actionLink = appendElement('a', col3, 'btn btn-outline-secondary btn-sm mx-auto', ' Cancel') + actionLink.setAttribute('data-role', 'cancel-job-btn') + actionLink.setAttribute('data-jobid', id) + } +} diff --git a/rt_dashboard/javascript/styles/main.scss b/rt_dashboard/javascript/styles/main.scss index eb4ffc80..f0ce3c1e 100644 --- a/rt_dashboard/javascript/styles/main.scss +++ b/rt_dashboard/javascript/styles/main.scss @@ -62,8 +62,11 @@ table#queues { } table#jobs td.actions a { - margin-right: 8px; - margin-bottom: 8px; + font-size: 80%; +} + +table#jobs td.actions { + width: auto; } table#jobs span.description { diff --git a/webpack.config.js b/webpack.config.js index 0a2f65fe..88b9cb11 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -68,7 +68,8 @@ module.exports = { queues: [ { name: '[test]', count: 0, url: '/admin/rt_dashboard/inner/test' }, { name: '[running]', count: 1, url: '/admin/rt_dashboard/inner/running' }, - ], + { name: 'default', count: 0, url: '/admin/rt_dashboard/inner/default' } + ] }) }) app.get('/admin/rt_dashboard/inner/workers.json', (req, res) => { @@ -84,6 +85,37 @@ module.exports = { }], }) }) + + const generateTask = (id, error, status) => ({ + id, + description: 'feeds.tasks.generate_feed_from_db(1113)', + origin: 'unnatural', + worker: status === 'running' ? 'v-yf.21' : null, + status, + error_message: error, + enqueued_at: new Date().getTime(), + started_at: new Date().getTime(), + ended_at: new Date().getTime() + }) + const getJobsHandler = (pagination) => (req, res) => { + res.json({ + jobs: [ + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3fdd', 'General error', 'failed'), + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), + generateTask('fa02bf65-0527-40d0-BBBB-9f3c041f3fdd', null, 'running') + ], + pagination + }) + } + app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/1.json', + getJobsHandler({ pages_in_window: 2, next_page: 2, prev_page: null })) + app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', + getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + app.get('admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', + getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + app.get('admin/rt_dashboard/inner/jobs/default/1.json', + getJobsHandler({ pages_in_window: 1, next_page: null, prev_page: null })) }, proxy: { '/admin': 'https://172.16.0.5/admin/', diff --git a/yarn.lock b/yarn.lock index e3b48302..9d41e578 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6351,6 +6351,18 @@ style-loader@^1.1.3: loader-utils "^1.2.3" schema-utils "^2.6.4" +sugar-core@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/sugar-core/-/sugar-core-2.0.6.tgz#785e0cd64aa7302ea54d47bc1213efe52c006270" + integrity sha512-YmLFysR3Si6RImqL1+aB6JH81EXxvXn5iXhPf2PsjfoUYEwCxFDYCQY+zC3WqviuGWzxFaSkkJvkUE05Y03L5Q== + +sugar@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/sugar/-/sugar-2.0.6.tgz#aa08e389add27109fb35718598313e0503a4fc39" + integrity sha512-s0P2/pjJtAD9VA44+2Gqm3NdC4v+08melA6YubOxzshu628krTbn95/M2GWMrI9rYspZMpYBIrChR46fjQ7xsQ== + dependencies: + sugar-core "^2.0.0" + supports-color@6.1.0, supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" From 0ddda3dbb251badab980a83c8d06216c7e56cf47 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Fri, 27 Mar 2020 10:33:09 +0200 Subject: [PATCH 50/86] Empty, Delete and cancel functionalities --- rt_dashboard/javascript/src/api.js | 16 ++- .../src/components/dashboard/dashboard.js | 3 +- .../src/components/queues/queues.js | 3 +- .../src/components/tasks/tasks.html | 27 ++-- .../javascript/src/components/tasks/tasks.js | 120 ++++++++++++++---- rt_dashboard/javascript/src/utils/dom.js | 10 +- webpack.config.js | 26 +++- 7 files changed, 147 insertions(+), 58 deletions(-) diff --git a/rt_dashboard/javascript/src/api.js b/rt_dashboard/javascript/src/api.js index 31abe7f6..93581e0e 100644 --- a/rt_dashboard/javascript/src/api.js +++ b/rt_dashboard/javascript/src/api.js @@ -79,7 +79,19 @@ export const getWorkers = (cb) => { export const getHistory = (init) => fetch(urlFor('history'), init) export const cancelJob = (jobId, cb) => { - // TODO Test! - $.getJSON(getApiUrl() + `job/${jobId}/cancel`, cb) + // TODO Test! Seems to be GET + $.post(getApiUrl() + `job/${jobId}/cancel`, cb) + .fail(requestErrorHandler) +} + +export const deleteQueue = (queue, cb) => { + // TODO test! + $.post(getApiUrl() + `queue/${queue}/delete`, cb) + .fail(requestErrorHandler) +} + +export const emptyQueue = (queue, cb) => { + // TODO test + $.post(getApiUrl() + `queue/${queue}/empty`, cb) .fail(requestErrorHandler) } diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js index b1f558c4..da16c2d0 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -22,7 +22,6 @@ export default class Dashboard extends HTMLElement { selectedQueueChange (event) { const { detail: { queueName, count } } = event const tasksComponent = this.shadowRoot.querySelector('tasks-component') - tasksComponent.setAttribute('queue', queueName) - tasksComponent.setAttribute('count', count) + tasksComponent.setAttribute('queue-info', JSON.stringify({ queue: queueName, count })) } } diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index 442ce674..8a8c3c58 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -27,7 +27,8 @@ export default class Queues extends HTMLElement { this.queuesLinks.push(link) link.addEventListener('click', this.onQueueClicked) }) - const [first] = data + let [first] = data + first = data.find(q => q.name.startsWith('[running')) ?? first this.sendChangedEvent(first.name, first.count) }) } diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.html b/rt_dashboard/javascript/src/components/tasks/tasks.html index bd4d084b..3c7e8447 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.html +++ b/rt_dashboard/javascript/src/components/tasks/tasks.html @@ -1,30 +1,23 @@
-

Tasks on

- - + This list below contains all the registered tasks on queue {{ queue.name }}, sorted by age - - (newest on top). - - + +

diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 47ac3147..54a1fb26 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -4,13 +4,14 @@ import { loadTemplate, appendElement, appendNoDataRow, - mapDataToElements + mapDataToElements, + removeChildNode } from '../../utils/dom' -import { getJobs, cancelJob } from '../../api' +import { getJobs, cancelJob, deleteQueue, emptyQueue } from '../../api' export default class Tasks extends HTMLElement { static get observedAttributes () { - return ['queue', 'count'] + return ['queue-info'] } constructor () { @@ -18,25 +19,58 @@ export default class Tasks extends HTMLElement { loadTemplate(this.attachShadow({ mode: 'open' }), html) this.mapToRow = this.mapToRow.bind(this) + this.onEmptyClicked = this.onEmptyClicked.bind(this) + this.onDeleteClicked = this.onDeleteClicked.bind(this) } connectedCallback () { - + this.emptyBtn = this.shadowRoot.querySelector('p.intro #empty-btn') + this.deleteBtn = this.shadowRoot.querySelector('p.intro #delete-btn') + this.emptyBtn.addEventListener('click', this.onEmptyClicked) + this.deleteBtn.addEventListener('click', this.onDeleteClicked) } disconnectedCallback () { + this.removeEventListener.addEventListener('click', this.onEmptyClicked) + this.removeEventListener.addEventListener('click', this.onDeleteClicked) + this.removeTableClickListeners() } attributeChangedCallback () { - const queue = this.getAttribute('queue') - const count = this.getAttribute('count') + const queueInfo = JSON.parse(this.getAttribute('queue-info')) + const { queue, count } = queueInfo + + this.queue = queue + this.count = count + this.updateTitles(queue, count) + this.toggleEmptyBtns(queue, count) + + this.loadQueueTasks(queue) + } + + onEmptyClicked () { + emptyQueue(this.queue) + } + + onDeleteClicked (e) { + deleteQueue(this.queue) + } + + updateTitles (queue, count) { const queueName = this.shadowRoot.querySelector('h1 strong') queueName.innerHTML = queue + if (queue === '[failed]') { + queueName.classList.add('failed') + } + const queueNameSubTitle = this.shadowRoot.querySelector('p.intro strong') queueNameSubTitle.innerHTML = queue - this.toggleEmptyBtns(queue, count) - this.loadQueueTasks(queue) + + const orderDescInfo = this.shadowRoot.querySelector('p.intro #oldest-on-top') + const orderAscInfo = this.shadowRoot.querySelector('p.intro #newes-on-top') + orderDescInfo.hidden = queue.startsWith('[') + orderAscInfo.hidden = !queue.startsWith('[') } toggleEmptyBtns (queue, count) { @@ -52,14 +86,13 @@ export default class Tasks extends HTMLElement { } loadQueueTasks (queue) { - this.cancelLinks = this.cancelLinks || [] - this.cancelLinks.forEach(link => { - link.removeEventListener('click', this.onQueueClicked) - }) + this.removeTableClickListeners() - getJobs(queue, 1, (jobs, pagination) => { - const tbody = this.shadowRoot.querySelector('tbody') + const tbody = this.shadowRoot.querySelector('tbody') + removeChildNode(tbody) + appendNoDataRow(tbody, 'Loading...', 3) + getJobs(queue, 1, (jobs, pagination) => { if (!jobs || jobs.length <= 0) { appendNoDataRow(tbody, 'No jobs.', 3) return @@ -74,6 +107,15 @@ export default class Tasks extends HTMLElement { }) } + removeTableClickListeners () { + this.cancelLinks = this.cancelLinks || [] + this.cancelLinks.forEach(link => { + link.removeEventListener('click', this.onQueueClicked) + }) + + this.cancelLinks = [] + } + onCancelClicked (e) { const { target: cancelTaskBtn } = e cancelJob(cancelTaskBtn.getAttribute('data-jobid')) @@ -95,11 +137,47 @@ export default class Tasks extends HTMLElement { row.setAttribute('data-role', 'job') row.setAttribute('data-job-id', id) + this.mapFirstColumn(row, { + id, + description, + origin, + worker, + status, + error, + enqueued, + started, + ended + }) + + const col2 = appendElement('td', row) + if (status === 'running') { + appendElement('span', col2, 'creation_date', `${Number(new Date().getTime() - started).duration()}`) + } else { + appendElement('span', col2, 'creation_date', `${Date(ended ?? enqueued).relative()}`) + } + + const col3 = appendElement('td', row, 'actions narrow') + const actionLink = appendElement('a', col3, 'btn btn-outline-secondary btn-sm mx-auto', ' Cancel') + actionLink.setAttribute('data-role', 'cancel-job-btn') + actionLink.setAttribute('data-jobid', id) + } + + mapFirstColumn (row, { + id, + description, + origin, + worker, + status, + error, + enqueued, + started, + ended + }) { const td = appendElement('td', row) appendElement('i', td, 'fas fa-file') appendElement('span', td, 'description ml-1', description) - if (this.getAttribute('queue').startsWith('[')) { + if (this.queue.startsWith('[')) { let originInfo = ` from ${origin}` if (worker) { originInfo += ` running on ${worker}` @@ -119,17 +197,5 @@ export default class Tasks extends HTMLElement { appendElement('span', td, 'end_date', `Enqueued ${Date(enqueued).relative()}, finished ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) } - - const col2 = appendElement('td', row) - if (status === 'running') { - appendElement('span', col2, 'creation_date', `${Number(new Date().getTime() - started).duration()}`) - } else { - appendElement('span', col2, 'creation_date', `${Date(ended ?? enqueued).relative()}`) - } - - const col3 = appendElement('td', row, 'actions narrow') - const actionLink = appendElement('a', col3, 'btn btn-outline-secondary btn-sm mx-auto', ' Cancel') - actionLink.setAttribute('data-role', 'cancel-job-btn') - actionLink.setAttribute('data-jobid', id) } } diff --git a/rt_dashboard/javascript/src/utils/dom.js b/rt_dashboard/javascript/src/utils/dom.js index aa7fdf7d..ec28c8d6 100644 --- a/rt_dashboard/javascript/src/utils/dom.js +++ b/rt_dashboard/javascript/src/utils/dom.js @@ -17,10 +17,14 @@ export const loadTemplate = (parent, templateHtml) => { parent.appendChild(template.content.cloneNode(true)) } -export const mapDataToElements = (table, data, itemMapper) => { - Array.from(table.childNodes).forEach((el) => { - table.removeChild(el) +export const removeChildNode = (node) => { + Array.from(node.childNodes).forEach((el) => { + node.removeChild(el) }) +} + +export const mapDataToElements = (table, data, itemMapper) => { + removeChildNode(table) data.forEach(item => itemMapper(table, item)) } diff --git a/webpack.config.js b/webpack.config.js index 88b9cb11..31fa484a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -100,10 +100,10 @@ module.exports = { const getJobsHandler = (pagination) => (req, res) => { res.json({ jobs: [ - generateTask('fa02bf65-0527-40d0-acae-9f3c041f3fdd', 'General error', 'failed'), + generateTask('fa02bf65-0527-40d0-acae-9f3c041fAAAA', 'General error', 'failed'), generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), - generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), - generateTask('fa02bf65-0527-40d0-BBBB-9f3c041f3fdd', null, 'running') + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3FFF', null, 'finished'), + generateTask('fa02bf65-0527-40d0-BBBB-9f3c041fBBBB', null, 'running') ], pagination }) @@ -112,10 +112,24 @@ module.exports = { getJobsHandler({ pages_in_window: 2, next_page: 2, prev_page: null })) app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) - app.get('admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', + app.get('/admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) - app.get('admin/rt_dashboard/inner/jobs/default/1.json', - getJobsHandler({ pages_in_window: 1, next_page: null, prev_page: null })) + app.get('/admin/rt_dashboard/inner/jobs/default/1.json', (req, res) => { + res.json({ + jobs: [ + ], + pagination: { pages_in_window: 0, next_page: null, prev_page: null } + }) + }) + app.post('/admin/rt_dashboard/inner/queue/default/delete', (req, res) => { + res.json({}) + }) + app.post('/admin/rt_dashboard/inner/queue/[running]/empty', (req, res) => { + res.json({}) + }) + app.post('/admin/rt_dashboard/inner/job/fa02bf65-0527-40d0-BBBB-9f3c041fBBBB/cancel', (req, res) => { + res.json({}) + }) }, proxy: { '/admin': 'https://172.16.0.5/admin/', From 958a0dfc06e1a4d11178b5085f11f803b91db540 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Fri, 27 Mar 2020 10:45:33 +0200 Subject: [PATCH 51/86] Separate mock api from webpackconfig --- webpack.config.js | 73 ++----------------------------------- webpack.devserver.config.js | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 70 deletions(-) create mode 100644 webpack.devserver.config.js diff --git a/webpack.config.js b/webpack.config.js index 31fa484a..a1960fd0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,6 @@ const path = require('path') const MiniCssExtractPlugin = require('mini-css-extract-plugin') +const devServerConfig = require('./webpack.devserver.config') module.exports = { context: path.resolve(__dirname, 'rt_dashboard'), @@ -62,75 +63,6 @@ module.exports = { devtool: 'source-map', target: 'web', devServer: { - before: (app, server, compiler) => { - app.get('/admin/rt_dashboard/inner/queues.json', (req, res) => { - res.json({ - queues: [ - { name: '[test]', count: 0, url: '/admin/rt_dashboard/inner/test' }, - { name: '[running]', count: 1, url: '/admin/rt_dashboard/inner/running' }, - { name: 'default', count: 0, url: '/admin/rt_dashboard/inner/default' } - ] - }) - }) - app.get('/admin/rt_dashboard/inner/workers.json', (req, res) => { - res.json({ - workers: [{ - state: 'pause', - name: 'v-yf.2193', - queues: ['default', 'low_prio_queue'], - }, { - state: 'busy', - name: 'v-yf.2192', - queues: ['empty', 'high_prio_queue'], - }], - }) - }) - - const generateTask = (id, error, status) => ({ - id, - description: 'feeds.tasks.generate_feed_from_db(1113)', - origin: 'unnatural', - worker: status === 'running' ? 'v-yf.21' : null, - status, - error_message: error, - enqueued_at: new Date().getTime(), - started_at: new Date().getTime(), - ended_at: new Date().getTime() - }) - const getJobsHandler = (pagination) => (req, res) => { - res.json({ - jobs: [ - generateTask('fa02bf65-0527-40d0-acae-9f3c041fAAAA', 'General error', 'failed'), - generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), - generateTask('fa02bf65-0527-40d0-acae-9f3c041f3FFF', null, 'finished'), - generateTask('fa02bf65-0527-40d0-BBBB-9f3c041fBBBB', null, 'running') - ], - pagination - }) - } - app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/1.json', - getJobsHandler({ pages_in_window: 2, next_page: 2, prev_page: null })) - app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', - getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) - app.get('/admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', - getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) - app.get('/admin/rt_dashboard/inner/jobs/default/1.json', (req, res) => { - res.json({ - jobs: [ - ], - pagination: { pages_in_window: 0, next_page: null, prev_page: null } - }) - }) - app.post('/admin/rt_dashboard/inner/queue/default/delete', (req, res) => { - res.json({}) - }) - app.post('/admin/rt_dashboard/inner/queue/[running]/empty', (req, res) => { - res.json({}) - }) - app.post('/admin/rt_dashboard/inner/job/fa02bf65-0527-40d0-BBBB-9f3c041fBBBB/cancel', (req, res) => { - res.json({}) - }) - }, proxy: { '/admin': 'https://172.16.0.5/admin/', }, @@ -139,5 +71,6 @@ module.exports = { hot: true, https: false, noInfo: true, - }, + ...devServerConfig + } } diff --git a/webpack.devserver.config.js b/webpack.devserver.config.js new file mode 100644 index 00000000..96439c46 --- /dev/null +++ b/webpack.devserver.config.js @@ -0,0 +1,71 @@ +module.exports = { + before: (app, server, compiler) => { + app.get('/admin/rt_dashboard/inner/queues.json', (req, res) => { + res.json({ + queues: [ + { name: '[test]', count: 0, url: '/admin/rt_dashboard/inner/test' }, + { name: '[running]', count: 1, url: '/admin/rt_dashboard/inner/running' }, + { name: 'default', count: 0, url: '/admin/rt_dashboard/inner/default' } + ] + }) + }) + app.get('/admin/rt_dashboard/inner/workers.json', (req, res) => { + res.json({ + workers: [{ + state: 'pause', + name: 'v-yf.2193', + queues: ['default', 'low_prio_queue'] + }, { + state: 'busy', + name: 'v-yf.2192', + queues: ['empty', 'high_prio_queue'] + }] + }) + }) + + const generateTask = (id, error, status) => ({ + id, + description: 'feeds.tasks.generate_feed_from_db(1113)', + origin: 'unnatural', + worker: status === 'running' ? 'v-yf.21' : null, + status, + error_message: error, + enqueued_at: new Date().getTime(), + started_at: new Date().getTime(), + ended_at: new Date().getTime() + }) + const getJobsHandler = (pagination) => (req, res) => { + res.json({ + jobs: [ + generateTask('fa02bf65-0527-40d0-acae-9f3c041fAAAA', 'General error', 'failed'), + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), + generateTask('fa02bf65-0527-40d0-acae-9f3c041f3FFF', null, 'finished'), + generateTask('fa02bf65-0527-40d0-BBBB-9f3c041fBBBB', null, 'running') + ], + pagination + }) + } + app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/1.json', + getJobsHandler({ pages_in_window: 2, next_page: 2, prev_page: null })) + app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', + getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + app.get('/admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', + getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + app.get('/admin/rt_dashboard/inner/jobs/default/1.json', (req, res) => { + res.json({ + jobs: [ + ], + pagination: { pages_in_window: 0, next_page: null, prev_page: null } + }) + }) + app.post('/admin/rt_dashboard/inner/queue/default/delete', (req, res) => { + res.json({}) + }) + app.post('/admin/rt_dashboard/inner/queue/[running]/empty', (req, res) => { + res.json({}) + }) + app.post('/admin/rt_dashboard/inner/job/fa02bf65-0527-40d0-BBBB-9f3c041fBBBB/cancel', (req, res) => { + res.json({}) + }) + } +} From 8d454b2d99026680c6ddf1f02139634631adae4b Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Fri, 27 Mar 2020 14:28:10 +0200 Subject: [PATCH 52/86] implement pager --- rt_dashboard/javascript/app.js | 1 + .../src/components/dashboard/dashboard.js | 2 +- .../javascript/src/components/pager/index.js | 3 + .../src/components/pager/pager.html | 9 ++ .../javascript/src/components/pager/pager.js | 97 +++++++++++++++++++ .../src/components/tasks/tasks.html | 32 +----- .../javascript/src/components/tasks/tasks.js | 37 +++++-- rt_dashboard/javascript/src/utils/dom.js | 4 +- webpack.devserver.config.js | 15 ++- 9 files changed, 155 insertions(+), 45 deletions(-) create mode 100644 rt_dashboard/javascript/src/components/pager/index.js create mode 100644 rt_dashboard/javascript/src/components/pager/pager.html create mode 100644 rt_dashboard/javascript/src/components/pager/pager.js diff --git a/rt_dashboard/javascript/app.js b/rt_dashboard/javascript/app.js index 707a066d..2a5f1c10 100644 --- a/rt_dashboard/javascript/app.js +++ b/rt_dashboard/javascript/app.js @@ -8,3 +8,4 @@ import './src/components/queues' import './src/components/rt-dashboard' import './src/components/workers' import './src/components/tasks' +import './src/components/pager' diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js index da16c2d0..d154ad6f 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -22,6 +22,6 @@ export default class Dashboard extends HTMLElement { selectedQueueChange (event) { const { detail: { queueName, count } } = event const tasksComponent = this.shadowRoot.querySelector('tasks-component') - tasksComponent.setAttribute('queue-info', JSON.stringify({ queue: queueName, count })) + tasksComponent.queueInfo = { queue: queueName, count } } } diff --git a/rt_dashboard/javascript/src/components/pager/index.js b/rt_dashboard/javascript/src/components/pager/index.js new file mode 100644 index 00000000..a191882f --- /dev/null +++ b/rt_dashboard/javascript/src/components/pager/index.js @@ -0,0 +1,3 @@ +import Pager from './pager' + +window.customElements.define('pager-component', Pager) diff --git a/rt_dashboard/javascript/src/components/pager/pager.html b/rt_dashboard/javascript/src/components/pager/pager.html new file mode 100644 index 00000000..bd5d5ae6 --- /dev/null +++ b/rt_dashboard/javascript/src/components/pager/pager.html @@ -0,0 +1,9 @@ + + + + diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js new file mode 100644 index 00000000..e8ccfe49 --- /dev/null +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -0,0 +1,97 @@ +import templateHtml from './pager.html' +import { loadTemplate, mapDataToElements, appendElement } from '../../utils/dom' + +export default class Pager extends HTMLElement { + get pagination () { + return this.paging + } + + set pagination (value) { + this.paging = value + this.updatePager(this.mapPaging(value)) + } + + constructor () { + super() + + loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml) + + this.mapToPageLinks = this.mapToPageLinks.bind(this) + this.onPageClicked = this.onPageClicked.bind(this) + + this.current = 1 + } + + disconnectedCallback () { + this.removeEventListeners() + } + + onPageClicked (e) { + const { target: pageLink } = e + const number = pageLink.getAttribute('data-page') + this.current = number + + this.dispatchEvent( + new CustomEvent('selectedPageChanged', { + detail: { number }, + bubbles: true + }) + ) + + e.preventDefault() + return false + } + + mapPaging ({ + pages_in_window: pagesArray, + next_page: nextPage, + prev_page: prevPage + }) { + let nextPageNum = null + let prevPageNum = null + if (prevPage) { + prevPageNum = prevPage.url.split('/').pop() + } + if (nextPage) { + nextPageNum = nextPage.url.split('/').pop() + } + + return [ + { text: '«', number: prevPageNum }, + ...pagesArray.map(({ number }) => ({ text: number, number })), + { text: '»', number: nextPageNum } + ] + } + + updatePager (pages) { + this.pageLinks = [] + this.removeEventListeners() + + const pagesList = this.shadowRoot.querySelector('ul.pagination') + mapDataToElements(pagesList, pages, this.mapToPageLinks) + + Array.from(this.shadowRoot.querySelectorAll('li a')).forEach(link => { + this.pageLinks.push(link) + link.addEventListener('click', this.onPageClicked) + }) + } + + removeEventListeners () { + this.pageLinks.forEach(l => { + l.removeEventListener('click', this.onPageClicked) + }) + this.pageLinks = [] + } + + mapToPageLinks (parent, page) { + const disabledClass = page.number ? '' : 'disabled' + const li = appendElement('li', parent, `page-item ${disabledClass}`) + + const activeClass = this.current === page.number ? 'active' : '' + const link = appendElement('a', li, `page-link ${activeClass}`, page.text) + if (page.number) { + link.setAttribute('href', `#${page.number}`) + link.setAttribute('data-page', page.number) + } + } +} diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.html b/rt_dashboard/javascript/src/components/tasks/tasks.html index 3c7e8447..a50ee4e6 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.html +++ b/rt_dashboard/javascript/src/components/tasks/tasks.html @@ -35,35 +35,5 @@

- - - - - - - - - - - - - - +
diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 54a1fb26..60357eb2 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -5,13 +5,18 @@ import { appendElement, appendNoDataRow, mapDataToElements, - removeChildNode + removeChildNodes } from '../../utils/dom' import { getJobs, cancelJob, deleteQueue, emptyQueue } from '../../api' export default class Tasks extends HTMLElement { - static get observedAttributes () { - return ['queue-info'] + get queueInfo() { + return this.queueInfo_ + } + + set queueInfo(val) { + this.queueInfo_ = val + this.queueInfoChanged(val) } constructor () { @@ -21,6 +26,7 @@ export default class Tasks extends HTMLElement { this.mapToRow = this.mapToRow.bind(this) this.onEmptyClicked = this.onEmptyClicked.bind(this) this.onDeleteClicked = this.onDeleteClicked.bind(this) + this.selectedPageChange = this.selectedPageChange.bind(this) } connectedCallback () { @@ -28,6 +34,9 @@ export default class Tasks extends HTMLElement { this.deleteBtn = this.shadowRoot.querySelector('p.intro #delete-btn') this.emptyBtn.addEventListener('click', this.onEmptyClicked) this.deleteBtn.addEventListener('click', this.onDeleteClicked) + + const pagerComponent = this.shadowRoot.querySelector('pager-component') + pagerComponent.addEventListener('selectedPageChanged', this.selectedPageChange) } disconnectedCallback () { @@ -35,10 +44,16 @@ export default class Tasks extends HTMLElement { this.removeEventListener.addEventListener('click', this.onDeleteClicked) this.removeTableClickListeners() + + const pagerComponent = this.shadowRoot.querySelector('pager-component') + pagerComponent.removeEventListener('selectedPageChanged', this.selectedPageChange) } - attributeChangedCallback () { - const queueInfo = JSON.parse(this.getAttribute('queue-info')) + selectedPageChange ({ detail: { number } }) { + this.loadQueueTasks(this.queueInfo_.queue, number) + } + + queueInfoChanged (queueInfo) { const { queue, count } = queueInfo this.queue = queue @@ -85,14 +100,14 @@ export default class Tasks extends HTMLElement { } } - loadQueueTasks (queue) { + loadQueueTasks (queue, page = 1) { this.removeTableClickListeners() const tbody = this.shadowRoot.querySelector('tbody') - removeChildNode(tbody) + removeChildNodes(tbody) appendNoDataRow(tbody, 'Loading...', 3) - getJobs(queue, 1, (jobs, pagination) => { + getJobs(queue, page, (jobs, pagination) => { if (!jobs || jobs.length <= 0) { appendNoDataRow(tbody, 'No jobs.', 3) return @@ -104,6 +119,7 @@ export default class Tasks extends HTMLElement { this.cancelLinks.push(link) link.addEventListener('click', this.onCancelClicked) }) + this.updatePager(pagination) }) } @@ -198,4 +214,9 @@ export default class Tasks extends HTMLElement { `Enqueued ${Date(enqueued).relative()}, finished ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) } } + + updatePager (pagination) { + const pagerComponent = this.shadowRoot.querySelector('pager-component') + pagerComponent.pagination = pagination + } } diff --git a/rt_dashboard/javascript/src/utils/dom.js b/rt_dashboard/javascript/src/utils/dom.js index ec28c8d6..01d8eb63 100644 --- a/rt_dashboard/javascript/src/utils/dom.js +++ b/rt_dashboard/javascript/src/utils/dom.js @@ -17,14 +17,14 @@ export const loadTemplate = (parent, templateHtml) => { parent.appendChild(template.content.cloneNode(true)) } -export const removeChildNode = (node) => { +export const removeChildNodes = (node) => { Array.from(node.childNodes).forEach((el) => { node.removeChild(el) }) } export const mapDataToElements = (table, data, itemMapper) => { - removeChildNode(table) + removeChildNodes(table) data.forEach(item => itemMapper(table, item)) } diff --git a/webpack.devserver.config.js b/webpack.devserver.config.js index 96439c46..cc698267 100644 --- a/webpack.devserver.config.js +++ b/webpack.devserver.config.js @@ -46,11 +46,20 @@ module.exports = { }) } app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/1.json', - getJobsHandler({ pages_in_window: 2, next_page: 2, prev_page: null })) + getJobsHandler({ + pages_in_window: [{ number: 1 }, { number: 2 }], + next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' } + })) app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', - getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + getJobsHandler({ + pages_in_window: [{ number: 1 }, { number: 2 }], + prev_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/1' } + })) app.get('/admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', - getJobsHandler({ pages_in_window: 2, next_page: null, prev_page: 1 })) + getJobsHandler({ + pages_in_window: [{ number: 1 }, { number: 2 }], + next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' } + })) app.get('/admin/rt_dashboard/inner/jobs/default/1.json', (req, res) => { res.json({ jobs: [ From 189e3a3dd179ee147d4ee352d63d818c766f16b7 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Mon, 30 Mar 2020 10:03:32 +0300 Subject: [PATCH 53/86] visual indication for ccurrent page --- .../javascript/src/components/pager/pager.js | 15 +++++++++++---- .../javascript/src/components/tasks/tasks.js | 10 +++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js index e8ccfe49..dee762fc 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.js +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -45,7 +45,8 @@ export default class Pager extends HTMLElement { mapPaging ({ pages_in_window: pagesArray, next_page: nextPage, - prev_page: prevPage + prev_page: prevPage, + currentPage }) { let nextPageNum = null let prevPageNum = null @@ -56,6 +57,10 @@ export default class Pager extends HTMLElement { nextPageNum = nextPage.url.split('/').pop() } + if (currentPage) { + this.current = currentPage + } + return [ { text: '«', number: prevPageNum }, ...pagesArray.map(({ number }) => ({ text: number, number })), @@ -85,10 +90,12 @@ export default class Pager extends HTMLElement { mapToPageLinks (parent, page) { const disabledClass = page.number ? '' : 'disabled' - const li = appendElement('li', parent, `page-item ${disabledClass}`) + // Attributes are string. Disabling error for == comparison + // eslint-disable-next-line eqeqeq + const activeClass = this.current == page.number ? 'active' : '' + const li = appendElement('li', parent, `page-item ${disabledClass} ${activeClass}`) - const activeClass = this.current === page.number ? 'active' : '' - const link = appendElement('a', li, `page-link ${activeClass}`, page.text) + const link = appendElement('a', li, 'page-link', page.text) if (page.number) { link.setAttribute('href', `#${page.number}`) link.setAttribute('data-page', page.number) diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 60357eb2..538331d4 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -119,7 +119,8 @@ export default class Tasks extends HTMLElement { this.cancelLinks.push(link) link.addEventListener('click', this.onCancelClicked) }) - this.updatePager(pagination) + + this.updatePager(pagination, page) }) } @@ -215,8 +216,11 @@ export default class Tasks extends HTMLElement { } } - updatePager (pagination) { + updatePager (pagination, currentPage = 1) { const pagerComponent = this.shadowRoot.querySelector('pager-component') - pagerComponent.pagination = pagination + pagerComponent.pagination = { + ...pagination, + currentPage + } } } From fe1349aca148b709414cf0f3a6a03ae7a651d992 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 2 Apr 2020 00:18:28 +0300 Subject: [PATCH 54/86] try babel-parser for ?? --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index b452ec27..45c4f45f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { extends: [ 'standard', ], - + parser: 'babel-eslint', parserOptions: { sourceType: 'module', }, From 0214b248463015ecde473ae7c5da98cf71a30832 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 2 Apr 2020 00:18:56 +0300 Subject: [PATCH 55/86] add babel-parser --- package.json | 1 + yarn.lock | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ce1c18c5..28c82723 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "homepage": "https://github.com/djangsters/rt-dashboard#readme", "dependencies": { "@fortawesome/fontawesome-free": "^5.13.0", + "babel-eslint": "^10.1.0", "bootstrap": "^4.4.1", "command-line-args": "^5.1.1", "css-loader": "^3.4.2", diff --git a/yarn.lock b/yarn.lock index 9d41e578..982a4448 100644 --- a/yarn.lock +++ b/yarn.lock @@ -257,6 +257,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.7.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" + integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== + "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": version "7.9.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.3.tgz#043a5fc2ad8b7ea9facddc4e802a1f0f25da7255" @@ -796,7 +801,7 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": +"@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== @@ -811,7 +816,7 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": +"@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng== @@ -1298,6 +1303,18 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-loader@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" @@ -2654,7 +2671,7 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== From cc317b74cf7184d03daee8b65ba33940ff720314 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Thu, 2 Apr 2020 00:22:54 +0300 Subject: [PATCH 56/86] fix linter issues?? --- .../javascript/src/components/pager/pager.js | 8 +++--- .../src/components/queues/queues.js | 6 ++--- .../javascript/src/components/tasks/tasks.js | 14 +++++----- webpack.config.js | 4 +-- webpack.devserver.config.js | 26 +++++++++---------- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js index dee762fc..85b33514 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.js +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -34,8 +34,8 @@ export default class Pager extends HTMLElement { this.dispatchEvent( new CustomEvent('selectedPageChanged', { detail: { number }, - bubbles: true - }) + bubbles: true, + }), ) e.preventDefault() @@ -46,7 +46,7 @@ export default class Pager extends HTMLElement { pages_in_window: pagesArray, next_page: nextPage, prev_page: prevPage, - currentPage + currentPage, }) { let nextPageNum = null let prevPageNum = null @@ -64,7 +64,7 @@ export default class Pager extends HTMLElement { return [ { text: '«', number: prevPageNum }, ...pagesArray.map(({ number }) => ({ text: number, number })), - { text: '»', number: nextPageNum } + { text: '»', number: nextPageNum }, ] } diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index 8a8c3c58..a976464a 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -58,7 +58,7 @@ export default class Queues extends HTMLElement { const { target: selectedQueue } = e this.sendChangedEvent( selectedQueue.name, - selectedQueue.getAttribute('data-count') + selectedQueue.getAttribute('data-count'), ) e.preventDefault() return false @@ -68,8 +68,8 @@ export default class Queues extends HTMLElement { this.dispatchEvent( new CustomEvent('selectedQueueChange', { detail: { queueName, count }, - bubbles: true - }) + bubbles: true, + }), ) } } diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 538331d4..6ab01d91 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -5,16 +5,16 @@ import { appendElement, appendNoDataRow, mapDataToElements, - removeChildNodes + removeChildNodes, } from '../../utils/dom' import { getJobs, cancelJob, deleteQueue, emptyQueue } from '../../api' export default class Tasks extends HTMLElement { - get queueInfo() { + get queueInfo () { return this.queueInfo_ } - set queueInfo(val) { + set queueInfo (val) { this.queueInfo_ = val this.queueInfoChanged(val) } @@ -148,7 +148,7 @@ export default class Tasks extends HTMLElement { error_message: error, enqueued_at: enqueued, started_at: started, - ended_at: ended + ended_at: ended, }) { const row = appendElement('tr', parent) row.setAttribute('data-role', 'job') @@ -163,7 +163,7 @@ export default class Tasks extends HTMLElement { error, enqueued, started, - ended + ended, }) const col2 = appendElement('td', row) @@ -188,7 +188,7 @@ export default class Tasks extends HTMLElement { error, enqueued, started, - ended + ended, }) { const td = appendElement('td', row) appendElement('i', td, 'fas fa-file') @@ -220,7 +220,7 @@ export default class Tasks extends HTMLElement { const pagerComponent = this.shadowRoot.querySelector('pager-component') pagerComponent.pagination = { ...pagination, - currentPage + currentPage, } } } diff --git a/webpack.config.js b/webpack.config.js index a1960fd0..8adbf9a1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -71,6 +71,6 @@ module.exports = { hot: true, https: false, noInfo: true, - ...devServerConfig - } + ...devServerConfig, + }, } diff --git a/webpack.devserver.config.js b/webpack.devserver.config.js index cc698267..f665b0c1 100644 --- a/webpack.devserver.config.js +++ b/webpack.devserver.config.js @@ -5,8 +5,8 @@ module.exports = { queues: [ { name: '[test]', count: 0, url: '/admin/rt_dashboard/inner/test' }, { name: '[running]', count: 1, url: '/admin/rt_dashboard/inner/running' }, - { name: 'default', count: 0, url: '/admin/rt_dashboard/inner/default' } - ] + { name: 'default', count: 0, url: '/admin/rt_dashboard/inner/default' }, + ], }) }) app.get('/admin/rt_dashboard/inner/workers.json', (req, res) => { @@ -14,12 +14,12 @@ module.exports = { workers: [{ state: 'pause', name: 'v-yf.2193', - queues: ['default', 'low_prio_queue'] + queues: ['default', 'low_prio_queue'], }, { state: 'busy', name: 'v-yf.2192', - queues: ['empty', 'high_prio_queue'] - }] + queues: ['empty', 'high_prio_queue'], + }], }) }) @@ -32,7 +32,7 @@ module.exports = { error_message: error, enqueued_at: new Date().getTime(), started_at: new Date().getTime(), - ended_at: new Date().getTime() + ended_at: new Date().getTime(), }) const getJobsHandler = (pagination) => (req, res) => { res.json({ @@ -40,31 +40,31 @@ module.exports = { generateTask('fa02bf65-0527-40d0-acae-9f3c041fAAAA', 'General error', 'failed'), generateTask('fa02bf65-0527-40d0-acae-9f3c041f3EEE', null, 'finished'), generateTask('fa02bf65-0527-40d0-acae-9f3c041f3FFF', null, 'finished'), - generateTask('fa02bf65-0527-40d0-BBBB-9f3c041fBBBB', null, 'running') + generateTask('fa02bf65-0527-40d0-BBBB-9f3c041fBBBB', null, 'running'), ], - pagination + pagination, }) } app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/1.json', getJobsHandler({ pages_in_window: [{ number: 1 }, { number: 2 }], - next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' } + next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' }, })) app.get('/admin/rt_dashboard/inner/jobs/%5Btest%5D/2.json', getJobsHandler({ pages_in_window: [{ number: 1 }, { number: 2 }], - prev_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/1' } + prev_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/1' }, })) app.get('/admin/rt_dashboard/inner/jobs/%5Brunning%5D/1.json', getJobsHandler({ pages_in_window: [{ number: 1 }, { number: 2 }], - next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' } + next_page: { url: '/admin/rt_dashboard/inner/%5Btest%5D/5' }, })) app.get('/admin/rt_dashboard/inner/jobs/default/1.json', (req, res) => { res.json({ jobs: [ ], - pagination: { pages_in_window: 0, next_page: null, prev_page: null } + pagination: { pages_in_window: 0, next_page: null, prev_page: null }, }) }) app.post('/admin/rt_dashboard/inner/queue/default/delete', (req, res) => { @@ -76,5 +76,5 @@ module.exports = { app.post('/admin/rt_dashboard/inner/job/fa02bf65-0527-40d0-BBBB-9f3c041fBBBB/cancel', (req, res) => { res.json({}) }) - } + }, } From aaf6d1f402865b42378dc0e8932b69eea654ef1d Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 19 May 2020 10:43:19 +0300 Subject: [PATCH 57/86] Create date functions wrapper and tests --- package.json | 12 +- .../javascript/src/components/tasks/tasks.js | 12 +- rt_dashboard/javascript/src/utils/utils.js | 9 + .../javascript/src/utils/utils.test.js | 40 + yarn.lock | 1795 ++++++++++++++++- 5 files changed, 1839 insertions(+), 29 deletions(-) create mode 100644 rt_dashboard/javascript/src/utils/utils.js create mode 100644 rt_dashboard/javascript/src/utils/utils.test.js diff --git a/package.json b/package.json index 28c82723..c3e12736 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "tests" }, "scripts": { - "test": "test", + "test": "jest", "build": "webpack", "start": "webpack-dev-server --watch", "lint": "eslint ." @@ -47,6 +47,7 @@ "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.0", "@babel/preset-react": "^7.9.1", + "babel-jest": "^26.0.1", "babel-loader": "^8.1.0", "eslint": "^6.8.0", "eslint-config-standard": "^14.1.1", @@ -54,6 +55,7 @@ "eslint-plugin-node": "^11.0.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", + "jest": "^26.0.1", "mini-css-extract-plugin": "^0.9.0", "node-sass": "^4.13.1", "postcss-loader": "^3.0.0", @@ -69,5 +71,11 @@ "**/*.scss", "./rt_dashboard/javascript/src/app.js", "./rt_dashboard/javascript/src/components/*/index.js" - ] + ], + "jest": { + "verbose": true, + "transform": { + "^.+\\.js$": "babel-jest" + } + } } diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 6ab01d91..a36fd6dd 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -1,4 +1,3 @@ -import { Date, Number } from 'sugar' import html from './tasks.html' import { loadTemplate, @@ -8,6 +7,7 @@ import { removeChildNodes, } from '../../utils/dom' import { getJobs, cancelJob, deleteQueue, emptyQueue } from '../../api' +import { duration, relative } from '../../utils/utils' export default class Tasks extends HTMLElement { get queueInfo () { @@ -168,9 +168,9 @@ export default class Tasks extends HTMLElement { const col2 = appendElement('td', row) if (status === 'running') { - appendElement('span', col2, 'creation_date', `${Number(new Date().getTime() - started).duration()}`) + appendElement('span', col2, 'creation_date', `${duration(started, new Date().getTime())}`) } else { - appendElement('span', col2, 'creation_date', `${Date(ended ?? enqueued).relative()}`) + appendElement('span', col2, 'creation_date', `${relative(ended ?? enqueued)}`) } const col3 = appendElement('td', row, 'actions narrow') @@ -205,14 +205,14 @@ export default class Tasks extends HTMLElement { appendElement('div', td, 'job_id d-block', id) if (status === 'running') { - appendElement('span', td, 'end_date', `Enqueued ${Date(enqueued).relative()}`) + appendElement('span', td, 'end_date', `Enqueued ${relative(enqueued)}`) } else if (status === 'failed') { appendElement('span', td, 'end_date', - `Enqueued ${Date(enqueued).relative()}, failed ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) + `Enqueued ${relative(enqueued)}, failed ${relative(ended)}, ran for ${duration(started, ended)}`) appendElement('pre', td, 'exc_info', `
${error}
`) } else if (status === 'finished') { appendElement('span', td, 'end_date', - `Enqueued ${Date(enqueued).relative()}, finished ${Date(ended).relative()}, ran for ${Number(ended - started).duration()}`) + `Enqueued ${relative(enqueued)}, finished ${relative(ended)}, ran for ${duration(started, ended)}`) } } diff --git a/rt_dashboard/javascript/src/utils/utils.js b/rt_dashboard/javascript/src/utils/utils.js new file mode 100644 index 00000000..77e762be --- /dev/null +++ b/rt_dashboard/javascript/src/utils/utils.js @@ -0,0 +1,9 @@ +import { Date, Number } from 'sugar' + +export const duration = (start, end) => { + return `${Number(end - start).duration()}` +} + +export const relative = (start) => { + return `${Date(start).relative().toString()}` +} diff --git a/rt_dashboard/javascript/src/utils/utils.test.js b/rt_dashboard/javascript/src/utils/utils.test.js new file mode 100644 index 00000000..3d4fecb7 --- /dev/null +++ b/rt_dashboard/javascript/src/utils/utils.test.js @@ -0,0 +1,40 @@ +/* globals describe, test, expect */ +import { duration, relative } from './utils' + +describe('duration', () => { + test('handles miliseconds args ', () => { + const interval = 5 * 1000 + const start = new Date().getTime() - interval + const end = new Date().getTime() + + expect(duration(start, end)).toBe('5 seconds') + }) + + test('handles Date args ', () => { + const start = new Date() + const end = new Date() + + expect(duration(start, end)).toBe('0 milliseconds') + }) +}) + +describe('relative', () => { + test('handles miliseconds arg', () => { + const interval = 5 * 1000 + const start = new Date().getTime() - interval + + expect(relative(start)).toBe('5 seconds ago') + }) + + test('handles Date arg', () => { + const start = new Date() + + expect(relative(start)).toBe('1 second ago') + }) + + test('handles ISO string arg', () => { + const start = new Date().toISOString() + + expect(relative(start)).toBe('1 second ago') + }) +}) diff --git a/yarn.lock b/yarn.lock index 982a4448..af5e55c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,6 +18,28 @@ invariant "^2.2.4" semver "^5.5.0" +"@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" + integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.6" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.6" + "@babel/parser" "^7.9.6" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.6" + "@babel/types" "^7.9.6" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/core@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" @@ -50,6 +72,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" + integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== + dependencies: + "@babel/types" "^7.9.6" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -128,6 +160,15 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" + integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" + "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" @@ -229,6 +270,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== +"@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + "@babel/helper-wrap-function@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" @@ -248,6 +294,15 @@ "@babel/traverse" "^7.9.0" "@babel/types" "^7.9.0" +"@babel/helpers@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" + integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.6" + "@babel/types" "^7.9.6" + "@babel/highlight@^7.8.3": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" @@ -257,6 +312,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.1.0", "@babel/parser@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" + integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== + "@babel/parser@^7.7.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" @@ -340,13 +400,27 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.8" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-async-generators@^7.8.0": +"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz#6cb933a8872c8d359bfde69bbeaae5162fd1e8f7" + integrity sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -354,7 +428,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-json-strings@^7.8.0": +"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -368,7 +442,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz#3995d7d7ffff432f6ddc742b47e730c054599897" + integrity sha512-Zpg2Sgc++37kuFl6ppq2Q7Awc6E6AIW671x5PY8E/f7MCIyPPGK/EoeZXvvY3P42exZ3Q4/t3YOzP/HiN79jDg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== @@ -382,21 +463,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-object-rest-spread@^7.8.0": +"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.8.0": +"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.8.0": +"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== @@ -792,7 +873,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.3.3", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== @@ -801,6 +882,21 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" +"@babel/traverse@^7.1.0", "@babel/traverse@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" + integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.6" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.6" + "@babel/types" "^7.9.6" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" @@ -816,6 +912,15 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.9.5", "@babel/types@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" + integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" @@ -825,11 +930,252 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + "@fortawesome/fontawesome-free@^5.13.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz#fcb113d1aca4b471b709e8c9c168674fbd6e06d9" integrity sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" + integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + +"@jest/console@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.0.1.tgz#62b3b2fa8990f3cbffbef695c42ae9ddbc8f4b39" + integrity sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-message-util "^26.0.1" + jest-util "^26.0.1" + slash "^3.0.0" + +"@jest/core@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.0.1.tgz#aa538d52497dfab56735efb00e506be83d841fae" + integrity sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ== + dependencies: + "@jest/console" "^26.0.1" + "@jest/reporters" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^26.0.1" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-resolve-dependencies "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + jest-watcher "^26.0.1" + micromatch "^4.0.2" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.0.1.tgz#82f519bba71959be9b483675ee89de8c8f72a5c8" + integrity sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g== + dependencies: + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + +"@jest/fake-timers@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.0.1.tgz#f7aeff13b9f387e9d0cac9a8de3bba538d19d796" + integrity sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg== + dependencies: + "@jest/types" "^26.0.1" + "@sinonjs/fake-timers" "^6.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + +"@jest/globals@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.0.1.tgz#3f67b508a7ce62b6e6efc536f3d18ec9deb19a9c" + integrity sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/types" "^26.0.1" + expect "^26.0.1" + +"@jest/reporters@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.0.1.tgz#14ae00e7a93e498cec35b0c00ab21c375d9b078f" + integrity sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^26.0.1" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^4.1.3" + optionalDependencies: + node-notifier "^7.0.0" + +"@jest/source-map@^26.0.0": + version "26.0.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.0.0.tgz#fd7706484a7d3faf7792ae29783933bbf48a4749" + integrity sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.0.1.tgz#1ffdc1ba4bc289919e54b9414b74c9c2f7b2b718" + integrity sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg== + dependencies: + "@jest/console" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz#b0563424728f3fe9e75d1442b9ae4c11da73f090" + integrity sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg== + dependencies: + "@jest/test-result" "^26.0.1" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" + +"@jest/transform@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.0.1.tgz#0e3ecbb34a11cd4b2080ed0a9c4856cf0ceb0639" + integrity sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.0.1" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-regex-util "^26.0.0" + jest-util "^26.0.1" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.0.1.tgz#b78333fbd113fa7aec8d39de24f88de8686dac67" + integrity sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@sinonjs/commons@^1.7.0": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2" + integrity sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@types/babel__core@^7.1.7": + version "7.1.7" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89" + integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" + integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.11.tgz#1ae3010e8bf8851d324878b42acec71986486d18" + integrity sha512-ddHK5icION5U6q11+tV2f9Mo6CZVuT8GJKld2q9LqHSZbvLbH34Kcu2yFGckZut453+eQU6btIA3RihmnRgI+Q== + dependencies: + "@babel/types" "^7.3.0" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -849,6 +1195,33 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/graceful-fs@^4.1.2": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" + integrity sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5" + integrity sha512-rsZg7eL+Xcxsxk2XlBt9KcG8nOp9iYdKCOikY9x2RFJCyOdNj4MKPQty0e8oZr29vVAzKXr1BmR+kZauti3o1w== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -859,6 +1232,33 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.3.tgz#6356df2647de9eac569f9a52eda3480fa9e70b4d" integrity sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/prettier@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4" + integrity sha512-/rM+sWiuOZ5dvuVzV37sUuklsbg+JPOP8d+nNFlo2ZtfpzPiPvh1/gc8liWOLBqe+sR+ZM7guPaIcTt6UZTo7Q== + +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + +"@types/yargs-parser@*": + version "15.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== + +"@types/yargs@^15.0.0": + version "15.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" + integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -1015,6 +1415,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abab@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1028,11 +1433,24 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + acorn-jsx@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== +acorn-walk@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" + integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== + acorn@^6.2.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" @@ -1117,7 +1535,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -1133,6 +1551,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1315,6 +1741,20 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" +babel-jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.0.1.tgz#450139ce4b6c17174b136425bda91885c397bc46" + integrity sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw== + dependencies: + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + babel-loader@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" @@ -1333,6 +1773,50 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz#fd1d35f95cf8849fc65cb01b5e58aedd710b34a8" + integrity sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz#fb4a4c51fe38ca60fede1dc74ab35eb843cb41d6" + integrity sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +babel-preset-jest@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz#1eac82f513ad36c4db2e9263d7c485c825b1faa6" + integrity sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw== + dependencies: + babel-plugin-jest-hoist "^26.0.0" + babel-preset-current-node-syntax "^0.1.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1459,11 +1943,23 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -1533,6 +2029,13 @@ browserslist@^4.8.3, browserslist@^4.9.1: node-releases "^1.1.52" pkg-up "^3.1.0" +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1663,11 +2166,23 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== + caniuse-lite@^1.0.30001035: version "1.0.30001036" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001036.tgz#930ea5272010d8bf190d859159d757c0b398caf0" integrity sha512-jU8CIFIj2oR7r4W+5AKcsvWNVIb6Q6OZE3UsrXrZBHFtreT4YgTeOJtTucp+zSedEpTi3L5wASSP0LYIE3if6w== +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1701,6 +2216,19 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1737,6 +2265,11 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1801,6 +2334,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -1810,11 +2352,21 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -1956,7 +2508,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -2063,6 +2615,15 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" + integrity sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2103,6 +2664,23 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2204,6 +2782,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2230,6 +2817,11 @@ decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" + integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2252,6 +2844,11 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -2335,11 +2932,21 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + detect-node@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +diff-sequences@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" + integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -2402,6 +3009,13 @@ domelementtype@^2.0.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + domhandler@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" @@ -2572,6 +3186,23 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" + integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + eslint-config-standard@^14.1.1: version "14.1.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" @@ -2728,7 +3359,7 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -2747,7 +3378,7 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" -estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -2792,6 +3423,11 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +exec-sh@^0.3.2: + version "0.3.4" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" + integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -2805,6 +3441,26 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.1.tgz#988488781f1f0238cd156f7aaede11c3e853b4c1" + integrity sha512-SCjM/zlBdOK8Q5TIjOn6iEHZaPHFsMoTxXQ2nvUvtPnuohz3H2dIozSg+etNR98dGoYUp2ENSKLL/XaMmbxVgw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -2825,6 +3481,18 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" + integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== + dependencies: + "@jest/types" "^26.0.1" + ansi-styles "^4.0.0" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" + express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -2943,6 +3611,13 @@ faye-websocket@~0.11.1: dependencies: websocket-driver ">=0.5.1" +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -2985,6 +3660,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + finalhandler@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" @@ -3036,6 +3718,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + findup-sync@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" @@ -3142,6 +3832,11 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" +fsevents@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" @@ -3210,6 +3905,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3237,7 +3939,7 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3322,6 +4024,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + handle-thing@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" @@ -3457,11 +4169,23 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + html-entities@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-loader@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.0.0.tgz#40000ff27bfb4fbf087d37f8438cae0b1d8b53b1" @@ -3571,6 +4295,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3643,6 +4372,14 @@ import-local@2.0.0, import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3808,6 +4545,13 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -3850,6 +4594,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -3889,6 +4638,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -3910,6 +4664,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-path-cwd@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" @@ -3941,6 +4700,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -3958,6 +4722,11 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" @@ -3970,7 +4739,7 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -3990,6 +4759,13 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -4017,6 +4793,407 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.0.1.tgz#1334630c6a1ad75784120f39c3aa9278e59f349f" + integrity sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw== + dependencies: + "@jest/types" "^26.0.1" + execa "^4.0.0" + throat "^5.0.0" + +jest-cli@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.0.1.tgz#3a42399a4cbc96a519b99ad069a117d955570cac" + integrity sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w== + dependencies: + "@jest/core" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + is-ci "^2.0.0" + jest-config "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + prompts "^2.0.1" + yargs "^15.3.1" + +jest-config@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.0.1.tgz#096a3d4150afadf719d1fab00e9a6fb2d6d67507" + integrity sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^26.0.1" + "@jest/types" "^26.0.1" + babel-jest "^26.0.1" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.0.1" + jest-environment-node "^26.0.1" + jest-get-type "^26.0.0" + jest-jasmine2 "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + micromatch "^4.0.2" + pretty-format "^26.0.1" + +jest-diff@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.0.1.tgz#c44ab3cdd5977d466de69c46929e0e57f89aa1de" + integrity sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.0.0" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== + dependencies: + detect-newline "^3.0.0" + +jest-each@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.0.1.tgz#633083061619302fc90dd8f58350f9d77d67be04" + integrity sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-get-type "^26.0.0" + jest-util "^26.0.1" + pretty-format "^26.0.1" + +jest-environment-jsdom@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz#217690852e5bdd7c846a4e3b50c8ffd441dfd249" + integrity sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + jsdom "^16.2.2" + +jest-environment-node@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.0.1.tgz#584a9ff623124ff6eeb49e0131b5f7612b310b13" + integrity sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + +jest-get-type@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" + integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== + +jest-haste-map@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.0.1.tgz#40dcc03c43ac94d25b8618075804d09cd5d49de7" + integrity sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA== + dependencies: + "@jest/types" "^26.0.1" + "@types/graceful-fs" "^4.1.2" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-serializer "^26.0.0" + jest-util "^26.0.1" + jest-worker "^26.0.0" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + which "^2.0.2" + optionalDependencies: + fsevents "^2.1.2" + +jest-jasmine2@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz#947c40ee816636ba23112af3206d6fa7b23c1c1c" + integrity sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + co "^4.6.0" + expect "^26.0.1" + is-generator-fn "^2.0.0" + jest-each "^26.0.1" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + pretty-format "^26.0.1" + throat "^5.0.0" + +jest-leak-detector@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz#79b19ab3f41170e0a78eb8fa754a116d3447fb8c" + integrity sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA== + dependencies: + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-matcher-utils@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" + integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-message-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" + integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.0.1" + "@types/stack-utils" "^1.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +jest-mock@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.0.1.tgz#7fd1517ed4955397cf1620a771dc2d61fad8fd40" + integrity sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q== + dependencies: + "@jest/types" "^26.0.1" + +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-resolve-dependencies@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz#607ba7ccc32151d185a477cff45bf33bce417f0b" + integrity sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw== + dependencies: + "@jest/types" "^26.0.1" + jest-regex-util "^26.0.0" + jest-snapshot "^26.0.1" + +jest-resolve@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.0.1.tgz#21d1ee06f9ea270a343a8893051aeed940cde736" + integrity sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.1" + jest-util "^26.0.1" + read-pkg-up "^7.0.1" + resolve "^1.17.0" + slash "^3.0.0" + +jest-runner@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.0.1.tgz#ea03584b7ae4bacfb7e533d680a575a49ae35d50" + integrity sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA== + dependencies: + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-docblock "^26.0.0" + jest-haste-map "^26.0.1" + jest-jasmine2 "^26.0.1" + jest-leak-detector "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" + jest-runtime "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" + source-map-support "^0.5.6" + throat "^5.0.0" + +jest-runtime@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.0.1.tgz#a121a6321235987d294168e282d52b364d7d3f89" + integrity sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw== + dependencies: + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/globals" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.3.1" + +jest-serializer@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.0.0.tgz#f6c521ddb976943b93e662c0d4d79245abec72a3" + integrity sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ== + dependencies: + graceful-fs "^4.2.4" + +jest-snapshot@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.0.1.tgz#1baa942bd83d47b837a84af7fcf5fd4a236da399" + integrity sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^26.0.1" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.0.1" + graceful-fs "^4.2.4" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" + make-dir "^3.0.0" + natural-compare "^1.4.0" + pretty-format "^26.0.1" + semver "^7.3.2" + +jest-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.0.1.tgz#72c4c51177b695fdd795ca072a6f94e3d7cef00a" + integrity sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + make-dir "^3.0.0" + +jest-validate@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.0.1.tgz#a62987e1da5b7f724130f904725e22f4e5b2e23c" + integrity sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA== + dependencies: + "@jest/types" "^26.0.1" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.0.0" + leven "^3.1.0" + pretty-format "^26.0.1" + +jest-watcher@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.0.1.tgz#5b5e3ebbdf10c240e22a98af66d645631afda770" + integrity sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw== + dependencies: + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^26.0.1" + string-length "^4.0.1" + +jest-worker@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066" + integrity sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.0.1.tgz#5c51a2e58dff7525b65f169721767173bf832694" + integrity sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg== + dependencies: + "@jest/core" "^26.0.1" + import-local "^3.0.2" + jest-cli "^26.0.1" + jquery@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" @@ -4045,6 +5222,38 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsdom@^16.2.2: + version "16.2.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" + integrity sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" + tough-cookie "^3.0.1" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.0.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + ws "^7.2.3" + xml-name-validator "^3.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4138,6 +5347,11 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -4172,6 +5386,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -4241,11 +5460,23 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.12: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -4301,6 +5532,20 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + mamacro@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" @@ -4390,6 +5635,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -4414,6 +5664,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -4476,7 +5734,7 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -4637,6 +5895,11 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -4666,6 +5929,23 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + +node-notifier@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.0.tgz#513bc42f2aa3a49fce1980a7ff375957c71f718a" + integrity sha512-y8ThJESxsHcak81PGpzWwQKxzk+5YtP3IxR8AYdpXQ1IB6FmcVzFdZXrkPin49F/DKUCfeeiziB8ptY9npzGuA== + dependencies: + growly "^1.3.0" + is-wsl "^2.1.1" + semver "^7.2.1" + shellwords "^0.1.1" + uuid "^7.0.3" + which "^2.0.2" + node-releases@^1.1.52: version "1.1.52" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9" @@ -4703,7 +5983,7 @@ node-sass@^4.13.1: dependencies: abbrev "1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -4742,6 +6022,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -4757,6 +6044,11 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -4863,7 +6155,7 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optionator@^0.8.3: +optionator@^0.8.1, optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4926,6 +6218,11 @@ p-defer@^1.0.0: resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= +p-each-series@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" + integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -4950,6 +6247,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -4964,6 +6268,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -5042,6 +6353,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -5052,6 +6373,11 @@ parse-srcset@^1.0.2: resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -5092,6 +6418,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -5107,6 +6438,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -5149,6 +6485,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picomatch@^2.0.4, picomatch@^2.0.5: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5171,6 +6512,13 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -5185,6 +6533,13 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" @@ -5295,6 +6650,16 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +pretty-format@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.0.1.tgz#a4fe54fe428ad2fd3413ca6bbd1ec8c2e277e197" + integrity sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw== + dependencies: + "@jest/types" "^26.0.1" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -5320,6 +6685,14 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +prompts@^2.0.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" + integrity sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.4" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -5458,6 +6831,11 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +react-is@^16.12.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -5474,6 +6852,15 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -5492,6 +6879,16 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -5633,7 +7030,23 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.87.0, request@^2.88.0: +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + +request-promise-native@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + dependencies: + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.87.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -5686,6 +7099,13 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" @@ -5704,6 +7124,11 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -5716,6 +7141,13 @@ resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3 dependencies: path-parse "^1.0.6" +resolve@^1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -5748,6 +7180,13 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -5756,6 +7195,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + run-async@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" @@ -5799,6 +7243,21 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" @@ -5820,6 +7279,13 @@ sass-loader@^8.0.2: schema-utils "^2.6.1" semver "^6.3.0" +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -5867,11 +7333,16 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -5976,16 +7447,43 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +sisteransi@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -6068,6 +7566,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.5.6: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.12: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" @@ -6098,6 +7604,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -6181,6 +7692,13 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +stack-utils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" + integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + dependencies: + escape-string-regexp "^2.0.0" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -6201,6 +7719,11 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -6238,6 +7761,14 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= +string-length@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" + integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -6264,7 +7795,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: +string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -6343,11 +7874,21 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -6399,13 +7940,26 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" + integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -6430,6 +7984,14 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + terser-webpack-plugin@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" @@ -6454,11 +8016,25 @@ terser@^4.1.2, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -6491,6 +8067,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -6516,6 +8097,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -6531,7 +8119,7 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -tough-cookie@~2.5.0: +tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -6539,6 +8127,22 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== + dependencies: + punycode "^2.1.1" + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -6580,11 +8184,21 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -6598,6 +8212,13 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -6740,6 +8361,11 @@ uuid@^3.0.1, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + v8-compile-cache@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" @@ -6750,6 +8376,15 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== +v8-to-istanbul@^4.1.3: + version "4.1.4" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" + integrity sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -6777,6 +8412,27 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7, walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -6793,6 +8449,16 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + webpack-cli@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631" @@ -6919,6 +8585,27 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771" + integrity sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^5.0.0" + which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -6936,6 +8623,13 @@ which@1, which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -6972,11 +8666,30 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" @@ -6991,6 +8704,21 @@ ws@^6.2.1: dependencies: async-limiter "~1.0.0" +ws@^7.2.3: + version "7.3.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" + integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -7032,6 +8760,14 @@ yargs-parser@^13.1.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -7074,6 +8810,23 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" + yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From c787551210b6cf3e942689b3d96d714f7dd46de8 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 19 May 2020 11:03:15 +0300 Subject: [PATCH 58/86] replace sugar with date-fns --- package.json | 2 +- rt_dashboard/javascript/src/utils/utils.js | 12 ++++++++---- rt_dashboard/javascript/src/utils/utils.test.js | 6 +++--- yarn.lock | 17 +++++------------ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index c3e12736..4201484b 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "d3-time": "^1.1.0", "d3-time-format": "^2.2.3", "d3-transition": "^1.3.2", + "date-fns": "^2.14.0", "file-loader": "^6.0.0", "html-loader": "^1.0.0", "jquery": "^3.4.1", @@ -61,7 +62,6 @@ "postcss-loader": "^3.0.0", "sass-loader": "^8.0.2", "style-loader": "^1.1.3", - "sugar": "^2.0.6", "webpack": "^4.42.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3" diff --git a/rt_dashboard/javascript/src/utils/utils.js b/rt_dashboard/javascript/src/utils/utils.js index 77e762be..f95cff39 100644 --- a/rt_dashboard/javascript/src/utils/utils.js +++ b/rt_dashboard/javascript/src/utils/utils.js @@ -1,9 +1,13 @@ -import { Date, Number } from 'sugar' +import { formatDistanceStrict, parseISO } from 'date-fns' export const duration = (start, end) => { - return `${Number(end - start).duration()}` + return `${formatDistanceStrict(start, end)}` } -export const relative = (start) => { - return `${Date(start).relative().toString()}` +export const relative = (startDate) => { + let start = startDate + if (typeof startDate === 'string') { + start = parseISO(startDate) + } + return `${formatDistanceStrict(start, new Date(), { addSuffix: true })}` } diff --git a/rt_dashboard/javascript/src/utils/utils.test.js b/rt_dashboard/javascript/src/utils/utils.test.js index 3d4fecb7..89370c5a 100644 --- a/rt_dashboard/javascript/src/utils/utils.test.js +++ b/rt_dashboard/javascript/src/utils/utils.test.js @@ -14,7 +14,7 @@ describe('duration', () => { const start = new Date() const end = new Date() - expect(duration(start, end)).toBe('0 milliseconds') + expect(duration(start, end)).toBe('0 seconds') }) }) @@ -29,12 +29,12 @@ describe('relative', () => { test('handles Date arg', () => { const start = new Date() - expect(relative(start)).toBe('1 second ago') + expect(relative(start)).toBe('0 seconds ago') }) test('handles ISO string arg', () => { const start = new Date().toISOString() - expect(relative(start)).toBe('1 second ago') + expect(relative(start)).toBe('0 seconds ago') }) }) diff --git a/yarn.lock b/yarn.lock index af5e55c1..ddcf7865 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2791,6 +2791,11 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +date-fns@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.14.0.tgz#359a87a265bb34ef2e38f93ecf63ac453f9bc7ba" + integrity sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -7909,18 +7914,6 @@ style-loader@^1.1.3: loader-utils "^1.2.3" schema-utils "^2.6.4" -sugar-core@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/sugar-core/-/sugar-core-2.0.6.tgz#785e0cd64aa7302ea54d47bc1213efe52c006270" - integrity sha512-YmLFysR3Si6RImqL1+aB6JH81EXxvXn5iXhPf2PsjfoUYEwCxFDYCQY+zC3WqviuGWzxFaSkkJvkUE05Y03L5Q== - -sugar@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/sugar/-/sugar-2.0.6.tgz#aa08e389add27109fb35718598313e0503a4fc39" - integrity sha512-s0P2/pjJtAD9VA44+2Gqm3NdC4v+08melA6YubOxzshu628krTbn95/M2GWMrI9rYspZMpYBIrChR46fjQ7xsQ== - dependencies: - sugar-core "^2.0.0" - supports-color@6.1.0, supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" From 0c5a43edd7f76f3823bde4c0917933d1d38b1f43 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 19 May 2020 12:22:06 +0300 Subject: [PATCH 59/86] Fix PR comments --- .../src/components/pager/pager.html | 4 --- .../javascript/src/components/pager/pager.js | 35 +++++++++---------- .../javascript/src/components/tasks/tasks.js | 2 +- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/rt_dashboard/javascript/src/components/pager/pager.html b/rt_dashboard/javascript/src/components/pager/pager.html index bd5d5ae6..c8938521 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.html +++ b/rt_dashboard/javascript/src/components/pager/pager.html @@ -1,9 +1,5 @@ diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js index 85b33514..d9faf77e 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.js +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -6,9 +6,17 @@ export default class Pager extends HTMLElement { return this.paging } + /** + * Sets current paggination settings + * @param {object} value New paggination settings + * @param {number[]} value.pages_in_window Array of page numbers + * @param {string} value.next_page Url to the next page data + * @param {string} value.prev_page Url to the previous page data + * @param {number} value.currentPage Current page number + */ set pagination (value) { this.paging = value - this.updatePager(this.mapPaging(value)) + this.update(value) } constructor () { @@ -28,11 +36,11 @@ export default class Pager extends HTMLElement { onPageClicked (e) { const { target: pageLink } = e - const number = pageLink.getAttribute('data-page') + const number = pageLink.page this.current = number this.dispatchEvent( - new CustomEvent('selectedPageChanged', { + new CustomEvent('change', { detail: { number }, bubbles: true, }), @@ -42,7 +50,7 @@ export default class Pager extends HTMLElement { return false } - mapPaging ({ + update ({ pages_in_window: pagesArray, next_page: nextPage, prev_page: prevPage, @@ -56,29 +64,20 @@ export default class Pager extends HTMLElement { if (nextPage) { nextPageNum = nextPage.url.split('/').pop() } - if (currentPage) { this.current = currentPage } - return [ + const pages = [ { text: '«', number: prevPageNum }, ...pagesArray.map(({ number }) => ({ text: number, number })), { text: '»', number: nextPageNum }, ] - } - - updatePager (pages) { this.pageLinks = [] this.removeEventListeners() const pagesList = this.shadowRoot.querySelector('ul.pagination') mapDataToElements(pagesList, pages, this.mapToPageLinks) - - Array.from(this.shadowRoot.querySelectorAll('li a')).forEach(link => { - this.pageLinks.push(link) - link.addEventListener('click', this.onPageClicked) - }) } removeEventListeners () { @@ -90,15 +89,15 @@ export default class Pager extends HTMLElement { mapToPageLinks (parent, page) { const disabledClass = page.number ? '' : 'disabled' - // Attributes are string. Disabling error for == comparison - // eslint-disable-next-line eqeqeq - const activeClass = this.current == page.number ? 'active' : '' + const activeClass = `${this.current}` === `${page.number}` ? 'active' : '' const li = appendElement('li', parent, `page-item ${disabledClass} ${activeClass}`) const link = appendElement('a', li, 'page-link', page.text) if (page.number) { link.setAttribute('href', `#${page.number}`) - link.setAttribute('data-page', page.number) + link.page = page.number + link.addEventListener('click', this.onPageClicked) + this.pageLinks.push(link) } } } diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index a36fd6dd..1107cce1 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -36,7 +36,7 @@ export default class Tasks extends HTMLElement { this.deleteBtn.addEventListener('click', this.onDeleteClicked) const pagerComponent = this.shadowRoot.querySelector('pager-component') - pagerComponent.addEventListener('selectedPageChanged', this.selectedPageChange) + pagerComponent.addEventListener('change', this.selectedPageChange) } disconnectedCallback () { From 094816fed5c8d11727b761e532c05e0cd44d4754 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 19 May 2020 12:41:26 +0300 Subject: [PATCH 60/86] Fix docs --- rt_dashboard/javascript/src/components/pager/pager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js index d9faf77e..0705215e 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.js +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -9,7 +9,7 @@ export default class Pager extends HTMLElement { /** * Sets current paggination settings * @param {object} value New paggination settings - * @param {number[]} value.pages_in_window Array of page numbers + * @param {{ number: number, url: string }[]} value.pages_in_window Array of page numbers * @param {string} value.next_page Url to the next page data * @param {string} value.prev_page Url to the previous page data * @param {number} value.currentPage Current page number From 247955e7d75459b5019929ad42acf63ecdf50428 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Tue, 19 May 2020 14:27:22 +0300 Subject: [PATCH 61/86] Fix build --- babel.config.js | 17 ++++++++++++++++- package.json | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/babel.config.js b/babel.config.js index 238905bd..92f5f6bd 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,6 +1,6 @@ module.exports = { env: { - test: { + production: { presets: [ [ '@babel/preset-env', @@ -10,5 +10,20 @@ module.exports = { ], ], }, + test: { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + ], + }, }, + plugins: [ + '@babel/plugin-proposal-nullish-coalescing-operator', + ], } diff --git a/package.json b/package.json index 4201484b..453077e9 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "homepage": "https://github.com/djangsters/rt-dashboard#readme", "dependencies": { + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", "@fortawesome/fontawesome-free": "^5.13.0", "babel-eslint": "^10.1.0", "bootstrap": "^4.4.1", From 2819e69dfd073f3c2dc288a2ff82b8569bf714c5 Mon Sep 17 00:00:00 2001 From: Geno Roupsky Date: Tue, 19 May 2020 14:59:09 +0300 Subject: [PATCH 62/86] Remove forgotted debug log --- rt_dashboard/javascript/src/components/history/HistoryChart.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/rt_dashboard/javascript/src/components/history/HistoryChart.js b/rt_dashboard/javascript/src/components/history/HistoryChart.js index 09eb7680..ad879399 100644 --- a/rt_dashboard/javascript/src/components/history/HistoryChart.js +++ b/rt_dashboard/javascript/src/components/history/HistoryChart.js @@ -96,8 +96,6 @@ export default class HistoryChart extends HTMLElement { }, } - console.log(ganttConfig) - if (this._gantt) { this._gantt.redraw() } else { From 8ca4a579a4e206a6cd63c2aacfe8b245e52ec4a1 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Wed, 20 May 2020 13:18:52 +0300 Subject: [PATCH 63/86] Fix date parsing issue --- rt_dashboard/javascript/src/utils/utils.js | 10 +++++++++- rt_dashboard/javascript/src/utils/utils.test.js | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/rt_dashboard/javascript/src/utils/utils.js b/rt_dashboard/javascript/src/utils/utils.js index f95cff39..f57e3253 100644 --- a/rt_dashboard/javascript/src/utils/utils.js +++ b/rt_dashboard/javascript/src/utils/utils.js @@ -1,6 +1,14 @@ import { formatDistanceStrict, parseISO } from 'date-fns' -export const duration = (start, end) => { +export const duration = (startDate, endDate) => { + let start = startDate + let end = endDate + if (typeof startDate === 'string') { + start = parseISO(startDate) + } + if (typeof endDate === 'string') { + end = parseISO(endDate) + } return `${formatDistanceStrict(start, end)}` } diff --git a/rt_dashboard/javascript/src/utils/utils.test.js b/rt_dashboard/javascript/src/utils/utils.test.js index 89370c5a..d61ed2a0 100644 --- a/rt_dashboard/javascript/src/utils/utils.test.js +++ b/rt_dashboard/javascript/src/utils/utils.test.js @@ -10,6 +10,14 @@ describe('duration', () => { expect(duration(start, end)).toBe('5 seconds') }) + test('handles ISO string arg', () => { + const interval = 5 * 1000 + const start = new Date(new Date().getTime() - interval).toISOString() + const end = new Date().toISOString() + + expect(duration(start, end)).toBe('5 seconds') + }) + test('handles Date args ', () => { const start = new Date() const end = new Date() From e4377b4acec61fd510a749e85aec62564547c417 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Wed, 20 May 2020 14:20:46 +0300 Subject: [PATCH 64/86] Fix pager issue when no paging info is provided --- rt_dashboard/javascript/src/components/tasks/tasks.js | 1 + 1 file changed, 1 insertion(+) diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 1107cce1..2e188e1f 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -219,6 +219,7 @@ export default class Tasks extends HTMLElement { updatePager (pagination, currentPage = 1) { const pagerComponent = this.shadowRoot.querySelector('pager-component') pagerComponent.pagination = { + pages_in_window: [{ number: 1 }], ...pagination, currentPage, } From 6299be48aa56d0077e65c46197f98467f723ffb8 Mon Sep 17 00:00:00 2001 From: Dimitar Nikolov Date: Wed, 20 May 2020 14:38:51 +0300 Subject: [PATCH 65/86] Fix css class usage --- rt_dashboard/javascript/src/components/tasks/tasks.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rt_dashboard/javascript/src/components/tasks/tasks.js b/rt_dashboard/javascript/src/components/tasks/tasks.js index 2e188e1f..cc754daa 100644 --- a/rt_dashboard/javascript/src/components/tasks/tasks.js +++ b/rt_dashboard/javascript/src/components/tasks/tasks.js @@ -77,6 +77,8 @@ export default class Tasks extends HTMLElement { queueName.innerHTML = queue if (queue === '[failed]') { queueName.classList.add('failed') + } else { + queueName.classList.remove('failed') } const queueNameSubTitle = this.shadowRoot.querySelector('p.intro strong') From 3b216b7b4c75191ee2b5e7f4e2be6e5775b96c90 Mon Sep 17 00:00:00 2001 From: Geno Roupsky Date: Wed, 20 May 2020 15:37:45 +0300 Subject: [PATCH 66/86] Include styles from js and embed in the bundle --- .../javascript/src/components/dashboard/dashboard.html | 1 - rt_dashboard/javascript/src/components/dashboard/dashboard.js | 3 ++- .../javascript/src/components/history/HistoryPage.html | 1 - rt_dashboard/javascript/src/components/history/HistoryPage.js | 3 ++- rt_dashboard/javascript/src/components/pager/pager.html | 1 - rt_dashboard/javascript/src/components/pager/pager.js | 3 ++- rt_dashboard/javascript/src/components/queues/queues.html | 1 - rt_dashboard/javascript/src/components/queues/queues.js | 3 ++- .../javascript/src/components/rt-dashboard/rt-dashboard.html | 1 - .../javascript/src/components/rt-dashboard/rt-dashboard.js | 3 ++- rt_dashboard/javascript/src/components/tasks/tasks.html | 1 - rt_dashboard/javascript/src/components/tasks/tasks.js | 3 ++- rt_dashboard/javascript/src/components/workers/workers.html | 1 - rt_dashboard/javascript/src/components/workers/workers.js | 3 ++- rt_dashboard/javascript/src/utils/dom.js | 4 ++-- webpack.config.js | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.html b/rt_dashboard/javascript/src/components/dashboard/dashboard.html index 4ee44adb..7ec2eb2b 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.html +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.html @@ -1,4 +1,3 @@ -
diff --git a/rt_dashboard/javascript/src/components/dashboard/dashboard.js b/rt_dashboard/javascript/src/components/dashboard/dashboard.js index d154ad6f..ae8db10b 100644 --- a/rt_dashboard/javascript/src/components/dashboard/dashboard.js +++ b/rt_dashboard/javascript/src/components/dashboard/dashboard.js @@ -1,11 +1,12 @@ import templateHtml from './dashboard.html' +import styles from '../../../styles/main.scss' import { loadTemplate } from '../../utils/dom' export default class Dashboard extends HTMLElement { constructor () { super() - loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml) + loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml, styles) this.selectedQueueChange = this.selectedQueueChange.bind(this) } diff --git a/rt_dashboard/javascript/src/components/history/HistoryPage.html b/rt_dashboard/javascript/src/components/history/HistoryPage.html index 750565bb..48426d38 100644 --- a/rt_dashboard/javascript/src/components/history/HistoryPage.html +++ b/rt_dashboard/javascript/src/components/history/HistoryPage.html @@ -1,4 +1,3 @@ - diff --git a/rt_dashboard/javascript/src/components/history/HistoryPage.js b/rt_dashboard/javascript/src/components/history/HistoryPage.js index 6250d505..a1a592c7 100644 --- a/rt_dashboard/javascript/src/components/history/HistoryPage.js +++ b/rt_dashboard/javascript/src/components/history/HistoryPage.js @@ -1,4 +1,5 @@ import templateHtml from './HistoryPage.html' +import styles from '../../../styles/main.scss' import { loadTemplate } from '../../utils/dom' import { getHistory } from '../../api' @@ -8,7 +9,7 @@ export default class HistoryPage extends HTMLElement { this.attachShadow({ mode: 'open' }) - loadTemplate(this.shadowRoot, templateHtml) + loadTemplate(this.shadowRoot, templateHtml, styles) this._chart = this.shadowRoot.getElementById('chart') diff --git a/rt_dashboard/javascript/src/components/pager/pager.html b/rt_dashboard/javascript/src/components/pager/pager.html index c8938521..99204abf 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.html +++ b/rt_dashboard/javascript/src/components/pager/pager.html @@ -1,4 +1,3 @@ -
diff --git a/rt_dashboard/javascript/src/components/pager/pager.js b/rt_dashboard/javascript/src/components/pager/pager.js index 0705215e..8e39415d 100644 --- a/rt_dashboard/javascript/src/components/pager/pager.js +++ b/rt_dashboard/javascript/src/components/pager/pager.js @@ -1,4 +1,5 @@ import templateHtml from './pager.html' +import styles from '../../../styles/main.scss' import { loadTemplate, mapDataToElements, appendElement } from '../../utils/dom' export default class Pager extends HTMLElement { @@ -22,7 +23,7 @@ export default class Pager extends HTMLElement { constructor () { super() - loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml) + loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml, styles) this.mapToPageLinks = this.mapToPageLinks.bind(this) this.onPageClicked = this.onPageClicked.bind(this) diff --git a/rt_dashboard/javascript/src/components/queues/queues.html b/rt_dashboard/javascript/src/components/queues/queues.html index 8bc56ced..88ac1971 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.html +++ b/rt_dashboard/javascript/src/components/queues/queues.html @@ -1,4 +1,3 @@ -

Queues

This list below contains all the registered queues with the number of tasks currently diff --git a/rt_dashboard/javascript/src/components/queues/queues.js b/rt_dashboard/javascript/src/components/queues/queues.js index a976464a..7ea11122 100644 --- a/rt_dashboard/javascript/src/components/queues/queues.js +++ b/rt_dashboard/javascript/src/components/queues/queues.js @@ -1,4 +1,5 @@ import templateHtml from './queues.html' +import styles from '../../../styles/main.scss' import { appendElement, loadTemplate, mapDataToElements, appendNoDataRow } from '../../utils/dom' import { getQueues } from '../../api' @@ -6,7 +7,7 @@ export default class Queues extends HTMLElement { constructor () { super() - loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml) + loadTemplate(this.attachShadow({ mode: 'open' }), templateHtml, styles) this.onQueueClicked = this.onQueueClicked.bind(this) } diff --git a/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html b/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html index b545dc58..578a3249 100644 --- a/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html +++ b/rt_dashboard/javascript/src/components/rt-dashboard/rt-dashboard.html @@ -1,4 +1,3 @@ -