mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-22 17:10:26 +03:00
Merge branch 'main' into develop
This commit is contained in:
commit
18042dba6e
20 changed files with 1047 additions and 101 deletions
|
@ -13,5 +13,6 @@
|
|||
"globals": {
|
||||
"process": true,
|
||||
"setImmediate": true
|
||||
}
|
||||
},
|
||||
"ignorePatterns": ["src/service*.ts"]
|
||||
}
|
||||
|
|
1
.github/workflows/deploy-preview.yml
vendored
1
.github/workflows/deploy-preview.yml
vendored
|
@ -24,6 +24,7 @@ jobs:
|
|||
run: |
|
||||
npm ci && \
|
||||
node ./scripts/set-homepage.js /shlink-web-client/${{ steps.generate_slug.outputs.slug }} && \
|
||||
rm src/service-worker.ts && \
|
||||
npm run build
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.1
|
||||
|
|
|
@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
## [Unreleased]
|
||||
## [3.1.2] - 2021-06-06
|
||||
### Added
|
||||
* [#433](https://github.com/shlinkio/shlink-web-client/pull/433) Added support to provide a default server to connect to via env vars:
|
||||
|
||||
|
@ -24,7 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
* *Nothing*
|
||||
|
||||
### Fixed
|
||||
* *Nothing*
|
||||
* [#371](https://github.com/shlinkio/shlink-web-client/issues/371) Recovered PWA functionality.
|
||||
|
||||
|
||||
## [3.1.1] - 2021-05-08
|
||||
|
|
|
@ -83,6 +83,7 @@ module.exports = {
|
|||
appNodeModules: resolveApp('node_modules'),
|
||||
publicUrl: getPublicUrl(resolveApp('package.json')),
|
||||
servedPath: getServedPath(resolveApp('package.json')),
|
||||
swSrc: resolveModule(resolveApp, 'src/service-worker'),
|
||||
};
|
||||
|
||||
module.exports.moduleFileExtensions = moduleFileExtensions;
|
||||
|
|
|
@ -13,6 +13,7 @@ const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
|||
const safePostCssParser = require('postcss-safe-parser');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
||||
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
|
@ -32,6 +33,9 @@ const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
|||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// Get the path to the uncompiled service worker (if it exists).
|
||||
const swSrc = paths.swSrc;
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
|
@ -610,6 +614,18 @@ module.exports = (webpackEnv) => {
|
|||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the webpack build.
|
||||
isEnvProduction && fs.existsSync(swSrc) && new WorkboxWebpackPlugin.InjectManifest({
|
||||
swSrc,
|
||||
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
|
||||
exclude: [ /\.map$/, /asset-manifest\.json$/, /LICENSE/ ],
|
||||
// Bump up the default maximum size (2mb) that's precached,
|
||||
// to make lazy-loading failure scenarios less likely.
|
||||
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
}),
|
||||
|
||||
// TypeScript type checking
|
||||
useTypeScript &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
|
|
730
package-lock.json
generated
730
package-lock.json
generated
|
@ -190,12 +190,6 @@
|
|||
"node-releases": "^1.1.70"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001192",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz",
|
||||
"integrity": "sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
|
@ -438,12 +432,6 @@
|
|||
"node-releases": "^1.1.66"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.595",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.595.tgz",
|
||||
|
@ -922,12 +910,6 @@
|
|||
"node-releases": "^1.1.70"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001192",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz",
|
||||
"integrity": "sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
|
@ -2414,12 +2396,6 @@
|
|||
"node-releases": "^1.1.70"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001192",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz",
|
||||
"integrity": "sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.675",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.675.tgz",
|
||||
|
@ -4231,12 +4207,6 @@
|
|||
"node-releases": "^1.1.70"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001192",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz",
|
||||
"integrity": "sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
|
@ -4705,6 +4675,52 @@
|
|||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@hapi/address": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||
"integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/formula": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-1.2.0.tgz",
|
||||
"integrity": "sha512-UFbtbGPjstz0eWHb+ga/GM3Z9EzqKXFWIbSOFURU0A/Gku0Bky4bCk9/h//K2Xr3IrCfjFNhMm4jyZ5dbCewGA==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/hoek": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz",
|
||||
"integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/joi": {
|
||||
"version": "16.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-16.1.8.tgz",
|
||||
"integrity": "sha512-wAsVvTPe+FwSrsAurNt5vkg3zo+TblvC5Bb1zMVK6SJzZqw9UrJnexxR+76cpePmtUZKHAPxcQ2Bf7oVHyahhg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@hapi/address": "^2.1.2",
|
||||
"@hapi/formula": "^1.2.0",
|
||||
"@hapi/hoek": "^8.2.4",
|
||||
"@hapi/pinpoint": "^1.0.2",
|
||||
"@hapi/topo": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"@hapi/pinpoint": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-1.0.2.tgz",
|
||||
"integrity": "sha512-dtXC/WkZBfC5vxscazuiJ6iq4j9oNx1SHknmIr8hofarpKUZKmlUVYVIhNVzIEgK5Wrc4GMHL5lZtt1uS2flmQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/topo": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz",
|
||||
"integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@hapi/hoek": "^8.3.0"
|
||||
}
|
||||
},
|
||||
"@hypnosphi/create-react-context": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz",
|
||||
|
@ -5184,6 +5200,59 @@
|
|||
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-1.0.2.tgz",
|
||||
"integrity": "sha512-QbleYZTMcgujAEyWGki8Lx6cXQqWkNtQlqf5c7NImlIp8bKW66bFpez/6EVatW7+p9WKBOEOVci/9W7WW70EZg=="
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz",
|
||||
"integrity": "sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.10.4",
|
||||
"@rollup/pluginutils": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-node-resolve": {
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
|
||||
"integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rollup/pluginutils": "^3.1.0",
|
||||
"@types/resolve": "1.17.1",
|
||||
"builtin-modules": "^3.1.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.19.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"builtin-modules": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
|
||||
"integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-replace": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz",
|
||||
"integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rollup/pluginutils": "^3.1.0",
|
||||
"magic-string": "^0.25.7"
|
||||
}
|
||||
},
|
||||
"@rollup/pluginutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
|
||||
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/estree": "0.0.39",
|
||||
"estree-walker": "^1.0.1",
|
||||
"picomatch": "^2.2.2"
|
||||
}
|
||||
},
|
||||
"@shlinkio/eslint-config-js-coding-standard": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/eslint-config-js-coding-standard/-/eslint-config-js-coding-standard-1.2.2.tgz",
|
||||
|
@ -5907,12 +5976,6 @@
|
|||
"node-releases": "^1.1.71"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001228",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
|
||||
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
|
@ -6068,6 +6131,16 @@
|
|||
"unist-util-find-all-after": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"@surma/rollup-plugin-off-main-thread": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz",
|
||||
"integrity": "sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ejs": "^2.6.1",
|
||||
"magic-string": "^0.25.0"
|
||||
}
|
||||
},
|
||||
"@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz",
|
||||
|
@ -6324,6 +6397,12 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "0.0.39",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/geojson": {
|
||||
"version": "7946.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||
|
@ -6617,6 +6696,15 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/source-list-map": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||
|
@ -8297,12 +8385,6 @@
|
|||
"node-releases": "^1.1.66"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.596",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.596.tgz",
|
||||
|
@ -9705,12 +9787,6 @@
|
|||
"node-releases": "^1.1.66"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
},
|
||||
"convert-source-map": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
|
||||
|
@ -10400,9 +10476,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30000998",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000998.tgz",
|
||||
"integrity": "sha512-8Tj5sPZR9kMHeDD9SZXIVr5m9ofufLLCG2Y4QwQrH18GIwG+kCc+zYdlR036ZRkuKjVVetyxeAgGA1xF7XdmzQ==",
|
||||
"version": "1.0.30001235",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz",
|
||||
"integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==",
|
||||
"dev": true
|
||||
},
|
||||
"capture-exit": {
|
||||
|
@ -10938,6 +11014,12 @@
|
|||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true
|
||||
},
|
||||
"common-tags": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
|
||||
"integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==",
|
||||
"dev": true
|
||||
},
|
||||
"commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
|
@ -11162,12 +11244,6 @@
|
|||
"node-releases": "^1.1.70"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001192",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001192.tgz",
|
||||
"integrity": "sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.675",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.675.tgz",
|
||||
|
@ -12539,6 +12615,12 @@
|
|||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
|
||||
"dev": true
|
||||
},
|
||||
"ejs": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.274",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.274.tgz",
|
||||
|
@ -13903,6 +13985,12 @@
|
|||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
|
||||
"dev": true
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz",
|
||||
|
@ -15374,6 +15462,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
|
||||
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
|
||||
"dev": true
|
||||
},
|
||||
"get-package-type": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
|
||||
|
@ -16655,6 +16749,12 @@
|
|||
"is-path-inside": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
|
||||
"dev": true
|
||||
},
|
||||
"is-negative-zero": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
|
||||
|
@ -18378,6 +18478,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.25.7",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
||||
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sourcemap-codec": "^1.4.4"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
|
@ -23386,12 +23495,6 @@
|
|||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.66"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -24621,12 +24724,6 @@
|
|||
"node-releases": "^1.1.61"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
|
@ -25734,6 +25831,107 @@
|
|||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.50.6",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.50.6.tgz",
|
||||
"integrity": "sha512-6c5CJPLVgo0iNaZWWliNu1Kl43tjP9LZcp6D/tkf2eLH2a9/WeHxg9vfTFl8QV/2SOyaJX37CEm9XuGM0rviUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollup-plugin-terser": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
|
||||
"integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"jest-worker": "^26.2.1",
|
||||
"serialize-javascript": "^4.0.0",
|
||||
"terser": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.12.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
|
||||
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
|
||||
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
|
||||
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-validator-identifier": "^7.14.0",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz",
|
||||
"integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.7.2",
|
||||
"source-map-support": "~0.5.19"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rst-selector-parser": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
|
||||
|
@ -26469,6 +26667,12 @@
|
|||
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
||||
"dev": true
|
||||
},
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
},
|
||||
"spdx-correct": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz",
|
||||
|
@ -27261,6 +27465,31 @@
|
|||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"stringify-object": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
|
||||
"integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-own-enumerable-property-symbols": "^3.0.0",
|
||||
"is-obj": "^1.0.1",
|
||||
"is-regexp": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
"is-regexp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
|
||||
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
|
@ -27276,6 +27505,12 @@
|
|||
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
|
@ -27605,12 +27840,6 @@
|
|||
"node-releases": "^1.1.66"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001157",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz",
|
||||
"integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==",
|
||||
"dev": true
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
@ -28394,6 +28623,53 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"temp-dir": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
|
||||
"integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
|
||||
"dev": true
|
||||
},
|
||||
"tempy": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz",
|
||||
"integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-stream": "^2.0.0",
|
||||
"temp-dir": "^2.0.0",
|
||||
"type-fest": "^0.16.0",
|
||||
"unique-string": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"crypto-random-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
|
||||
"dev": true
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"dev": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
|
||||
"integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
|
||||
"dev": true
|
||||
},
|
||||
"unique-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
|
||||
"integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"crypto-random-string": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"term-size": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
|
||||
|
@ -30684,6 +30960,310 @@
|
|||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"workbox-background-sync": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.1.5.tgz",
|
||||
"integrity": "sha512-VbUmPLsdz+sLzuNxHvMylzyRTiM4q+q7rwLBk3p2mtRL5NZozI8j/KgoGbno96vs84jx4b9zCZMEOIKEUTPf6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-broadcast-update": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.1.5.tgz",
|
||||
"integrity": "sha512-zGrTTs+n4wHpYtqYMqBg6kl/x5j1UrczGCQnODSHTxIDV8GXLb/GtA1BCZdysNxpMmdVSeLmTcgIYAAqWFamrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-build": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.1.5.tgz",
|
||||
"integrity": "sha512-P+fakR5QFVqJN9l9xHVXtmafga72gh9I+jM3A9HiB/6UNRmOAejXnDgD+RMegOHgQHPwnB44TalMToFaXKWIyA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.11.1",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"@hapi/joi": "^16.1.8",
|
||||
"@rollup/plugin-babel": "^5.2.0",
|
||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||
"@rollup/plugin-replace": "^2.4.1",
|
||||
"@surma/rollup-plugin-off-main-thread": "^1.4.1",
|
||||
"common-tags": "^1.8.0",
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"glob": "^7.1.6",
|
||||
"lodash": "^4.17.20",
|
||||
"pretty-bytes": "^5.3.0",
|
||||
"rollup": "^2.43.1",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"source-map": "^0.8.0-beta.0",
|
||||
"source-map-url": "^0.4.0",
|
||||
"stringify-object": "^3.3.0",
|
||||
"strip-comments": "^2.0.1",
|
||||
"tempy": "^0.6.0",
|
||||
"upath": "^1.2.0",
|
||||
"workbox-background-sync": "^6.1.5",
|
||||
"workbox-broadcast-update": "^6.1.5",
|
||||
"workbox-cacheable-response": "^6.1.5",
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-expiration": "^6.1.5",
|
||||
"workbox-google-analytics": "^6.1.5",
|
||||
"workbox-navigation-preload": "^6.1.5",
|
||||
"workbox-precaching": "^6.1.5",
|
||||
"workbox-range-requests": "^6.1.5",
|
||||
"workbox-recipes": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5",
|
||||
"workbox-streams": "^6.1.5",
|
||||
"workbox-sw": "^6.1.5",
|
||||
"workbox-window": "^6.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.7",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
|
||||
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
|
||||
"integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
|
||||
"dev": true
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.7",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.8.0-beta.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
|
||||
"integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"whatwg-url": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
|
||||
"integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"upath": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
|
||||
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
|
||||
"dev": true
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
||||
"dev": true
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
||||
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"tr46": "^1.0.1",
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"workbox-cacheable-response": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.1.5.tgz",
|
||||
"integrity": "sha512-x8DC71lO/JCgiaJ194l9le8wc8lFPLgUpDkLhp2si7mXV6S/wZO+8Osvw1LLgYa8YYTWGbhbFhFTXIkEMknIIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-core": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.1.5.tgz",
|
||||
"integrity": "sha512-9SOEle7YcJzg3njC0xMSmrPIiFjfsFm9WjwGd5enXmI8Lwk8wLdy63B0nzu5LXoibEmS9k+aWF8EzaKtOWjNSA=="
|
||||
},
|
||||
"workbox-expiration": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.1.5.tgz",
|
||||
"integrity": "sha512-6cN+FVbh8fNq56LFKPMchGNKCJeyboHsDuGBqmhDUPvD4uDjsegQpDQzn52VaE0cpywbSIsDF/BSq9E9Yjh5oQ==",
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-google-analytics": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.1.5.tgz",
|
||||
"integrity": "sha512-LYsJ/VxTkYVLxM1uJKXZLz4cJdemidY7kPyAYtKVZ6EiDG89noASqis75/5lhqM1m3HwQfp2DtoPrelKSpSDBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-background-sync": "^6.1.5",
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-navigation-preload": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.1.5.tgz",
|
||||
"integrity": "sha512-hDbNcWlffv0uvS21jCAC/mYk7NzaGRSWOQXv1p7bj2aONAX5l699D2ZK4D27G8TO0BaLHUmW/1A5CZcsvweQdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-precaching": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.1.5.tgz",
|
||||
"integrity": "sha512-yhm1kb6wgi141JeM5X7z42XJxCry53tbMLB3NgrxktrZbwbrJF8JILzYy+RFKC9tHC6u2bPmL789GPLT2NCDzw==",
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-range-requests": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.1.5.tgz",
|
||||
"integrity": "sha512-iACChSapzB0yuIum3ascP/+cfBNuZi5DRrE+u4u5mCHigPlwfSWtlaY+y8p+a8EwcDTVTZVtnrGrRnF31SiLqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-recipes": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.1.5.tgz",
|
||||
"integrity": "sha512-MD1yabHca6O/oj1hrRdfj9cRwhKA5zqIE53rWOAg/dKMMzWQsf9nyRbXRgzK3a13iQvYKuQzURU4Cx58tdnR+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-cacheable-response": "^6.1.5",
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-expiration": "^6.1.5",
|
||||
"workbox-precaching": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-routing": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.1.5.tgz",
|
||||
"integrity": "sha512-uC/Ctz+4GXGL42h1WxUNKxqKRik/38uS0NZ6VY/EHqL2F1ObLFqMHUZ4ZYvyQsKdyI82cxusvhJZHOrY0a2fIQ==",
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-strategies": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.1.5.tgz",
|
||||
"integrity": "sha512-QhiOn9KT9YGBdbfWOmJT6pXZOIAxaVrs6J6AMYzRpkUegBTEcv36+ZhE/cfHoT0u2fxVtthHnskOQ/snEzaXQw==",
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-streams": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.1.5.tgz",
|
||||
"integrity": "sha512-OI1kLvRHGFXV+soDvs6aEwfBwdAkvPB0mRryqdh3/K17qUj/1gRXc8QtpgU+83xqx/I/ar2bTCIj0KPzI/ChCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"workbox-sw": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.1.5.tgz",
|
||||
"integrity": "sha512-IMDiqxYbKzPorZLGMUMacLB6r76iVQbdTzYthIZoPfy+uFURJFUtqiWQJKg1L+RMyuYXwKXTahCIGkgFs4jBeg==",
|
||||
"dev": true
|
||||
},
|
||||
"workbox-webpack-plugin": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.1.5.tgz",
|
||||
"integrity": "sha512-tsgeNAYiFP4STNPDxBVT58eiU8nGUmcv7Lq9FFJkQf5MMu6tPw1OLp+KpszhbCWP+R/nEdu85Gjexs6fY647Kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"pretty-bytes": "^5.4.1",
|
||||
"source-map-url": "^0.4.0",
|
||||
"upath": "^1.2.0",
|
||||
"webpack-sources": "^1.4.3",
|
||||
"workbox-build": "^6.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
|
||||
"integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
|
||||
"dev": true
|
||||
},
|
||||
"upath": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
|
||||
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"workbox-window": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.1.5.tgz",
|
||||
"integrity": "sha512-akL0X6mAegai2yypnq78RgfazeqvKbsllRtEI4dnbhPcRINEY1NmecFmsQk8SD+zWLK1gw5OdwAOX+zHSRVmeA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"workbox-core": "^6.1.5"
|
||||
}
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
|
|
10
package.json
10
package.json
|
@ -57,7 +57,12 @@
|
|||
"redux": "^4.0.5",
|
||||
"redux-localstorage-simple": "^2.4.0",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"uuid": "^8.3.2"
|
||||
"uuid": "^8.3.2",
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-expiration": "^6.1.5",
|
||||
"workbox-precaching": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.13.8",
|
||||
|
@ -146,7 +151,8 @@
|
|||
"webpack": "^4.44.2",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"whatwg-fetch": "^3.5.0"
|
||||
"whatwg-fetch": "^3.5.0",
|
||||
"workbox-webpack-plugin": "^6.1.5"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
|
|
16
src/App.scss
16
src/App.scss
|
@ -1,4 +1,5 @@
|
|||
@import './utils/base';
|
||||
@import './utils/mixins/horizontal-align';
|
||||
|
||||
.app-container {
|
||||
height: 100%;
|
||||
|
@ -24,3 +25,18 @@
|
|||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.app__update-banner.app__update-banner {
|
||||
@include horizontal-align();
|
||||
|
||||
position: fixed;
|
||||
top: $headerHeight - 25px;
|
||||
padding: 0 4rem 0 0;
|
||||
z-index: 1040;
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
width: 700px;
|
||||
max-width: calc(100% - 30px);
|
||||
box-shadow: 0 0 1rem var(--brand-color);
|
||||
}
|
||||
|
|
19
src/App.tsx
19
src/App.tsx
|
@ -1,15 +1,19 @@
|
|||
import { useEffect, FC } from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { Alert } from 'reactstrap';
|
||||
import NotFound from './common/NotFound';
|
||||
import { ServersMap } from './servers/data';
|
||||
import { Settings } from './settings/reducers/settings';
|
||||
import { changeThemeInMarkup } from './utils/theme';
|
||||
import { SimpleCard } from './utils/SimpleCard';
|
||||
import './App.scss';
|
||||
|
||||
interface AppProps {
|
||||
fetchServers: Function;
|
||||
fetchServers: () => void;
|
||||
servers: ServersMap;
|
||||
settings: Settings;
|
||||
resetAppUpdate: () => void;
|
||||
appUpdated: boolean;
|
||||
}
|
||||
|
||||
const App = (
|
||||
|
@ -20,7 +24,7 @@ const App = (
|
|||
EditServer: FC,
|
||||
Settings: FC,
|
||||
ShlinkVersionsContainer: FC,
|
||||
) => ({ fetchServers, servers, settings }: AppProps) => {
|
||||
) => ({ fetchServers, servers, settings, appUpdated, resetAppUpdate }: AppProps) => {
|
||||
useEffect(() => {
|
||||
// On first load, try to fetch the remote servers if the list is empty
|
||||
if (Object.keys(servers).length === 0) {
|
||||
|
@ -50,6 +54,17 @@ const App = (
|
|||
<ShlinkVersionsContainer />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Alert
|
||||
className="app__update-banner"
|
||||
tag={SimpleCard}
|
||||
color="secondary"
|
||||
isOpen={appUpdated}
|
||||
toggle={resetAppUpdate}
|
||||
>
|
||||
<h4 className="mb-4">This app has just been updated!</h4>
|
||||
<p className="mb-0">Restart it to enjoy the new features.</p>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
18
src/app/reducers/appUpdates.ts
Normal file
18
src/app/reducers/appUpdates.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Action } from 'redux';
|
||||
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
|
||||
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
export const APP_UPDATE_AVAILABLE = 'shlink/appUpdates/APP_UPDATE_AVAILABLE';
|
||||
export const RESET_APP_UPDATE = 'shlink/appUpdates/RESET_APP_UPDATE';
|
||||
/* eslint-enable padding-line-between-statements */
|
||||
|
||||
const initialState = false;
|
||||
|
||||
export default buildReducer<boolean, Action<string>>({
|
||||
[APP_UPDATE_AVAILABLE]: () => true,
|
||||
[RESET_APP_UPDATE]: () => false,
|
||||
}, initialState);
|
||||
|
||||
export const appUpdateAvailable = buildActionCreator(APP_UPDATE_AVAILABLE);
|
||||
|
||||
export const resetAppUpdate = buildActionCreator(RESET_APP_UPDATE);
|
26
src/app/services/provideServices.ts
Normal file
26
src/app/services/provideServices.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import Bottle from 'bottlejs';
|
||||
import { appUpdateAvailable, resetAppUpdate } from '../reducers/appUpdates';
|
||||
import App from '../../App';
|
||||
import { ConnectDecorator } from '../../container/types';
|
||||
|
||||
const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||
// Components
|
||||
bottle.serviceFactory(
|
||||
'App',
|
||||
App,
|
||||
'MainHeader',
|
||||
'Home',
|
||||
'MenuLayout',
|
||||
'CreateServer',
|
||||
'EditServer',
|
||||
'Settings',
|
||||
'ShlinkVersionsContainer',
|
||||
);
|
||||
bottle.decorator('App', connect([ 'servers', 'settings', 'appUpdated' ], [ 'fetchServers', 'resetAppUpdate' ]));
|
||||
|
||||
// Actions
|
||||
bottle.serviceFactory('appUpdateAvailable', () => appUpdateAvailable);
|
||||
bottle.serviceFactory('resetAppUpdate', () => resetAppUpdate);
|
||||
};
|
||||
|
||||
export default provideServices;
|
|
@ -3,9 +3,9 @@ import { Link } from 'react-router-dom';
|
|||
import { Card, Row } from 'reactstrap';
|
||||
import { ExternalLink } from 'react-external-link';
|
||||
import ServersListGroup from '../servers/ServersListGroup';
|
||||
import './Home.scss';
|
||||
import { ServersMap } from '../servers/data';
|
||||
import { ShlinkLogo } from './img/ShlinkLogo';
|
||||
import './Home.scss';
|
||||
|
||||
export interface HomeProps {
|
||||
servers: ServersMap;
|
||||
|
|
|
@ -2,7 +2,6 @@ import Bottle, { IContainer } from 'bottlejs';
|
|||
import { withRouter } from 'react-router-dom';
|
||||
import { connect as reduxConnect } from 'react-redux';
|
||||
import { pick } from 'ramda';
|
||||
import App from '../App';
|
||||
import provideApiServices from '../api/services/provideServices';
|
||||
import provideCommonServices from '../common/services/provideServices';
|
||||
import provideShortUrlsServices from '../short-urls/services/provideServices';
|
||||
|
@ -13,6 +12,7 @@ import provideUtilsServices from '../utils/services/provideServices';
|
|||
import provideMercureServices from '../mercure/services/provideServices';
|
||||
import provideSettingsServices from '../settings/services/provideServices';
|
||||
import provideDomainsServices from '../domains/services/provideServices';
|
||||
import provideAppServices from '../app/services/provideServices';
|
||||
import { ConnectDecorator } from './types';
|
||||
|
||||
type LazyActionMap = Record<string, Function>;
|
||||
|
@ -33,19 +33,7 @@ const connect: ConnectDecorator = (propsFromState: string[] | null, actionServic
|
|||
actionServiceNames.reduce(mapActionService, {}),
|
||||
);
|
||||
|
||||
bottle.serviceFactory(
|
||||
'App',
|
||||
App,
|
||||
'MainHeader',
|
||||
'Home',
|
||||
'MenuLayout',
|
||||
'CreateServer',
|
||||
'EditServer',
|
||||
'Settings',
|
||||
'ShlinkVersionsContainer',
|
||||
);
|
||||
bottle.decorator('App', connect([ 'servers', 'settings' ], [ 'fetchServers' ]));
|
||||
|
||||
provideAppServices(bottle, connect);
|
||||
provideCommonServices(bottle, connect, withRouter);
|
||||
provideApiServices(bottle);
|
||||
provideShortUrlsServices(bottle, connect);
|
||||
|
|
|
@ -35,6 +35,7 @@ export interface ShlinkState {
|
|||
settings: Settings;
|
||||
domainsList: DomainsList;
|
||||
visitsOverview: VisitsOverview;
|
||||
appUpdated: boolean;
|
||||
}
|
||||
|
||||
export type ConnectDecorator = (props: string[] | null, actions?: string[]) => any;
|
||||
|
|
|
@ -5,6 +5,7 @@ import { homepage } from '../package.json';
|
|||
import container from './container';
|
||||
import store from './container/store';
|
||||
import { fixLeafletIcons } from './utils/helpers/leaflet';
|
||||
import { register as registerServiceWorker } from './serviceWorkerRegistration';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import './index.scss';
|
||||
|
@ -12,7 +13,7 @@ import './index.scss';
|
|||
// This overwrites icons used for leaflet maps, fixing some issues caused by webpack while processing the CSS
|
||||
fixLeafletIcons();
|
||||
|
||||
const { App, ScrollToTop, ErrorHandler } = container;
|
||||
const { App, ScrollToTop, ErrorHandler, appUpdateAvailable } = container;
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
|
@ -26,3 +27,12 @@ render(
|
|||
</Provider>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://cra.link/PWA
|
||||
registerServiceWorker({
|
||||
onUpdate() {
|
||||
store.dispatch(appUpdateAvailable()); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import mercureInfoReducer from '../mercure/reducers/mercureInfo';
|
|||
import settingsReducer from '../settings/reducers/settings';
|
||||
import domainsListReducer from '../domains/reducers/domainsList';
|
||||
import visitsOverviewReducer from '../visits/reducers/visitsOverview';
|
||||
import appUpdatesReducer from '../app/reducers/appUpdates';
|
||||
import { ShlinkState } from '../container/types';
|
||||
|
||||
export default combineReducers<ShlinkState>({
|
||||
|
@ -38,4 +39,5 @@ export default combineReducers<ShlinkState>({
|
|||
settings: settingsReducer,
|
||||
domainsList: domainsListReducer,
|
||||
visitsOverview: visitsOverviewReducer,
|
||||
appUpdated: appUpdatesReducer,
|
||||
});
|
||||
|
|
80
src/service-worker.ts
Normal file
80
src/service-worker.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
/// <reference lib="webworker" />
|
||||
/* eslint-disable no-restricted-globals */
|
||||
|
||||
// This service worker can be customized!
|
||||
// See https://developers.google.com/web/tools/workbox/modules
|
||||
// for the list of available Workbox modules, or add any other
|
||||
// code you'd like.
|
||||
// You can also remove this file if you'd prefer not to use a
|
||||
// service worker, and the Workbox build step will be skipped.
|
||||
|
||||
import { clientsClaim } from 'workbox-core';
|
||||
import { ExpirationPlugin } from 'workbox-expiration';
|
||||
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
|
||||
import { registerRoute } from 'workbox-routing';
|
||||
import { StaleWhileRevalidate } from 'workbox-strategies';
|
||||
|
||||
declare const self: ServiceWorkerGlobalScope;
|
||||
|
||||
clientsClaim();
|
||||
|
||||
// Precache all of the assets generated by your build process.
|
||||
// Their URLs are injected into the manifest variable below.
|
||||
// This variable must be present somewhere in your service worker file,
|
||||
// even if you decide not to use precaching. See https://cra.link/PWA
|
||||
precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
// Set up App Shell-style routing, so that all navigation requests
|
||||
// are fulfilled with your index.html shell. Learn more at
|
||||
// https://developers.google.com/web/fundamentals/architecture/app-shell
|
||||
const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
|
||||
registerRoute(
|
||||
// Return false to exempt requests from being fulfilled by index.html.
|
||||
({ request, url }: { request: Request; url: URL }) => {
|
||||
// If this isn't a navigation, skip.
|
||||
if (request.mode !== 'navigate') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a URL that starts with /_, skip.
|
||||
if (url.pathname.startsWith('/_')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this looks like a URL for a resource, because it contains
|
||||
// a file extension, skip.
|
||||
if (url.pathname.match(fileExtensionRegexp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true to signal that we want to use the handler.
|
||||
return true;
|
||||
},
|
||||
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
|
||||
);
|
||||
|
||||
// An example runtime caching route for requests that aren't handled by the
|
||||
// precache, in this case same-origin .png requests like those from in public/
|
||||
registerRoute(
|
||||
// Add in any other file extensions or routing criteria as needed.
|
||||
({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'),
|
||||
// Customize this strategy as needed, e.g., by changing to CacheFirst.
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: 'images',
|
||||
plugins: [
|
||||
// Ensure that once this runtime cache reaches a maximum size the
|
||||
// least-recently used images are removed.
|
||||
new ExpirationPlugin({ maxEntries: 50 }),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// This allows the web app to trigger skipWaiting via
|
||||
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
|
||||
self.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting();
|
||||
}
|
||||
});
|
||||
|
||||
// Any other custom service worker logic can go here.
|
142
src/serviceWorkerRegistration.ts
Normal file
142
src/serviceWorkerRegistration.ts
Normal file
|
@ -0,0 +1,142 @@
|
|||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://cra.link/PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
|
||||
);
|
||||
|
||||
type Config = {
|
||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||
};
|
||||
|
||||
export function register(config?: Config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL ?? '', window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://cra.link/PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl: string, config?: Config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://cra.link/PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('No internet connection found. App is running in offline mode.');
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,23 +1,36 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { identity } from 'ramda';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { Alert } from 'reactstrap';
|
||||
import { Settings } from '../src/settings/reducers/settings';
|
||||
import appFactory from '../src/App';
|
||||
|
||||
describe('<App />', () => {
|
||||
let wrapper: ShallowWrapper;
|
||||
const MainHeader = () => null;
|
||||
const ShlinkVersions = () => null;
|
||||
|
||||
beforeEach(() => {
|
||||
const App = appFactory(MainHeader, () => null, () => null, () => null, () => null, () => null, () => null);
|
||||
const App = appFactory(MainHeader, () => null, () => null, () => null, () => null, () => null, ShlinkVersions);
|
||||
|
||||
wrapper = shallow(<App fetchServers={identity} servers={{}} settings={Mock.all<Settings>()} />);
|
||||
wrapper = shallow(
|
||||
<App
|
||||
fetchServers={() => {}}
|
||||
servers={{}}
|
||||
settings={Mock.all<Settings>()}
|
||||
appUpdated={false}
|
||||
resetAppUpdate={() => {}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
afterEach(() => wrapper.unmount());
|
||||
|
||||
it('renders a header', () => expect(wrapper.find(MainHeader)).toHaveLength(1));
|
||||
|
||||
it('renders versions', () => expect(wrapper.find(ShlinkVersions)).toHaveLength(1));
|
||||
|
||||
it('renders an Alert', () => expect(wrapper.find(Alert)).toHaveLength(1));
|
||||
|
||||
it('renders app main routes', () => {
|
||||
const routes = wrapper.find(Route);
|
||||
const expectedPaths = [
|
||||
|
|
30
test/app/reducers/appUpdates.test.ts
Normal file
30
test/app/reducers/appUpdates.test.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import reducer, {
|
||||
APP_UPDATE_AVAILABLE,
|
||||
RESET_APP_UPDATE,
|
||||
appUpdateAvailable,
|
||||
resetAppUpdate,
|
||||
} from '../../../src/app/reducers/appUpdates';
|
||||
|
||||
describe('appUpdatesReducer', () => {
|
||||
describe('reducer', () => {
|
||||
it('returns true on APP_UPDATE_AVAILABLE', () => {
|
||||
expect(reducer(undefined, { type: APP_UPDATE_AVAILABLE })).toEqual(true);
|
||||
});
|
||||
|
||||
it('returns false on RESET_APP_UPDATE', () => {
|
||||
expect(reducer(undefined, { type: RESET_APP_UPDATE })).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('appUpdateAvailable', () => {
|
||||
test('creates expected action', () => {
|
||||
expect(appUpdateAvailable()).toEqual({ type: APP_UPDATE_AVAILABLE });
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetAppUpdate', () => {
|
||||
test('creates expected action', () => {
|
||||
expect(resetAppUpdate()).toEqual({ type: RESET_APP_UPDATE });
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue