Merge branch 'gw/20201003-initial'
This commit is contained in:
3
web/.env.development
Normal file
3
web/.env.development
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
NEXT_PUBLIC_ADMIN_USERNAME=admin
|
||||||
|
NEXT_PUBLIC_ADMIN_STREAMKEY=abc123
|
||||||
|
NEXT_PUBLIC_API_HOST=http://localhost:8080/
|
||||||
@@ -23,5 +23,29 @@ module.exports = {
|
|||||||
"react/react-in-jsx-scope": "off",
|
"react/react-in-jsx-scope": "off",
|
||||||
"react/jsx-filename-extension": [1, { extensions: [".js", ".jsx", ".tsx"] }],
|
"react/jsx-filename-extension": [1, { extensions: [".js", ".jsx", ".tsx"] }],
|
||||||
"react/jsx-props-no-spreading": "off",
|
"react/jsx-props-no-spreading": "off",
|
||||||
|
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'error',
|
||||||
|
|
||||||
|
'no-use-before-define': [0],
|
||||||
|
'@typescript-eslint/no-use-before-define': [1],
|
||||||
|
|
||||||
|
"import/extensions": [
|
||||||
|
"error",
|
||||||
|
"ignorePackages",
|
||||||
|
{
|
||||||
|
"js": "never",
|
||||||
|
"jsx": "never",
|
||||||
|
"ts": "never",
|
||||||
|
"tsx": "never"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
"import/resolver": {
|
||||||
|
"node": {
|
||||||
|
"extensions": [".js", ".jsx", ".ts", ".tsx"]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
3
web/.gitignore
vendored
3
web/.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
.next
|
||||||
@@ -10,7 +10,7 @@ npm run dev
|
|||||||
yarn dev
|
yarn dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Open [http://localhost:3000/admin](http://localhost:3000/admin) with your browser to see the result.
|
In production this Admin instance would ideally live on the domain as your Owncast instance, for example: `myowncast-site.com/admin`. So open [http://localhost:3000/admin](http://localhost:3000/admin) with your browser to see the result.
|
||||||
|
|
||||||
You can start editing a page by modifying `pages/something.js`. The page auto-updates as you edit the file.
|
You can start editing a page by modifying `pages/something.js`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
@@ -18,6 +18,15 @@ Add new pages by adding files to the `pages` directory and [routes](https://next
|
|||||||
|
|
||||||
Since this project hits API endpoints you should make requests in [`componentDidMount`](https://reactjs.org/docs/react-component.html#componentdidmount), and not in [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching), since they're not static and we don't want to fetch them at build time, but instead at runtime.
|
Since this project hits API endpoints you should make requests in [`componentDidMount`](https://reactjs.org/docs/react-component.html#componentdidmount), and not in [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching), since they're not static and we don't want to fetch them at build time, but instead at runtime.
|
||||||
|
|
||||||
|
|
||||||
|
A list of API end points can be found here:
|
||||||
|
https://github.com/owncast/owncast/blob/master/router/router.go
|
||||||
|
|
||||||
|
### Auth-ing for APIs
|
||||||
|
username: admin
|
||||||
|
pw: [your stramkey]
|
||||||
|
|
||||||
|
|
||||||
## Learn More
|
## Learn More
|
||||||
|
|
||||||
To learn more about Next.js, take a look at the following resources:
|
To learn more about Next.js, take a look at the following resources:
|
||||||
@@ -26,3 +35,4 @@ To learn more about Next.js, take a look at the following resources:
|
|||||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
|||||||
BIN
web/favicon.ico
Normal file
BIN
web/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
234
web/package-lock.json
generated
234
web/package-lock.json
generated
@@ -2685,6 +2685,11 @@
|
|||||||
"toggle-selection": "^1.0.6"
|
"toggle-selection": "^1.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.6.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||||
|
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||||
|
},
|
||||||
"core-js-compat": {
|
"core-js-compat": {
|
||||||
"version": "3.6.5",
|
"version": "3.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
|
||||||
@@ -2904,6 +2909,72 @@
|
|||||||
"type": "^1.0.1"
|
"type": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-array": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.8.0.tgz",
|
||||||
|
"integrity": "sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw=="
|
||||||
|
},
|
||||||
|
"d3-collection": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
|
||||||
|
},
|
||||||
|
"d3-color": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
|
||||||
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
|
||||||
|
},
|
||||||
|
"d3-interpolate": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1 - 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-path": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "3.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.3.tgz",
|
||||||
|
"integrity": "sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^2.3.0",
|
||||||
|
"d3-format": "1 - 2",
|
||||||
|
"d3-interpolate": "1.2.0 - 2",
|
||||||
|
"d3-time": "1 - 2",
|
||||||
|
"d3-time-format": "2 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-shape": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-path": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q=="
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1 - 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
|
||||||
@@ -2936,6 +3007,11 @@
|
|||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"decimal.js-light": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
|
||||||
|
},
|
||||||
"decode-uri-component": {
|
"decode-uri-component": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||||
@@ -3041,6 +3117,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz",
|
||||||
"integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA=="
|
"integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA=="
|
||||||
},
|
},
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dom-serializer": {
|
"dom-serializer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.0.1.tgz",
|
||||||
@@ -4872,11 +4956,21 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||||
},
|
},
|
||||||
|
"lodash.debounce": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||||
|
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
|
||||||
|
},
|
||||||
"lodash.sortby": {
|
"lodash.sortby": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
|
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
|
||||||
},
|
},
|
||||||
|
"lodash.throttle": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
|
},
|
||||||
"loose-envify": {
|
"loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
@@ -4921,6 +5015,11 @@
|
|||||||
"object-visit": "^1.0.0"
|
"object-visit": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"math-expression-evaluator": {
|
||||||
|
"version": "1.2.22",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz",
|
||||||
|
"integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ=="
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
@@ -6369,6 +6468,39 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||||
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
|
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
|
||||||
},
|
},
|
||||||
|
"react-resize-detector": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ==",
|
||||||
|
"requires": {
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"resize-observer-polyfill": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-smooth": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "~4.17.4",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"raf": "^3.4.0",
|
||||||
|
"react-transition-group": "^2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.4.0",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||||
@@ -6482,6 +6614,108 @@
|
|||||||
"readable-stream": "^2.0.2"
|
"readable-stream": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"recharts": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/recharts/-/recharts-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-tM9mprJbXVEBxjM7zHsIy6Cc41oO/pVYqyAsOHLxlJrbNBuLs0PHB3iys2M+RqCF0//k8nJtZF6X6swSkWY3tg==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"core-js": "^2.6.10",
|
||||||
|
"d3-interpolate": "^1.3.0",
|
||||||
|
"d3-scale": "^2.1.0",
|
||||||
|
"d3-shape": "^1.2.0",
|
||||||
|
"lodash": "^4.17.5",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"react-resize-detector": "^2.3.0",
|
||||||
|
"react-smooth": "^1.0.5",
|
||||||
|
"recharts-scale": "^0.4.2",
|
||||||
|
"reduce-css-calc": "^1.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
|
||||||
|
},
|
||||||
|
"d3-color": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
|
||||||
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
|
||||||
|
},
|
||||||
|
"d3-interpolate": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^1.2.0",
|
||||||
|
"d3-collection": "1",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-interpolate": "1",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recharts-scale": {
|
||||||
|
"version": "0.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz",
|
||||||
|
"integrity": "sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==",
|
||||||
|
"requires": {
|
||||||
|
"decimal.js-light": "^2.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reduce-css-calc": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
|
||||||
|
"integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^0.4.2",
|
||||||
|
"math-expression-evaluator": "^1.2.14",
|
||||||
|
"reduce-function-call": "^1.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
|
||||||
|
"integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reduce-function-call": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==",
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
|
||||||
|
|||||||
@@ -10,13 +10,19 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.2.2",
|
"@ant-design/icons": "^4.2.2",
|
||||||
"antd": "^4.6.6",
|
"antd": "^4.6.6",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"d3-scale": "^3.2.3",
|
||||||
|
"d3-time-format": "^3.0.0",
|
||||||
"next": "9.5.3",
|
"next": "9.5.3",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1",
|
"react-dom": "16.13.1",
|
||||||
|
"recharts": "^1.8.5",
|
||||||
"sass": "^1.26.11"
|
"sass": "^1.26.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^14.11.2",
|
"@types/node": "^14.11.2",
|
||||||
|
"@types/prop-types": "^15.7.3",
|
||||||
"@types/react": "^16.9.49",
|
"@types/react": "^16.9.49",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.3.0",
|
"@typescript-eslint/eslint-plugin": "^4.3.0",
|
||||||
"@typescript-eslint/parser": "^4.3.0",
|
"@typescript-eslint/parser": "^4.3.0",
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
import 'antd/dist/antd.css';
|
import 'antd/dist/antd.dark.css';
|
||||||
import '../styles/globals.scss'
|
import 'antd/dist/antd.compact.css';
|
||||||
|
import "../styles/globals.scss";
|
||||||
|
|
||||||
|
import { AppProps } from 'next/app';
|
||||||
|
import BroadcastStatusProvider from './utils/broadcast-status-context';
|
||||||
|
import MainLayout from './components/main-layout';
|
||||||
|
|
||||||
import { AppProps } from 'next/app'
|
|
||||||
|
|
||||||
function App({ Component, pageProps }: AppProps) {
|
function App({ Component, pageProps }: AppProps) {
|
||||||
return <Component {...pageProps} />
|
return (
|
||||||
|
<BroadcastStatusProvider>
|
||||||
|
<MainLayout>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</MainLayout>
|
||||||
|
</BroadcastStatusProvider>
|
||||||
|
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
export default App;
|
||||||
18
web/pages/broadcast-info.tsx
Normal file
18
web/pages/broadcast-info.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { BroadcastStatusContext } from './utils/broadcast-status-context';
|
||||||
|
|
||||||
|
|
||||||
|
export default function BroadcastInfo() {
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcaster } = context || {};
|
||||||
|
const { remoteAddr, time, streamDetails } = broadcaster || {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{border: '1px solid green', width: '100%'}}>
|
||||||
|
<h2>Broadcast Info</h2>
|
||||||
|
<p>Remote Address: {remoteAddr}</p>
|
||||||
|
<p>Time: {(new Date(time)).toLocaleTimeString()}</p>
|
||||||
|
<p>Stream Details: {JSON.stringify(streamDetails)}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
85
web/pages/components/logo.tsx
Normal file
85
web/pages/components/logo.tsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import adminStyles from '../../styles/styles.module.css';
|
||||||
|
|
||||||
|
export default function Logo() {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 95.68623352050781 104.46271514892578" className={adminStyles.logoSVG}>
|
||||||
|
<g transform="matrix(1 0 0 1 -37.08803939819336 -18.940391540527344)">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g transform="matrix(1.0445680396949917 0 0 1.0445679172996596 36.34559138380523 18.877718021903796)">
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient120" gradientTransform="rotate(-90 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#1f2022" stopOpacity="1"/>
|
||||||
|
<stop offset="1" stopColor="#635e69" stopOpacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient120)" d="M91.5 75.35Q93.05 71.15 91.65 67.7 90.35 64.5 86.65 62.3 83.2 60.3 78.3 59.4 73.85 58.6 68.6 58.7 63.55 58.85 58.8 59.8 54.25 60.75 50.8 62.2 47.4 63.65 45.5 65.35 43.6 67.15 43.5 69.05 43.35 71.3 45.8 73.9 48.05 76.3 52.1 78.6 56.15 80.9 61.05 82.55 66.3 84.3 71.4 84.8 74.7 85.1 77.55 84.9 80.65 84.6 83.3 83.6 86.15 82.5 88.15 80.55 90.4 78.4 91.5 75.35M70.6 67.5Q72.3 68.4 73.1 69.7 73.9 71.15 73.45 73 73.1 74.3 72.3 75.25 71.55 76.1 70.3 76.6 69.25 77.05 67.75 77.25 66.3 77.4 64.85 77.3 62.3 77.15 59.25 76.3 56.6 75.5 54.15 74.3 51.9 73.2 50.45 72 49.05 70.75 49.1 69.8 49.2 69 50.25 68.25 51.3 67.55 53.15 67 55 66.4 57.25 66.1 59.8 65.8 62.1 65.8 64.65 65.85 66.7 66.2 68.9 66.65 70.6 67.5Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient121" gradientTransform="rotate(-180 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#2087e2" stopOpacity="1"/>
|
||||||
|
<stop offset="1" stopColor="#b63fff" stopOpacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient121)" d="M66.6 15.05Q66.4 9.65 63.9 6.05 61.25 2.1 56.1 0.65 54.95 0.3 53.65 0.15 52.5 0 51.3 0.1 50.2 0.1 49.1 0.35 48.15 0.55 47 1 43.3 2.45 40.3 6.1 37.5 9.4 35.5 14.3 33.75 18.45 32.7 23.4 31.7 28.05 31.35 32.85 31.05 37.2 31.3 41.2 31.6 45.15 32.4 48.35 34 54.9 37.3 56.4 37.6 56.55 37.9 56.65L39.2 56.85Q39.45 56.85 39.95 56.8 42.05 56.6 44.7 55.05 47.25 53.5 50.05 50.8 53.05 47.9 55.85 44.05 58.8 40.05 61.1 35.6 63.8 30.35 65.25 25.3 66.75 19.75 66.6 15.05M47.55 23.15Q48.05 23.25 48.4 23.4 52.45 24.8 52.55 29.85 52.6 34 50 39.4 47.85 43.9 44.85 47.3 42.05 50.5 40.15 50.7L39.9 50.75 39.45 50.7 39.2 50.6Q37.8 49.95 37.25 46.35 36.7 42.7 37.3 38 37.95 32.75 39.75 28.8 41.9 24.1 45.05 23.25 45.6 23.1 45.85 23.1 46.25 23.05 46.65 23.05 47.05 23.05 47.55 23.15Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient122" gradientTransform="rotate(-90 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#100f0f" stopOpacity="1"/>
|
||||||
|
<stop offset="1" stopColor="#49261F" stopOpacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient122)" d="M2.7 33.6Q2.1 34.4 1.7 35.35 1.25 36.5 1.05 37.7 0 42.6 2.2 47.2 4 51 8 54.35 11.55 57.3 16 59.15 20.5 61 23.85 60.85 24.5 60.85 25.25 60.7 26 60.55 26.5 60.3 27 60.05 27.45 59.65 27.9 59.25 28.15 58.75 29.35 56.45 27.5 51.65 25.6 47 21.75 42.1 17.75 37 13.4 34.05 8.7 30.9 5.45 31.7 4.65 31.9 3.95 32.4 3.25 32.85 2.7 33.6M10.1 43.55Q10.35 43.1 10.6 42.85 10.85 42.6 11.2 42.4 11.6 42.25 11.9 42.2 13.5 41.9 15.95 43.6 18.15 45.05 20.35 47.7 22.35 50.1 23.55 52.4 24.7 54.75 24.25 55.7 24.15 55.9 24 56 23.85 56.2 23.65 56.25 23.55 56.35 23.25 56.4L22.7 56.5Q21.1 56.6 18.55 55.6 16.05 54.6 13.85 52.95 11.5 51.2 10.35 49.15 9.05 46.8 9.75 44.45 9.9 43.95 10.1 43.55Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient123" gradientTransform="rotate(-180 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#222020" stopOpacity="1"/>
|
||||||
|
<stop offset="1" stopColor="#49261F" stopOpacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient123)" d="M34.95 74.2L34.75 74.2Q33.2 74.15 31.9 75.25 30.7 76.3 29.85 78.25 29.1 80 28.8 82.2 28.5 84.4 28.7 86.65 29.1 91.4 31.5 94.7 34.3 98.5 39.3 99.7L39.4 99.7 39.7 99.8 39.85 99.8Q45.3 100.85 47.15 97.75 48 96.3 48 94.05 47.95 91.9 47.2 89.35 46.45 86.75 45.1 84.15 43.75 81.5 42.05 79.35 40.25 77.1 38.45 75.75 36.55 74.35 34.95 74.2M33.55 80.4Q34.35 78.2 35.6 78.3L35.65 78.3Q36.9 78.45 38.6 80.9 40.3 83.35 41.15 86.05 42.1 89 41.55 90.75 40.9 92.6 38.35 92.25L38.3 92.25 38.25 92.2 38.1 92.2Q35.6 91.7 34.25 89.6 33.1 87.7 32.95 85 32.8 82.35 33.55 80.4Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.9999999999999999 0 0 1 0 5.684341886080802e-14)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient124" gradientTransform="rotate(-180 .5 .5)"> <stop offset="0" stopColor="#1e1c1c" stopOpacity="1"/>
|
||||||
|
<stop offset="1" stopColor="#49261F" stopOpacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient124)" d="M22.7 69.65Q22.25 69.3 21.6 69.05 20.95 68.8 20.25 68.7 19.6 68.55 18.85 68.5 16.7 68.45 14.65 69.15 12.65 69.8 11.4 71.1 10.15 72.5 10.2 74.2 10.25 76.05 11.95 78.2 12.4 78.75 13.05 79.4 13.55 79.9 14.2 80.3 14.7 80.6 15.3 80.85 16 81.1 16.4 81.1 18.2 81.35 19.9 80.35 21.55 79.4 22.75 77.65 24 75.85 24.3 73.95 24.6 71.85 23.55 70.5 23.15 70 22.7 69.65M21.7 71.7Q22.15 72.3 21.9 73.3 21.7 74.25 21 75.25 20.3 76.2 19.4 76.75 18.45 77.35 17.55 77.25L17 77.15Q16.7 77.05 16.45 76.85 16.25 76.75 15.9 76.45 15.7 76.25 15.4 75.9 14.5 74.75 14.7 73.8 14.8 72.95 15.75 72.3 16.6 71.7 17.8 71.4 19 71.1 20.1 71.15L20.65 71.2 21.1 71.3Q21.3 71.4 21.45 71.5L21.7 71.7Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient125" gradientTransform="rotate(-360 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#FFFFFF" stopOpacity="0.5"/>
|
||||||
|
<stop offset="1" stopColor="#FFFFFF" stopOpacity="0.2"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient125)" d="M52.6 19.25Q59.6 19.25 66.2 20.95 66.7 17.8 66.6 15.05 66.4 9.65 63.9 6.05 61.25 2.1 56.1 0.65 54.95 0.3 53.65 0.15 52.5 0 51.3 0.1 50.2 0.1 49.1 0.35 48.15 0.55 47 1 43.3 2.45 40.3 6.1 37.5 9.4 35.5 14.3 33.85 18.3 32.8 22.85 42.25 19.25 52.6 19.25Z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 0 0)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="0" y1="0" x2="0" y2="1" id="gradient126" gradientTransform="rotate(-360 .5 .5)">
|
||||||
|
<stop offset="0" stopColor="#FFFFFF" stopOpacity="0.5"/>
|
||||||
|
<stop offset="1" stopColor="#FFFFFF" stopOpacity="0.2"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient126)" d="M1.05 37.7Q0 42.6 2.2 47.2 2.95 48.8 4.05 50.25 7.55 41.65 14.4 34.75 14 34.45 13.4 34.05 8.7 30.9 5.45 31.7 4.65 31.9 3.95 32.4 3.25 32.85 2.7 33.6 2.1 34.4 1.7 35.35 1.25 36.5 1.05 37.7Z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.219512230276127 0 0 1.2195122143630526 32.82519274395008 88.56945194723018)">
|
||||||
|
<path fill="#000000" fillOpacity="1" d=""/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
123
web/pages/components/main-layout.tsx
Normal file
123
web/pages/components/main-layout.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { Layout, Menu } from 'antd';
|
||||||
|
import {
|
||||||
|
SettingOutlined,
|
||||||
|
HomeOutlined,
|
||||||
|
LineChartOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
PlayCircleFilled,
|
||||||
|
StopFilled,
|
||||||
|
MinusSquareFilled,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
|
||||||
|
import OwncastLogo from './logo';
|
||||||
|
import { BroadcastStatusContext } from '../utils/broadcast-status-context';
|
||||||
|
|
||||||
|
import adminStyles from '../../styles/styles.module.css';
|
||||||
|
|
||||||
|
export default function MainLayout(props) {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcastActive } = context || {};
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { route } = router || {};
|
||||||
|
|
||||||
|
const { Header, Footer, Content, Sider } = Layout;
|
||||||
|
const { SubMenu } = Menu;
|
||||||
|
|
||||||
|
const statusIcon = broadcastActive ?
|
||||||
|
<PlayCircleFilled /> : <MinusSquareFilled />;
|
||||||
|
const statusMessage = broadcastActive ?
|
||||||
|
'Online' : 'Offline';
|
||||||
|
|
||||||
|
const appClass = classNames({
|
||||||
|
'owncast-layout': true,
|
||||||
|
[adminStyles.online]: broadcastActive,
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<Layout className={appClass}>
|
||||||
|
<Sider
|
||||||
|
width={240}
|
||||||
|
style={{
|
||||||
|
overflow: 'auto',
|
||||||
|
height: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Menu
|
||||||
|
theme="dark"
|
||||||
|
defaultSelectedKeys={[route.substring(1)]}
|
||||||
|
defaultOpenKeys={['current-stream-menu', 'utilities-menu']}
|
||||||
|
mode="inline"
|
||||||
|
>
|
||||||
|
<h1 className={adminStyles.owncastTitleContainer}>
|
||||||
|
<span className={adminStyles.logoContainer}>
|
||||||
|
<OwncastLogo />
|
||||||
|
</span>
|
||||||
|
<span className={adminStyles.owncastTitle}>Owncast Admin</span>
|
||||||
|
</h1>
|
||||||
|
<Menu.Item key="home" icon={<HomeOutlined />}>
|
||||||
|
<Link href="/">Home</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
|
||||||
|
<SubMenu key="current-stream-menu" icon={<LineChartOutlined />} title="Stream Details">
|
||||||
|
<Menu.Item key="hardware-info">
|
||||||
|
<Link href="/hardware-info">Hardware</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="broadcast-info">
|
||||||
|
<Link href="/broadcast-info">Broadcaster Info</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="viewer-info">
|
||||||
|
<Link href="/viewer-info">Viewers</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="connected-clients">
|
||||||
|
<Link href="/connected-clients">Connected Clients</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
{ broadcastActive ? (
|
||||||
|
<Menu.Item key="disconnect-stream" icon={<CloseCircleOutlined />}>
|
||||||
|
<Link href="/disconnect-stream">Disconnect Stream...</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
) : null}
|
||||||
|
</SubMenu>
|
||||||
|
|
||||||
|
<SubMenu key="utilities-menu" icon={<SettingOutlined />} title="Utilities">
|
||||||
|
<Menu.Item key="update-server-config">
|
||||||
|
<Link href="/update-server-config">Update Server Configuration</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="update-stream-key">
|
||||||
|
<Link href="/update-stream-key">Change Stream Key</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
</SubMenu>
|
||||||
|
</Menu>
|
||||||
|
</Sider>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<Header className={adminStyles.header}>
|
||||||
|
<div className={adminStyles.statusIndicatorContainer}>
|
||||||
|
<span className={adminStyles.statusLabel}>
|
||||||
|
{statusMessage}
|
||||||
|
</span>
|
||||||
|
<span className={adminStyles.statusIcon}>
|
||||||
|
{statusIcon}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Header>
|
||||||
|
<Content className={adminStyles.contentMain}>
|
||||||
|
{children}
|
||||||
|
</Content>
|
||||||
|
|
||||||
|
<Footer style={{ textAlign: 'center' }}><a href="https://owncast.online/">About Owncast</a></Footer>
|
||||||
|
</Layout>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLayout.propTypes = {
|
||||||
|
children: PropTypes.element.isRequired,
|
||||||
|
};
|
||||||
92
web/pages/connected-clients.tsx
Normal file
92
web/pages/connected-clients.tsx
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
|
import { Table } from 'antd';
|
||||||
|
import { BroadcastStatusContext } from './utils/broadcast-status-context';
|
||||||
|
|
||||||
|
import { CONNECTED_CLIENTS, fetchData, FETCH_INTERVAL } from './utils/apis';
|
||||||
|
|
||||||
|
/*
|
||||||
|
geo data looks like this
|
||||||
|
"geo": {
|
||||||
|
"countryCode": "US",
|
||||||
|
"regionName": "California",
|
||||||
|
"timeZone": "America/Los_Angeles"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function ConnectedClients() {
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcastActive } = context || {};
|
||||||
|
|
||||||
|
const [clients, setClients] = useState([]);
|
||||||
|
const getInfo = async () => {
|
||||||
|
try {
|
||||||
|
const result = await fetchData(CONNECTED_CLIENTS);
|
||||||
|
console.log("result",result)
|
||||||
|
setClients(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("==== error", error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let getStatusIntervalId = null;
|
||||||
|
|
||||||
|
getInfo();
|
||||||
|
if (broadcastActive) {
|
||||||
|
getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL);
|
||||||
|
// returned function will be called on component unmount
|
||||||
|
return () => {
|
||||||
|
clearInterval(getStatusIntervalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!clients.length) {
|
||||||
|
return "no clients";
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo - check to see if broadcast active has changed. if so, start polling.
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: 'User name',
|
||||||
|
dataIndex: 'username',
|
||||||
|
key: 'username',
|
||||||
|
render: username => username || '-',
|
||||||
|
sorter: (a, b) => a.username - b.username,
|
||||||
|
sortDirections: ['descend', 'ascend'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Messages sent',
|
||||||
|
dataIndex: 'messageCount',
|
||||||
|
key: 'messageCount',
|
||||||
|
sorter: (a, b) => a.messageCount - b.messageCount,
|
||||||
|
sortDirections: ['descend', 'ascend'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Connected Time',
|
||||||
|
dataIndex: 'connectedAt',
|
||||||
|
key: 'connectedAt',
|
||||||
|
render: time => (Date.now() - (new Date(time).getTime())) / 1000 / 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'User Agent',
|
||||||
|
dataIndex: 'userAgent',
|
||||||
|
key: 'userAgent',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Location',
|
||||||
|
dataIndex: 'geo',
|
||||||
|
key: 'geo',
|
||||||
|
render: geo => geo && `${geo.regionName}, ${geo.countryCode}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Connected Clients</h2>
|
||||||
|
<Table dataSource={clients} columns={columns} />;
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
45
web/pages/hardware-info.tsx
Normal file
45
web/pages/hardware-info.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
|
import { HARDWARE_STATS, fetchData, FETCH_INTERVAL } from './utils/apis';
|
||||||
|
import { BroadcastStatusContext } from './utils/broadcast-status-context';
|
||||||
|
|
||||||
|
export default function HardwareInfo() {
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcastActive } = context || {};
|
||||||
|
|
||||||
|
const [hardwareStatus, setHardwareStatus] = useState({});
|
||||||
|
|
||||||
|
const getHardwareStatus = async () => {
|
||||||
|
try {
|
||||||
|
const result = await fetchData(HARDWARE_STATS);
|
||||||
|
console.log("hardare result", result)
|
||||||
|
|
||||||
|
setHardwareStatus({ ...result });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
setHardwareStatus({ ...hardwareStatus, message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let getStatusIntervalId = null;
|
||||||
|
|
||||||
|
getHardwareStatus();
|
||||||
|
getStatusIntervalId = setInterval(getHardwareStatus, FETCH_INTERVAL); //runs every 1 min.
|
||||||
|
|
||||||
|
// returned function will be called on component unmount
|
||||||
|
return () => {
|
||||||
|
clearInterval(getStatusIntervalId);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Hardware Info</h2>
|
||||||
|
<p>cpu:[], disk: [], memory: []; value = %age.</p>
|
||||||
|
<p>the times should be the same for each, though milliseconds differ</p>
|
||||||
|
<div style={{border: '1px solid blue', height: '300px', width: '100%', overflow:'auto'}}>
|
||||||
|
{JSON.stringify(hardwareStatus)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
import { Card, Alert, Statistic, Row, Col } from "antd";
|
import { Card, Alert, Statistic, Row, Col } from "antd";
|
||||||
import { LikeOutlined } from "@ant-design/icons";
|
import { LikeOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
const { Meta } = Card;
|
const { Meta } = Card;
|
||||||
|
|
||||||
export default function Home() {
|
export default function AdminHome() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<div>
|
||||||
|
< pick something<br />
|
||||||
|
Home view. pretty pictures. Rainbows. Kittens.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
<Alert
|
<Alert
|
||||||
message="These are some ant design component example I stole from their web site."
|
message="These are some ant design component example I stole from their web site."
|
||||||
type="success"
|
type="success"
|
||||||
|
|||||||
45
web/pages/update-server-config.tsx
Normal file
45
web/pages/update-server-config.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
|
import { SERVER_CONFIG, fetchData, FETCH_INTERVAL } from './utils/apis';
|
||||||
|
import { BroadcastStatusContext } from './utils/broadcast-status-context';
|
||||||
|
|
||||||
|
export default function ServerConfig() {
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcastActive } = context || {};
|
||||||
|
|
||||||
|
|
||||||
|
const [clients, setClients] = useState({});
|
||||||
|
|
||||||
|
const getInfo = async () => {
|
||||||
|
try {
|
||||||
|
const result = await fetchData(SERVER_CONFIG);
|
||||||
|
console.log("viewers result", result)
|
||||||
|
|
||||||
|
setClients({ ...result });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
setClients({ ...clients, message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let getStatusIntervalId = null;
|
||||||
|
|
||||||
|
getInfo();
|
||||||
|
getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL);
|
||||||
|
|
||||||
|
// returned function will be called on component unmount
|
||||||
|
return () => {
|
||||||
|
clearInterval(getStatusIntervalId);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Server Config</h2>
|
||||||
|
<p>Display this data all pretty, most things will be editable in the future, not now.</p>
|
||||||
|
<div style={{border: '1px solid pink', height: '300px', width: '100%', overflow:'auto'}}>
|
||||||
|
{JSON.stringify(clients)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
59
web/pages/utils/apis.ts
Normal file
59
web/pages/utils/apis.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* eslint-disable prefer-destructuring */
|
||||||
|
const ADMIN_USERNAME = process.env.NEXT_PUBLIC_ADMIN_USERNAME;
|
||||||
|
const ADMIN_STREAMKEY = process.env.NEXT_PUBLIC_ADMIN_STREAMKEY;
|
||||||
|
const NEXT_PUBLIC_API_HOST = process.env.NEXT_PUBLIC_API_HOST;
|
||||||
|
|
||||||
|
const API_LOCATION = `${NEXT_PUBLIC_API_HOST}api/admin/`;
|
||||||
|
|
||||||
|
export const FETCH_INTERVAL = 15000;
|
||||||
|
|
||||||
|
// Current inbound broadcaster info
|
||||||
|
export const BROADCASTER = `${API_LOCATION}broadcaster`;
|
||||||
|
|
||||||
|
// Disconnect inbound stream
|
||||||
|
export const DISCONNECT = `${API_LOCATION}disconnect`;
|
||||||
|
|
||||||
|
// Change the current streaming key in memory
|
||||||
|
export const STREAMKEY_CHANGE = `${API_LOCATION}changekey`;
|
||||||
|
|
||||||
|
// Current server config
|
||||||
|
export const SERVER_CONFIG = `${API_LOCATION}serverconfig`;
|
||||||
|
|
||||||
|
// Get viewer count over time
|
||||||
|
export const VIEWERS_OVER_TIME = `${API_LOCATION}viewersOverTime`;
|
||||||
|
|
||||||
|
// Get currently connected clients
|
||||||
|
export const CONNECTED_CLIENTS = `${API_LOCATION}clients`;
|
||||||
|
|
||||||
|
|
||||||
|
// Get hardware stats
|
||||||
|
export const HARDWARE_STATS = `${API_LOCATION}hardwarestats`;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Current Stream status (no auth)
|
||||||
|
// use `admin/broadcaster` instead
|
||||||
|
// export const STREAM_STATUS = '/api/status';
|
||||||
|
|
||||||
|
export async function fetchData(url) {
|
||||||
|
const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Basic ${encoded}`,
|
||||||
|
},
|
||||||
|
mode: 'cors',
|
||||||
|
credentials: 'include',
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const message = `An error has occured: ${response.status}`;
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
const json = await response.json();
|
||||||
|
return json;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
51
web/pages/utils/broadcast-status-context.tsx
Normal file
51
web/pages/utils/broadcast-status-context.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { BROADCASTER, fetchData, FETCH_INTERVAL } from './apis';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
broadcastActive: false,
|
||||||
|
message: '',
|
||||||
|
broadcaster: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BroadcastStatusContext = React.createContext(initialState);
|
||||||
|
|
||||||
|
const BroadcastStatusProvider = ({ children }) => {
|
||||||
|
const [broadcasterStatus, setBroadcasterStatus] = useState(initialState);
|
||||||
|
|
||||||
|
const getBroadcastStatus = async () => {
|
||||||
|
try {
|
||||||
|
const result = await fetchData(BROADCASTER);
|
||||||
|
const broadcastActive = !!result.broadcaster || result.success;
|
||||||
|
setBroadcasterStatus({ ...result, broadcastActive });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
setBroadcasterStatus({ ...broadcasterStatus, message: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let getStatusIntervalId = null;
|
||||||
|
|
||||||
|
getBroadcastStatus();
|
||||||
|
getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL);
|
||||||
|
|
||||||
|
// returned function will be called on component unmount
|
||||||
|
return () => {
|
||||||
|
clearInterval(getStatusIntervalId);
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BroadcastStatusContext.Provider value={broadcasterStatus}>
|
||||||
|
{children}
|
||||||
|
</BroadcastStatusContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BroadcastStatusProvider.propTypes = {
|
||||||
|
children: PropTypes.element.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BroadcastStatusProvider;
|
||||||
85
web/pages/viewer-info.tsx
Normal file
85
web/pages/viewer-info.tsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
|
import {timeFormat} from 'd3-time-format';
|
||||||
|
import { LineChart, XAxis, YAxis, Line, Tooltip } from 'recharts';
|
||||||
|
import { BroadcastStatusContext } from './utils/broadcast-status-context';
|
||||||
|
|
||||||
|
import { VIEWERS_OVER_TIME, fetchData } from './utils/apis';
|
||||||
|
|
||||||
|
const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins
|
||||||
|
|
||||||
|
export default function ViewersOverTime() {
|
||||||
|
const context = useContext(BroadcastStatusContext);
|
||||||
|
const { broadcastActive } = context || {};
|
||||||
|
|
||||||
|
const [viewerInfo, setViewerInfo] = useState([]);
|
||||||
|
|
||||||
|
const getInfo = async () => {
|
||||||
|
try {
|
||||||
|
const result = await fetchData(VIEWERS_OVER_TIME);
|
||||||
|
setViewerInfo(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("==== error", error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let getStatusIntervalId = null;
|
||||||
|
|
||||||
|
getInfo();
|
||||||
|
if (broadcastActive) {
|
||||||
|
getStatusIntervalId = setInterval(getInfo, FETCH_INTERVAL);
|
||||||
|
// returned function will be called on component unmount
|
||||||
|
return () => {
|
||||||
|
clearInterval(getStatusIntervalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
// todo - check to see if broadcast active has changed. if so, start polling.
|
||||||
|
|
||||||
|
|
||||||
|
if (!viewerInfo.length) {
|
||||||
|
return "no info";
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeFormatter = (tick) => {return timeFormat('%H:%M:%S')(new Date(tick));};
|
||||||
|
|
||||||
|
const CustomizedTooltip = (props) => {
|
||||||
|
const { active, payload, label } = props;
|
||||||
|
if (active) {
|
||||||
|
const numViewers = payload && payload[0] && payload[0].value;
|
||||||
|
const time = timeFormatter(label);
|
||||||
|
const message = `${numViewers} viewer(s) at ${time}`;
|
||||||
|
return (
|
||||||
|
<div className="custom-tooltip">
|
||||||
|
<p className="label">{message}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Current Viewers</h2>
|
||||||
|
<div className="chart-container">
|
||||||
|
<LineChart width={800} height={400} data={viewerInfo}>
|
||||||
|
<XAxis dataKey="time" tickFormatter={timeFormatter}/>
|
||||||
|
<YAxis dataKey="value"/>
|
||||||
|
<Tooltip
|
||||||
|
content={<CustomizedTooltip />}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
type="monotone"
|
||||||
|
dataKey="value"
|
||||||
|
stroke="#ff84d8"
|
||||||
|
dot={{ stroke: 'red', strokeWidth: 2 }}
|
||||||
|
/>
|
||||||
|
</LineChart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
|
$owncast-purple: rgba(90,103,216,1);;
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
font-family: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
||||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
color: rgba(90,103,216,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.owncast-layout .ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||||||
|
background-color: $owncast-purple;
|
||||||
|
}
|
||||||
|
|||||||
70
web/styles/styles.module.css
Normal file
70
web/styles/styles.module.css
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
.logoSVG {
|
||||||
|
height: 2rem;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.owncastTitleContainer {
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
.logoContainer {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: .35rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
.owncastTitle {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 1rem;
|
||||||
|
color: rgba(203,213,224, 1);
|
||||||
|
font-size: 1.15rem;
|
||||||
|
font-weight: 200;
|
||||||
|
text-transform: uppercase;
|
||||||
|
line-height: normal;
|
||||||
|
letter-spacing: .05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentMain {
|
||||||
|
padding: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusIndicatorContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
.statusIcon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
.statusIcon svg {
|
||||||
|
fill: #999;
|
||||||
|
}
|
||||||
|
.statusLabel {
|
||||||
|
color: #fff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: .75rem;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: .5rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.online .statusIcon svg {
|
||||||
|
fill: #52c41a;
|
||||||
|
}
|
||||||
|
.online .statusLabel {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* //844-227-3943 */
|
||||||
223
web/yarn.lock
223
web/yarn.lock
@@ -1020,7 +1020,7 @@
|
|||||||
core-js-pure "^3.0.0"
|
core-js-pure "^3.0.0"
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@7.11.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4":
|
"@babel/runtime@7.11.2", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4":
|
||||||
version "7.11.2"
|
version "7.11.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
|
||||||
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
|
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
|
||||||
@@ -1147,7 +1147,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256"
|
||||||
integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==
|
integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==
|
||||||
|
|
||||||
"@types/prop-types@*":
|
"@types/prop-types@*", "@types/prop-types@^15.7.3":
|
||||||
version "15.7.3"
|
version "15.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||||
@@ -1747,6 +1747,11 @@ babel-plugin-transform-react-remove-prop-types@0.4.24:
|
|||||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
|
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
|
||||||
integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
|
integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
|
||||||
|
|
||||||
|
balanced-match@^0.4.2:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
|
||||||
|
integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
@@ -2287,6 +2292,11 @@ core-js-pure@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
|
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
|
||||||
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
|
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
|
||||||
|
|
||||||
|
core-js@^2.6.10:
|
||||||
|
version "2.6.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
|
||||||
|
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
@@ -2443,6 +2453,114 @@ cyclist@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||||
|
|
||||||
|
d3-array@^1.2.0:
|
||||||
|
version "1.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
|
||||||
|
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
|
||||||
|
|
||||||
|
d3-array@^2.3.0:
|
||||||
|
version "2.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.8.0.tgz#f76e10ad47f1f4f75f33db5fc322eb9ffde5ef23"
|
||||||
|
integrity sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw==
|
||||||
|
|
||||||
|
d3-collection@1:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
|
||||||
|
integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==
|
||||||
|
|
||||||
|
d3-color@1:
|
||||||
|
version "1.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a"
|
||||||
|
integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==
|
||||||
|
|
||||||
|
"d3-color@1 - 2":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
|
||||||
|
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
|
||||||
|
|
||||||
|
d3-format@1:
|
||||||
|
version "1.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4"
|
||||||
|
integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==
|
||||||
|
|
||||||
|
"d3-format@1 - 2":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
|
||||||
|
integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
|
||||||
|
|
||||||
|
d3-interpolate@1, d3-interpolate@^1.3.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987"
|
||||||
|
integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==
|
||||||
|
dependencies:
|
||||||
|
d3-color "1"
|
||||||
|
|
||||||
|
"d3-interpolate@1.2.0 - 2":
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
|
||||||
|
integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==
|
||||||
|
dependencies:
|
||||||
|
d3-color "1 - 2"
|
||||||
|
|
||||||
|
d3-path@1:
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
|
||||||
|
integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
|
||||||
|
|
||||||
|
d3-scale@^2.1.0:
|
||||||
|
version "2.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f"
|
||||||
|
integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==
|
||||||
|
dependencies:
|
||||||
|
d3-array "^1.2.0"
|
||||||
|
d3-collection "1"
|
||||||
|
d3-format "1"
|
||||||
|
d3-interpolate "1"
|
||||||
|
d3-time "1"
|
||||||
|
d3-time-format "2"
|
||||||
|
|
||||||
|
d3-scale@^3.2.3:
|
||||||
|
version "3.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.2.3.tgz#be380f57f1f61d4ff2e6cbb65a40593a51649cfd"
|
||||||
|
integrity sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==
|
||||||
|
dependencies:
|
||||||
|
d3-array "^2.3.0"
|
||||||
|
d3-format "1 - 2"
|
||||||
|
d3-interpolate "1.2.0 - 2"
|
||||||
|
d3-time "1 - 2"
|
||||||
|
d3-time-format "2 - 3"
|
||||||
|
|
||||||
|
d3-shape@^1.2.0:
|
||||||
|
version "1.3.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
|
||||||
|
integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==
|
||||||
|
dependencies:
|
||||||
|
d3-path "1"
|
||||||
|
|
||||||
|
d3-time-format@2:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850"
|
||||||
|
integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==
|
||||||
|
dependencies:
|
||||||
|
d3-time "1"
|
||||||
|
|
||||||
|
"d3-time-format@2 - 3", d3-time-format@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6"
|
||||||
|
integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==
|
||||||
|
dependencies:
|
||||||
|
d3-time "1 - 2"
|
||||||
|
|
||||||
|
d3-time@1:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
|
||||||
|
integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
|
||||||
|
|
||||||
|
"d3-time@1 - 2":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab"
|
||||||
|
integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==
|
||||||
|
|
||||||
d@1, d@^1.0.1:
|
d@1, d@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
|
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
|
||||||
@@ -2487,6 +2605,11 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
decimal.js-light@^2.4.1:
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934"
|
||||||
|
integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==
|
||||||
|
|
||||||
decode-uri-component@^0.2.0:
|
decode-uri-component@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||||
@@ -2577,6 +2700,13 @@ dom-align@^1.7.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.0.tgz#56fb7156df0b91099830364d2d48f88963f5a29c"
|
resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.0.tgz#56fb7156df0b91099830364d2d48f88963f5a29c"
|
||||||
integrity sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==
|
integrity sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==
|
||||||
|
|
||||||
|
dom-helpers@^3.4.0:
|
||||||
|
version "3.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
|
||||||
|
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.1.2"
|
||||||
|
|
||||||
dom-serializer@1.0.1:
|
dom-serializer@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.0.1.tgz#79695eb49af3cd8abc8d93a73da382deb1ca0795"
|
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.0.1.tgz#79695eb49af3cd8abc8d93a73da382deb1ca0795"
|
||||||
@@ -3983,12 +4113,22 @@ locate-path@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^4.1.0"
|
p-locate "^4.1.0"
|
||||||
|
|
||||||
|
lodash.debounce@^4.0.8:
|
||||||
|
version "4.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
|
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||||
|
|
||||||
lodash.sortby@^4.7.0:
|
lodash.sortby@^4.7.0:
|
||||||
version "4.7.0"
|
version "4.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||||
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
||||||
|
|
||||||
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20:
|
lodash.throttle@^4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||||
|
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||||
|
|
||||||
|
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@~4.17.4:
|
||||||
version "4.17.20"
|
version "4.17.20"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||||
@@ -4041,6 +4181,11 @@ map-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object-visit "^1.0.0"
|
object-visit "^1.0.0"
|
||||||
|
|
||||||
|
math-expression-evaluator@^1.2.14:
|
||||||
|
version "1.2.22"
|
||||||
|
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz#c14dcb3d8b4d150e5dcea9c68c8dad80309b0d5e"
|
||||||
|
integrity sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ==
|
||||||
|
|
||||||
md5.js@^1.3.4:
|
md5.js@^1.3.4:
|
||||||
version "1.3.5"
|
version "1.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||||
@@ -4873,7 +5018,7 @@ promise-inflight@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||||
|
|
||||||
prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2:
|
prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||||
version "15.7.2"
|
version "15.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||||
@@ -5352,6 +5497,36 @@ react-refresh@0.8.3:
|
|||||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||||
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
||||||
|
|
||||||
|
react-resize-detector@^2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c"
|
||||||
|
integrity sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ==
|
||||||
|
dependencies:
|
||||||
|
lodash.debounce "^4.0.8"
|
||||||
|
lodash.throttle "^4.1.1"
|
||||||
|
prop-types "^15.6.0"
|
||||||
|
resize-observer-polyfill "^1.5.0"
|
||||||
|
|
||||||
|
react-smooth@^1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-1.0.5.tgz#94ae161d7951cdd893ccb7099d031d342cb762ad"
|
||||||
|
integrity sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==
|
||||||
|
dependencies:
|
||||||
|
lodash "~4.17.4"
|
||||||
|
prop-types "^15.6.0"
|
||||||
|
raf "^3.4.0"
|
||||||
|
react-transition-group "^2.5.0"
|
||||||
|
|
||||||
|
react-transition-group@^2.5.0:
|
||||||
|
version "2.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
|
||||||
|
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
|
||||||
|
dependencies:
|
||||||
|
dom-helpers "^3.4.0"
|
||||||
|
loose-envify "^1.4.0"
|
||||||
|
prop-types "^15.6.2"
|
||||||
|
react-lifecycles-compat "^3.0.4"
|
||||||
|
|
||||||
react@16.13.1:
|
react@16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||||
@@ -5416,6 +5591,46 @@ readdirp@~3.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch "^2.2.1"
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
|
recharts-scale@^0.4.2:
|
||||||
|
version "0.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.3.tgz#040b4f638ed687a530357292ecac880578384b59"
|
||||||
|
integrity sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==
|
||||||
|
dependencies:
|
||||||
|
decimal.js-light "^2.4.1"
|
||||||
|
|
||||||
|
recharts@^1.8.5:
|
||||||
|
version "1.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/recharts/-/recharts-1.8.5.tgz#ca94a3395550946334a802e35004ceb2583fdb12"
|
||||||
|
integrity sha512-tM9mprJbXVEBxjM7zHsIy6Cc41oO/pVYqyAsOHLxlJrbNBuLs0PHB3iys2M+RqCF0//k8nJtZF6X6swSkWY3tg==
|
||||||
|
dependencies:
|
||||||
|
classnames "^2.2.5"
|
||||||
|
core-js "^2.6.10"
|
||||||
|
d3-interpolate "^1.3.0"
|
||||||
|
d3-scale "^2.1.0"
|
||||||
|
d3-shape "^1.2.0"
|
||||||
|
lodash "^4.17.5"
|
||||||
|
prop-types "^15.6.0"
|
||||||
|
react-resize-detector "^2.3.0"
|
||||||
|
react-smooth "^1.0.5"
|
||||||
|
recharts-scale "^0.4.2"
|
||||||
|
reduce-css-calc "^1.3.0"
|
||||||
|
|
||||||
|
reduce-css-calc@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
|
||||||
|
integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=
|
||||||
|
dependencies:
|
||||||
|
balanced-match "^0.4.2"
|
||||||
|
math-expression-evaluator "^1.2.14"
|
||||||
|
reduce-function-call "^1.0.1"
|
||||||
|
|
||||||
|
reduce-function-call@^1.0.1:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.3.tgz#60350f7fb252c0a67eb10fd4694d16909971300f"
|
||||||
|
integrity sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==
|
||||||
|
dependencies:
|
||||||
|
balanced-match "^1.0.0"
|
||||||
|
|
||||||
regenerate-unicode-properties@^8.2.0:
|
regenerate-unicode-properties@^8.2.0:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
|
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
|
||||||
|
|||||||
Reference in New Issue
Block a user