mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-12-10 12:41:22 -06:00
Update to latest shlink-frontend-kit and shlink-web-component
This commit is contained in:
parent
34aca8ff3f
commit
0bdf5f206e
256
package-lock.json
generated
256
package-lock.json
generated
@ -16,10 +16,9 @@
|
||||
"@json2csv/plainjs": "^7.0.6",
|
||||
"@reduxjs/toolkit": "^2.8.2",
|
||||
"@shlinkio/data-manipulation": "^1.0.3",
|
||||
"@shlinkio/shlink-frontend-kit": "^0.9.13",
|
||||
"@shlinkio/shlink-frontend-kit": "^1.0.0",
|
||||
"@shlinkio/shlink-js-sdk": "^2.1.0",
|
||||
"@shlinkio/shlink-web-component": "^0.14.3",
|
||||
"bootstrap": "5.2.3",
|
||||
"@shlinkio/shlink-web-component": "^0.15.0",
|
||||
"bottlejs": "^2.0.1",
|
||||
"clsx": "^2.1.1",
|
||||
"compare-versions": "^6.1.1",
|
||||
@ -62,7 +61,6 @@
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"history": "^5.3.0",
|
||||
"playwright": "^1.53.0",
|
||||
"sass": "^1.89.2",
|
||||
"tailwindcss": "^4.1.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.34.0",
|
||||
@ -2783,6 +2781,7 @@
|
||||
"integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^1.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
@ -2823,6 +2822,7 @@
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2843,6 +2843,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2863,6 +2864,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2883,6 +2885,7 @@
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2903,6 +2906,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2923,6 +2927,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2943,6 +2948,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2963,6 +2969,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -2983,6 +2990,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -3003,6 +3011,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -3023,6 +3032,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -3043,6 +3053,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
@ -3068,16 +3079,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@reduxjs/toolkit": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
|
||||
@ -3516,9 +3517,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@shlinkio/shlink-frontend-kit": {
|
||||
"version": "0.9.13",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-frontend-kit/-/shlink-frontend-kit-0.9.13.tgz",
|
||||
"integrity": "sha512-qiEDmrzYA/rmHPdLI9znaYqMKD16ITWon/vG66LlUeDL3zR0Psppy79FjM5k3CmIGsCCZdekXQle6U19YSOQLA==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-frontend-kit/-/shlink-frontend-kit-1.0.0.tgz",
|
||||
"integrity": "sha512-S8gY2bKYj/Mfv94VoSWsT8/uAq/03XoPB0jbphwts1stLvNv6HX1uczirmw1GkeLrZ05KwcbryajpSOQDrKNGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.27.12",
|
||||
@ -3534,7 +3535,6 @@
|
||||
"react": "^18.3 || ^19.0",
|
||||
"react-dom": "^18.3 || ^19.0",
|
||||
"react-router": "^7.0.2",
|
||||
"reactstrap": "^9.2.0",
|
||||
"tailwindcss": "^4.0.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
@ -3550,9 +3550,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@shlinkio/shlink-web-component": {
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.14.3.tgz",
|
||||
"integrity": "sha512-IgTHJYkxp6Pqo4E8waouBXbpytiRasqPyMAMQ5vYfGXU5Y53D4QNkRwPsILkEVTb7B+qwQegyNax4YKjRi/hgA==",
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.15.0.tgz",
|
||||
"integrity": "sha512-B4eTlE5fuXFmJyk4pAJbTeiGlHCdAIZ69AV6A5KCQd1dKwDGRp4Lf/At3MT1nIIu98fkvrM/RPrGtaht63o0MA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formkit/drag-and-drop": "^0.5.3",
|
||||
@ -3578,7 +3578,7 @@
|
||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@reduxjs/toolkit": "^2.5.0",
|
||||
"@shlinkio/shlink-frontend-kit": "^0.9.11",
|
||||
"@shlinkio/shlink-frontend-kit": "^1.0.0",
|
||||
"@shlinkio/shlink-js-sdk": "^2.0.0",
|
||||
"react": "^18.3 || ^19.0",
|
||||
"react-dom": "^18.3 || ^19.0",
|
||||
@ -5252,24 +5252,6 @@
|
||||
"version": "3.7.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
|
||||
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/bottlejs": {
|
||||
"version": "2.0.1",
|
||||
"license": "MIT"
|
||||
@ -5470,6 +5452,8 @@
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.0.tgz",
|
||||
"integrity": "sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
@ -5490,11 +5474,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.2",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
@ -5988,6 +5967,7 @@
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"detect-libc": "bin/detect-libc.js"
|
||||
},
|
||||
@ -7435,7 +7415,9 @@
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz",
|
||||
"integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
@ -8768,7 +8750,8 @@
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.18",
|
||||
@ -9312,13 +9295,6 @@
|
||||
"react-dom": "^19.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"license": "MIT"
|
||||
@ -9417,45 +9393,13 @@
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reactstrap": {
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.2.3.tgz",
|
||||
"integrity": "sha512-1nXy7FIBIoOgXr3AIHOpgzcZXdj6rZE5YvNSPd1hYgwv8X64m6TAJsU0ExlieJdlRXhaRfTYRSZoTWa127b0gw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@popperjs/core": "^2.6.0",
|
||||
"classnames": "^2.2.3",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-popper": "^2.2.4",
|
||||
"react-transition-group": "^4.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reactstrap/node_modules/react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.0.0",
|
||||
"react": "^16.8.0 || ^17 || ^18",
|
||||
"react-dom": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz",
|
||||
"integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
@ -9845,6 +9789,8 @@
|
||||
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.0",
|
||||
"immutable": "^5.0.2",
|
||||
@ -11307,16 +11253,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
@ -13723,6 +13659,7 @@
|
||||
"integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@parcel/watcher-android-arm64": "2.4.1",
|
||||
"@parcel/watcher-darwin-arm64": "2.4.1",
|
||||
@ -13747,84 +13684,96 @@
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz",
|
||||
"integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz",
|
||||
"integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-darwin-x64": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz",
|
||||
"integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz",
|
||||
"integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz",
|
||||
"integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz",
|
||||
"integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz",
|
||||
"integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz",
|
||||
"integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz",
|
||||
"integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-win32-arm64": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz",
|
||||
"integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-win32-ia32": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz",
|
||||
"integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@parcel/watcher-win32-x64": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz",
|
||||
"integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
@ -13839,12 +13788,6 @@
|
||||
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
|
||||
"dev": true
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"peer": true
|
||||
},
|
||||
"@reduxjs/toolkit": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
|
||||
@ -14066,9 +14009,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@shlinkio/shlink-frontend-kit": {
|
||||
"version": "0.9.13",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-frontend-kit/-/shlink-frontend-kit-0.9.13.tgz",
|
||||
"integrity": "sha512-qiEDmrzYA/rmHPdLI9znaYqMKD16ITWon/vG66LlUeDL3zR0Psppy79FjM5k3CmIGsCCZdekXQle6U19YSOQLA==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-frontend-kit/-/shlink-frontend-kit-1.0.0.tgz",
|
||||
"integrity": "sha512-S8gY2bKYj/Mfv94VoSWsT8/uAq/03XoPB0jbphwts1stLvNv6HX1uczirmw1GkeLrZ05KwcbryajpSOQDrKNGA==",
|
||||
"requires": {
|
||||
"@floating-ui/react": "^0.27.12",
|
||||
"clsx": "^2.1.1"
|
||||
@ -14080,9 +14023,9 @@
|
||||
"integrity": "sha512-K6zmA/A7Ux9hTn+ZjAm85YmMl7/v5XgZBM62syCxCsK7Tdw7Gg4+C06cZ2gUv+HWrHtv5IXsi4ax00++8Kg5vw=="
|
||||
},
|
||||
"@shlinkio/shlink-web-component": {
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.14.3.tgz",
|
||||
"integrity": "sha512-IgTHJYkxp6Pqo4E8waouBXbpytiRasqPyMAMQ5vYfGXU5Y53D4QNkRwPsILkEVTb7B+qwQegyNax4YKjRi/hgA==",
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@shlinkio/shlink-web-component/-/shlink-web-component-0.15.0.tgz",
|
||||
"integrity": "sha512-B4eTlE5fuXFmJyk4pAJbTeiGlHCdAIZ69AV6A5KCQd1dKwDGRp4Lf/At3MT1nIIu98fkvrM/RPrGtaht63o0MA==",
|
||||
"requires": {
|
||||
"@formkit/drag-and-drop": "^0.5.3",
|
||||
"@json2csv/plainjs": "^7.0.6",
|
||||
@ -15227,12 +15170,6 @@
|
||||
"bluebird": {
|
||||
"version": "3.7.2"
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
|
||||
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"bottlejs": {
|
||||
"version": "2.0.1"
|
||||
},
|
||||
@ -15352,6 +15289,8 @@
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.0.tgz",
|
||||
"integrity": "sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"readdirp": "^4.0.1"
|
||||
}
|
||||
@ -15362,10 +15301,6 @@
|
||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||
"dev": true
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.3.2",
|
||||
"peer": true
|
||||
},
|
||||
"clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
@ -15709,7 +15644,8 @@
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "2.1.0",
|
||||
@ -16776,7 +16712,9 @@
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz",
|
||||
"integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.1",
|
||||
@ -17607,7 +17545,8 @@
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.18",
|
||||
@ -17959,12 +17898,6 @@
|
||||
"integrity": "sha512-YEPZEMntlG42lHyOnep6J86LQYA/eZB4aH5Hd2tKxtN1qcNwp8cpR0rDgL/0Ar3F3os6qkglWy8IMwBkwc9kDA==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
|
||||
"peer": true
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1"
|
||||
},
|
||||
@ -18019,37 +17952,13 @@
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"reactstrap": {
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.2.3.tgz",
|
||||
"integrity": "sha512-1nXy7FIBIoOgXr3AIHOpgzcZXdj6rZE5YvNSPd1hYgwv8X64m6TAJsU0ExlieJdlRXhaRfTYRSZoTWa127b0gw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@popperjs/core": "^2.6.0",
|
||||
"classnames": "^2.2.3",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-popper": "^2.2.4",
|
||||
"react-transition-group": "^4.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz",
|
||||
"integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"recharts": {
|
||||
"version": "2.15.3",
|
||||
@ -18319,6 +18228,8 @@
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
|
||||
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"chokidar": "^4.0.0",
|
||||
@ -19273,15 +19184,6 @@
|
||||
"xml-name-validator": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
|
||||
@ -29,10 +29,9 @@
|
||||
"@json2csv/plainjs": "^7.0.6",
|
||||
"@reduxjs/toolkit": "^2.8.2",
|
||||
"@shlinkio/data-manipulation": "^1.0.3",
|
||||
"@shlinkio/shlink-frontend-kit": "^0.9.13",
|
||||
"@shlinkio/shlink-frontend-kit": "^1.0.0",
|
||||
"@shlinkio/shlink-js-sdk": "^2.1.0",
|
||||
"@shlinkio/shlink-web-component": "^0.14.3",
|
||||
"bootstrap": "5.2.3",
|
||||
"@shlinkio/shlink-web-component": "^0.15.0",
|
||||
"bottlejs": "^2.0.1",
|
||||
"clsx": "^2.1.1",
|
||||
"compare-versions": "^6.1.1",
|
||||
@ -75,7 +74,6 @@
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"history": "^5.3.0",
|
||||
"playwright": "^1.53.0",
|
||||
"sass": "^1.89.2",
|
||||
"tailwindcss": "^4.1.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.34.0",
|
||||
|
||||
@ -61,15 +61,15 @@ const App: FCWithDeps<AppProps, AppDeps> = (
|
||||
}, [settings.ui?.theme]);
|
||||
|
||||
return (
|
||||
<div className="tw:h-full">
|
||||
<div className="h-full">
|
||||
<MainHeader />
|
||||
|
||||
<div className="tw:h-full tw:pt-(--tw-header-height)">
|
||||
<div className="h-full pt-(--header-height)">
|
||||
<div
|
||||
data-testid="shlink-wrapper"
|
||||
className={clsx(
|
||||
'tw:min-h-full tw:pb-[calc(var(--footer-height)+var(--footer-margin))] tw:-mb-[calc(var(--footer-height)+var(--footer-margin))]',
|
||||
{ 'tw:flex tw:items-center tw:pt-4': isHome },
|
||||
'min-h-full pb-[calc(var(--footer-height)+var(--footer-margin))] -mb-[calc(var(--footer-height)+var(--footer-margin))]',
|
||||
{ 'flex items-center pt-4': isHome },
|
||||
)}
|
||||
>
|
||||
<Routes>
|
||||
@ -87,7 +87,7 @@ const App: FCWithDeps<AppProps, AppDeps> = (
|
||||
</Routes>
|
||||
</div>
|
||||
|
||||
<div className="tw:h-(--footer-height) tw:mt-(--footer-margin) tw:md:px-4">
|
||||
<div className="h-(--footer-height) mt-(--footer-margin) md:px-4">
|
||||
<ShlinkVersionsContainer />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { faSyncAlt as reloadIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { Button, Card, CloseButton } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button, Card, CloseButton,useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { clsx } from 'clsx';
|
||||
import type { FC } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
@ -13,7 +12,7 @@ interface AppUpdateBannerProps {
|
||||
}
|
||||
|
||||
export const AppUpdateBanner: FC<AppUpdateBannerProps> = ({ isOpen, onClose, forceUpdate }) => {
|
||||
const { flag: isUpdating, setToTrue: setUpdating } = useToggle(false, true);
|
||||
const { flag: isUpdating, setToTrue: setUpdating } = useToggle();
|
||||
const update = useCallback(() => {
|
||||
setUpdating();
|
||||
forceUpdate();
|
||||
@ -27,15 +26,15 @@ export const AppUpdateBanner: FC<AppUpdateBannerProps> = ({ isOpen, onClose, for
|
||||
<Card
|
||||
role="alert"
|
||||
className={clsx(
|
||||
'tw:w-[700px] tw:max-w-[calc(100%-30px)]',
|
||||
'tw:fixed tw:top-[35px] tw:left-[50%] tw:translate-x-[-50%] tw:z-[1040]',
|
||||
'w-[700px] max-w-[calc(100%-30px)]',
|
||||
'fixed top-[35px] left-[50%] translate-x-[-50%] z-[1040]',
|
||||
)}
|
||||
>
|
||||
<Card.Header className="tw:flex tw:items-center tw:justify-between">
|
||||
<Card.Header className="flex items-center justify-between">
|
||||
<h5>This app has just been updated!</h5>
|
||||
<CloseButton onClick={onClose} />
|
||||
</Card.Header>
|
||||
<Card.Body className="tw:flex tw:gap-4 tw:items-center tw:justify-between tw:max-md:flex-col">
|
||||
<Card.Body className="flex gap-4 items-center justify-between max-md:flex-col">
|
||||
Restart it to enjoy the new features.
|
||||
<Button disabled={isUpdating} variant="secondary" solid onClick={update}>
|
||||
{!isUpdating && <>Restart now <FontAwesomeIcon icon={reloadIcon} /></>}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Button } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { PropsWithChildren, ReactNode } from 'react';
|
||||
import { Component } from 'react';
|
||||
import { ErrorLayout } from './ErrorLayout';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SimpleCard } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { SimpleCard } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
|
||||
export type ErrorLayoutProps = PropsWithChildren<{
|
||||
@ -6,8 +6,8 @@ export type ErrorLayoutProps = PropsWithChildren<{
|
||||
}>;
|
||||
|
||||
export const ErrorLayout: FC<ErrorLayoutProps> = ({ children, title }) => (
|
||||
<div className="tw:pt-4">
|
||||
<SimpleCard className="tw:p-4 tw:w-full tw:lg:w-[65%] tw:m-auto">
|
||||
<div className="pt-4">
|
||||
<SimpleCard className="p-4 w-full lg:w-[65%] m-auto">
|
||||
<h2>{title}</h2>
|
||||
{children}
|
||||
</SimpleCard>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { faExternalLinkAlt, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Button, Card } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button, Card } from '@shlinkio/shlink-frontend-kit';
|
||||
import { clsx } from 'clsx';
|
||||
import { useEffect } from 'react';
|
||||
import { ExternalLink } from 'react-external-link';
|
||||
@ -27,26 +27,26 @@ export const Home = ({ servers }: HomeProps) => {
|
||||
}, [serversList, navigate]);
|
||||
|
||||
return (
|
||||
<div className="tw:px-3 tw:w-full">
|
||||
<Card className="tw:mx-auto tw:max-w-[720px] tw:overflow-hidden">
|
||||
<div className="tw:flex tw:flex-col tw:md:flex-row">
|
||||
<div className="tw:p-6 tw:hidden tw:md:flex tw:items-center tw:w-[40%]">
|
||||
<div className="tw:w-full">
|
||||
<div className="px-3 w-full">
|
||||
<Card className="mx-auto max-w-[720px] overflow-hidden">
|
||||
<div className="flex flex-col md:flex-row">
|
||||
<div className="p-6 hidden md:flex items-center w-[40%]">
|
||||
<div className="w-full">
|
||||
<ShlinkLogo />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="tw:md:border-l tw:border-lm-border tw:dark:border-dm-border tw:flex-grow">
|
||||
<div className="md:border-l border-lm-border dark:border-dm-border flex-grow">
|
||||
<h1
|
||||
className={clsx(
|
||||
'tw:p-4 tw:text-center tw:border-lm-border tw:dark:border-dm-border',
|
||||
{ 'tw:border-b': !hasServers },
|
||||
'p-4 text-center border-lm-border dark:border-dm-border',
|
||||
{ 'border-b': !hasServers },
|
||||
)}
|
||||
>
|
||||
Welcome!
|
||||
</h1>
|
||||
{hasServers ? <ServersListGroup servers={serversList} /> : (
|
||||
<div className="tw:p-6 tw:text-center tw:flex tw:flex-col tw:gap-12 tw:text-xl">
|
||||
<div className="p-6 text-center flex flex-col gap-12 text-xl">
|
||||
<p>This application will help you manage your Shlink servers.</p>
|
||||
<p>
|
||||
<Button to="/server/create" size="lg" inline>
|
||||
@ -56,7 +56,7 @@ export const Home = ({ servers }: HomeProps) => {
|
||||
<p>
|
||||
<ExternalLink href="https://shlink.io/documentation">
|
||||
<small>
|
||||
<span className="tw:mr-2">Learn more about Shlink</span>
|
||||
<span className="mr-2">Learn more about Shlink</span>
|
||||
<FontAwesomeIcon icon={faExternalLinkAlt} />
|
||||
</small>
|
||||
</ExternalLink>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { faCogs as cogsIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { NavBar } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { NavBar } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { Link, useLocation } from 'react-router';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
@ -19,17 +19,17 @@ const MainHeader: FCWithDeps<unknown, MainHeaderDeps> = () => {
|
||||
|
||||
return (
|
||||
<NavBar
|
||||
className="tw:[&]:fixed tw:top-0 tw:z-900"
|
||||
className="[&]:fixed top-0 z-900"
|
||||
brand={(
|
||||
<Link to="/" className="tw:[&]:text-white tw:no-underline tw:flex tw:items-center tw:gap-2">
|
||||
<ShlinkLogo className="tw:w-7" color="white" /> <small className="tw:font-normal">Shlink</small>
|
||||
<Link to="/" className="[&]:text-white no-underline flex items-center gap-2">
|
||||
<ShlinkLogo className="w-7" color="white" /> <small className="font-normal">Shlink</small>
|
||||
</Link>
|
||||
)}
|
||||
>
|
||||
<NavBar.MenuItem
|
||||
to={settingsPath}
|
||||
active={pathname.startsWith(settingsPath)}
|
||||
className="tw:flex tw:items-center tw:gap-1.5"
|
||||
className="flex items-center gap-1.5"
|
||||
>
|
||||
<FontAwesomeIcon icon={cogsIcon} /> Settings
|
||||
</NavBar.MenuItem>
|
||||
|
||||
@ -6,7 +6,7 @@ export type NoMenuLayoutProps = PropsWithChildren & {
|
||||
};
|
||||
|
||||
export const NoMenuLayout: FC<NoMenuLayoutProps> = ({ children, className }) => (
|
||||
<div className={clsx('tw:container tw:mx-auto tw:p-5 tw:pt-8 tw:max-md:p-3 tw:max-md:py-4', className)}>
|
||||
<div className={clsx('container mx-auto p-5 pt-8 max-md:p-3 max-md:py-4', className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Button } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
import { ErrorLayout } from './ErrorLayout';
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ export interface ShlinkVersionsProps {
|
||||
}
|
||||
|
||||
const VersionLink = ({ project, version }: { project: 'shlink' | 'shlink-web-client'; version: string }) => (
|
||||
<ExternalLink href={`https://github.com/shlinkio/${project}/releases/${version}`} className="tw:text-gray-500">
|
||||
<ExternalLink href={`https://github.com/shlinkio/${project}/releases/${version}`} className="text-gray-500">
|
||||
<b>{version}</b>
|
||||
</ExternalLink>
|
||||
);
|
||||
@ -21,7 +21,7 @@ export const ShlinkVersions = ({ selectedServer, clientVersion = SHLINK_WEB_CLIE
|
||||
const normalizedClientVersion = normalizeVersion(clientVersion);
|
||||
|
||||
return (
|
||||
<small className="tw:text-gray-500">
|
||||
<small className="text-gray-500">
|
||||
{isReachableServer(selectedServer) && (
|
||||
<>Server: <VersionLink project="shlink" version={selectedServer.printableVersion} /> - </>
|
||||
)}
|
||||
|
||||
@ -9,7 +9,7 @@ export type ShlinkVersionsContainerProps = {
|
||||
|
||||
export const ShlinkVersionsContainer = ({ selectedServer }: ShlinkVersionsContainerProps) => (
|
||||
<div
|
||||
className={clsx('tw:text-center', { 'tw:md:ml-(--aside-menu-width)': isReachableServer(selectedServer) })}
|
||||
className={clsx('text-center', { 'md:ml-(--aside-menu-width)': isReachableServer(selectedServer) })}
|
||||
>
|
||||
<ShlinkVersions selectedServer={selectedServer} />
|
||||
</div>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { MAIN_COLOR } from '@shlinkio/shlink-frontend-kit';
|
||||
import { brandColor } from '@shlinkio/shlink-frontend-kit';
|
||||
|
||||
export interface ShlinkLogoProps {
|
||||
color?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const ShlinkLogo = ({ color = MAIN_COLOR, className }: ShlinkLogoProps) => (
|
||||
export const ShlinkLogo = ({ color = brandColor(), className }: ShlinkLogoProps) => (
|
||||
<svg className={className} viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill={color}>
|
||||
<path
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
@use '../node_modules/@shlinkio/shlink-frontend-kit/dist/base'; // Before bootstrap stylesheet
|
||||
@use '../node_modules/bootstrap/scss/bootstrap.scss' with (
|
||||
$primary: base.$mainColor // Override bootstrap's primary color
|
||||
);
|
||||
@use '../node_modules/@shlinkio/shlink-frontend-kit/dist/index'; // After bootstrap. Includes CSS overrides
|
||||
@use '../node_modules/@shlinkio/shlink-web-component/dist/index' as c-index;
|
||||
@ -5,7 +5,6 @@ import pack from '../package.json';
|
||||
import { container } from './container';
|
||||
import { setUpStore } from './container/store';
|
||||
import { register as registerServiceWorker } from './serviceWorkerRegistration';
|
||||
import './index.scss';
|
||||
import './tailwind.css';
|
||||
|
||||
const store = setUpStore(container);
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { ResultProps } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button, Result } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import type { ResultProps,TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { Button, Result,useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
@ -28,7 +26,7 @@ type CreateServerDeps = {
|
||||
};
|
||||
|
||||
const ImportResult = ({ variant }: Pick<ResultProps, 'variant'>) => (
|
||||
<div className="tw:mt-4">
|
||||
<div className="mt-4">
|
||||
<Result variant={variant}>
|
||||
{variant === 'success' && 'Servers properly imported. You can now select one from the list :)'}
|
||||
{variant === 'error' && 'The servers could not be imported. Make sure the format is correct.'}
|
||||
@ -42,10 +40,10 @@ const CreateServer: FCWithDeps<CreateServerProps, CreateServerDeps> = ({ servers
|
||||
const goBack = useGoBack();
|
||||
const hasServers = !!Object.keys(servers).length;
|
||||
// eslint-disable-next-line react-compiler/react-compiler
|
||||
const [serversImported, setServersImported] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
|
||||
const [serversImported, setServersImported] = useTimeoutToggle({ delay: SHOW_IMPORT_MSG_TIME });
|
||||
// eslint-disable-next-line react-compiler/react-compiler
|
||||
const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
|
||||
const [isConfirmModalOpen, toggleConfirmModal] = useToggle();
|
||||
const [errorImporting, setErrorImporting] = useTimeoutToggle({ delay: SHOW_IMPORT_MSG_TIME });
|
||||
const { flag: isConfirmModalOpen, toggle: toggleConfirmModal } = useToggle();
|
||||
const [serverData, setServerData] = useState<ServerData>();
|
||||
const saveNewServer = useCallback((newServerData: ServerData) => {
|
||||
const [newServerWithUniqueId] = ensureUniqueIds(servers, [newServerData]);
|
||||
|
||||
@ -17,7 +17,7 @@ type DeleteServerButtonDeps = {
|
||||
|
||||
const DeleteServerButton: FCWithDeps<DeleteServerButtonProps, DeleteServerButtonDeps> = ({ server, children }) => {
|
||||
const { DeleteServerModal } = useDependencies(DeleteServerButton);
|
||||
const [isModalOpen, , showModal, hideModal] = useToggle();
|
||||
const { flag: isModalOpen, setToTrue: showModal, setToFalse: hideModal } = useToggle();
|
||||
const navigate = useNavigate();
|
||||
const onClose = useCallback((confirmed: boolean) => {
|
||||
hideModal();
|
||||
@ -28,7 +28,7 @@ const DeleteServerButton: FCWithDeps<DeleteServerButtonProps, DeleteServerButton
|
||||
|
||||
return (
|
||||
<>
|
||||
<button type="button" className="tw:text-danger tw:hover:underline" onClick={showModal}>
|
||||
<button type="button" className="text-danger hover:underline" onClick={showModal}>
|
||||
{children}
|
||||
</button>
|
||||
<DeleteServerModal server={server} open={isModalOpen} onClose={onClose} />
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { ExitAction } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { CardModal } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import type { ExitAction } from '@shlinkio/shlink-frontend-kit';
|
||||
import { CardModal } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import type { ServerWithId } from './data';
|
||||
@ -31,7 +31,7 @@ export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ({ server, o
|
||||
onClosed={onClosed}
|
||||
confirmText="Delete"
|
||||
>
|
||||
<div className="tw:flex tw:flex-col tw:gap-y-4">
|
||||
<div className="flex flex-col gap-y-4">
|
||||
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
|
||||
<p>
|
||||
<i>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useParsedQuery } from '@shlinkio/shlink-frontend-kit';
|
||||
import { Button } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button,useParsedQuery } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { NoMenuLayout } from '../common/NoMenuLayout';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { faFileDownload as exportIcon, faPlus as plusIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { Button, Result, SearchInput, SimpleCard, Table } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button, Result, SearchInput, SimpleCard, Table } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { NoMenuLayout } from '../common/NoMenuLayout';
|
||||
@ -40,22 +40,22 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
|
||||
);
|
||||
const hasAutoConnect = allServers.some(({ autoConnect }) => !!autoConnect);
|
||||
// eslint-disable-next-line react-compiler/react-compiler
|
||||
const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
|
||||
const [errorImporting, setErrorImporting] = useTimeoutToggle({ delay: SHOW_IMPORT_MSG_TIME });
|
||||
|
||||
return (
|
||||
<NoMenuLayout className="tw:flex tw:flex-col tw:gap-y-4">
|
||||
<NoMenuLayout className="flex flex-col gap-y-4">
|
||||
<SearchInput onChange={setSearchTerm} />
|
||||
|
||||
<div className="tw:flex tw:flex-col tw:md:flex-row tw:gap-2">
|
||||
<div className="tw:flex tw:gap-2">
|
||||
<ImportServersBtn className="tw:flex-grow" onError={setErrorImporting}>Import servers</ImportServersBtn>
|
||||
<div className="flex flex-col md:flex-row gap-2">
|
||||
<div className="flex gap-2">
|
||||
<ImportServersBtn className="flex-grow" onError={setErrorImporting}>Import servers</ImportServersBtn>
|
||||
{filteredServers.length > 0 && (
|
||||
<Button variant="secondary" className="tw:flex-grow" onClick={async () => serversExporter.exportServers()}>
|
||||
<Button variant="secondary" className="flex-grow" onClick={async () => serversExporter.exportServers()}>
|
||||
<FontAwesomeIcon icon={exportIcon} /> Export servers
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<Button className="tw:md:ml-auto" to="/server/create">
|
||||
<Button className="md:ml-auto" to="/server/create">
|
||||
<FontAwesomeIcon icon={plusIcon} /> Add a server
|
||||
</Button>
|
||||
</div>
|
||||
@ -64,7 +64,7 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
|
||||
<Table header={(
|
||||
<Table.Row>
|
||||
{hasAutoConnect && (
|
||||
<Table.Cell className="tw:w-[35px]"><span className="tw:sr-only">Auto-connect</span></Table.Cell>
|
||||
<Table.Cell className="w-[35px]"><span className="sr-only">Auto-connect</span></Table.Cell>
|
||||
)}
|
||||
<Table.Cell>Name</Table.Cell>
|
||||
<Table.Cell>Base URL</Table.Cell>
|
||||
@ -72,7 +72,7 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
|
||||
</Table.Row>
|
||||
)}>
|
||||
{!filteredServers.length && (
|
||||
<Table.Row className="tw:text-center"><Table.Cell colSpan={4}>No servers found.</Table.Cell></Table.Row>
|
||||
<Table.Row className="text-center"><Table.Cell colSpan={4}>No servers found.</Table.Cell></Table.Row>
|
||||
)}
|
||||
{filteredServers.map((server) => (
|
||||
<ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { faCheck as checkIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Table, Tooltip, useTooltip } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Table, Tooltip, useTooltip } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
@ -22,14 +22,14 @@ const ManageServersRow: FCWithDeps<ManageServersRowProps, ManageServersRowDeps>
|
||||
const { anchor, tooltip } = useTooltip();
|
||||
|
||||
return (
|
||||
<Table.Row className="tw:relative">
|
||||
<Table.Row className="relative">
|
||||
{hasAutoConnect && (
|
||||
<Table.Cell columnName="Auto-connect">
|
||||
{server.autoConnect && (
|
||||
<>
|
||||
<FontAwesomeIcon
|
||||
icon={checkIcon}
|
||||
className="tw:text-lm-brand tw:dark:text-dm-brand"
|
||||
className="text-lm-brand dark:text-dm-brand"
|
||||
{...anchor}
|
||||
/>
|
||||
<Tooltip {...tooltip}>Auto-connect to this server</Tooltip>
|
||||
@ -37,11 +37,11 @@ const ManageServersRow: FCWithDeps<ManageServersRowProps, ManageServersRowDeps>
|
||||
)}
|
||||
</Table.Cell>
|
||||
)}
|
||||
<Table.Cell className="tw:font-bold" columnName="Name">
|
||||
<Table.Cell className="font-bold" columnName="Name">
|
||||
<Link to={`/server/${server.id}`}>{server.name}</Link>
|
||||
</Table.Cell>
|
||||
<Table.Cell columnName="Base URL" className="tw:max-lg:border-b-0">{server.url}</Table.Cell>
|
||||
<Table.Cell className="tw:text-right tw:max-lg:absolute tw:right-0 tw:-top-1 tw:mx-lg:pt-0">
|
||||
<Table.Cell columnName="Base URL" className="max-lg:border-b-0">{server.url}</Table.Cell>
|
||||
<Table.Cell className="text-right max-lg:absolute right-0 -top-1 mx-lg:pt-0">
|
||||
<ManageServersRowDropdown server={server} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
|
||||
@ -6,8 +6,7 @@ import {
|
||||
faPlug as connectIcon,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { RowDropdown } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { RowDropdown,useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
import { componentFactory, useDependencies } from '../container/utils';
|
||||
@ -30,7 +29,7 @@ const ManageServersRowDropdown: FCWithDeps<ManageServersRowDropdownConnectProps,
|
||||
{ server, setAutoConnect },
|
||||
) => {
|
||||
const { DeleteServerModal } = useDependencies(ManageServersRowDropdown);
|
||||
const { flag: isModalOpen, setToTrue: showModal, setToFalse: hideModal } = useToggle(false, true);
|
||||
const { flag: isModalOpen, setToTrue: showModal, setToFalse: hideModal } = useToggle();
|
||||
const serverUrl = `/server/${server.id}`;
|
||||
const { autoConnect: isAutoConnect } = server;
|
||||
const autoConnectIcon = isAutoConnect ? toggleOffIcon : toggleOnIcon;
|
||||
@ -38,17 +37,17 @@ const ManageServersRowDropdown: FCWithDeps<ManageServersRowDropdownConnectProps,
|
||||
return (
|
||||
<>
|
||||
<RowDropdown menuAlignment="right">
|
||||
<RowDropdown.Item to={serverUrl} className="tw:gap-1.5">
|
||||
<RowDropdown.Item to={serverUrl} className="gap-1.5">
|
||||
<FontAwesomeIcon icon={connectIcon} fixedWidth /> Connect
|
||||
</RowDropdown.Item>
|
||||
<RowDropdown.Item to={`${serverUrl}/edit`} className="tw:gap-1.5">
|
||||
<RowDropdown.Item to={`${serverUrl}/edit`} className="gap-1.5">
|
||||
<FontAwesomeIcon icon={editIcon} fixedWidth /> Edit server
|
||||
</RowDropdown.Item>
|
||||
<RowDropdown.Item onClick={() => setAutoConnect(server, !isAutoConnect)} className="tw:gap-1.5">
|
||||
<RowDropdown.Item onClick={() => setAutoConnect(server, !isAutoConnect)} className="gap-1.5">
|
||||
<FontAwesomeIcon icon={autoConnectIcon} fixedWidth /> {isAutoConnect ? 'Do not a' : 'A'}uto-connect
|
||||
</RowDropdown.Item>
|
||||
<RowDropdown.Separator />
|
||||
<RowDropdown.Item className="tw:[&]:text-danger tw:gap-1.5" onClick={showModal}>
|
||||
<RowDropdown.Item className="[&]:text-danger gap-1.5" onClick={showModal}>
|
||||
<FontAwesomeIcon icon={deleteIcon} fixedWidth /> Remove server
|
||||
</RowDropdown.Item>
|
||||
</RowDropdown>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { faPlus as plusIcon, faServer as serverIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Dropdown, NavBar } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Dropdown, NavBar } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { SelectedServer, ServersMap } from './data';
|
||||
import { getServerId } from './data';
|
||||
|
||||
@ -14,7 +14,7 @@ export const ServersDropdown = ({ servers, selectedServer }: ServersDropdownProp
|
||||
|
||||
return (
|
||||
<NavBar.Dropdown buttonContent={(
|
||||
<span className="tw:flex tw:items-center tw:gap-1.5">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<FontAwesomeIcon icon={serverIcon} fixedWidth /> Servers
|
||||
</span>
|
||||
)}>
|
||||
|
||||
@ -15,12 +15,12 @@ const ServerListItem = ({ id, name }: { id: string; name: string }) => (
|
||||
to={`/server/${id}`}
|
||||
className={clsx(
|
||||
'servers-list__server-item',
|
||||
'tw:flex tw:items-center tw:justify-between tw:gap-x-2 tw:px-4 tw:py-3',
|
||||
'tw:rounded-none tw:hover:bg-lm-secondary tw:hover:dark:bg-dm-secondary',
|
||||
'tw:border-b tw:last:border-0 tw:border-lm-border tw:dark:border-dm-border',
|
||||
'flex items-center justify-between gap-x-2 px-4 py-3',
|
||||
'rounded-none hover:bg-lm-secondary hover:dark:bg-dm-secondary',
|
||||
'border-b last:border-0 border-lm-border dark:border-dm-border',
|
||||
)}
|
||||
>
|
||||
<span className="tw:truncate">{name}</span>
|
||||
<span className="truncate">{name}</span>
|
||||
<FontAwesomeIcon icon={chevronIcon} />
|
||||
</Link>
|
||||
);
|
||||
@ -31,9 +31,9 @@ export const ServersListGroup: FC<ServersListGroupProps> = ({ servers, borderles
|
||||
<div
|
||||
data-testid="list"
|
||||
className={clsx(
|
||||
'tw:w-full tw:border-lm-border tw:dark:border-dm-border',
|
||||
'tw:md:max-h-56 tw:md:overflow-y-auto tw:-mb-1 tw:scroll-thin',
|
||||
{ 'tw:border-y': !borderless },
|
||||
'w-full border-lm-border dark:border-dm-border',
|
||||
'md:max-h-56 md:overflow-y-auto -mb-1 scroll-thin',
|
||||
{ 'border-y': !borderless },
|
||||
)}
|
||||
>
|
||||
{servers.map(({ id, name }) => <ServerListItem key={id} id={id} name={name} />)}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CardModal } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { CardModal } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import type { ServerData } from '../data';
|
||||
@ -26,7 +26,7 @@ export const DuplicatedServersModal: FC<DuplicatedServersModalProps> = (
|
||||
cancelText={hasMultipleServers ? 'Ignore duplicates' : 'Discard'}
|
||||
>
|
||||
<p>{hasMultipleServers ? 'The next servers already exist:' : 'There is already a server with:'}</p>
|
||||
<ul className="tw:list-disc tw:mt-4">
|
||||
<ul className="list-disc mt-4">
|
||||
{duplicatedServers.map(({ url, apiKey }, index) => (!hasMultipleServers ? (
|
||||
<Fragment key={index}>
|
||||
<li>URL: <b>{url}</b></li>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { faFileUpload as importIcon } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import { Button, Tooltip, useTooltip } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Button, Tooltip, useToggle , useTooltip } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { ChangeEvent, PropsWithChildren } from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import type { FCWithDeps } from '../../container/utils';
|
||||
@ -40,7 +39,7 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const { anchor, tooltip } = useTooltip({ placement: tooltipPlacement });
|
||||
const [duplicatedServers, setDuplicatedServers] = useState<ServerData[]>([]);
|
||||
const { flag: isModalOpen, setToTrue: showModal, setToFalse: hideModal } = useToggle(false, true);
|
||||
const { flag: isModalOpen, setToTrue: showModal, setToFalse: hideModal } = useToggle();
|
||||
const newServersCreatedRef = useRef(false);
|
||||
|
||||
const onFile = useCallback(
|
||||
@ -94,7 +93,7 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
|
||||
<input
|
||||
type="file"
|
||||
accept=".csv"
|
||||
className="tw:hidden"
|
||||
className="hidden"
|
||||
aria-hidden
|
||||
tabIndex={-1}
|
||||
ref={fileInputRef}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Card, Message } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Card, Message } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import { NoMenuLayout } from '../../common/NoMenuLayout';
|
||||
@ -23,8 +23,8 @@ const ServerError: FCWithDeps<ServerErrorProps, ServerErrorDeps> = ({ servers, s
|
||||
|
||||
return (
|
||||
<NoMenuLayout>
|
||||
<div className="tw:flex tw:flex-col tw:items-center tw:gap-y-4 tw:md:gap-y-8">
|
||||
<Message className="tw:w-full tw:lg:w-[80%]" variant="error">
|
||||
<div className="flex flex-col items-center gap-y-4 md:gap-y-8">
|
||||
<Message className="w-full lg:w-[80%]" variant="error">
|
||||
{!isServerWithId(selectedServer) && 'Could not find this Shlink server.'}
|
||||
{isServerWithId(selectedServer) && (
|
||||
<>
|
||||
@ -34,16 +34,16 @@ const ServerError: FCWithDeps<ServerErrorProps, ServerErrorDeps> = ({ servers, s
|
||||
)}
|
||||
</Message>
|
||||
|
||||
<p className="tw:text-xl">
|
||||
<p className="text-xl">
|
||||
These are the Shlink servers currently configured. Choose one of
|
||||
them or <Link to="/server/create">add a new one</Link>.
|
||||
</p>
|
||||
<Card className="tw:w-full tw:max-w-100 tw:overflow-hidden">
|
||||
<Card className="w-full max-w-100 overflow-hidden">
|
||||
<ServersListGroup borderless servers={Object.values(servers)} />
|
||||
</Card>
|
||||
|
||||
{isServerWithId(selectedServer) && (
|
||||
<p className="tw:text-xl">
|
||||
<p className="text-xl">
|
||||
Alternatively, if you think you may have misconfigured this server, you
|
||||
can <DeleteServerButton server={selectedServer}>remove
|
||||
it</DeleteServerButton> or
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import {
|
||||
Checkbox,
|
||||
import { Checkbox,
|
||||
Details,
|
||||
Label,
|
||||
LabelledInput,
|
||||
LabelledRevealablePasswordInput,
|
||||
SimpleCard,
|
||||
} from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
useToggle ,
|
||||
} from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { usePreventDefault } from '../../utils/utils';
|
||||
@ -24,13 +23,12 @@ export const ServerForm: FC<ServerFormProps> = ({ onSubmit, initialValues, child
|
||||
const [apiKey, setApiKey] = useState(initialValues?.apiKey ?? '');
|
||||
const { flag: forwardCredentials, toggle: toggleForwardCredentials } = useToggle(
|
||||
initialValues?.forwardCredentials ?? false,
|
||||
true,
|
||||
);
|
||||
const handleSubmit = usePreventDefault(() => onSubmit({ name, url, apiKey, forwardCredentials }));
|
||||
|
||||
return (
|
||||
<form name="serverForm" onSubmit={handleSubmit}>
|
||||
<SimpleCard className="tw:mb-4" bodyClassName="tw:flex tw:flex-col tw:gap-y-3" title={title}>
|
||||
<SimpleCard className="mb-4" bodyClassName="flex flex-col gap-y-3" title={title}>
|
||||
<LabelledInput label="Name" value={name} onChange={(e) => setName(e.target.value)} required />
|
||||
<LabelledInput label="URL" type="url" value={url} onChange={(e) => setUrl(e.target.value)} required />
|
||||
<LabelledRevealablePasswordInput
|
||||
@ -40,25 +38,25 @@ export const ServerForm: FC<ServerFormProps> = ({ onSubmit, initialValues, child
|
||||
required
|
||||
/>
|
||||
<Details summary="Advanced options">
|
||||
<div className="tw:flex tw:flex-col tw:gap-0.5">
|
||||
<Label className="tw:flex tw:items-center tw:gap-x-1.5 tw:cursor-pointer">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<Label className="flex items-center gap-x-1.5 cursor-pointer">
|
||||
<Checkbox onChange={toggleForwardCredentials} checked={forwardCredentials} />
|
||||
Forward credentials to this server on every request.
|
||||
</Label>
|
||||
<small className="tw:pl-5.5 tw:text-gray-600 tw:dark:text-gray-400 tw:mt-0.5">
|
||||
<small className="pl-5.5 text-gray-600 dark:text-gray-400 mt-0.5">
|
||||
{'"'}Credentials{'"'} here means cookies, TLS client certificates, or authentication headers containing a username
|
||||
and password.
|
||||
</small>
|
||||
<small className="tw:pl-5.5 tw:text-gray-600 tw:dark:text-gray-400">
|
||||
<small className="pl-5.5 text-gray-600 dark:text-gray-400">
|
||||
<b>Important!</b> If you are not sure what this means, leave it unchecked. Enabling this option will
|
||||
make all requests fail for Shlink older than v4.5.0, as it requires the server to set a more strict
|
||||
value for <code className="tw:whitespace-nowrap">Access-Control-Allow-Origin</code> than <code>*</code>.
|
||||
value for <code className="whitespace-nowrap">Access-Control-Allow-Origin</code> than <code>*</code>.
|
||||
</small>
|
||||
</div>
|
||||
</Details>
|
||||
</SimpleCard>
|
||||
|
||||
<div className="tw:flex tw:items-center tw:justify-end tw:gap-x-2">{children}</div>
|
||||
<div className="flex items-center justify-end gap-x-2">{children}</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Message } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Message } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { FC } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@import 'tailwindcss' prefix(tw) important;
|
||||
@import 'tailwindcss';
|
||||
@import '@shlinkio/shlink-frontend-kit/tailwind.preset.css';
|
||||
@import '@shlinkio/shlink-web-component/tailwind.preset.css';
|
||||
@source '../node_modules/@shlinkio/shlink-frontend-kit';
|
||||
@ -8,7 +8,7 @@
|
||||
:root {
|
||||
--footer-height: 2.3rem;
|
||||
--footer-margin: .8rem;
|
||||
/* Temp alias fo header-height to tw-header-height, so that shlink-web-component uses the right value */
|
||||
--header-height: var(--tw-header-height);
|
||||
/* FIXME Remove this once updated to shlink-web-component 0.15.1 */
|
||||
--header-height: 52px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,9 +62,9 @@ describe('<App />', () => {
|
||||
const shlinkWrapper = screen.getByTestId('shlink-wrapper');
|
||||
|
||||
if (isFlex) {
|
||||
expect(shlinkWrapper).toHaveClass('tw:flex');
|
||||
expect(shlinkWrapper).toHaveClass('flex');
|
||||
} else {
|
||||
expect(shlinkWrapper).not.toHaveClass('tw:flex');
|
||||
expect(shlinkWrapper).not.toHaveClass('flex');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -23,9 +23,9 @@ describe('<ShlinkVersionsContainer />', () => {
|
||||
const { container } = setUp(selectedServer);
|
||||
|
||||
if (shouldAddMargin) {
|
||||
expect(container.firstChild).toHaveClass('tw:md:ml-(--aside-menu-width)');
|
||||
expect(container.firstChild).toHaveClass('md:ml-(--aside-menu-width)');
|
||||
} else {
|
||||
expect(container.firstChild).not.toHaveClass('tw:md:ml-(--aside-menu-width)');
|
||||
expect(container.firstChild).not.toHaveClass('md:ml-(--aside-menu-width)');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { MAIN_COLOR } from '@shlinkio/shlink-frontend-kit';
|
||||
import { brandColor } from '@shlinkio/shlink-frontend-kit';
|
||||
import { render } from '@testing-library/react';
|
||||
import type { ShlinkLogoProps } from '../../../src/common/img/ShlinkLogo';
|
||||
import { ShlinkLogo } from '../../../src/common/img/ShlinkLogo';
|
||||
@ -10,7 +10,7 @@ describe('<ShlinkLogo />', () => {
|
||||
it('passes a11y checks', () => checkAccessibility(setUp()));
|
||||
|
||||
it.each([
|
||||
[undefined, MAIN_COLOR],
|
||||
[undefined, brandColor()],
|
||||
['red', 'red'],
|
||||
['white', 'white'],
|
||||
])('renders expected color', (color, expectedColor) => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Table } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||
import { Table } from '@shlinkio/shlink-frontend-kit';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
|
||||
@ -41,9 +41,9 @@ describe('<ServersListGroup />', () => {
|
||||
const list = screen.getByTestId('list');
|
||||
|
||||
if (!borderless) {
|
||||
expect(list).toHaveClass('tw:border-y');
|
||||
expect(list).toHaveClass('border-y');
|
||||
} else {
|
||||
expect(list).not.toHaveClass('tw:border-y');
|
||||
expect(list).not.toHaveClass('border-y');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
exports[`<DeleteServerButton /> > renders expected content 1`] = `
|
||||
<button
|
||||
class="tw:text-danger tw:hover:underline"
|
||||
class="text-danger hover:underline"
|
||||
type="button"
|
||||
>
|
||||
Foo bar
|
||||
@ -11,7 +11,7 @@ exports[`<DeleteServerButton /> > renders expected content 1`] = `
|
||||
|
||||
exports[`<DeleteServerButton /> > renders expected content 2`] = `
|
||||
<button
|
||||
class="tw:text-danger tw:hover:underline"
|
||||
class="text-danger hover:underline"
|
||||
type="button"
|
||||
>
|
||||
baz
|
||||
@ -20,7 +20,7 @@ exports[`<DeleteServerButton /> > renders expected content 2`] = `
|
||||
|
||||
exports[`<DeleteServerButton /> > renders expected content 3`] = `
|
||||
<button
|
||||
class="tw:text-danger tw:hover:underline"
|
||||
class="text-danger hover:underline"
|
||||
type="button"
|
||||
>
|
||||
something
|
||||
|
||||
@ -3,28 +3,28 @@
|
||||
exports[`<ManageServersRow /> > renders auto-connect icon only if server is autoConnect 1`] = `
|
||||
<div>
|
||||
<table
|
||||
class="tw:w-full"
|
||||
class="w-full"
|
||||
>
|
||||
<thead
|
||||
class="tw:hidden tw:lg:table-header-group"
|
||||
class="hidden lg:table-header-group"
|
||||
>
|
||||
<tr
|
||||
class="tw:group tw:lg:table-row tw:flex tw:flex-col tw:lg:border-0 tw:border-y-2 tw:border-lm-border tw:dark:border-dm-border"
|
||||
class="group lg:table-row flex flex-col lg:border-0 border-y-2 border-lm-border dark:border-dm-border"
|
||||
/>
|
||||
</thead>
|
||||
<tbody
|
||||
class="tw:lg:table-row-group tw:flex tw:flex-col tw:gap-y-3"
|
||||
class="lg:table-row-group flex flex-col gap-y-3"
|
||||
>
|
||||
<tr
|
||||
class="tw:group tw:lg:table-row tw:flex tw:flex-col tw:lg:border-0 tw:border-y-2 tw:border-lm-border tw:dark:border-dm-border tw:hover:bg-lm-primary tw:dark:hover:bg-dm-primary tw:group-[&]/card:hover:bg-lm-secondary tw:dark:group-[&]/card:hover:bg-dm-secondary tw:relative"
|
||||
class="group lg:table-row flex flex-col lg:border-0 border-y-2 border-lm-border dark:border-dm-border hover:bg-lm-primary dark:hover:bg-dm-primary group-[&]/card:hover:bg-lm-secondary dark:group-[&]/card:hover:bg-dm-secondary relative"
|
||||
>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1"
|
||||
data-column="Auto-connect"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-check tw:text-lm-brand tw:dark:text-dm-brand"
|
||||
class="svg-inline--fa fa-check text-lm-brand dark:text-dm-brand"
|
||||
data-icon="check"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
@ -39,7 +39,7 @@ exports[`<ManageServersRow /> > renders auto-connect icon only if server is auto
|
||||
</svg>
|
||||
</td>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:font-bold"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 font-bold"
|
||||
data-column="Name"
|
||||
>
|
||||
<a
|
||||
@ -50,13 +50,13 @@ exports[`<ManageServersRow /> > renders auto-connect icon only if server is auto
|
||||
</a>
|
||||
</td>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:max-lg:border-b-0"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 max-lg:border-b-0"
|
||||
data-column="Base URL"
|
||||
>
|
||||
https://example.com
|
||||
</td>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:text-right tw:max-lg:absolute tw:right-0 tw:-top-1 tw:mx-lg:pt-0"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 text-right max-lg:absolute right-0 -top-1 mx-lg:pt-0"
|
||||
>
|
||||
<span>
|
||||
ManageServersRowDropdown
|
||||
@ -71,27 +71,27 @@ exports[`<ManageServersRow /> > renders auto-connect icon only if server is auto
|
||||
exports[`<ManageServersRow /> > renders auto-connect icon only if server is autoConnect 2`] = `
|
||||
<div>
|
||||
<table
|
||||
class="tw:w-full"
|
||||
class="w-full"
|
||||
>
|
||||
<thead
|
||||
class="tw:hidden tw:lg:table-header-group"
|
||||
class="hidden lg:table-header-group"
|
||||
>
|
||||
<tr
|
||||
class="tw:group tw:lg:table-row tw:flex tw:flex-col tw:lg:border-0 tw:border-y-2 tw:border-lm-border tw:dark:border-dm-border"
|
||||
class="group lg:table-row flex flex-col lg:border-0 border-y-2 border-lm-border dark:border-dm-border"
|
||||
/>
|
||||
</thead>
|
||||
<tbody
|
||||
class="tw:lg:table-row-group tw:flex tw:flex-col tw:gap-y-3"
|
||||
class="lg:table-row-group flex flex-col gap-y-3"
|
||||
>
|
||||
<tr
|
||||
class="tw:group tw:lg:table-row tw:flex tw:flex-col tw:lg:border-0 tw:border-y-2 tw:border-lm-border tw:dark:border-dm-border tw:hover:bg-lm-primary tw:dark:hover:bg-dm-primary tw:group-[&]/card:hover:bg-lm-secondary tw:dark:group-[&]/card:hover:bg-dm-secondary tw:relative"
|
||||
class="group lg:table-row flex flex-col lg:border-0 border-y-2 border-lm-border dark:border-dm-border hover:bg-lm-primary dark:hover:bg-dm-primary group-[&]/card:hover:bg-lm-secondary dark:group-[&]/card:hover:bg-dm-secondary relative"
|
||||
>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1"
|
||||
data-column="Auto-connect"
|
||||
/>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:font-bold"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 font-bold"
|
||||
data-column="Name"
|
||||
>
|
||||
<a
|
||||
@ -102,13 +102,13 @@ exports[`<ManageServersRow /> > renders auto-connect icon only if server is auto
|
||||
</a>
|
||||
</td>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:max-lg:border-b-0"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 max-lg:border-b-0"
|
||||
data-column="Base URL"
|
||||
>
|
||||
https://example.com
|
||||
</td>
|
||||
<td
|
||||
class="tw:border-lm-border tw:dark:border-dm-border tw:p-2 tw:block tw:lg:table-cell tw:not-last:border-b-1 tw:lg:border-b-1 tw:before:lg:hidden tw:before:content-[attr(data-column)] tw:before:font-bold tw:before:mr-1 tw:text-right tw:max-lg:absolute tw:right-0 tw:-top-1 tw:mx-lg:pt-0"
|
||||
class="border-lm-border dark:border-dm-border p-2 block lg:table-cell not-last:border-b-1 lg:border-b-1 before:lg:hidden before:content-[attr(data-column)] before:font-bold before:mr-1 text-right max-lg:absolute right-0 -top-1 mx-lg:pt-0"
|
||||
>
|
||||
<span>
|
||||
ManageServersRowDropdown
|
||||
|
||||
@ -3,14 +3,14 @@
|
||||
exports[`<ManageServersRowDropdown /> > renders expected size and icon 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="tw:relative tw:inline-block"
|
||||
class="relative inline-block"
|
||||
>
|
||||
<button
|
||||
aria-controls="«r9»"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="tw:flex tw:items-center tw:rounded-md tw:focus-ring tw:cursor-pointer tw:border tw:border-lm-border tw:dark:border-dm-border tw:bg-lm-primary tw:dark:bg-dm-primary tw:group-[&]/card:bg-lm-input tw:group-[&]/card:dark:bg-dm-input tw:px-3 tw:py-1.5 tw:gap-x-2"
|
||||
class="flex items-center rounded-md focus-ring cursor-pointer border border-lm-border dark:border-dm-border bg-lm-primary dark:bg-dm-primary group-[&]/card:bg-lm-input group-[&]/card:dark:bg-dm-input px-3 py-1.5 gap-x-2"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
@ -40,14 +40,14 @@ exports[`<ManageServersRowDropdown /> > renders expected size and icon 1`] = `
|
||||
exports[`<ManageServersRowDropdown /> > renders expected size and icon 2`] = `
|
||||
<div>
|
||||
<div
|
||||
class="tw:relative tw:inline-block"
|
||||
class="relative inline-block"
|
||||
>
|
||||
<button
|
||||
aria-controls="«rb»"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="tw:flex tw:items-center tw:rounded-md tw:focus-ring tw:cursor-pointer tw:border tw:border-lm-border tw:dark:border-dm-border tw:bg-lm-primary tw:dark:bg-dm-primary tw:group-[&]/card:bg-lm-input tw:group-[&]/card:dark:bg-dm-input tw:px-3 tw:py-1.5 tw:gap-x-2"
|
||||
class="flex items-center rounded-md focus-ring cursor-pointer border border-lm-border dark:border-dm-border bg-lm-primary dark:bg-dm-primary group-[&]/card:bg-lm-input group-[&]/card:dark:bg-dm-input px-3 py-1.5 gap-x-2"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user