diff --git a/components/UptimeDot/UptimeDot.js b/components/UptimeDot/UptimeDot.js index c6e1c83..5543081 100644 --- a/components/UptimeDot/UptimeDot.js +++ b/components/UptimeDot/UptimeDot.js @@ -10,10 +10,12 @@ const DEFAULT_THRESHOLD = 5; const state = (timeserie, threshold) => { if (timeserie.missingDataPoint) return "missing"; - return Object.values(timeserie.values).reduce((a, b) => Math.max(a, b)) > - threshold - ? "down" - : "up"; + const maxDowntime = Object.values(timeserie.values).reduce((a, b) => + Math.max(a, b) + ); + if (maxDowntime === 1440) return "down"; + if (maxDowntime > threshold) return "partial"; + return "up"; }; export const downtimeSummary = (timeserie, threshold) => { @@ -41,6 +43,7 @@ const UptimeDot = ({ timeserie, threshold = DEFAULT_THRESHOLD }) => { const stateColor = { up: "bg-green-500", down: "bg-red-500", + partial: "bg-yellow-500", missing: "bg-gray-200", }; diff --git a/components/UptimeDot/UptimeDot.test.js b/components/UptimeDot/UptimeDot.test.js index 391332f..9bc01d1 100644 --- a/components/UptimeDot/UptimeDot.test.js +++ b/components/UptimeDot/UptimeDot.test.js @@ -41,7 +41,7 @@ describe("UptimeDot", () => { test("dot is red when down and above threshold", () => { const { container } = build({ timeserie: down, threshold: 0 }); const dot = container.querySelector("div"); - expect(dot.classList).toContain("bg-red-500"); + expect(dot.classList).toContain("bg-yellow-500"); }); test("dot is green when down and under threshold", () => { diff --git a/components/UptimeMonitor/UptimeMonitor.js b/components/UptimeMonitor/UptimeMonitor.js index b4efad5..fa0a78e 100644 --- a/components/UptimeMonitor/UptimeMonitor.js +++ b/components/UptimeMonitor/UptimeMonitor.js @@ -1,9 +1,16 @@ import React from "react"; import PropTypes from "prop-types"; +import Tippy from "@tippyjs/react"; + import OutagesOverlay from "../OutagesOverlay"; import UptimeDots from "../UptimeDots"; +import { + timeseriesByDay as groupTimeseriesByDay, + roundDecimal, +} from "../../utils"; + export const LoadingDot = () => { return (
diff --git a/components/UptimeMonitor/__snapshots__/UptimeMonitor.test.js.snap b/components/UptimeMonitor/__snapshots__/UptimeMonitor.test.js.snap index 1c2221a..c525e5f 100644 --- a/components/UptimeMonitor/__snapshots__/UptimeMonitor.test.js.snap +++ b/components/UptimeMonitor/__snapshots__/UptimeMonitor.test.js.snap @@ -14,6 +14,7 @@ exports[`UptimeMonitor renders without errors 1`] = ` class="c_h-heading focus:outline-none" > homepage +
Always Down +
blog +
homepage +
{ }; export const timeseriesByDay = (timeseries, expectedRegions) => { + if (timeseries === undefined) return []; return sortedTimeseries(timeseries.slice()).reduce((group, timeserie) => { const startOfDay = dayjs(timeserie.timestamp).startOf("day").utc().format(); @@ -67,3 +68,7 @@ export const fillMissingDataPoints = (timeseries, expectedDays) => { } return sortedTimeseries(timeseries); }; + +export const roundDecimal = (number) => { + return parseInt(number.toFixed(3) * 100) / 100; +}; diff --git a/utils/index.test.js b/utils/index.test.js index 8217c2e..603a44a 100644 --- a/utils/index.test.js +++ b/utils/index.test.js @@ -4,6 +4,7 @@ import { timeseriesByDay, sortedTimeseries, fillMissingDataPoints, + roundDecimal, } from "./index"; import homepageMock from "../mocks/monitors/homepage.json"; @@ -120,3 +121,21 @@ describe("#fillMissingDataPoints", () => { expect(withFilledMissingPoints[1].missingDataPoint).toBeFalsy(); }); }); + +describe("#roundDecimal", () => { + it("returns a round number if round number is given", () => { + expect(roundDecimal(100)).toEqual(100); + expect(roundDecimal(50)).toEqual(50); + }); + + it("rounds a number with two decimals", () => { + expect(roundDecimal(100.12)).toEqual(100.12); + expect(roundDecimal(50.34)).toEqual(50.34); + }); + + it("rounds number with more decimals", () => { + expect(roundDecimal(100.122342342344234)).toEqual(100.12); + expect(roundDecimal(50.3499999)).toEqual(50.35); + expect(roundDecimal(99.9075)).toEqual(99.9); + }); +}); diff --git a/yarn.lock b/yarn.lock index 6811e0c..89178dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -926,10 +926,10 @@ lz-string "^1.4.4" pretty-format "^27.0.2" -"@testing-library/jest-dom@^5.14.1": - version "5.16.5" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e" - integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA== +"@testing-library/jest-dom@^5.17.0": + version "5.17.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c" + integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg== dependencies: "@adobe/css-tools" "^4.0.1" "@babel/runtime" "^7.9.2" @@ -2395,10 +2395,10 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -dayjs@^1.10.6: - version "1.11.7" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" - integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== +dayjs@^1.11.11: + version "1.11.11" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" + integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== debug@2: version "2.6.9" @@ -3198,7 +3198,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.2.12, fast-glob@^3.2.9: +fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -3209,6 +3209,17 @@ fast-glob@^3.2.12, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -4633,10 +4644,10 @@ jest@^27.0.6: import-local "^3.0.2" jest-cli "^27.5.1" -jiti@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" - integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== +jiti@^1.21.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== js-cookie@^2.2.1: version "2.2.1" @@ -5094,6 +5105,11 @@ nanoid@^3.3.6: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + native-url@0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.3.4.tgz#29c943172aed86c63cee62c8c04db7f5756661f8" @@ -5966,7 +5982,7 @@ postcss@^8.3.5: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.23, postcss@^8.4.24: +postcss@^8.4.23: version "8.4.24" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df" integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== @@ -5975,6 +5991,15 @@ postcss@^8.4.23, postcss@^8.4.24: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.4.38: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.2.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6656,6 +6681,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-support@^0.5.6: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -7043,20 +7073,20 @@ table@^6.0.9: string-width "^4.2.3" strip-ansi "^6.0.1" -tailwindcss@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3" - integrity sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w== +tailwindcss@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.4.tgz#351d932273e6abfa75ce7d226b5bf3a6cb257c05" + integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" chokidar "^3.5.3" didyoumean "^1.2.2" dlv "^1.1.3" - fast-glob "^3.2.12" + fast-glob "^3.3.0" glob-parent "^6.0.2" is-glob "^4.0.3" - jiti "^1.18.2" + jiti "^1.21.0" lilconfig "^2.1.0" micromatch "^4.0.5" normalize-path "^3.0.0" @@ -7068,7 +7098,6 @@ tailwindcss@^3.3.2: postcss-load-config "^4.0.1" postcss-nested "^6.0.1" postcss-selector-parser "^6.0.11" - postcss-value-parser "^4.2.0" resolve "^1.22.2" sucrase "^3.32.0"