mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-15 21:36:36 +00:00
Add timer card and badge (#810)
* Add timer card and badge * Disable interval on disconnect * Tests! * One more test case * Remove padStart * Remove state from timer state card
This commit is contained in:
parent
85d58ba134
commit
783f356679
@ -1,6 +1,7 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-syntax": 0,
|
||||
"no-console": 0
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"no-restricted-syntax": 0,
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
||||
|
4
js/common/util/duration_to_seconds.js
Normal file
4
js/common/util/duration_to_seconds.js
Normal file
@ -0,0 +1,4 @@
|
||||
export default function durationToSeconds(duration) {
|
||||
const parts = duration.split(':').map(Number);
|
||||
return (parts[0] * 3600) + (parts[1] * 60) + parts[2];
|
||||
}
|
16
js/common/util/seconds_to_duration.js
Normal file
16
js/common/util/seconds_to_duration.js
Normal file
@ -0,0 +1,16 @@
|
||||
const leftPad = number => (number < 10 ? `0${number}` : number);
|
||||
|
||||
export default function secondsToDuration(d) {
|
||||
const h = Math.floor(d / 3600);
|
||||
const m = Math.floor((d % 3600) / 60);
|
||||
const s = Math.floor(d % 3600 % 60);
|
||||
|
||||
if (h > 0) {
|
||||
return `${h}:${leftPad(m)}:${leftPad(s)}`;
|
||||
} else if (m > 0) {
|
||||
return `${m}:${leftPad(s)}`;
|
||||
} else if (s > 0) {
|
||||
return '' + s;
|
||||
}
|
||||
return null;
|
||||
}
|
@ -11,6 +11,7 @@ const DOMAINS_WITH_CARD = [
|
||||
'media_player',
|
||||
'scene',
|
||||
'script',
|
||||
'timer',
|
||||
'weblink',
|
||||
];
|
||||
|
||||
|
13
js/common/util/timer_time_remaining.js
Normal file
13
js/common/util/timer_time_remaining.js
Normal file
@ -0,0 +1,13 @@
|
||||
import durationToSeconds from './duration_to_seconds.js';
|
||||
|
||||
export default function timerTimeRemaining(stateObj) {
|
||||
let timeRemaining = durationToSeconds(stateObj.attributes.remaining);
|
||||
|
||||
if (stateObj.state === 'active') {
|
||||
const now = new Date();
|
||||
const madeActive = new Date(stateObj.last_changed);
|
||||
timeRemaining = Math.max(timeRemaining - ((now - madeActive) / 1000), 0);
|
||||
}
|
||||
|
||||
return timeRemaining;
|
||||
}
|
32
js/util.js
32
js/util.js
@ -9,14 +9,17 @@
|
||||
import attributeClassNames from './common/util/attribute_class_names.js';
|
||||
import canToggleDomain from './common/util/can_toggle_domain.js';
|
||||
import canToggleState from './common/util/can_toggle_state.js';
|
||||
import computeStateDomain from './common/util/compute_state_domain.js';
|
||||
import computeStateDisplay from './common/util/compute_state_display.js';
|
||||
import computeDomain from './common/util/compute_state_domain.js';
|
||||
import durationToSeconds from './common/util/duration_to_seconds.js';
|
||||
import featureClassNames from './common/util/feature_class_names.js';
|
||||
import formatDate from './common/util/format_date.js';
|
||||
import formatDateTime from './common/util/format_date_time.js';
|
||||
import formatTime from './common/util/format_time.js';
|
||||
import secondsToDuration from './common/util/seconds_to_duration.js';
|
||||
import stateCardType from './common/util/state_card_type.js';
|
||||
import stateMoreInfoType from './common/util/state_more_info_type.js';
|
||||
import timerTimeRemaining from './common/util/timer_time_remaining.js';
|
||||
|
||||
window.hassUtil = window.hassUtil || {};
|
||||
|
||||
@ -25,14 +28,19 @@ const language = navigator.languages ?
|
||||
|
||||
window.fecha.masks.haDateTime = window.fecha.masks.shortTime + ' ' + window.fecha.masks.mediumDate;
|
||||
|
||||
window.hassUtil.attributeClassNames = attributeClassNames;
|
||||
window.hassUtil.canToggleDomain = canToggleDomain;
|
||||
window.hassUtil.canToggleState = canToggleState;
|
||||
window.hassUtil.computeDomain = computeStateDomain;
|
||||
window.hassUtil.computeStateDisplay = computeStateDisplay;
|
||||
window.hassUtil.featureClassNames = featureClassNames;
|
||||
window.hassUtil.formatDate = dateObj => formatDate(dateObj, language);
|
||||
window.hassUtil.formatDateTime = dateObj => formatDateTime(dateObj, language);
|
||||
window.hassUtil.formatTime = dateObj => formatTime(dateObj, language);
|
||||
window.hassUtil.stateCardType = stateCardType;
|
||||
window.hassUtil.stateMoreInfoType = stateMoreInfoType;
|
||||
Object.assign(window.hassUtil, {
|
||||
attributeClassNames,
|
||||
canToggleDomain,
|
||||
canToggleState,
|
||||
computeDomain,
|
||||
computeStateDisplay,
|
||||
durationToSeconds,
|
||||
featureClassNames,
|
||||
secondsToDuration,
|
||||
stateCardType,
|
||||
stateMoreInfoType,
|
||||
timerTimeRemaining,
|
||||
formatDate: dateObj => formatDate(dateObj, language),
|
||||
formatDateTime: dateObj => formatDateTime(dateObj, language),
|
||||
formatTime: dateObj => formatTime(dateObj, language),
|
||||
});
|
||||
|
15
package.json
15
package.json
@ -23,6 +23,13 @@
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"es6-object-assign": "^1.1.0",
|
||||
"home-assistant-js-websocket": "^1.1.2",
|
||||
"mdn-polyfills": "^5.5.0",
|
||||
"preact": "^8.2.6",
|
||||
"unfetch": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
@ -32,7 +39,6 @@
|
||||
"chai": "^4.1.2",
|
||||
"css-slam": "^2.0.2",
|
||||
"del": "^3.0.0",
|
||||
"es6-object-assign": "^1.1.0",
|
||||
"eslint": "^4.11.0",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-plugin-html": "^3.2.2",
|
||||
@ -58,9 +64,7 @@
|
||||
"gulp-util": "^3.0.8",
|
||||
"gulp-vinyl-zip": "^2.1.0",
|
||||
"gulp-zopfli": "^1.0.0",
|
||||
"home-assistant-js-websocket": "^1.1.2",
|
||||
"html-minifier": "^3.5.6",
|
||||
"mdn-polyfills": "^5.5.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"mocha": "^4.0.1",
|
||||
"parse5": "^3.0.3",
|
||||
@ -68,7 +72,6 @@
|
||||
"polymer-build": "^2.1.0",
|
||||
"polymer-bundler": "^3.1.0",
|
||||
"polymer-cli": "^1.5.6",
|
||||
"preact": "^8.2.6",
|
||||
"pump": "^1.0.2",
|
||||
"reify": "^0.12.3",
|
||||
"require-dir": "^0.3.2",
|
||||
@ -79,12 +82,10 @@
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-watch": "^4.3.1",
|
||||
"run-sequence": "^2.2.0",
|
||||
"sinon": "^4.1.6",
|
||||
"sw-precache": "^5.2.0",
|
||||
"uglify-es": "^3.1.9",
|
||||
"uglify-js": "^3.1.9",
|
||||
"unfetch": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"web-component-tester": "^6.4.0"
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
value='[[computeValue(state)]]'
|
||||
icon='[[computeIcon(state)]]'
|
||||
image='[[computeImage(state)]]'
|
||||
label='[[computeLabel(localize, state)]]'
|
||||
label='[[computeLabel(localize, state, timerTimeRemaining)]]'
|
||||
description='[[computeDescription(state)]]'
|
||||
></ha-label-badge>
|
||||
</template>
|
||||
@ -62,9 +62,23 @@ class HaStateLabelBadge extends
|
||||
type: Object,
|
||||
observer: 'stateChanged',
|
||||
},
|
||||
timerTimeRemaining: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.startInterval(this.state);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.clearInterval();
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.addEventListener('tap', ev => this.badgeTap(ev));
|
||||
@ -92,6 +106,7 @@ class HaStateLabelBadge extends
|
||||
case 'updater':
|
||||
case 'sun':
|
||||
case 'alarm_control_panel':
|
||||
case 'timer':
|
||||
return null;
|
||||
case 'sensor':
|
||||
default:
|
||||
@ -128,6 +143,8 @@ class HaStateLabelBadge extends
|
||||
case 'sun':
|
||||
return state.state === 'above_horizon' ?
|
||||
window.hassUtil.domainIcon(domain) : 'mdi:brightness-3';
|
||||
case 'timer':
|
||||
return state.state === 'active' ? 'mdi:timer' : 'mdi:timer-off';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -137,7 +154,7 @@ class HaStateLabelBadge extends
|
||||
return state.attributes.entity_picture || null;
|
||||
}
|
||||
|
||||
computeLabel(localize, state) {
|
||||
computeLabel(localize, state, timerTimeRemaining) {
|
||||
const domain = window.hassUtil.computeDomain(state);
|
||||
if (state.state === 'unavailable' ||
|
||||
['device_tracker', 'alarm_control_panel'].includes(domain)) {
|
||||
@ -146,6 +163,9 @@ class HaStateLabelBadge extends
|
||||
// are only added for device_tracker and alarm_control_panel.
|
||||
return localize(`state_badge.${domain}.${state.state}`) || localize(`state_badge.default.${state.state}`) || state.state;
|
||||
}
|
||||
if (domain === 'timer') {
|
||||
return window.hassUtil.secondsToDuration(timerTimeRemaining);
|
||||
}
|
||||
return state.attributes.unit_of_measurement || null;
|
||||
}
|
||||
|
||||
@ -153,8 +173,31 @@ class HaStateLabelBadge extends
|
||||
return window.hassUtil.computeStateName(state);
|
||||
}
|
||||
|
||||
stateChanged() {
|
||||
stateChanged(stateObj) {
|
||||
this.updateStyles();
|
||||
this.startInterval(stateObj);
|
||||
}
|
||||
|
||||
clearInterval() {
|
||||
if (this._updateRemaining) {
|
||||
clearInterval(this._updateRemaining);
|
||||
this._updateRemaining = null;
|
||||
}
|
||||
}
|
||||
|
||||
startInterval(stateObj) {
|
||||
this.clearInterval();
|
||||
if (window.hassUtil.computeDomain(stateObj) === 'timer') {
|
||||
this.calculateTimerRemaining(stateObj);
|
||||
|
||||
if (stateObj.state === 'active') {
|
||||
this._updateRemaining = setInterval(() => this.calculateTimerRemaining(this.state), 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calculateTimerRemaining(stateObj) {
|
||||
this.timerTimeRemaining = window.hassUtil.timerTimeRemaining(stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,7 @@
|
||||
sun: 1,
|
||||
device_tracker: 2,
|
||||
alarm_control_panel: 3,
|
||||
timer: 4,
|
||||
sensor: 5,
|
||||
binary_sensor: 6,
|
||||
mailbox: 7,
|
||||
|
@ -10,6 +10,7 @@
|
||||
<link rel="import" href="state-card-media_player.html">
|
||||
<link rel="import" href="state-card-scene.html">
|
||||
<link rel="import" href="state-card-script.html">
|
||||
<link rel="import" href="state-card-timer.html">
|
||||
<link rel="import" href="state-card-toggle.html">
|
||||
<link rel="import" href="state-card-weblink.html">
|
||||
|
||||
|
88
src/state-summary/state-card-timer.html
Normal file
88
src/state-summary/state-card-timer.html
Normal file
@ -0,0 +1,88 @@
|
||||
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
|
||||
|
||||
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
|
||||
|
||||
<link rel="import" href="../components/entity/state-info.html">
|
||||
<link rel="import" href="../util/hass-mixins.html">
|
||||
<link rel="import" href="../util/hass-util.html">
|
||||
|
||||
<dom-module id="state-card-timer">
|
||||
<template>
|
||||
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
.state {
|
||||
@apply(--paper-font-body1);
|
||||
color: var(--primary-text-color);
|
||||
|
||||
margin-left: 16px;
|
||||
text-align: right;
|
||||
line-height: 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class='horizontal justified layout'>
|
||||
<state-info state-obj="[[stateObj]]" in-dialog='[[inDialog]]'></state-info>
|
||||
<div class='state'>[[secondsToDuration(timeRemaining)]]</div>
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class StateCardTimer extends window.hassMixins.LocalizeMixin(Polymer.Element) {
|
||||
static get is() { return 'state-card-timer'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
stateObj: {
|
||||
type: Object,
|
||||
observer: 'stateObjChanged',
|
||||
},
|
||||
timeRemaining: Number,
|
||||
inDialog: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.startInterval(this.stateObj);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.clearInterval();
|
||||
}
|
||||
|
||||
stateObjChanged(stateObj) {
|
||||
this.startInterval(stateObj);
|
||||
}
|
||||
|
||||
clearInterval() {
|
||||
if (this._updateRemaining) {
|
||||
clearInterval(this._updateRemaining);
|
||||
this._updateRemaining = null;
|
||||
}
|
||||
}
|
||||
|
||||
startInterval(stateObj) {
|
||||
this.clearInterval();
|
||||
this.calculateRemaining(stateObj);
|
||||
|
||||
if (stateObj.state === 'active') {
|
||||
this._updateRemaining = setInterval(() => this.calculateRemaining(this.stateObj), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
calculateRemaining(stateObj) {
|
||||
this.timeRemaining = window.hassUtil.timerTimeRemaining(stateObj);
|
||||
}
|
||||
|
||||
secondsToDuration(time) {
|
||||
return window.hassUtil.secondsToDuration(time);
|
||||
}
|
||||
}
|
||||
customElements.define(StateCardTimer.is, StateCardTimer);
|
||||
</script>
|
@ -187,6 +187,9 @@ window.hassUtil.domainIcon = function (domain, state) {
|
||||
case 'switch':
|
||||
return 'mdi:flash';
|
||||
|
||||
case 'timer':
|
||||
return 'mdi:timer';
|
||||
|
||||
case 'updater':
|
||||
return 'mdi:cloud-upload';
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
{
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": 0
|
||||
}
|
||||
}
|
||||
|
10
test-mocha/common/util/duration_to_seconds_test.js
Normal file
10
test-mocha/common/util/duration_to_seconds_test.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import durationToSeconds from '../../../js/common/util/duration_to_seconds.js';
|
||||
|
||||
describe('durationToSeconds', () => {
|
||||
it('works', () => {
|
||||
assert.strictEqual(durationToSeconds('0:01:05'), 65);
|
||||
assert.strictEqual(durationToSeconds('11:01:05'), 39665);
|
||||
});
|
||||
});
|
12
test-mocha/common/util/seconds_to_duration_test.js
Normal file
12
test-mocha/common/util/seconds_to_duration_test.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import secondsToDuration from '../../../js/common/util/seconds_to_duration.js';
|
||||
|
||||
describe('secondsToDuration', () => {
|
||||
it('works', () => {
|
||||
assert.strictEqual(secondsToDuration(0), null);
|
||||
assert.strictEqual(secondsToDuration(65), '1:05');
|
||||
assert.strictEqual(secondsToDuration(3665), '1:01:05');
|
||||
assert.strictEqual(secondsToDuration(39665), '11:01:05');
|
||||
});
|
||||
});
|
43
test-mocha/common/util/timer_time_remaining_test.js
Normal file
43
test-mocha/common/util/timer_time_remaining_test.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { assert } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import timerTimeRemaining from '../../../js/common/util/timer_time_remaining.js';
|
||||
|
||||
describe('timerTimeRemaining', () => {
|
||||
it('works with idle timers', () => {
|
||||
assert.strictEqual(timerTimeRemaining({
|
||||
state: 'idle',
|
||||
attributes: {
|
||||
remaining: '0:01:05'
|
||||
}
|
||||
}), 65);
|
||||
});
|
||||
|
||||
it('works with paused timers', () => {
|
||||
assert.strictEqual(timerTimeRemaining({
|
||||
state: 'paused',
|
||||
attributes: {
|
||||
remaining: '0:01:05'
|
||||
}
|
||||
}), 65);
|
||||
});
|
||||
|
||||
describe('active timers', () => {
|
||||
let clock;
|
||||
beforeEach(() => {
|
||||
clock = sinon.useFakeTimers(new Date('2018-01-17T16:15:30Z'));
|
||||
});
|
||||
afterEach(() => {
|
||||
clock.restore();
|
||||
});
|
||||
it('works', () => {
|
||||
assert.strictEqual(timerTimeRemaining({
|
||||
state: 'active',
|
||||
attributes: {
|
||||
remaining: '0:01:05'
|
||||
},
|
||||
last_changed: '2018-01-17T16:15:12Z',
|
||||
}), 47);
|
||||
});
|
||||
});
|
||||
});
|
48
yarn.lock
48
yarn.lock
@ -3275,7 +3275,7 @@ formatio@1.1.1:
|
||||
dependencies:
|
||||
samsam "~1.1"
|
||||
|
||||
formatio@1.2.0:
|
||||
formatio@1.2.0, formatio@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
|
||||
dependencies:
|
||||
@ -4679,6 +4679,10 @@ jsx-ast-utils@^2.0.0:
|
||||
dependencies:
|
||||
array-includes "^3.0.3"
|
||||
|
||||
just-extend@^1.1.26:
|
||||
version "1.1.27"
|
||||
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905"
|
||||
|
||||
kind-of@^3.0.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||
@ -4968,6 +4972,10 @@ lodash.escape@~2.4.1:
|
||||
lodash._reunescapedhtml "~2.4.1"
|
||||
lodash.keys "~2.4.1"
|
||||
|
||||
lodash.get@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||
|
||||
lodash.identity@~2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.identity/-/lodash.identity-2.4.1.tgz#6694cffa65fef931f7c31ce86c74597cf560f4f1"
|
||||
@ -5137,6 +5145,10 @@ lolex@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
|
||||
|
||||
lolex@^2.2.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362"
|
||||
|
||||
longest@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
||||
@ -5544,6 +5556,16 @@ netrc@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444"
|
||||
|
||||
nise@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53"
|
||||
dependencies:
|
||||
formatio "^1.2.0"
|
||||
just-extend "^1.1.26"
|
||||
lolex "^1.6.0"
|
||||
path-to-regexp "^1.7.0"
|
||||
text-encoding "^0.6.4"
|
||||
|
||||
no-case@^2.2.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.1.tgz#7aeba1c73a52184265554b7dc03baf720df80081"
|
||||
@ -7150,6 +7172,18 @@ sinon@^2.3.5:
|
||||
text-encoding "0.6.4"
|
||||
type-detect "^4.0.0"
|
||||
|
||||
sinon@^4.1.6:
|
||||
version "4.1.6"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.6.tgz#9cb346bddb180d68a804429ffe14978d7fafd629"
|
||||
dependencies:
|
||||
diff "^3.1.0"
|
||||
formatio "1.2.0"
|
||||
lodash.get "^4.4.2"
|
||||
lolex "^2.2.0"
|
||||
nise "^1.2.0"
|
||||
supports-color "^5.1.0"
|
||||
type-detect "^4.0.5"
|
||||
|
||||
slash@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
@ -7556,6 +7590,12 @@ supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
|
||||
supports-color@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5"
|
||||
dependencies:
|
||||
has-flag "^2.0.0"
|
||||
|
||||
sw-precache@^5.1.1, sw-precache@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/sw-precache/-/sw-precache-5.2.0.tgz#eb6225ce580ceaae148194578a0ad01ab7ea199c"
|
||||
@ -7684,7 +7724,7 @@ test-value@^2.1.0:
|
||||
array-back "^1.0.3"
|
||||
typical "^2.6.0"
|
||||
|
||||
text-encoding@0.6.4:
|
||||
text-encoding@0.6.4, text-encoding@^0.6.4:
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
|
||||
|
||||
@ -7854,6 +7894,10 @@ type-detect@^4.0.0:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2"
|
||||
|
||||
type-detect@^4.0.5:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.6.tgz#88cbce3d13bc675a63f840b3225c180f870786d7"
|
||||
|
||||
type-is@^1.6.4, type-is@~1.6.15:
|
||||
version "1.6.15"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
|
||||
|
Loading…
x
Reference in New Issue
Block a user