Merge pull request #1103 from shlinkio/develop

Release 4.1.0
This commit is contained in:
Alejandro Celaya 2024-03-17 12:26:34 +01:00 committed by GitHub
commit c75a3a4073
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 981 additions and 603 deletions

View file

@ -34,5 +34,10 @@ body:
validations: validations:
required: true required: true
attributes: attributes:
label: How to reproduce label: Minimum steps to reproduce
value: '<!-- Provide steps to reproduce the bug. -->' value: |
<!--
Emphasis in MINIMUM: What is the simplest way to reproduce the bug?
Avoid things like "Create a kubernetes cluster", or anything related with cloud providers, as that is rarely the root cause and the bug may be closed as "not reproducible".
If you can provide a simple docker compose config, that's even better.
-->

View file

@ -4,6 +4,27 @@ 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).
## [4.1.0] - 2024-03-17
### Added
* [#1079](https://github.com/shlinkio/shlink-web-client/issues/1079) Add support Shlink 4.0.0.
* [shlink-web-component#271](https://github.com/shlinkio/shlink-web-component/issues/271) Add support for redirect rules when consuming Shlink 4.0.0.
Now, if the server supports it, there will be a new item for every short URL dropdown, which will take you to a page where it will be possible to edit that short URL's redirect rules.
### Changed
* [shlink-web-component#249](https://github.com/shlinkio/shlink-web-component/issues/249) Replace `react-datepicker` with native `input[type="date"]` and `input[type="datetime-local"]` elements.
* Update dependencies.
### Deprecated
* *Nothing*
### Removed
* [shlink-web-component#276](https://github.com/shlinkio/shlink-web-component/issues/276) Drop support for Shlink older than 3.3.0
### Fixed
* [#1084](https://github.com/shlinkio/shlink-web-client/issues/1084) Fix broken server dropdown menu when auto-connect is enabled.
## [4.0.1] - 2024-02-01 ## [4.0.1] - 2024-02-01
### Added ### Added
* *Nothing* * *Nothing*

View file

@ -1,4 +1,4 @@
FROM node:21.6-alpine as node FROM node:21.7-alpine as node
COPY . /shlink-web-client COPY . /shlink-web-client
ARG VERSION="latest" ARG VERSION="latest"
ENV VERSION ${VERSION} ENV VERSION ${VERSION}

View file

@ -75,7 +75,7 @@ If you are using the shlink-web-client docker image, you can mount the `servers.
Alternatively, you can mount a `conf.d` directory, which in turn contains the `servers.json` file, in a volume inside `/usr/share/nginx/html`. *(since shlink-web-client 3.2.0)*. Alternatively, you can mount a `conf.d` directory, which in turn contains the `servers.json` file, in a volume inside `/usr/share/nginx/html`. *(since shlink-web-client 3.2.0)*.
docker run --name shlink-web-client -p 8000:80 -v ${PWD}/my-config/:/usr/share/nginx/html/conf.d/ shlinkio/shlink-web-client docker run --name shlink-web-client -p 8000:8080 -v ${PWD}/my-config/:/usr/share/nginx/html/conf.d/ shlinkio/shlink-web-client
If you want to pre-configure a single server, you can provide its config via env vars. When the container starts up, it will build the `servers.json` file dynamically based on them. *(since shlink-web-client 3.2.0)*. If you want to pre-configure a single server, you can provide its config via env vars. When the container starts up, it will build the `servers.json` file dynamically based on them. *(since shlink-web-client 3.2.0)*.
@ -86,7 +86,7 @@ If you want to pre-configure a single server, you can provide its config via env
```shell ```shell
docker run \ docker run \
--name shlink-web-client \ --name shlink-web-client \
-p 8000:80 \ -p 8000:8080 \
-e SHLINK_SERVER_URL=https://s.test \ -e SHLINK_SERVER_URL=https://s.test \
-e SHLINK_SERVER_API_KEY=6aeb82c6-e275-4538-a747-31f9abfba63c \ -e SHLINK_SERVER_API_KEY=6aeb82c6-e275-4538-a747-31f9abfba63c \
shlinkio/shlink-web-client shlinkio/shlink-web-client

1214
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -30,23 +30,23 @@
"@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@json2csv/plainjs": "^7.0.5", "@json2csv/plainjs": "^7.0.6",
"@reduxjs/toolkit": "^2.1.0", "@reduxjs/toolkit": "^2.2.1",
"@shlinkio/data-manipulation": "^1.0.3", "@shlinkio/data-manipulation": "^1.0.3",
"@shlinkio/shlink-frontend-kit": "^0.4.2", "@shlinkio/shlink-frontend-kit": "^0.5.0",
"@shlinkio/shlink-js-sdk": "^0.2.2", "@shlinkio/shlink-js-sdk": "^1.0.0",
"@shlinkio/shlink-web-component": "^0.5.0", "@shlinkio/shlink-web-component": "^0.6.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",
"compare-versions": "^6.1.0", "compare-versions": "^6.1.0",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",
"date-fns": "^3.3.1", "date-fns": "^3.5.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-external-link": "^2.2.0", "react-external-link": "^2.2.0",
"react-redux": "^9.1.0", "react-redux": "^9.1.0",
"react-router-dom": "^6.21.3", "react-router-dom": "^6.22.3",
"reactstrap": "^9.2.2", "reactstrap": "^9.2.2",
"redux-localstorage-simple": "^2.5.1", "redux-localstorage-simple": "^2.5.1",
"uuid": "^9.0.1", "uuid": "^9.0.1",
@ -59,26 +59,26 @@
"devDependencies": { "devDependencies": {
"@shlinkio/eslint-config-js-coding-standard": "~2.3.0", "@shlinkio/eslint-config-js-coding-standard": "~2.3.0",
"@shlinkio/stylelint-config-css-coding-standard": "~1.1.1", "@shlinkio/stylelint-config-css-coding-standard": "~1.1.1",
"@testing-library/jest-dom": "^6.3.0", "@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.1.2", "@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@total-typescript/shoehorn": "^0.1.1", "@total-typescript/shoehorn": "^0.1.2",
"@types/react": "^18.2.48", "@types/react": "^18.2.66",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.22",
"@types/uuid": "^9.0.8", "@types/uuid": "^9.0.8",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.2.2", "@vitest/coverage-v8": "^1.4.0",
"adm-zip": "^0.5.10", "adm-zip": "^0.5.12",
"axe-core": "^4.8.3", "axe-core": "^4.8.4",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"history": "^5.3.0", "history": "^5.3.0",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"sass": "^1.70.0", "sass": "^1.72.0",
"stylelint": "^15.11.0", "stylelint": "^15.11.0",
"typescript": "^5.3.3", "typescript": "^5.4.2",
"vite": "^5.0.12", "vite": "^5.1.6",
"vite-plugin-pwa": "^0.17.5", "vite-plugin-pwa": "^0.19.4",
"vitest": "^1.2.2" "vitest": "^1.2.2"
}, },
"browserslist": [ "browserslist": [

View file

@ -37,7 +37,7 @@ const ManageServersRowDropdown: FCWithDeps<ManageServersRowDropdownConnectProps,
const autoConnectIcon = isAutoConnect ? toggleOffIcon : toggleOnIcon; const autoConnectIcon = isAutoConnect ? toggleOffIcon : toggleOnIcon;
return ( return (
<RowDropdownBtn minWidth={170}> <RowDropdownBtn minWidth={isAutoConnect ? 210 : 170}>
<DropdownItem tag={Link} to={serverUrl}> <DropdownItem tag={Link} to={serverUrl}>
<FontAwesomeIcon icon={connectIcon} fixedWidth /> Connect <FontAwesomeIcon icon={connectIcon} fixedWidth /> Connect
</DropdownItem> </DropdownItem>

View file

@ -67,4 +67,9 @@ describe('<ManageServersRowDropdown />', () => {
expect(screen.getByText('DeleteServerModal [OPEN]')).toBeInTheDocument(); expect(screen.getByText('DeleteServerModal [OPEN]')).toBeInTheDocument();
expect(screen.queryByText('DeleteServerModal [CLOSED]')).not.toBeInTheDocument(); expect(screen.queryByText('DeleteServerModal [CLOSED]')).not.toBeInTheDocument();
}); });
it.each([[true], [false]])('renders expected size and icon', (autoConnect) => {
const { container } = setUp(autoConnect);
expect(container).toMatchSnapshot();
});
}); });

View file

@ -0,0 +1,287 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<ManageServersRowDropdown /> > renders expected size and icon 1`] = `
<div>
<div
class="dropdown"
>
<button
aria-expanded="false"
aria-haspopup="true"
aria-label="Options"
class="dropdown-btn__toggle btn btn-primary btn-sm"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-ellipsis-vertical px-1"
data-icon="ellipsis-vertical"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 128 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"
fill="currentColor"
/>
</svg>
</button>
<div
aria-hidden="true"
class="w-100 dropdown-menu dropdown-menu-end"
data-bs-popper="static"
role="menu"
style="min-width: 210px;"
tabindex="-1"
>
<a
class="dropdown-item"
href="/server/abc123"
role="menuitem"
tabindex="0"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plug fa-fw "
data-icon="plug"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 384 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M96 0C78.3 0 64 14.3 64 32v96h64V32c0-17.7-14.3-32-32-32zM288 0c-17.7 0-32 14.3-32 32v96h64V32c0-17.7-14.3-32-32-32zM32 160c-17.7 0-32 14.3-32 32s14.3 32 32 32v32c0 77.4 55 142 128 156.8V480c0 17.7 14.3 32 32 32s32-14.3 32-32V412.8C297 398 352 333.4 352 256V224c17.7 0 32-14.3 32-32s-14.3-32-32-32H32z"
fill="currentColor"
/>
</svg>
Connect
</a>
<a
class="dropdown-item"
href="/server/abc123/edit"
role="menuitem"
tabindex="0"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-pen-to-square fa-fw "
data-icon="pen-to-square"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160V416c0 53 43 96 96 96H352c53 0 96-43 96-96V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H96z"
fill="currentColor"
/>
</svg>
Edit server
</a>
<button
class="dropdown-item"
role="menuitem"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-ban fa-fw "
data-icon="ban"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M367.2 412.5L99.5 144.8C77.1 176.1 64 214.5 64 256c0 106 86 192 192 192c41.5 0 79.9-13.1 111.2-35.5zm45.3-45.3C434.9 335.9 448 297.5 448 256c0-106-86-192-192-192c-41.5 0-79.9 13.1-111.2 35.5L412.5 367.2zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z"
fill="currentColor"
/>
</svg>
Do not a
uto-connect
</button>
<hr
class="dropdown-divider"
tabindex="-1"
/>
<button
class="dropdown-item--danger dropdown-item"
role="menuitem"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-circle-minus fa-fw "
data-icon="circle-minus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM184 232H328c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"
fill="currentColor"
/>
</svg>
Remove server
</button>
<span>
DeleteServerModal
[CLOSED]
</span>
</div>
</div>
</div>
`;
exports[`<ManageServersRowDropdown /> > renders expected size and icon 2`] = `
<div>
<div
class="dropdown"
>
<button
aria-expanded="false"
aria-haspopup="true"
aria-label="Options"
class="dropdown-btn__toggle btn btn-primary btn-sm"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-ellipsis-vertical px-1"
data-icon="ellipsis-vertical"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 128 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"
fill="currentColor"
/>
</svg>
</button>
<div
aria-hidden="true"
class="w-100 dropdown-menu dropdown-menu-end"
data-bs-popper="static"
role="menu"
style="min-width: 170px;"
tabindex="-1"
>
<a
class="dropdown-item"
href="/server/abc123"
role="menuitem"
tabindex="0"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plug fa-fw "
data-icon="plug"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 384 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M96 0C78.3 0 64 14.3 64 32v96h64V32c0-17.7-14.3-32-32-32zM288 0c-17.7 0-32 14.3-32 32v96h64V32c0-17.7-14.3-32-32-32zM32 160c-17.7 0-32 14.3-32 32s14.3 32 32 32v32c0 77.4 55 142 128 156.8V480c0 17.7 14.3 32 32 32s32-14.3 32-32V412.8C297 398 352 333.4 352 256V224c17.7 0 32-14.3 32-32s-14.3-32-32-32H32z"
fill="currentColor"
/>
</svg>
Connect
</a>
<a
class="dropdown-item"
href="/server/abc123/edit"
role="menuitem"
tabindex="0"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-pen-to-square fa-fw "
data-icon="pen-to-square"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160V416c0 53 43 96 96 96H352c53 0 96-43 96-96V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H96z"
fill="currentColor"
/>
</svg>
Edit server
</a>
<button
class="dropdown-item"
role="menuitem"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-circle fa-fw "
data-icon="circle"
data-prefix="far"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z"
fill="currentColor"
/>
</svg>
A
uto-connect
</button>
<hr
class="dropdown-divider"
tabindex="-1"
/>
<button
class="dropdown-item--danger dropdown-item"
role="menuitem"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-circle-minus fa-fw "
data-icon="circle-minus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM184 232H328c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"
fill="currentColor"
/>
</svg>
Remove server
</button>
<span>
DeleteServerModal
[CLOSED]
</span>
</div>
</div>
</div>
`;