mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-31 21:38:19 +03:00
Merge pull request #1044 from acelaya-forks/feature/swc-0.5
Update to latest shlink-web-component
This commit is contained in:
commit
b12bb6cdc5
5 changed files with 135 additions and 96 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -4,21 +4,31 @@ 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).
|
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]
|
## [4.0.0] - 2024-01-29
|
||||||
### Added
|
### Added
|
||||||
* *Nothing*
|
* [shlink-web-component #7](https://github.com/shlinkio/shlink-web-component/issues/7) Allow comparing visits for multiple short URLs, tags or domains.
|
||||||
|
|
||||||
|
When in the tags, domains or short URLs tables, you can now pick up to 5 items to compare their visits. Once selected, you are taken to a section displaying a comparative line chart, which supports all regular visits filtering capabilities.
|
||||||
|
|
||||||
|
* [shlink-web-component #9](https://github.com/shlinkio/shlink-web-component/issues/9) Allow comparing visits with the previous period.
|
||||||
|
* [shlink-web-component #12](https://github.com/shlinkio/shlink-web-component/issues/12) and [#13](https://github.com/shlinkio/shlink-web-component/issues/13) Add new "Visits options" section for arbitrary visit stats options. Add section to delete short URL and orphan visits there.
|
||||||
|
|
||||||
|
This section is only visible if short URL visits deletion or orphan visits deletion are supported by connected Shlink server.
|
||||||
|
|
||||||
|
* [shlink-web-component #10](https://github.com/shlinkio/shlink-web-component/issues/10) Improve general accessibility: Add accessibility tests, fix accessibility issues and enable accessibility linting rules.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* [#338](https://github.com/shlinkio/shlink-web-client/issues/338) Extract `@shlinkio/shlink-web-component` and `@shlinkio/shlink-frontend-kit` as external libs.
|
* [#338](https://github.com/shlinkio/shlink-web-client/issues/338) Extract `@shlinkio/shlink-web-component` and `@shlinkio/shlink-frontend-kit` as external libs.
|
||||||
* [#978](https://github.com/shlinkio/shlink-web-client/issues/978) Use system preferred theme as default theme.
|
* [#978](https://github.com/shlinkio/shlink-web-client/issues/978) Use system preferred theme as default theme.
|
||||||
* Use API client from `@shlinkio/shlink-js-sdk` to consume Shlink servers.
|
* Use API client from `@shlinkio/shlink-js-sdk` to consume Shlink servers.
|
||||||
* [#902](https://github.com/shlinkio/shlink-web-client/pull/902) Docker image is no longer running as root. As a side effect, exposed port is `8080`, not `80` anymore.
|
* [#902](https://github.com/shlinkio/shlink-web-client/pull/902) Docker image is no longer running as root. As a side effect, exposed port is `8080`, not `80` anymore.
|
||||||
|
* [shlink-web-component #117](https://github.com/shlinkio/shlink-web-component/issues/117) Migrate charts from Chart.JS to Recharts.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
* *Nothing*
|
* *Nothing*
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
* *Nothing*
|
* Drop support for Shlink older than v3.0.0
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* [#910](https://github.com/shlinkio/shlink-web-client/issues/910) Fix warnings related with missing `act` in tests and refs in `AppUpdateBanner`.
|
* [#910](https://github.com/shlinkio/shlink-web-client/issues/910) Fix warnings related with missing `act` in tests and refs in `AppUpdateBanner`.
|
||||||
|
|
105
package-lock.json
generated
105
package-lock.json
generated
|
@ -18,7 +18,7 @@
|
||||||
"@shlinkio/data-manipulation": "^1.0.3",
|
"@shlinkio/data-manipulation": "^1.0.3",
|
||||||
"@shlinkio/shlink-frontend-kit": "^0.4.2",
|
"@shlinkio/shlink-frontend-kit": "^0.4.2",
|
||||||
"@shlinkio/shlink-js-sdk": "^0.2.2",
|
"@shlinkio/shlink-js-sdk": "^0.2.2",
|
||||||
"@shlinkio/shlink-web-component": "^0.4.1",
|
"@shlinkio/shlink-web-component": "^0.5.0",
|
||||||
"bootstrap": "5.2.3",
|
"bootstrap": "5.2.3",
|
||||||
"bottlejs": "^2.0.1",
|
"bottlejs": "^2.0.1",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
|
@ -2980,26 +2980,26 @@
|
||||||
"integrity": "sha512-gY9EiaULbEwmrTsnXk0MQUG/3bOvhxHQNOU35psFX2NbB8OzdfoE1iiT/Sez3awmmxz+/p8d6aULBt/ywxukIQ=="
|
"integrity": "sha512-gY9EiaULbEwmrTsnXk0MQUG/3bOvhxHQNOU35psFX2NbB8OzdfoE1iiT/Sez3awmmxz+/p8d6aULBt/ywxukIQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@shlinkio/shlink-web-component": {
|
"node_modules/@shlinkio/shlink-web-component": {
|
||||||
"version": "0.4.1",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.5.0.tgz",
|
||||||
"integrity": "sha512-jzzrbe6ufzF6X1JTqZAjLr5eAtfhJDseglqXVdQ+UXLNYvvGcxrp5LlTxsnf9LQUgLkvZ1qfz5Knfk143B1PtA==",
|
"integrity": "sha512-YuZ7VSJtGpHUVUoO1Zvdmn0P5msbxh8xqiJVyvKx9F/x5uvodRIHuUypR3n/A69DfvYt9SUagGZAz3BtG1UB8g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@json2csv/plainjs": "^7.0.4",
|
"@json2csv/plainjs": "^7.0.5",
|
||||||
"@shlinkio/data-manipulation": "^1.0.2",
|
"@shlinkio/data-manipulation": "^1.0.3",
|
||||||
"bottlejs": "^2.0.1",
|
"bottlejs": "^2.0.1",
|
||||||
"bowser": "^2.11.0",
|
"bowser": "^2.11.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.1.0",
|
||||||
"compare-versions": "^6.1.0",
|
"compare-versions": "^6.1.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^3.3.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"react-copy-to-clipboard": "^5.1.0",
|
"react-copy-to-clipboard": "^5.1.0",
|
||||||
"react-datepicker": "^4.24.0",
|
"react-datepicker": "^4.25.0",
|
||||||
"react-external-link": "^2.2.0",
|
"react-external-link": "^2.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-swipeable": "^7.0.1",
|
"react-swipeable": "^7.0.1",
|
||||||
"react-tag-autocomplete": "^7.1.0",
|
"react-tag-autocomplete": "^7.1.0",
|
||||||
"recharts": "^2.10.3"
|
"recharts": "^2.10.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||||
|
@ -3008,12 +3008,12 @@
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@reduxjs/toolkit": "^2.0.1",
|
"@reduxjs/toolkit": "^2.0.1",
|
||||||
"@shlinkio/shlink-frontend-kit": "^0.4.0",
|
"@shlinkio/shlink-frontend-kit": "^0.4.2",
|
||||||
"@shlinkio/shlink-js-sdk": "^0.2.0",
|
"@shlinkio/shlink-js-sdk": "^0.2.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^9.0.1",
|
"react-redux": "^9.0.1",
|
||||||
"react-router-dom": "^6.14.2",
|
"react-router-dom": "^6.20.1",
|
||||||
"reactstrap": "^9.2.0"
|
"reactstrap": "^9.2.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
|
@ -3022,21 +3022,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shlinkio/shlink-web-component/node_modules/date-fns": {
|
|
||||||
"version": "2.30.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
|
||||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.21.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.11"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/date-fns"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@shlinkio/stylelint-config-css-coding-standard": {
|
"node_modules/@shlinkio/stylelint-config-css-coding-standard": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@shlinkio/stylelint-config-css-coding-standard/-/stylelint-config-css-coding-standard-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shlinkio/stylelint-config-css-coding-standard/-/stylelint-config-css-coding-standard-1.1.1.tgz",
|
||||||
|
@ -8713,9 +8698,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-datepicker": {
|
"node_modules/react-datepicker": {
|
||||||
"version": "4.24.0",
|
"version": "4.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.25.0.tgz",
|
||||||
"integrity": "sha512-2QUC2pP+x4v3Jp06gnFllxKsJR0yoT/K6y86ItxEsveTXUpsx+NBkChWXjU0JsGx/PL8EQnsxN0wHl4zdA1m/g==",
|
"integrity": "sha512-zB7CSi44SJ0sqo8hUQ3BF1saE/knn7u25qEMTO1CQGofY1VAKahO8k9drZtp0cfW1DMfoYLR3uSY1/uMvbEzbg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -9031,9 +9016,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/recharts": {
|
"node_modules/recharts": {
|
||||||
"version": "2.10.3",
|
"version": "2.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.11.0.tgz",
|
||||||
"integrity": "sha512-G4J96fKTZdfFQd6aQnZjo2nVNdXhp+uuLb00+cBTGLo85pChvm1+E67K3wBOHDE/77spcYb2Cy9gYWVqiZvQCg==",
|
"integrity": "sha512-5s+u1m5Hwxb2nh0LABkE3TS/lFqFHyWl7FnPbQhHobbQQia4ih1t3o3+ikPYr31Ns+kYe4FASIthKeKi/YYvMg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"eventemitter3": "^4.0.1",
|
"eventemitter3": "^4.0.1",
|
||||||
|
@ -10432,9 +10417,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/victory-vendor": {
|
"node_modules/victory-vendor": {
|
||||||
"version": "36.7.0",
|
"version": "36.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.8.2.tgz",
|
||||||
"integrity": "sha512-nqYuTkLSdTTeACyXcCLbL7rl0y6jpzLPtTNGOtSnajdR+xxMxBdjMxDjfNJNlhR+ZU8vbXz+QejntcbY7h9/ZA==",
|
"integrity": "sha512-NfSQi7ISCdBbDpn3b6rg+8RpFZmWIM9mcks48BbogHE2F6h1XKdA34oiCKP5hP1OGvTotDRzsexiJKzrK4Exuw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/d3-array": "^3.0.3",
|
"@types/d3-array": "^3.0.3",
|
||||||
"@types/d3-ease": "^3.0.0",
|
"@types/d3-ease": "^3.0.0",
|
||||||
|
@ -13134,36 +13119,26 @@
|
||||||
"integrity": "sha512-gY9EiaULbEwmrTsnXk0MQUG/3bOvhxHQNOU35psFX2NbB8OzdfoE1iiT/Sez3awmmxz+/p8d6aULBt/ywxukIQ=="
|
"integrity": "sha512-gY9EiaULbEwmrTsnXk0MQUG/3bOvhxHQNOU35psFX2NbB8OzdfoE1iiT/Sez3awmmxz+/p8d6aULBt/ywxukIQ=="
|
||||||
},
|
},
|
||||||
"@shlinkio/shlink-web-component": {
|
"@shlinkio/shlink-web-component": {
|
||||||
"version": "0.4.1",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.5.0.tgz",
|
||||||
"integrity": "sha512-jzzrbe6ufzF6X1JTqZAjLr5eAtfhJDseglqXVdQ+UXLNYvvGcxrp5LlTxsnf9LQUgLkvZ1qfz5Knfk143B1PtA==",
|
"integrity": "sha512-YuZ7VSJtGpHUVUoO1Zvdmn0P5msbxh8xqiJVyvKx9F/x5uvodRIHuUypR3n/A69DfvYt9SUagGZAz3BtG1UB8g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@json2csv/plainjs": "^7.0.4",
|
"@json2csv/plainjs": "^7.0.5",
|
||||||
"@shlinkio/data-manipulation": "^1.0.2",
|
"@shlinkio/data-manipulation": "^1.0.3",
|
||||||
"bottlejs": "^2.0.1",
|
"bottlejs": "^2.0.1",
|
||||||
"bowser": "^2.11.0",
|
"bowser": "^2.11.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.1.0",
|
||||||
"compare-versions": "^6.1.0",
|
"compare-versions": "^6.1.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^3.3.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"react-copy-to-clipboard": "^5.1.0",
|
"react-copy-to-clipboard": "^5.1.0",
|
||||||
"react-datepicker": "^4.24.0",
|
"react-datepicker": "^4.25.0",
|
||||||
"react-external-link": "^2.2.0",
|
"react-external-link": "^2.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-swipeable": "^7.0.1",
|
"react-swipeable": "^7.0.1",
|
||||||
"react-tag-autocomplete": "^7.1.0",
|
"react-tag-autocomplete": "^7.1.0",
|
||||||
"recharts": "^2.10.3"
|
"recharts": "^2.10.4"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"date-fns": {
|
|
||||||
"version": "2.30.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
|
||||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.21.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@shlinkio/stylelint-config-css-coding-standard": {
|
"@shlinkio/stylelint-config-css-coding-standard": {
|
||||||
|
@ -17015,9 +16990,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-datepicker": {
|
"react-datepicker": {
|
||||||
"version": "4.24.0",
|
"version": "4.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.25.0.tgz",
|
||||||
"integrity": "sha512-2QUC2pP+x4v3Jp06gnFllxKsJR0yoT/K6y86ItxEsveTXUpsx+NBkChWXjU0JsGx/PL8EQnsxN0wHl4zdA1m/g==",
|
"integrity": "sha512-zB7CSi44SJ0sqo8hUQ3BF1saE/knn7u25qEMTO1CQGofY1VAKahO8k9drZtp0cfW1DMfoYLR3uSY1/uMvbEzbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -17221,9 +17196,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"recharts": {
|
"recharts": {
|
||||||
"version": "2.10.3",
|
"version": "2.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.11.0.tgz",
|
||||||
"integrity": "sha512-G4J96fKTZdfFQd6aQnZjo2nVNdXhp+uuLb00+cBTGLo85pChvm1+E67K3wBOHDE/77spcYb2Cy9gYWVqiZvQCg==",
|
"integrity": "sha512-5s+u1m5Hwxb2nh0LABkE3TS/lFqFHyWl7FnPbQhHobbQQia4ih1t3o3+ikPYr31Ns+kYe4FASIthKeKi/YYvMg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"eventemitter3": "^4.0.1",
|
"eventemitter3": "^4.0.1",
|
||||||
|
@ -18209,9 +18184,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"victory-vendor": {
|
"victory-vendor": {
|
||||||
"version": "36.7.0",
|
"version": "36.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.8.2.tgz",
|
||||||
"integrity": "sha512-nqYuTkLSdTTeACyXcCLbL7rl0y6jpzLPtTNGOtSnajdR+xxMxBdjMxDjfNJNlhR+ZU8vbXz+QejntcbY7h9/ZA==",
|
"integrity": "sha512-NfSQi7ISCdBbDpn3b6rg+8RpFZmWIM9mcks48BbogHE2F6h1XKdA34oiCKP5hP1OGvTotDRzsexiJKzrK4Exuw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/d3-array": "^3.0.3",
|
"@types/d3-array": "^3.0.3",
|
||||||
"@types/d3-ease": "^3.0.0",
|
"@types/d3-ease": "^3.0.0",
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
"@shlinkio/data-manipulation": "^1.0.3",
|
"@shlinkio/data-manipulation": "^1.0.3",
|
||||||
"@shlinkio/shlink-frontend-kit": "^0.4.2",
|
"@shlinkio/shlink-frontend-kit": "^0.4.2",
|
||||||
"@shlinkio/shlink-js-sdk": "^0.2.2",
|
"@shlinkio/shlink-js-sdk": "^0.2.2",
|
||||||
"@shlinkio/shlink-web-component": "^0.4.1",
|
"@shlinkio/shlink-web-component": "^0.5.0",
|
||||||
"bootstrap": "5.2.3",
|
"bootstrap": "5.2.3",
|
||||||
"bottlejs": "^2.0.1",
|
"bottlejs": "^2.0.1",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
|
|
|
@ -1,30 +1,50 @@
|
||||||
import { LabeledFormGroup, SimpleCard, ToggleSwitch } from '@shlinkio/shlink-frontend-kit';
|
import { LabeledFormGroup, SimpleCard, ToggleSwitch } from '@shlinkio/shlink-frontend-kit';
|
||||||
import type { Settings, VisitsSettings as VisitsSettingsConfig } from '@shlinkio/shlink-web-component';
|
import type { Settings, VisitsSettings as VisitsSettingsConfig } from '@shlinkio/shlink-web-component';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { FormGroup } from 'reactstrap';
|
import { FormGroup } from 'reactstrap';
|
||||||
import type { DateInterval } from '../utils/dates/DateIntervalSelector';
|
import type { DateInterval } from '../utils/dates/DateIntervalSelector';
|
||||||
import { DateIntervalSelector } from '../utils/dates/DateIntervalSelector';
|
import { DateIntervalSelector } from '../utils/dates/DateIntervalSelector';
|
||||||
import { FormText } from '../utils/forms/FormText';
|
import { FormText } from '../utils/forms/FormText';
|
||||||
|
|
||||||
interface VisitsProps {
|
type VisitsProps = {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
setVisitsSettings: (settings: VisitsSettingsConfig) => void;
|
setVisitsSettings: (settings: VisitsSettingsConfig) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const currentDefaultInterval = (settings: Settings): DateInterval => settings.visits?.defaultInterval ?? 'last30Days';
|
const currentDefaultInterval = (settings: Settings): DateInterval => settings.visits?.defaultInterval ?? 'last30Days';
|
||||||
|
|
||||||
export const VisitsSettings: FC<VisitsProps> = ({ settings, setVisitsSettings }) => (
|
export const VisitsSettings: FC<VisitsProps> = ({ settings, setVisitsSettings }) => {
|
||||||
|
const updateSettings = useCallback(
|
||||||
|
({ defaultInterval, ...rest }: Partial<VisitsSettingsConfig>) => setVisitsSettings(
|
||||||
|
{ defaultInterval: defaultInterval ?? currentDefaultInterval(settings), ...rest },
|
||||||
|
),
|
||||||
|
[setVisitsSettings, settings],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
<SimpleCard title="Visits" className="h-100">
|
<SimpleCard title="Visits" className="h-100">
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
checked={!!settings.visits?.excludeBots}
|
checked={!!settings.visits?.excludeBots}
|
||||||
onChange={(excludeBots) => setVisitsSettings(
|
onChange={(excludeBots) => updateSettings({ excludeBots })}
|
||||||
{ defaultInterval: currentDefaultInterval(settings), excludeBots },
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
Exclude bots wherever possible (this option‘s effect might depend on Shlink server‘s version).
|
Exclude bots wherever possible (this option‘s effect might depend on Shlink server‘s version).
|
||||||
<FormText>
|
<FormText>
|
||||||
The visits coming from potential bots will be <b>{settings.visits?.excludeBots ? 'excluded' : 'included'}</b>.
|
The visits coming from potential bots will
|
||||||
|
be <b>{settings.visits?.excludeBots ? 'excluded' : 'included'}</b>.
|
||||||
|
</FormText>
|
||||||
|
</ToggleSwitch>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<ToggleSwitch
|
||||||
|
checked={!!settings.visits?.loadPrevInterval}
|
||||||
|
onChange={(loadPrevInterval) => updateSettings({ loadPrevInterval })}
|
||||||
|
>
|
||||||
|
Compare visits with previous period.
|
||||||
|
<FormText>
|
||||||
|
When loading visits, previous period <b>{settings.visits?.loadPrevInterval ? 'will' : 'won\'t'}</b> be
|
||||||
|
loaded by default.
|
||||||
</FormText>
|
</FormText>
|
||||||
</ToggleSwitch>
|
</ToggleSwitch>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
@ -32,8 +52,9 @@ export const VisitsSettings: FC<VisitsProps> = ({ settings, setVisitsSettings })
|
||||||
<DateIntervalSelector
|
<DateIntervalSelector
|
||||||
allText="All visits"
|
allText="All visits"
|
||||||
active={currentDefaultInterval(settings)}
|
active={currentDefaultInterval(settings)}
|
||||||
onChange={(defaultInterval) => setVisitsSettings({ defaultInterval })}
|
onChange={(defaultInterval) => updateSettings({ defaultInterval })}
|
||||||
/>
|
/>
|
||||||
</LabeledFormGroup>
|
</LabeledFormGroup>
|
||||||
</SimpleCard>
|
</SimpleCard>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe('<VisitsSettings />', () => {
|
||||||
expect(screen.getByRole('heading')).toHaveTextContent('Visits');
|
expect(screen.getByRole('heading')).toHaveTextContent('Visits');
|
||||||
expect(screen.getByText('Default interval to load on visits sections:')).toBeInTheDocument();
|
expect(screen.getByText('Default interval to load on visits sections:')).toBeInTheDocument();
|
||||||
expect(screen.getByText(/^Exclude bots wherever possible/)).toBeInTheDocument();
|
expect(screen.getByText(/^Exclude bots wherever possible/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Compare visits with previous period.')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
@ -93,4 +94,36 @@ describe('<VisitsSettings />', () => {
|
||||||
await user.click(screen.getByText(/^Exclude bots wherever possible/));
|
await user.click(screen.getByText(/^Exclude bots wherever possible/));
|
||||||
expect(setVisitsSettings).toHaveBeenCalledWith(expect.objectContaining({ excludeBots: true }));
|
expect(setVisitsSettings).toHaveBeenCalledWith(expect.objectContaining({ excludeBots: true }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
fromPartial<Settings>({}),
|
||||||
|
/When loading visits, previous period won't be loaded by default.$/,
|
||||||
|
/When loading visits, previous period will be loaded by default.$/,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
fromPartial<Settings>({ visits: { loadPrevInterval: false } }),
|
||||||
|
/When loading visits, previous period won't be loaded by default.$/,
|
||||||
|
/When loading visits, previous period will be loaded by default.$/,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
fromPartial<Settings>({ visits: { loadPrevInterval: true } }),
|
||||||
|
/When loading visits, previous period will be loaded by default.$/,
|
||||||
|
/When loading visits, previous period won't be loaded by default.$/,
|
||||||
|
],
|
||||||
|
])('displays expected helper text for prev interval control', (settings, expectedText, notExpectedText) => {
|
||||||
|
setUp(settings);
|
||||||
|
|
||||||
|
const visitsComponent = screen.getByText('Compare visits with previous period.');
|
||||||
|
|
||||||
|
expect(visitsComponent).toHaveTextContent(expectedText);
|
||||||
|
expect(visitsComponent).not.toHaveTextContent(notExpectedText);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invokes setVisitsSettings when loading prev visits is toggled', async () => {
|
||||||
|
const { user } = setUp();
|
||||||
|
|
||||||
|
await user.click(screen.getByText('Compare visits with previous period.'));
|
||||||
|
expect(setVisitsSettings).toHaveBeenCalledWith(expect.objectContaining({ loadPrevInterval: true }));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue