mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-10 18:27:25 +03:00
Merged develop
This commit is contained in:
commit
308660287e
17 changed files with 201 additions and 246 deletions
|
@ -10,8 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
* [#570](https://github.com/shlinkio/shlink-web-client/pull/570) Added new section to load non-orphan visits all together.
|
||||
|
||||
### Changed
|
||||
* [#543](https://github.com/shlinkio/shlink-web-client/pull/543) Redesigned settings section.
|
||||
* [#567](https://github.com/shlinkio/shlink-web-client/pull/567) Improved Shlink 3.0.0 compatibility by checking the `INVALID_SHORT_URL_DELETION` error code when deleting short URLs.
|
||||
* [#524](https://github.com/shlinkio/shlink-web-client/pull/524) Updated to react-router v6.
|
||||
* [#579](https://github.com/shlinkio/shlink-web-client/pull/579) Replaced react-color with react-colorful.
|
||||
|
||||
### Deprecated
|
||||
* *Nothing*
|
||||
|
|
218
package-lock.json
generated
218
package-lock.json
generated
|
@ -28,7 +28,7 @@
|
|||
"ramda": "^0.27.1",
|
||||
"react": "^17.0.1",
|
||||
"react-chartjs-2": "^3.0.4",
|
||||
"react-color": "^2.19.3",
|
||||
"react-colorful": "^5.5.1",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-datepicker": "^3.6.0",
|
||||
"react-dom": "^17.0.1",
|
||||
|
@ -104,7 +104,7 @@
|
|||
"object-assign": "^4.1.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"pnp-webpack-plugin": "^1.6.4",
|
||||
"postcss": "^8.1.7",
|
||||
"postcss": "^8.2.13",
|
||||
"postcss-flexbugs-fixes": "^4.2.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
|
@ -2567,14 +2567,6 @@
|
|||
"react": ">=0.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@icons/material": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
|
||||
"integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||
|
@ -9206,9 +9198,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
|
||||
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
|
@ -18534,28 +18526,6 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/line-column": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz",
|
||||
"integrity": "sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isarray": "^1.0.0",
|
||||
"isobject": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/line-column/node_modules/isobject": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
|
||||
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isarray": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
|
||||
|
@ -18664,11 +18634,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
|
||||
"integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
|
||||
},
|
||||
"node_modules/lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
|
@ -18997,11 +18962,6 @@
|
|||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/material-colors": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
|
||||
"integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg=="
|
||||
},
|
||||
"node_modules/mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -19616,9 +19576,9 @@
|
|||
"optional": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.1.16",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.16.tgz",
|
||||
"integrity": "sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
|
||||
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
|
@ -21184,14 +21144,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.1.7",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.7.tgz",
|
||||
"integrity": "sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ==",
|
||||
"version": "8.2.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
|
||||
"integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colorette": "^1.2.1",
|
||||
"line-column": "^1.0.2",
|
||||
"nanoid": "^3.1.16",
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -26503,21 +26462,13 @@
|
|||
"react": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-color": {
|
||||
"version": "2.19.3",
|
||||
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz",
|
||||
"integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==",
|
||||
"dependencies": {
|
||||
"@icons/material": "^0.2.4",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash-es": "^4.17.15",
|
||||
"material-colors": "^1.2.1",
|
||||
"prop-types": "^15.5.10",
|
||||
"reactcss": "^1.2.0",
|
||||
"tinycolor2": "^1.4.1"
|
||||
},
|
||||
"node_modules/react-colorful": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz",
|
||||
"integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-copy-to-clipboard": {
|
||||
|
@ -26989,14 +26940,6 @@
|
|||
"react-dom": ">=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reactcss": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
|
||||
"integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/reactstrap": {
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
||||
|
@ -31626,14 +31569,6 @@
|
|||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tinycolor2": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
|
||||
"integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz",
|
||||
|
@ -33782,9 +33717,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webpack-dev-server/node_modules/ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async-limiter": "~1.0.0"
|
||||
|
@ -34561,9 +34496,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
|
||||
"integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
|
||||
"integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
|
@ -36622,12 +36557,6 @@
|
|||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"@icons/material": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
|
||||
"integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||
|
@ -41834,9 +41763,9 @@
|
|||
}
|
||||
},
|
||||
"colorette": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
|
||||
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
|
@ -49019,27 +48948,6 @@
|
|||
"type-check": "~0.4.0"
|
||||
}
|
||||
},
|
||||
"line-column": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz",
|
||||
"integrity": "sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isarray": "^1.0.0",
|
||||
"isobject": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"isobject": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
|
||||
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isarray": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"lines-and-columns": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
|
||||
|
@ -49128,11 +49036,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
|
||||
"integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
|
@ -49406,11 +49309,6 @@
|
|||
"repeat-string": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"material-colors": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
|
||||
"integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg=="
|
||||
},
|
||||
"mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -49919,9 +49817,9 @@
|
|||
"optional": true
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.16",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.16.tgz",
|
||||
"integrity": "sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
|
||||
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
|
||||
"dev": true
|
||||
},
|
||||
"nanomatch": {
|
||||
|
@ -51122,14 +51020,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.1.7",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.7.tgz",
|
||||
"integrity": "sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ==",
|
||||
"version": "8.2.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
|
||||
"integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colorette": "^1.2.1",
|
||||
"line-column": "^1.0.2",
|
||||
"nanoid": "^3.1.16",
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"source-map": "^0.6.1"
|
||||
}
|
||||
},
|
||||
|
@ -55346,19 +55243,11 @@
|
|||
"lodash": "^4.17.19"
|
||||
}
|
||||
},
|
||||
"react-color": {
|
||||
"version": "2.19.3",
|
||||
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz",
|
||||
"integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==",
|
||||
"requires": {
|
||||
"@icons/material": "^0.2.4",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash-es": "^4.17.15",
|
||||
"material-colors": "^1.2.1",
|
||||
"prop-types": "^15.5.10",
|
||||
"reactcss": "^1.2.0",
|
||||
"tinycolor2": "^1.4.1"
|
||||
}
|
||||
"react-colorful": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz",
|
||||
"integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-copy-to-clipboard": {
|
||||
"version": "5.0.2",
|
||||
|
@ -55710,14 +55599,6 @@
|
|||
"react-lifecycles-compat": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"reactcss": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
|
||||
"integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
|
||||
"requires": {
|
||||
"lodash": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"reactstrap": {
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
||||
|
@ -59307,11 +59188,6 @@
|
|||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
|
||||
"dev": true
|
||||
},
|
||||
"tinycolor2": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
|
||||
"integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz",
|
||||
|
@ -61005,9 +60881,9 @@
|
|||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
|
@ -61598,9 +61474,9 @@
|
|||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
|
||||
"integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
|
||||
"integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
"ramda": "^0.27.1",
|
||||
"react": "^17.0.1",
|
||||
"react-chartjs-2": "^3.0.4",
|
||||
"react-color": "^2.19.3",
|
||||
"react-colorful": "^5.5.1",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-datepicker": "^3.6.0",
|
||||
"react-dom": "^17.0.1",
|
||||
|
@ -119,7 +119,7 @@
|
|||
"object-assign": "^4.1.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"pnp-webpack-plugin": "^1.6.4",
|
||||
"postcss": "^8.1.7",
|
||||
"postcss": "^8.2.13",
|
||||
"postcss-flexbugs-fixes": "^4.2.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
|
|
|
@ -47,7 +47,7 @@ const App = (
|
|||
<div className={classNames('shlink-wrapper', { 'd-flex d-md-block align-items-center': isHome })}>
|
||||
<Routes>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="/settings" element={<Settings />} />
|
||||
<Route path="/settings/*" element={<Settings />} />
|
||||
<Route path="/manage-servers" element={<ManageServers />} />
|
||||
<Route path="/server/create" element={<CreateServer />} />
|
||||
<Route path="/server/:serverId/edit" element={<EditServer />} />
|
||||
|
|
|
@ -31,7 +31,7 @@ const MainHeader = (ServersDropdown: FC) => () => {
|
|||
<Collapse navbar isOpen={isOpen}>
|
||||
<Nav navbar className="ml-auto">
|
||||
<NavItem>
|
||||
<NavLink tag={Link} to={settingsPath} active={pathname === settingsPath}>
|
||||
<NavLink tag={Link} to={settingsPath} active={pathname.startsWith(settingsPath)}>
|
||||
<FontAwesomeIcon icon={cogsIcon} /> Settings
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
import { FC, ReactNode } from 'react';
|
||||
import { Row } from 'reactstrap';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
import { NoMenuLayout } from '../common/NoMenuLayout';
|
||||
import { NavPillItem, NavPills } from '../utils/NavPills';
|
||||
|
||||
const SettingsSections: FC<{ items: ReactNode[][] }> = ({ items }) => (
|
||||
const SettingsSections: FC<{ items: ReactNode[] }> = ({ items }) => (
|
||||
<>
|
||||
{items.map((child, index) => (
|
||||
<Row key={index}>
|
||||
{child.map((subChild, subIndex) => (
|
||||
<div key={subIndex} className={`col-lg-${12 / child.length} mb-3`}>
|
||||
{subChild}
|
||||
</div>
|
||||
))}
|
||||
</Row>
|
||||
))}
|
||||
{items.map((child, index) => <div key={index} className="mb-3">{child}</div>)}
|
||||
</>
|
||||
);
|
||||
|
||||
|
@ -25,13 +18,18 @@ const Settings = (
|
|||
Tags: FC,
|
||||
) => () => (
|
||||
<NoMenuLayout>
|
||||
<SettingsSections
|
||||
items={[
|
||||
[ <UserInterface />, <Visits /> ], // eslint-disable-line react/jsx-key
|
||||
[ <ShortUrlCreation />, <ShortUrlsList /> ], // eslint-disable-line react/jsx-key
|
||||
[ <Tags />, <RealTimeUpdates /> ], // eslint-disable-line react/jsx-key
|
||||
]}
|
||||
/>
|
||||
<NavPills>
|
||||
<NavPillItem to="general">General</NavPillItem>
|
||||
<NavPillItem to="short-urls">Short URLs</NavPillItem>
|
||||
<NavPillItem to="secondary-items">Secondary items</NavPillItem>
|
||||
</NavPills>
|
||||
|
||||
<Routes>
|
||||
<Route path="general" element={<SettingsSections items={[ <UserInterface key="one" />, <RealTimeUpdates key="two" /> ]} />} />
|
||||
<Route path="short-urls" element={<SettingsSections items={[ <ShortUrlCreation key="one" />, <ShortUrlsList key="two" /> ]} />} />
|
||||
<Route path="secondary-items" element={<SettingsSections items={[ <Tags key="one" />, <Visits key="two" /> ]} />} />
|
||||
<Route path="*" element={<Navigate replace to="general" />} />
|
||||
</Routes>
|
||||
</NoMenuLayout>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { FC } from 'react';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faSun, faMoon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FormGroup } from 'reactstrap';
|
||||
import { SimpleCard } from '../utils/SimpleCard';
|
||||
import ToggleSwitch from '../utils/ToggleSwitch';
|
||||
import { changeThemeInMarkup, Theme } from '../utils/theme';
|
||||
|
@ -15,19 +14,17 @@ interface UserInterfaceProps {
|
|||
|
||||
export const UserInterfaceSettings: FC<UserInterfaceProps> = ({ settings: { ui }, setUiSettings }) => (
|
||||
<SimpleCard title="User interface" className="h-100">
|
||||
<FormGroup>
|
||||
<FontAwesomeIcon icon={ui?.theme === 'dark' ? faMoon : faSun} className="user-interface__theme-icon" />
|
||||
<ToggleSwitch
|
||||
checked={ui?.theme === 'dark'}
|
||||
onChange={(useDarkTheme) => {
|
||||
const theme: Theme = useDarkTheme ? 'dark' : 'light';
|
||||
<FontAwesomeIcon icon={ui?.theme === 'dark' ? faMoon : faSun} className="user-interface__theme-icon" />
|
||||
<ToggleSwitch
|
||||
checked={ui?.theme === 'dark'}
|
||||
onChange={(useDarkTheme) => {
|
||||
const theme: Theme = useDarkTheme ? 'dark' : 'light';
|
||||
|
||||
setUiSettings({ ...ui, theme });
|
||||
changeThemeInMarkup(theme);
|
||||
}}
|
||||
>
|
||||
Use dark theme.
|
||||
</ToggleSwitch>
|
||||
</FormGroup>
|
||||
setUiSettings({ ...ui, theme });
|
||||
changeThemeInMarkup(theme);
|
||||
}}
|
||||
>
|
||||
Use dark theme.
|
||||
</ToggleSwitch>
|
||||
</SimpleCard>
|
||||
);
|
||||
|
|
|
@ -5,3 +5,7 @@
|
|||
.edit-tag-modal__color-icon {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.edit-tag-modal__popover.edit-tag-modal__popover {
|
||||
border-radius: .6rem;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useState } from 'react';
|
||||
import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader, Popover } from 'reactstrap';
|
||||
import { ChromePicker } from 'react-color';
|
||||
import { HexColorPicker } from 'react-colorful';
|
||||
import { faPalette as colorIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useToggle } from '../../utils/helpers/hooks';
|
||||
|
@ -46,8 +46,15 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
|
|||
<FontAwesomeIcon icon={colorIcon} className="edit-tag-modal__color-icon" />
|
||||
</div>
|
||||
</div>
|
||||
<Popover isOpen={showColorPicker} toggle={toggleColorPicker} target="colorPickerBtn" placement="right">
|
||||
<ChromePicker color={color} disableAlpha onChange={({ hex }) => setColor(hex)} />
|
||||
<Popover
|
||||
isOpen={showColorPicker}
|
||||
toggle={toggleColorPicker}
|
||||
target="colorPickerBtn"
|
||||
placement="right"
|
||||
hideArrow
|
||||
popperClassName="edit-tag-modal__popover"
|
||||
>
|
||||
<HexColorPicker color={color} onChange={setColor} />
|
||||
</Popover>
|
||||
<Input
|
||||
value={newTagName}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
@import '../utils/base';
|
||||
@import './base';
|
||||
|
||||
.visits-stats__nav {
|
||||
.nav-pills__nav {
|
||||
position: sticky !important;
|
||||
top: $headerHeight - 1px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.visits-stats__nav-link {
|
||||
.nav-pills__nav-link {
|
||||
border-radius: 0 !important;
|
||||
padding-bottom: calc(.5rem - 3px) !important;
|
||||
border-bottom: 3px solid transparent;
|
||||
|
@ -19,11 +19,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.visits-stats__nav-link:hover {
|
||||
.nav-pills__nav-link:hover {
|
||||
color: $mainColor !important;
|
||||
}
|
||||
|
||||
.visits-stats__nav-link.active {
|
||||
.nav-pills__nav-link.active {
|
||||
border-color: $mainColor;
|
||||
background-color: var(--primary-color) !important;
|
||||
color: $mainColor !important;
|
29
src/utils/NavPills.tsx
Normal file
29
src/utils/NavPills.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { FC, Children, isValidElement } from 'react';
|
||||
import { Card, Nav, NavLink } from 'reactstrap';
|
||||
import { NavLink as RouterNavLink } from 'react-router-dom';
|
||||
import './NavPills.scss';
|
||||
|
||||
interface NavPillProps {
|
||||
to: string;
|
||||
replace?: boolean;
|
||||
}
|
||||
|
||||
export const NavPillItem: FC<NavPillProps> = ({ children, ...rest }) => (
|
||||
<NavLink className="nav-pills__nav-link" tag={RouterNavLink} {...rest}>
|
||||
{children}
|
||||
</NavLink>
|
||||
);
|
||||
|
||||
export const NavPills: FC<{ fill?: boolean }> = ({ children, fill = false }) => (
|
||||
<Card className="nav-pills__nav p-0 overflow-hidden mb-3" body>
|
||||
<Nav pills fill={fill}>
|
||||
{Children.map(children, (child) => {
|
||||
if (!isValidElement(child) || child.type !== NavPillItem) {
|
||||
throw new Error('Only NavPillItem children are allowed inside NavPills.');
|
||||
}
|
||||
|
||||
return child;
|
||||
})}
|
||||
</Nav>
|
||||
</Card>
|
||||
);
|
|
@ -1,11 +1,10 @@
|
|||
import { isEmpty, propEq, values } from 'ramda';
|
||||
import { useState, useEffect, useMemo, FC, useRef } from 'react';
|
||||
import { Button, Card, Nav, NavLink, Progress, Row } from 'reactstrap';
|
||||
import { Button, Progress, Row } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faCalendarAlt, faMapMarkedAlt, faList, faChartPie, faFileDownload } from '@fortawesome/free-solid-svg-icons';
|
||||
import { IconDefinition } from '@fortawesome/fontawesome-common-types';
|
||||
import { Route, Routes, NavLink as RouterNavLink, Navigate } from 'react-router-dom';
|
||||
import { Location } from 'history';
|
||||
import { Route, Routes, Navigate } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
|
||||
import Message from '../utils/Message';
|
||||
|
@ -16,6 +15,7 @@ import { Settings } from '../settings/reducers/settings';
|
|||
import { SelectedServer } from '../servers/data';
|
||||
import { supportsBotVisits } from '../utils/helpers/features';
|
||||
import { prettify } from '../utils/helpers/numbers';
|
||||
import { NavPillItem, NavPills } from '../utils/NavPills';
|
||||
import LineChartCard from './charts/LineChartCard';
|
||||
import VisitsTable from './VisitsTable';
|
||||
import { NormalizedOrphanVisit, NormalizedVisit, VisitsFilter, VisitsInfo, VisitsParams } from './types';
|
||||
|
@ -25,7 +25,6 @@ import { VisitsFilterDropdown } from './helpers/VisitsFilterDropdown';
|
|||
import { HighlightableProps, highlightedVisitsToStats } from './types/helpers';
|
||||
import { DoughnutChartCard } from './charts/DoughnutChartCard';
|
||||
import { SortableBarChartCard } from './charts/SortableBarChartCard';
|
||||
import './VisitsStats.scss';
|
||||
|
||||
export interface VisitsStatsProps {
|
||||
getVisits: (params: VisitsParams, doIntervalFallback?: boolean) => void;
|
||||
|
@ -55,19 +54,6 @@ const sections: Record<Section, VisitsNavLinkProps> = {
|
|||
|
||||
let selectedBar: string | undefined;
|
||||
|
||||
const VisitsNavLink: FC<VisitsNavLinkProps & { to: string }> = ({ subPath, title, icon, to }) => (
|
||||
<NavLink
|
||||
tag={RouterNavLink}
|
||||
className="visits-stats__nav-link"
|
||||
to={to}
|
||||
isActive={(_: null, { pathname }: Location) => pathname.endsWith(`visits${subPath}`)}
|
||||
replace
|
||||
>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
<span className="ml-2 d-none d-sm-inline">{title}</span>
|
||||
</NavLink>
|
||||
);
|
||||
|
||||
const VisitsStats: FC<VisitsStatsProps> = ({
|
||||
children,
|
||||
visitsInfo,
|
||||
|
@ -157,12 +143,14 @@ const VisitsStats: FC<VisitsStatsProps> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Card className="visits-stats__nav p-0 overflow-hidden" body>
|
||||
<Nav pills fill>
|
||||
{Object.entries(sections).map(([ section, props ]) =>
|
||||
<VisitsNavLink key={section} {...props} to={buildSectionUrl(props.subPath)} />)}
|
||||
</Nav>
|
||||
</Card>
|
||||
<NavPills fill>
|
||||
{Object.values(sections).map(({ title, icon, subPath }, index) => (
|
||||
<NavPillItem key={index} to={buildSectionUrl(subPath)} replace>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
<span className="ml-2 d-none d-sm-inline">{title}</span>
|
||||
</NavPillItem>
|
||||
))}
|
||||
</NavPills>
|
||||
<Row>
|
||||
<Routes>
|
||||
<Route
|
||||
|
|
|
@ -54,7 +54,7 @@ describe('<App />', () => {
|
|||
const routes = wrapper.find(Route);
|
||||
const expectedPaths = [
|
||||
undefined,
|
||||
'/settings',
|
||||
'/settings/*',
|
||||
'/manage-servers',
|
||||
'/server/create',
|
||||
'/server/:serverId/edit',
|
||||
|
|
|
@ -35,6 +35,8 @@ describe('<MainHeader />', () => {
|
|||
[ '/foo', false ],
|
||||
[ '/bar', false ],
|
||||
[ '/settings', true ],
|
||||
[ '/settings/foo', true ],
|
||||
[ '/settings/bar', true ],
|
||||
])('sets link to settings as active only when current path is settings', (currentPath, isActive) => {
|
||||
const wrapper = createWrapper(currentPath);
|
||||
const settingsLink = wrapper.find(NavLink);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { Route } from 'react-router-dom';
|
||||
import createSettings from '../../src/settings/Settings';
|
||||
import { NoMenuLayout } from '../../src/common/NoMenuLayout';
|
||||
import { NavPillItem } from '../../src/utils/NavPills';
|
||||
|
||||
describe('<Settings />', () => {
|
||||
const Component = () => null;
|
||||
|
@ -9,10 +11,19 @@ describe('<Settings />', () => {
|
|||
it('renders a no-menu layout with the expected settings sections', () => {
|
||||
const wrapper = shallow(<Settings />);
|
||||
const layout = wrapper.find(NoMenuLayout);
|
||||
const sections = wrapper.find('SettingsSections');
|
||||
const sections = wrapper.find(Route);
|
||||
|
||||
expect(layout).toHaveLength(1);
|
||||
expect(sections).toHaveLength(1);
|
||||
expect((sections.prop('items') as any[]).flat()).toHaveLength(6);
|
||||
expect(sections).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('renders expected menu', () => {
|
||||
const wrapper = shallow(<Settings />);
|
||||
const items = wrapper.find(NavPillItem);
|
||||
|
||||
expect(items).toHaveLength(3);
|
||||
expect(items.first().prop('to')).toEqual('general');
|
||||
expect(items.at(1).prop('to')).toEqual('short-urls');
|
||||
expect(items.last().prop('to')).toEqual('secondary-items');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { Button, Input, Modal, ModalHeader, Popover } from 'reactstrap';
|
||||
import { ChromePicker } from 'react-color';
|
||||
import { HexColorPicker } from 'react-colorful';
|
||||
import { TagEdition } from '../../../src/tags/reducers/tagEdit';
|
||||
import createEditTagModal from '../../../src/tags/helpers/EditTagModal';
|
||||
import ColorGenerator from '../../../src/utils/services/ColorGenerator';
|
||||
|
@ -92,9 +92,9 @@ describe('<EditTagModal />', () => {
|
|||
it('changes color when changing on color picker', () => {
|
||||
const wrapper = createWrapper();
|
||||
|
||||
expect(wrapper.find(ChromePicker).prop('color')).toEqual('red');
|
||||
wrapper.find(ChromePicker).simulate('change', { hex: 'blue' });
|
||||
expect(wrapper.find(ChromePicker).prop('color')).toEqual('blue');
|
||||
expect(wrapper.find(HexColorPicker).prop('color')).toEqual('red');
|
||||
wrapper.find(HexColorPicker).simulate('change', 'blue');
|
||||
expect(wrapper.find(HexColorPicker).prop('color')).toEqual('blue');
|
||||
});
|
||||
|
||||
it('allows toggling popover with different mechanisms', () => {
|
||||
|
|
41
test/utils/NavPills.test.tsx
Normal file
41
test/utils/NavPills.test.tsx
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { Card, Nav } from 'reactstrap';
|
||||
import { NavPillItem, NavPills } from '../../src/utils/NavPills';
|
||||
|
||||
describe('<NavPills />', () => {
|
||||
it.each([
|
||||
[ 'Foo' ],
|
||||
[ <span key="1">Hi!</span> ],
|
||||
[[ <NavPillItem key="1" to="" />, <span key="2">Hi!</span> ]],
|
||||
])('throws error when any of the children is not a NavPillItem', (children) => {
|
||||
expect.assertions(1);
|
||||
|
||||
try {
|
||||
shallow(<NavPills>{children}</NavPills>);
|
||||
} catch (e: any) {
|
||||
expect(e.message).toEqual('Only NavPillItem children are allowed inside NavPills.');
|
||||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
[ undefined ],
|
||||
[ true ],
|
||||
[ false ],
|
||||
])('renders provided items', (fill) => {
|
||||
const wrapper = shallow(
|
||||
<NavPills fill={fill}>
|
||||
<NavPillItem to="1">1</NavPillItem>
|
||||
<NavPillItem to="2">2</NavPillItem>
|
||||
<NavPillItem to="3">3</NavPillItem>
|
||||
</NavPills>,
|
||||
);
|
||||
const card = wrapper.find(Card);
|
||||
const nav = wrapper.find(Nav);
|
||||
|
||||
expect(card).toHaveLength(1);
|
||||
expect(card.prop('body')).toEqual(true);
|
||||
expect(nav).toHaveLength(1);
|
||||
expect(nav.prop('pills')).toEqual(true);
|
||||
expect(nav.prop('fill')).toEqual(!!fill);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue