Compare commits

...

118 Commits

Author SHA1 Message Date
Alejandro Celaya
5aa113ec16 Merge pull request #1387 from shlinkio/develop
Release 4.3.0
2024-11-30 10:48:52 +01:00
Alejandro Celaya
a390e1bdf9 Merge pull request #1386 from acelaya-forks/feature/vite-6
Update to vite 6
2024-11-30 10:42:28 +01:00
Alejandro Celaya
44e9a336aa Update to vite 6 2024-11-30 10:40:07 +01:00
Alejandro Celaya
8ac347f52d Merge pull request #1385 from acelaya-forks/feature/update-shlink-web-component
Update to shlink-web-component 0.11
2024-11-30 10:34:06 +01:00
Alejandro Celaya
a325af3cda Update to shlink-web-component 0.11 2024-11-30 10:31:42 +01:00
Alejandro Celaya
49ebfdbbaf Merge pull request #1378 from shlinkio/dependabot/npm_and_yarn/eslint-b9347fbce3
Bump the eslint group with 2 updates
2024-11-30 10:26:01 +01:00
Alejandro Celaya
742c7b9dd9 Merge pull request #1379 from shlinkio/dependabot/npm_and_yarn/shlink-e0384b93cb
Bump @shlinkio/shlink-js-sdk from 1.2.0 to 1.3.0 in the shlink group
2024-11-30 10:25:55 +01:00
Alejandro Celaya
558d2a09f7 Merge pull request #1381 from shlinkio/dependabot/npm_and_yarn/vitest-bbd5fc0bbb
Bump the vitest group with 2 updates
2024-11-30 10:25:47 +01:00
Alejandro Celaya
584362b426 Merge pull request #1382 from shlinkio/dependabot/npm_and_yarn/reduxjs/toolkit-2.4.0
Bump @reduxjs/toolkit from 2.3.0 to 2.4.0
2024-11-30 10:25:22 +01:00
Alejandro Celaya
0bcdcadee4 Merge pull request #1383 from shlinkio/dependabot/npm_and_yarn/vite-plugin-pwa-0.21.1
Bump vite-plugin-pwa from 0.21.0 to 0.21.1
2024-11-30 10:25:05 +01:00
dependabot[bot]
8ae6835a10 Bump vite-plugin-pwa from 0.21.0 to 0.21.1
Bumps [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) from 0.21.0 to 0.21.1.
- [Release notes](https://github.com/vite-pwa/vite-plugin-pwa/releases)
- [Commits](https://github.com/vite-pwa/vite-plugin-pwa/compare/v0.21.0...v0.21.1)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-30 08:32:00 +00:00
dependabot[bot]
8addfbdb3d Bump @reduxjs/toolkit from 2.3.0 to 2.4.0
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-30 08:31:49 +00:00
dependabot[bot]
db59d55326 Bump the vitest group with 2 updates
Bumps the vitest group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 2.1.5 to 2.1.6
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.6/packages/coverage-v8)

Updates `vitest` from 2.1.5 to 2.1.6
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.6/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-30 08:31:14 +00:00
dependabot[bot]
30ee16a9f6 Bump @shlinkio/shlink-js-sdk from 1.2.0 to 1.3.0 in the shlink group
Bumps the shlink group with 1 update: [@shlinkio/shlink-js-sdk](https://shlink.io).


Updates `@shlinkio/shlink-js-sdk` from 1.2.0 to 1.3.0

---
updated-dependencies:
- dependency-name: "@shlinkio/shlink-js-sdk"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: shlink
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-30 08:30:20 +00:00
dependabot[bot]
8c981811b3 Bump the eslint group with 2 updates
Bumps the eslint group with 2 updates: [eslint](https://github.com/eslint/eslint) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `eslint` from 9.15.0 to 9.16.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.15.0...v9.16.0)

Updates `typescript-eslint` from 8.15.0 to 8.16.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.16.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-30 08:30:03 +00:00
Alejandro Celaya
975807c143 Merge pull request #1374 from shlinkio/dependabot/npm_and_yarn/eslint-25372b66e4
Bump the eslint group across 1 directory with 3 updates
2024-11-23 11:27:05 +01:00
Alejandro Celaya
5aaf9111fd Merge pull request #1375 from shlinkio/dependabot/npm_and_yarn/fontawesome-951ff399f8
Bump the fontawesome group with 5 updates
2024-11-23 11:26:56 +01:00
dependabot[bot]
a10898f662 Bump the eslint group across 1 directory with 3 updates
Bumps the eslint group with 3 updates in the / directory: [@stylistic/eslint-plugin](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin), [eslint](https://github.com/eslint/eslint) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@stylistic/eslint-plugin` from 2.10.1 to 2.11.0
- [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases)
- [Changelog](https://github.com/eslint-stylistic/eslint-stylistic/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v2.11.0/packages/eslint-plugin)

Updates `eslint` from 9.14.0 to 9.15.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.14.0...v9.15.0)

Updates `typescript-eslint` from 8.13.0 to 8.15.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.15.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@stylistic/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-23 10:25:05 +00:00
Alejandro Celaya
a853078862 Merge pull request #1376 from shlinkio/dependabot/npm_and_yarn/typescript-5.7.2
Bump typescript from 5.6.3 to 5.7.2
2024-11-23 11:23:58 +01:00
Alejandro Celaya
b1c2b01998 Merge pull request #1377 from shlinkio/dependabot/docker/node-23.3-alpine
Bump node from 23.1-alpine to 23.3-alpine
2024-11-23 11:23:49 +01:00
dependabot[bot]
e0f5705c78 Bump node from 23.1-alpine to 23.3-alpine
Bumps node from 23.1-alpine to 23.3-alpine.

---
updated-dependencies:
- dependency-name: node
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-23 08:52:07 +00:00
dependabot[bot]
db1b58e32e Bump typescript from 5.6.3 to 5.7.2
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.3 to 5.7.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.3...v5.7.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-23 08:21:43 +00:00
dependabot[bot]
a777edb881 Bump the fontawesome group with 5 updates
Bumps the fontawesome group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) | `6.6.0` | `6.7.1` |
| [@fortawesome/fontawesome-svg-core](https://github.com/FortAwesome/Font-Awesome) | `6.6.0` | `6.7.1` |
| [@fortawesome/free-brands-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `6.6.0` | `6.7.1` |
| [@fortawesome/free-regular-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `6.6.0` | `6.7.1` |
| [@fortawesome/free-solid-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `6.6.0` | `6.7.1` |


Updates `@fortawesome/fontawesome-free` from 6.6.0 to 6.7.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.6.0...6.7.1)

Updates `@fortawesome/fontawesome-svg-core` from 6.6.0 to 6.7.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.6.0...6.7.1)

Updates `@fortawesome/free-brands-svg-icons` from 6.6.0 to 6.7.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.6.0...6.7.1)

Updates `@fortawesome/free-regular-svg-icons` from 6.6.0 to 6.7.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.6.0...6.7.1)

Updates `@fortawesome/free-solid-svg-icons` from 6.6.0 to 6.7.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.6.0...6.7.1)

---
updated-dependencies:
- dependency-name: "@fortawesome/fontawesome-free"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: fontawesome
- dependency-name: "@fortawesome/fontawesome-svg-core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: fontawesome
- dependency-name: "@fortawesome/free-brands-svg-icons"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: fontawesome
- dependency-name: "@fortawesome/free-regular-svg-icons"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: fontawesome
- dependency-name: "@fortawesome/free-solid-svg-icons"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: fontawesome
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-23 08:20:55 +00:00
Alejandro Celaya
81434a5649 Merge pull request #1370 from shlinkio/dependabot/npm_and_yarn/vite-74cd45698c
Bump vite from 5.4.10 to 5.4.11 in the vite group
2024-11-16 10:24:51 +01:00
dependabot[bot]
62642d891f Bump vite from 5.4.10 to 5.4.11 in the vite group
Bumps the vite group with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.10 to 5.4.11
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.11/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vite
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-16 09:20:42 +00:00
Alejandro Celaya
68126aad88 Merge pull request #1371 from shlinkio/dependabot/npm_and_yarn/vitest-9196e89f7c
Bump the vitest group with 2 updates
2024-11-16 10:20:19 +01:00
Alejandro Celaya
7e8d85ca73 Merge pull request #1372 from shlinkio/dependabot/npm_and_yarn/sass-1.81.0
Bump sass from 1.80.6 to 1.81.0
2024-11-16 10:20:11 +01:00
Alejandro Celaya
b2205a6258 Merge pull request #1373 from shlinkio/dependabot/npm_and_yarn/vite-plugin-pwa-0.21.0
Bump vite-plugin-pwa from 0.20.5 to 0.21.0
2024-11-16 10:19:53 +01:00
dependabot[bot]
158702bdfc Bump vite-plugin-pwa from 0.20.5 to 0.21.0
Bumps [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) from 0.20.5 to 0.21.0.
- [Release notes](https://github.com/vite-pwa/vite-plugin-pwa/releases)
- [Commits](https://github.com/vite-pwa/vite-plugin-pwa/compare/v0.20.5...v0.21.0)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-16 09:01:44 +00:00
dependabot[bot]
7220bf1ff4 Bump sass from 1.80.6 to 1.81.0
Bumps [sass](https://github.com/sass/dart-sass) from 1.80.6 to 1.81.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.80.6...1.81.0)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-16 09:01:26 +00:00
dependabot[bot]
03cb2d76d7 Bump the vitest group with 2 updates
Bumps the vitest group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 2.1.4 to 2.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.5/packages/coverage-v8)

Updates `vitest` from 2.1.4 to 2.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.5/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-16 09:01:07 +00:00
Alejandro Celaya
d6350131e6 Merge pull request #1367 from shlinkio/dependabot/npm_and_yarn/eslint-b3b6cd0b9f
Bump typescript-eslint from 8.12.2 to 8.13.0 in the eslint group
2024-11-09 10:07:57 +01:00
Alejandro Celaya
27db3532d9 Merge pull request #1368 from shlinkio/dependabot/npm_and_yarn/react-router-dom-6.28.0
Bump react-router-dom from 6.27.0 to 6.28.0
2024-11-09 10:07:47 +01:00
dependabot[bot]
03f826ffeb Bump react-router-dom from 6.27.0 to 6.28.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.27.0 to 6.28.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.28.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-09 08:16:53 +00:00
dependabot[bot]
049a588287 Bump typescript-eslint from 8.12.2 to 8.13.0 in the eslint group
Bumps the eslint group with 1 update: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.12.2 to 8.13.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.13.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-09 08:15:58 +00:00
Alejandro Celaya
3aeafec90f Merge pull request #1363 from shlinkio/dependabot/npm_and_yarn/eslint-479a1db07e
Bump the eslint group with 3 updates
2024-11-02 09:57:35 +01:00
dependabot[bot]
32ec9b98d4 Bump the eslint group with 3 updates
Bumps the eslint group with 3 updates: [@stylistic/eslint-plugin](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin), [eslint](https://github.com/eslint/eslint) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@stylistic/eslint-plugin` from 2.9.0 to 2.10.1
- [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases)
- [Changelog](https://github.com/eslint-stylistic/eslint-stylistic/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v2.10.1/packages/eslint-plugin)

Updates `eslint` from 9.13.0 to 9.14.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.13.0...v9.14.0)

Updates `typescript-eslint` from 8.11.0 to 8.12.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.12.2/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@stylistic/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-02 08:53:35 +00:00
Alejandro Celaya
6646906d58 Merge pull request #1366 from shlinkio/dependabot/npm_and_yarn/sass-1.80.6
Bump sass from 1.80.4 to 1.80.6
2024-11-02 09:52:20 +01:00
Alejandro Celaya
31c3290aec Merge pull request #1365 from shlinkio/dependabot/npm_and_yarn/workbox-218dd4e85e
Bump the workbox group with 5 updates
2024-11-02 09:52:11 +01:00
Alejandro Celaya
31c4192c24 Merge pull request #1364 from shlinkio/dependabot/npm_and_yarn/vitest-8e6bbe5855
Bump the vitest group with 2 updates
2024-11-02 09:51:47 +01:00
Alejandro Celaya
d4f8fdbd83 Merge pull request #1362 from shlinkio/dependabot/npm_and_yarn/testing-8a261f7dc1
Bump @testing-library/jest-dom from 6.5.0 to 6.6.3 in the testing group across 1 directory
2024-11-02 09:51:32 +01:00
dependabot[bot]
877d951a1b Bump sass from 1.80.4 to 1.80.6
Bumps [sass](https://github.com/sass/dart-sass) from 1.80.4 to 1.80.6.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.80.4...1.80.6)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-02 08:21:03 +00:00
dependabot[bot]
3a6ee5e3c0 Bump the workbox group with 5 updates
Bumps the workbox group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [workbox-core](https://github.com/googlechrome/workbox) | `7.1.0` | `7.3.0` |
| [workbox-expiration](https://github.com/googlechrome/workbox) | `7.1.0` | `7.3.0` |
| [workbox-precaching](https://github.com/googlechrome/workbox) | `7.1.0` | `7.3.0` |
| [workbox-routing](https://github.com/googlechrome/workbox) | `7.1.0` | `7.3.0` |
| [workbox-strategies](https://github.com/googlechrome/workbox) | `7.1.0` | `7.3.0` |


Updates `workbox-core` from 7.1.0 to 7.3.0
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v7.1.0...v7.3.0)

Updates `workbox-expiration` from 7.1.0 to 7.3.0
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v7.1.0...v7.3.0)

Updates `workbox-precaching` from 7.1.0 to 7.3.0
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v7.1.0...v7.3.0)

Updates `workbox-routing` from 7.1.0 to 7.3.0
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v7.1.0...v7.3.0)

Updates `workbox-strategies` from 7.1.0 to 7.3.0
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v7.1.0...v7.3.0)

---
updated-dependencies:
- dependency-name: workbox-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: workbox
- dependency-name: workbox-expiration
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: workbox
- dependency-name: workbox-precaching
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: workbox
- dependency-name: workbox-routing
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: workbox
- dependency-name: workbox-strategies
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: workbox
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-02 08:20:49 +00:00
dependabot[bot]
ca980b96fa Bump the vitest group with 2 updates
Bumps the vitest group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 2.1.3 to 2.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.4/packages/coverage-v8)

Updates `vitest` from 2.1.3 to 2.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.4/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-02 08:19:58 +00:00
dependabot[bot]
a5a0f36166 Bump @testing-library/jest-dom in the testing group across 1 directory
Bumps the testing group with 1 update in the / directory: [@testing-library/jest-dom](https://github.com/testing-library/jest-dom).


Updates `@testing-library/jest-dom` from 6.5.0 to 6.6.3
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.5.0...v6.6.3)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: testing
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-02 08:18:47 +00:00
Alejandro Celaya
238cefde73 Merge pull request #1361 from acelaya-forks/feature/predictable-server-ids
Feature/predictable server ids
2024-11-01 12:51:47 +01:00
Alejandro Celaya
b31949b468 Ensure generating server IDs work even if server URLs are invalid 2024-11-01 12:49:20 +01:00
Alejandro Celaya
645abea72a Add test for servers helpers 2024-11-01 12:21:42 +01:00
Alejandro Celaya
7a9209af03 Use better names for remoteServers test datasets 2024-11-01 12:15:15 +01:00
Alejandro Celaya
c83abc6e9a Update Bluesky handle 2024-11-01 12:11:38 +01:00
Alejandro Celaya
9b891c83fa Delete unused FormText component 2024-11-01 12:11:12 +01:00
Alejandro Celaya
dc8c749212 Remove dependency on uuid package 2024-11-01 12:09:13 +01:00
Alejandro Celaya
88ad2e7fc2 Fix serversReducer test 2024-11-01 12:01:58 +01:00
Alejandro Celaya
44fb07840e Fix remoteServers test 2024-11-01 11:59:54 +01:00
Alejandro Celaya
e786f9d21f Update CreateServer logic so that it ensures a unique human-friendly ID is set 2024-11-01 11:52:05 +01:00
Alejandro Celaya
9134d07969 Extract logic to determine if a list of servers contains duplicates 2024-10-31 09:36:18 +01:00
Alejandro Celaya
913264b0db Merge pull request #1359 from acelaya-forks/feature/improve-dev-setup
Simplify local dev setup, update CONTRIBUTING.md and recommend running scripts with node --run
2024-10-26 13:23:14 +02:00
Alejandro Celaya
2bbc3e6426 Update node version used during ci 2024-10-26 13:20:28 +02:00
Alejandro Celaya
4c74aec703 Simplify local dev setup, update CONTRIBUTING.md and recommend running scripts with node --run 2024-10-26 13:12:37 +02:00
Alejandro Celaya
83ca5b23f5 Add workflow to build docker image during PRs if Dockerfile changed 2024-10-26 10:32:28 +02:00
Alejandro Celaya
61a679b7cb Merge pull request #1354 from shlinkio/dependabot/npm_and_yarn/eslint-bddec486b2
Bump the eslint group with 4 updates
2024-10-26 09:34:14 +02:00
dependabot[bot]
fdbf094893 Bump the eslint group with 4 updates
Bumps the eslint group with 4 updates: [@shlinkio/eslint-config-js-coding-standard](https://github.com/shlinkio/js-coding-standard), [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@shlinkio/eslint-config-js-coding-standard` from 3.2.0 to 3.2.1
- [Release notes](https://github.com/shlinkio/js-coding-standard/releases)
- [Changelog](https://github.com/shlinkio/js-coding-standard/blob/main/CHANGELOG.md)
- [Commits](https://github.com/shlinkio/js-coding-standard/compare/v3.2.0...v3.2.1)

Updates `eslint-plugin-jsx-a11y` from 6.10.0 to 6.10.2
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/compare/v6.10.0...v6.10.2)

Updates `eslint-plugin-react` from 7.37.1 to 7.37.2
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.37.1...v7.37.2)

Updates `typescript-eslint` from 8.10.0 to 8.11.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.11.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@shlinkio/eslint-config-js-coding-standard"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: eslint-plugin-jsx-a11y
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:31:58 +00:00
Alejandro Celaya
fad0dfbe43 Merge pull request #1353 from shlinkio/dependabot/docker/node-23.1-alpine
Bump node from 23.0-alpine to 23.1-alpine
2024-10-26 09:30:20 +02:00
Alejandro Celaya
7ae8e52da8 Merge pull request #1355 from shlinkio/dependabot/npm_and_yarn/types-30814940ba
Bump @types/react from 18.3.11 to 18.3.12 in the types group
2024-10-26 09:29:59 +02:00
Alejandro Celaya
6a1f25ecf6 Merge pull request #1356 from shlinkio/dependabot/npm_and_yarn/vite-19a79babb4
Bump the vite group with 2 updates
2024-10-26 09:29:50 +02:00
Alejandro Celaya
10ba6cb51b Merge pull request #1357 from shlinkio/dependabot/npm_and_yarn/sass-1.80.4
Bump sass from 1.80.3 to 1.80.4
2024-10-26 09:29:43 +02:00
Alejandro Celaya
5943d2aaa6 Merge pull request #1358 from shlinkio/dependabot/npm_and_yarn/axe-core-4.10.2
Bump axe-core from 4.10.1 to 4.10.2
2024-10-26 09:29:36 +02:00
dependabot[bot]
c434b54969 Bump axe-core from 4.10.1 to 4.10.2
Bumps [axe-core](https://github.com/dequelabs/axe-core) from 4.10.1 to 4.10.2.
- [Release notes](https://github.com/dequelabs/axe-core/releases)
- [Changelog](https://github.com/dequelabs/axe-core/blob/v4.10.2/CHANGELOG.md)
- [Commits](https://github.com/dequelabs/axe-core/compare/v4.10.1...v4.10.2)

---
updated-dependencies:
- dependency-name: axe-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:13:10 +00:00
dependabot[bot]
3840d4a1be Bump sass from 1.80.3 to 1.80.4
Bumps [sass](https://github.com/sass/dart-sass) from 1.80.3 to 1.80.4.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.80.3...1.80.4)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:12:49 +00:00
dependabot[bot]
2b77b2411c Bump the vite group with 2 updates
Bumps the vite group with 2 updates: [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `@vitejs/plugin-react` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/v4.3.3/packages/plugin-react)

Updates `vite` from 5.4.9 to 5.4.10
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.10/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.10/packages/vite)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vite
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vite
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:12:26 +00:00
dependabot[bot]
714474d406 Bump @types/react from 18.3.11 to 18.3.12 in the types group
Bumps the types group with 1 update: [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).


Updates `@types/react` from 18.3.11 to 18.3.12
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: types
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:12:00 +00:00
dependabot[bot]
a1a1bc44ae Bump node from 23.0-alpine to 23.1-alpine
Bumps node from 23.0-alpine to 23.1-alpine.

---
updated-dependencies:
- dependency-name: node
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 07:05:01 +00:00
Alejandro Celaya
18d9ed7b0d Merge pull request #1352 from acelaya-forks/feature/remove-rows
Feature/remove rows
2024-10-19 14:17:36 +02:00
Alejandro Celaya
9094c1d23f Simplify styles in home page with flex utilities 2024-10-19 14:15:53 +02:00
Alejandro Celaya
dcac312d86 Use more flex utilities in ManageServers component 2024-10-19 13:35:20 +02:00
Alejandro Celaya
2e438f9814 Merge pull request #1351 from shlinkio/develop
Release 4.2.2
2024-10-19 12:15:18 +02:00
Alejandro Celaya
ae014e2a14 Update to @shlinkio/shlink-web-component 0.10.1 2024-10-19 12:13:34 +02:00
Alejandro Celaya
5f5b66a21e Merge pull request #1350 from acelaya-forks/feature/update-packages
Update to latest shlink-web-component and shlink-frontend-kit
2024-10-19 11:32:27 +02:00
Alejandro Celaya
723e8696af Update to latest shlink-web-component and shlink-frontend-kit 2024-10-19 11:23:20 +02:00
Alejandro Celaya
32c3c9955c Merge pull request #1346 from shlinkio/dependabot/npm_and_yarn/eslint-9.13.0
Bump eslint from 9.12.0 to 9.13.0
2024-10-19 11:15:19 +02:00
Alejandro Celaya
847a23ddeb Merge pull request #1343 from shlinkio/dependabot/npm_and_yarn/vite-dddd68210b
Bump vite from 5.4.8 to 5.4.9 in the vite group
2024-10-19 11:15:11 +02:00
dependabot[bot]
08e3e01526 Bump vite from 5.4.8 to 5.4.9 in the vite group
Bumps the vite group with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.8 to 5.4.9
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.9/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.9/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vite
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 09:12:14 +00:00
dependabot[bot]
82b26add88 Bump eslint from 9.12.0 to 9.13.0
Bumps [eslint](https://github.com/eslint/eslint) from 9.12.0 to 9.13.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.12.0...v9.13.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 09:12:01 +00:00
Alejandro Celaya
e3ab34eae1 Merge pull request #1341 from shlinkio/dependabot/npm_and_yarn/eslint-plugins-6f16f7b45b
Bump typescript-eslint from 8.8.1 to 8.10.0 in the eslint-plugins group
2024-10-19 11:11:25 +02:00
Alejandro Celaya
65d9a4125f Merge pull request #1344 from shlinkio/dependabot/npm_and_yarn/vitest-704a82ba63
Bump the vitest group with 2 updates
2024-10-19 11:10:34 +02:00
Alejandro Celaya
d05344eea7 Merge pull request #1345 from shlinkio/dependabot/npm_and_yarn/axe-core-4.10.1
Bump axe-core from 4.10.0 to 4.10.1
2024-10-19 11:10:23 +02:00
dependabot[bot]
47a2d981c8 Bump typescript-eslint from 8.8.1 to 8.10.0 in the eslint-plugins group
Bumps the eslint-plugins group with 1 update: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.8.1 to 8.10.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.10.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint-plugins
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 09:02:49 +00:00
Alejandro Celaya
2229573101 Merge pull request #1347 from shlinkio/dependabot/npm_and_yarn/reduxjs/toolkit-2.3.0
Bump @reduxjs/toolkit from 2.2.8 to 2.3.0
2024-10-19 11:02:00 +02:00
Alejandro Celaya
a8059c6f1f Merge pull request #1348 from shlinkio/dependabot/npm_and_yarn/sass-1.80.3
Bump sass from 1.79.5 to 1.80.3
2024-10-19 11:01:54 +02:00
Alejandro Celaya
51c1963f4b Merge pull request #1349 from shlinkio/dependabot/docker/node-23.0-alpine
Bump node from 22.9-alpine to 23.0-alpine
2024-10-19 11:01:44 +02:00
dependabot[bot]
8c10daeddd Bump node from 22.9-alpine to 23.0-alpine
Bumps node from 22.9-alpine to 23.0-alpine.

---
updated-dependencies:
- dependency-name: node
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 07:57:04 +00:00
dependabot[bot]
d168e98607 Bump sass from 1.79.5 to 1.80.3
Bumps [sass](https://github.com/sass/dart-sass) from 1.79.5 to 1.80.3.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.79.5...1.80.3)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 07:12:39 +00:00
dependabot[bot]
a45d990eb7 Bump @reduxjs/toolkit from 2.2.8 to 2.3.0
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.8 to 2.3.0.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.8...v2.3.0)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 07:12:28 +00:00
dependabot[bot]
31ae43708a Bump axe-core from 4.10.0 to 4.10.1
Bumps [axe-core](https://github.com/dequelabs/axe-core) from 4.10.0 to 4.10.1.
- [Release notes](https://github.com/dequelabs/axe-core/releases)
- [Changelog](https://github.com/dequelabs/axe-core/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/dequelabs/axe-core/compare/v4.10.0...v4.10.1)

---
updated-dependencies:
- dependency-name: axe-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 07:12:03 +00:00
dependabot[bot]
cefe327251 Bump the vitest group with 2 updates
Bumps the vitest group with 2 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 2.1.2 to 2.1.3
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.3/packages/coverage-v8)

Updates `vitest` from 2.1.2 to 2.1.3
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.3/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-19 07:11:38 +00:00
Alejandro Celaya
22280e9d89 Remove twitter badge from readme 2024-10-17 16:26:41 +02:00
Alejandro Celaya
c73ece41f0 Merge pull request #1339 from acelaya-forks/feature/avoid-side-effects
Remove not needed usages of useEffect
2024-10-14 18:02:04 +02:00
Alejandro Celaya
7825f7666f Remove not needed usages of useEffect 2024-10-14 17:59:56 +02:00
Alejandro Celaya
fc6901ee65 Merge pull request #1338 from shlinkio/dependabot/npm_and_yarn/eslint-plugins-0f7f25a9f5
Bump typescript-eslint from 8.8.0 to 8.8.1 in the eslint-plugins group across 1 directory
2024-10-12 20:21:15 +02:00
dependabot[bot]
1794a07204 Bump typescript-eslint in the eslint-plugins group across 1 directory
Bumps the eslint-plugins group with 1 update in the / directory: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.8.0 to 8.8.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.8.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint-plugins
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 18:11:31 +00:00
Alejandro Celaya
7215d188a2 Merge pull request #1337 from acelaya-forks/feature/eslint-9
Feature/eslint 9
2024-10-12 20:10:31 +02:00
Alejandro Celaya
94890da48f Update to ESLint 9 2024-10-12 20:09:02 +02:00
Alejandro Celaya
078c5c8889 Merge pull request #1332 from shlinkio/dependabot/npm_and_yarn/types-0d175a54fb
Bump @types/react-dom from 18.3.0 to 18.3.1 in the types group
2024-10-12 10:34:11 +02:00
Alejandro Celaya
23a0cb1245 Merge pull request #1333 from shlinkio/dependabot/npm_and_yarn/react-router-dom-6.27.0
Bump react-router-dom from 6.26.2 to 6.27.0
2024-10-12 10:34:03 +02:00
Alejandro Celaya
b4015bd8d1 Merge pull request #1334 from shlinkio/dependabot/npm_and_yarn/typescript-5.6.3
Bump typescript from 5.6.2 to 5.6.3
2024-10-12 10:33:51 +02:00
dependabot[bot]
3cffaa6e32 Bump typescript from 5.6.2 to 5.6.3
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.2 to 5.6.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.2...v5.6.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 08:33:32 +00:00
Alejandro Celaya
e68faa63c5 Merge pull request #1335 from shlinkio/dependabot/npm_and_yarn/reduxjs/toolkit-2.2.8
Bump @reduxjs/toolkit from 2.2.7 to 2.2.8
2024-10-12 10:32:54 +02:00
Alejandro Celaya
e0706a6a89 Merge pull request #1336 from shlinkio/dependabot/npm_and_yarn/sass-1.79.5
Bump sass from 1.79.4 to 1.79.5
2024-10-12 10:32:43 +02:00
dependabot[bot]
adcb405643 Bump sass from 1.79.4 to 1.79.5
Bumps [sass](https://github.com/sass/dart-sass) from 1.79.4 to 1.79.5.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.79.4...1.79.5)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 07:30:03 +00:00
dependabot[bot]
63df7db2f5 Bump @reduxjs/toolkit from 2.2.7 to 2.2.8
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.7 to 2.2.8.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.7...v2.2.8)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 07:29:47 +00:00
dependabot[bot]
04eb1b1b0e Bump react-router-dom from 6.26.2 to 6.27.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.26.2 to 6.27.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/react-router-dom@6.27.0/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.27.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 07:29:10 +00:00
dependabot[bot]
40bf57882a Bump @types/react-dom from 18.3.0 to 18.3.1 in the types group
Bumps the types group with 1 update: [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom).


Updates `@types/react-dom` from 18.3.0 to 18.3.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: types
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-12 07:28:32 +00:00
Alejandro Celaya
9a798c20c0 Merge pull request #1329 from shlinkio/develop
Release 4.2.1
2024-10-09 14:33:56 +02:00
Alejandro Celaya
45a9783e04 Remove extra empty line from changelog 2024-10-09 14:32:29 +02:00
Alejandro Celaya
ac95ff0166 Merge pull request #1328 from acelaya-forks/feature/web-client-0.8.1
Update to shlink-web-client 0.8.1
2024-10-09 14:31:40 +02:00
Alejandro Celaya
a0df3eeb93 Update to shlink-web-client 0.8.1 2024-10-09 14:29:47 +02:00
Alejandro Celaya
e8c5ac8320 Merge pull request #1327 from acelaya-forks/feature/uuid-fix
Get dependency on uuid package back to fix error on non-secure contexts
2024-10-09 09:30:10 +02:00
Alejandro Celaya
453d245924 Get dependency on uuid package back to fix error on non-secure contexts 2024-10-09 09:27:08 +02:00
46 changed files with 5379 additions and 5300 deletions

View File

@@ -12,11 +12,12 @@ updates:
fontawesome:
patterns:
- '@fortawesome/*'
eslint-plugins: # TODO Add eslint back once updated to v9
eslint:
patterns:
- '@shlinkio/eslint-config-js-coding-standard'
- 'typescript-eslint'
- '*eslint-plugin*'
- 'eslint'
shlink:
patterns:
- '@shlinkio/*'

View File

@@ -0,0 +1,10 @@
name: Test docker image build
on:
pull_request:
paths:
- 'Dockerfile'
jobs:
build-docker-image:
uses: shlinkio/github-actions/.github/workflows/docker-image-build-ci.yml@main

View File

@@ -11,5 +11,5 @@ jobs:
ci:
uses: shlinkio/github-actions/.github/workflows/web-app-ci.yml@main
with:
node-version: 20.7
node-version: 22.x
publish-coverage: true

View File

@@ -9,19 +9,19 @@ jobs:
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
- name: Use node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.7
node-version: 22.x
- name: Build
run: |
npm ci && \
node ./scripts/set-homepage.cjs /shlink-web-client/${GITHUB_HEAD_REF#refs/heads/} && \
npm run build
node --run build
- name: Deploy preview
uses: shlinkio/deploy-preview-action@v1.0.1
with:

View File

@@ -10,11 +10,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Use node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.7
node-version: 22.x
- name: Generate release assets
run: npm ci && VERSION=${GITHUB_REF#refs/tags/v} npm run build:dist
- name: Publish release with assets

4
.gitignore vendored
View File

@@ -7,9 +7,7 @@
# production
/build
/dist
npm-debug.log*
docker-compose.override.yml
home
public/servers.json*

View File

@@ -4,6 +4,72 @@ 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).
## [4.3.0] - 2024-11-30
### Added
* [#1360](https://github.com/shlinkio/shlink-web-client/issues/1360) Added ability for server IDs to be generated based on the server name and URL, instead of generating a random UUID.
This can improve sharing a predefined set of servers cia servers.json, env vars, or simply export and import your servers in some other device, and then be able to share server URLs which continue working.
All existing servers will keep their generated IDs in existing devices for backwards compatibility, but newly created servers will use the new approach.
* [shlink-web-component#491](https://github.com/shlinkio/shlink-web-component/issues/491) Add support for colors in QR code configurator.
* [shlink-web-component#515](https://github.com/shlinkio/shlink-web-component/issues/515) Add support for geolocation redirect conditions, when using Shlink 4.3 or newer.
* [shlink-web-component#514](https://github.com/shlinkio/shlink-web-component/issues/514) Allow filtering short URLs list by domain, when using Shlink 4.3 or newer.
* [shlink-web-component#520](https://github.com/shlinkio/shlink-web-component/issues/520) Allow navigating from domains list to short URLs list filtered by one domain, when using Shlink 4.3 or newer.
* [shlink-web-component#517](https://github.com/shlinkio/shlink-web-component/issues/517) Update list of known domains when a short URL is created with a new domain.
* [shlink-web-component#292](https://github.com/shlinkio/shlink-web-component/issues/292) Add icon in short URLs list indicating if a short URL has redirect rules.
### Changed
* *Nothing*
### Deprecated
* *Nothing*
### Removed
* *Nothing*
### Fixed
* [shlink-web-component#504](https://github.com/shlinkio/shlink-web-component/issues/504) Fix fallback interval not causing new visits to be loaded.
## [4.2.2] - 2024-10-19
### Added
* *Nothing*
### Changed
* Update to `@shlinkio/shlink-frontend-kit` 0.6.0
* Update to `@shlinkio/shlink-web-component` 0.10.1
### Deprecated
* *Nothing*
### Removed
* *Nothing*
### Fixed
* [shlink-web-component#475](https://github.com/shlinkio/shlink-web-component/issues/475) Fix incorrect amount of dots being displayed in line charts when the difference in days/weeks/months is rounded up.
## [4.2.1] - 2024-10-09
### Added
* *Nothing*
### Changed
* *Nothing*
### Deprecated
* *Nothing*
### Removed
* *Nothing*
### Fixed
* [#1325](https://github.com/shlinkio/shlink-web-client/issues/1325) Get dependency on `uuid` package back, as `crypto.randomUUID()` can only be used in [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
* [shlink-web-component#461](https://github.com/shlinkio/shlink-web-component/issues/461) Ensure `shortUrlsList.confirmDeletion` setting is `true` in any case, except when explicitly set to `false`.
* [shlink-web-component#237](https://github.com/shlinkio/shlink-web-component/issues/237) Set darker color for previous period in charts, when light theme is enabled.
* [shlink-web-component#246](https://github.com/shlinkio/shlink-web-component/issues/246) Fix selected date range not reflected in visits comparison date range selector, when selecting it in the line chart via drag'n'drop.
## [4.2.0] - 2024-10-07
### Added
* [shlink-web-component#411](https://github.com/shlinkio/shlink-web-component/issues/411) Add support for `ip-address` redirect conditions when Shlink server is >=4.2

View File

@@ -14,16 +14,13 @@ Because of this, the only actual dependencies are [docker](https://docs.docker.c
The first thing you need to do is fork the repository, and clone it in your local machine.
Then you will have to follow these steps:
Then simply run `docker compose up` and you will have the project exposed in port `3000` (http://localhost:3000).
* Copy the file `docker-compose.override.yml.dist` by also removing the `dist` extension.
* Start-up the project by running `docker compose up`.
Once this is finished, you will have the project exposed in port `3000` (http://localhost:3000).
> The first time the container is created, the project dependencies will be installed and the container may take a bit longer to start.
## Project structure
This project is a [react](https://reactjs.org/) & [redux](https://redux.js.org/) application, built with [typescript](https://www.typescriptlang.org/), which is distributed as a 100% client-side progressive web application.
This project is a [react](https://react.dev/) & [redux](https://redux.js.org/) application, built with [typescript](https://www.typescriptlang.org/), which is distributed as a 100% client-side progressive web application.
This is the basic project structure:
@@ -39,7 +36,7 @@ shlink-web-client
```
* `config`: It contains some configuration scripts, used during testing, linting and building of the project.
* `public`: Will act as the application document root once built, and contains some static assets (favicons, images, etc).
* `public`: Will act as the application document root once built, and contains some static assets (favicons, images, etc.).
* `scripts`: It has some of the CLI scripts used to run tests or building.
* `src`: Contains the main source code of the application, including both web components, SASS stylesheets and files with logic.
* `test`: Contains the project tests.
@@ -48,20 +45,19 @@ shlink-web-client
> Note: The `indocker` shell script is a helper used to run commands inside the docker container.
* `./indocker npm run lint`: Checks coding styles are fulfilled, both in JS/TS files as well as in stylesheets.
* `./indocker npm run lint:js`: Checks coding styles are fulfilled in JS/TS files.
* `./indocker npm run lint:css`: Checks coding styles are fulfilled in stylesheets.
* `./indocker npm run lint:js:fix`: Fixes coding styles in JS/TS files.
* `./indocker npm run lint:css:fix`: Fixes coding styles in stylesheets.
* `./indocker npm run test`: Runs unit tests with Jest.
* `./indocker npm run mutate`: Runs mutation tests with StrykerJS (this command can be very slow).
* `./indocker node --run lint`: Checks coding styles are fulfilled, both in JS/TS files and in stylesheets.
* `./indocker node --run lint:js`: Checks coding styles are fulfilled in JS/TS files.
* `./indocker node --run lint:css`: Checks coding styles are fulfilled in stylesheets.
* `./indocker node --run lint:js:fix`: Fixes coding styles in JS/TS files.
* `./indocker node --run lint:css:fix`: Fixes coding styles in stylesheets.
* `./indocker node --run test`: Runs unit tests with Jest.
## Building the project
The source code in this project cannot be run directly in a web browser, you need to build it first.
* `./indocker npm run build`: Builds the project using a combination of `webpack`, `babel` and `tsc`, generating the final static files. The content is placed in the `build` folder, which is automatically created if it does not exist.
* `./indocker npm run serve:build`: Serves the static files inside the `build` folder in port 5000 (http://localhost:5000). Useful to test the content built with previous command.
* `./indocker node --run run build`: Builds the project for production using [vite](https://vite.dev/), generating the final static files. The content is placed in the `build` folder, which is automatically created if it does not exist.
* `./indocker node --run run preview`: Serves the static files inside the `build` folder in a random port. Useful to test the content built with previous command.
## Pull request process

View File

@@ -1,8 +1,8 @@
FROM node:22.9-alpine as node
FROM node:23.3-alpine AS node
COPY . /shlink-web-client
ARG VERSION="latest"
ENV VERSION ${VERSION}
RUN cd /shlink-web-client && npm ci && npm run build
ENV VERSION=${VERSION}
RUN cd /shlink-web-client && npm ci && node --run build
FROM nginxinc/nginx-unprivileged:1.27-alpine
ARG UID=101

View File

@@ -7,8 +7,7 @@
[![GitHub license](https://img.shields.io/github/license/shlinkio/shlink-web-client.svg?style=flat-square)](https://github.com/shlinkio/shlink-web-client/blob/main/LICENSE)
[![Mastodon](https://img.shields.io/mastodon/follow/109329425426175098?color=%236364ff&domain=https%3A%2F%2Ffosstodon.org&label=follow&logo=mastodon&logoColor=white&style=flat-square)](https://fosstodon.org/@shlinkio)
[![Twitter](https://img.shields.io/badge/follow-shlinkio-blue.svg?style=flat-square&logo=x&color=black)](https://twitter.com/shlinkio)
[![Bluesky](https://img.shields.io/badge/follow-shlinkio-0285FF.svg?style=flat-square&logo=bluesky&logoColor=white)](https://bsky.app/profile/shlinkio.bsky.social)
[![Bluesky](https://img.shields.io/badge/follow-shlinkio-0285FF.svg?style=flat-square&logo=bluesky&logoColor=white)](https://bsky.app/profile/shlink.io)
[![Paypal Donate](https://img.shields.io/badge/Donate-paypal-blue.svg?style=flat-square&logo=paypal&colorA=cccccc)](https://slnk.to/donate)
A ReactJS-based progressive web application for [Shlink](https://shlink.io).

2
dist/.gitignore vendored
View File

@@ -1,2 +0,0 @@
*
!.gitignore

View File

@@ -1,7 +0,0 @@
services:
shlink_web_client_node:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
- ./home:/home/alejandro

View File

@@ -1,7 +1,8 @@
services:
shlink_web_client_node:
container_name: shlink_web_client_node
image: node:22.3-alpine
user: 1000:1000 # With this, files created via `indocker` script will belong to the host user
image: node:22.10-alpine
command: /bin/sh -c "cd /home/shlink/www && npm install && npm run start"
volumes:
- ./:/home/shlink/www

9873
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,35 +7,35 @@
"license": "MIT",
"type": "module",
"scripts": {
"lint": "npm run lint:css && npm run lint:js",
"lint": "node --run lint:css && node --run lint:js",
"lint:css": "stylelint src/*.scss src/**/*.scss",
"lint:js": "eslint src test config/test",
"lint:fix": "npm run lint:css:fix && npm run lint:js:fix",
"lint:css:fix": "npm run lint:css -- --fix",
"lint:js:fix": "npm run lint:js -- --fix",
"lint:fix": "node --run lint:css:fix && node --run lint:js:fix",
"lint:css:fix": "node --run lint:css -- --fix",
"lint:js:fix": "node --run lint:js -- --fix",
"types": "tsc",
"start": "vite serve --host=0.0.0.0",
"preview": "vite preview --host=0.0.0.0",
"build": "npm run types && vite build && node scripts/replace-version.mjs",
"build:dist": "npm run build && node scripts/create-dist-file.mjs",
"build": "node --run types && vite build && node scripts/replace-version.mjs",
"build:dist": "node --run build && node scripts/create-dist-file.mjs",
"test": "vitest run --run",
"test:watch": "vitest --watch",
"test:ci": "npm run test -- --coverage",
"test:verbose": "npm run test -- --verbose"
"test:ci": "node --run test -- --coverage",
"test:verbose": "node --run test -- --verbose"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.6.0",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-regular-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/fontawesome-free": "^6.7.1",
"@fortawesome/fontawesome-svg-core": "^6.7.1",
"@fortawesome/free-brands-svg-icons": "^6.7.1",
"@fortawesome/free-regular-svg-icons": "^6.7.1",
"@fortawesome/free-solid-svg-icons": "^6.7.1",
"@fortawesome/react-fontawesome": "^0.2.2",
"@json2csv/plainjs": "^7.0.6",
"@reduxjs/toolkit": "^2.2.7",
"@reduxjs/toolkit": "^2.4.0",
"@shlinkio/data-manipulation": "^1.0.3",
"@shlinkio/shlink-frontend-kit": "^0.5.2",
"@shlinkio/shlink-js-sdk": "^1.2.0",
"@shlinkio/shlink-web-component": "^0.8.0",
"@shlinkio/shlink-frontend-kit": "^0.6.0",
"@shlinkio/shlink-js-sdk": "^1.3.0",
"@shlinkio/shlink-web-component": "^0.11.0",
"bootstrap": "5.2.3",
"bottlejs": "^2.0.1",
"clsx": "^2.1.1",
@@ -46,44 +46,44 @@
"react-dom": "^18.3.1",
"react-external-link": "^2.3.1",
"react-redux": "^9.1.2",
"react-router-dom": "^6.26.2",
"react-router-dom": "^6.28.0",
"reactstrap": "^9.2.3",
"redux-localstorage-simple": "^2.5.1",
"workbox-core": "^7.1.0",
"workbox-expiration": "^7.1.0",
"workbox-precaching": "^7.1.0",
"workbox-routing": "^7.1.0",
"workbox-strategies": "^7.1.0"
"workbox-core": "^7.3.0",
"workbox-expiration": "^7.3.0",
"workbox-precaching": "^7.3.0",
"workbox-routing": "^7.3.0",
"workbox-strategies": "^7.3.0"
},
"devDependencies": {
"@shlinkio/eslint-config-js-coding-standard": "~3.1.0",
"@shlinkio/eslint-config-js-coding-standard": "~3.2.1",
"@shlinkio/stylelint-config-css-coding-standard": "~1.1.1",
"@stylistic/eslint-plugin": "^2.9.0",
"@testing-library/jest-dom": "^6.5.0",
"@stylistic/eslint-plugin": "^2.11.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@total-typescript/shoehorn": "^0.1.2",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.3.2",
"@vitest/coverage-v8": "^2.1.2",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/coverage-v8": "^2.1.6",
"adm-zip": "^0.5.16",
"axe-core": "^4.10.0",
"axe-core": "^4.10.2",
"chalk": "^5.3.0",
"eslint": "^8.57.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint": "^9.16.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"history": "^5.3.0",
"jsdom": "^25.0.1",
"sass": "^1.79.4",
"sass": "^1.81.0",
"stylelint": "^15.11.0",
"typescript": "^5.6.2",
"typescript-eslint": "^8.8.0",
"vite": "^5.4.8",
"vite-plugin-pwa": "^0.20.5",
"typescript": "^5.7.2",
"typescript-eslint": "^8.16.0",
"vite": "^6.0.1",
"vite-plugin-pwa": "^0.21.1",
"vitest": "^2.0.2"
},
"browserslist": [

View File

@@ -4,6 +4,8 @@ set -e
ME=$(basename $0)
# In order to allow people to pre-configure a server in their shlink-web-client instance via env vars, this function
# dumps a servers.json file based on the values provided via env vars
setup_single_shlink_server() {
[ -n "$SHLINK_SERVER_URL" ] || return 0
[ -n "$SHLINK_SERVER_API_KEY" ] || return 0

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.app-container {
height: 100%;

View File

@@ -50,8 +50,8 @@ const App: FCWithDeps<AppProps, AppDeps> = (
const isHome = location.pathname === '/';
useEffect(() => {
// Try to fetch the remote servers if the list is empty at first
// We use a ref because we don't care if the servers list becomes empty later
// Try to fetch the remote servers if the list is empty during first render.
// We use a ref because we don't care if the servers list becomes empty later.
if (Object.keys(initialServers.current).length === 0) {
fetchServers();
}
@@ -66,7 +66,7 @@ const App: FCWithDeps<AppProps, AppDeps> = (
<MainHeader />
<div className="app">
<div className={clsx('shlink-wrapper', { 'd-flex d-md-block align-items-center': isHome })}>
<div className={clsx('shlink-wrapper', { 'd-flex align-items-center pt-3': isHome })}>
<Routes>
<Route index element={<Home />} />
<Route path="/settings/*" element={<Settings />} />

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../utils/mixins/horizontal-align';
.app-update-banner.app-update-banner {

View File

@@ -1,50 +1,7 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../utils/mixins/vertical-align';
$mainCardWidth: 720px;
$fiveColumnsSize: .4167; // 12 / 5 -> Can't use "/" operator in latest dart-sass
.home {
position: relative;
padding-top: 15px;
width: 100%;
@media (min-width: $mdMin) {
padding-top: 0;
height: calc(100vh - #{$headerHeight} - #{($footer-height + $footer-margin)});
}
}
.home__logo-wrapper {
padding: 1.5rem !important;
height: 100% !important;
min-height: 300px;
}
.home__logo {
@include vertical-align();
width: calc(#{$mainCardWidth * $fiveColumnsSize} - 3rem);
}
.home__main-card {
margin: 0 auto;
max-width: $mainCardWidth;
@media (min-width: $mdMin) {
@include vertical-align();
}
}
.home__title-wrapper {
padding: 1.5rem !important;
border-bottom: 1px solid var(--border-color);
}
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.home__title {
text-align: center;
font-size: 1.75rem;
margin: 0;
@media (min-width: $mdMin) {
font-size: 2.2rem;

View File

@@ -1,9 +1,10 @@
import { faExternalLinkAlt, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { clsx } from 'clsx';
import { useEffect } from 'react';
import { ExternalLink } from 'react-external-link';
import { Link, useNavigate } from 'react-router-dom';
import { Card, Row } from 'reactstrap';
import { Card } from 'reactstrap';
import type { ServersMap } from '../servers/data';
import { ServersListGroup } from '../servers/ServersListGroup';
import { ShlinkLogo } from './img/ShlinkLogo';
@@ -27,33 +28,36 @@ export const Home = ({ servers }: HomeProps) => {
}, [serversList, navigate]);
return (
<div className="home">
<Card className="home__main-card">
<Row className="g-0">
<div className="col-md-5 d-none d-md-block">
<div className="home__logo-wrapper">
<div className="home__logo">
<ShlinkLogo />
</div>
<div className="w-100">
<Card className="mx-auto" style={{ maxWidth: '720px' }}>
<div className="d-flex flex-column flex-md-row">
<div className="p-4 d-none d-md-flex align-items-center" style={{ width: '40%' }}>
<div className="w-100">
<ShlinkLogo />
</div>
</div>
<div className="col-md-7 home__servers-container">
<div className="home__title-wrapper">
<h1 className="home__title">Welcome!</h1>
</div>
<div className="home__servers-container flex-grow-1">
<h1
className={clsx('home__title p-4 text-center m-0', { 'border-bottom': !hasServers })}
style={{ borderColor: 'var(--border-color) !important' }}
>
Welcome!
</h1>
<ServersListGroup embedded servers={serversList}>
{!hasServers && (
<div className="p-4 text-center">
<p className="mb-5">This application will help you manage your Shlink servers.</p>
<p>
<div className="p-4 text-center d-flex flex-column gap-5">
<p className="mb-0">This application will help you manage your Shlink servers.</p>
<p className="mb-0">
<Link to="/server/create" className="btn btn-outline-primary btn-lg me-2">
<FontAwesomeIcon icon={faPlus} /> <span className="ms-1">Add a server</span>
<FontAwesomeIcon icon={faPlus}/> <span className="ms-1">Add a server</span>
</Link>
</p>
<p className="mb-0 mt-5">
<p className="mb-0">
<ExternalLink href="https://shlink.io/documentation">
<small>
<span className="me-1">Learn more about Shlink</span> <FontAwesomeIcon icon={faExternalLinkAlt} />
<span className="me-2">Learn more about Shlink</span>
<FontAwesomeIcon icon={faExternalLinkAlt}/>
</small>
</ExternalLink>
</p>
@@ -61,7 +65,7 @@ export const Home = ({ servers }: HomeProps) => {
)}
</ServersListGroup>
</div>
</Row>
</div>
</Card>
</div>
);

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.main-header.main-header {
color: white;

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.no-menu-wrapper {
padding: 15px 0 0;

View File

@@ -1,6 +1,11 @@
import { clsx } from 'clsx';
import type { FC, PropsWithChildren } from 'react';
import './NoMenuLayout.scss';
export const NoMenuLayout: FC<PropsWithChildren> = ({ children }) => (
<div className="no-menu-wrapper container-xl">{children}</div>
export type NoMenuLayoutProps = PropsWithChildren & {
className?: string;
};
export const NoMenuLayout: FC<NoMenuLayoutProps> = ({ children, className }) => (
<div className={clsx('no-menu-wrapper container-xl', className)}>{children}</div>
);

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.shlink-versions-container--with-sidebar {
margin-left: 0;

View File

@@ -20,7 +20,6 @@ export function componentFactory<Deps, CompType = Omit<Partial<Deps>, keyof FC>>
console.error(`[Debug] Could not find "${dep as string}" dependency in container`);
}
// eslint-disable-next-line no-param-reassign
Component[dep] = resolvedDependency;
});

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base'; // Before bootstrap stylesheet. Includes SASS var overrides
@import 'node_modules/bootstrap/scss/bootstrap.scss';
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/index'; // After bootstrap. Includes CSS overwrites
@import 'node_modules/@shlinkio/shlink-web-component/dist/index';
@import '../node_modules/@shlinkio/shlink-frontend-kit/dist/base'; // Before bootstrap stylesheet. Includes SASS var overrides
@import '../node_modules/bootstrap/scss/bootstrap.scss';
@import '../node_modules/@shlinkio/shlink-frontend-kit/dist/index'; // After bootstrap. Includes CSS overwrites
@import '../node_modules/@shlinkio/shlink-web-component/dist/index';

View File

@@ -10,7 +10,7 @@ import './index.scss';
const store = setUpStore(container);
const { App, ScrollToTop, ErrorHandler, appUpdateAvailable } = container;
createRoot(document.getElementById('root')!).render( // eslint-disable-line @typescript-eslint/no-non-null-assertion
createRoot(document.getElementById('root')!).render(
<Provider store={store}>
<BrowserRouter basename={pack.homepage}>
<ErrorHandler>

View File

@@ -1,7 +1,7 @@
import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
import { Result, useToggle } from '@shlinkio/shlink-frontend-kit';
import type { FC } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button } from 'reactstrap';
import { NoMenuLayout } from '../common/NoMenuLayout';
@@ -9,6 +9,7 @@ import type { FCWithDeps } from '../container/utils';
import { componentFactory, useDependencies } from '../container/utils';
import { useGoBack } from '../utils/helpers/hooks';
import type { ServerData, ServersMap, ServerWithId } from './data';
import { ensureUniqueIds } from './helpers';
import { DuplicatedServersModal } from './helpers/DuplicatedServersModal';
import type { ImportServersBtnProps } from './helpers/ImportServersBtn';
import { ServerForm } from './helpers/ServerForm';
@@ -43,32 +44,29 @@ const CreateServer: FCWithDeps<CreateServerProps, CreateServerDeps> = ({ servers
const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
const [isConfirmModalOpen, toggleConfirmModal] = useToggle();
const [serverData, setServerData] = useState<ServerData>();
const saveNewServer = useCallback((theServerData: ServerData) => {
const id = crypto.randomUUID();
const saveNewServer = useCallback((newServerData: ServerData) => {
const [newServerWithUniqueId] = ensureUniqueIds(servers, [newServerData]);
createServers([{ ...theServerData, id }]);
navigate(`/server/${id}`);
}, [createServers, navigate]);
useEffect(() => {
if (!serverData) {
return;
}
createServers([newServerWithUniqueId]);
navigate(`/server/${newServerWithUniqueId.id}`);
}, [createServers, navigate, servers]);
const onSubmit = useCallback((newServerData: ServerData) => {
setServerData(newServerData);
const serverExists = Object.values(servers).some(
({ url, apiKey }) => serverData?.url === url && serverData?.apiKey === apiKey,
({ url, apiKey }) => newServerData.url === url && newServerData.apiKey === apiKey,
);
if (serverExists) {
toggleConfirmModal();
} else {
saveNewServer(serverData);
saveNewServer(newServerData);
}
}, [saveNewServer, serverData, servers, toggleConfirmModal]);
}, [saveNewServer, servers, toggleConfirmModal]);
return (
<NoMenuLayout>
<ServerForm title={<h5 className="mb-0">Add new server</h5>} onSubmit={setServerData}>
<ServerForm title={<h5 className="mb-0">Add new server</h5>} onSubmit={onSubmit}>
{!hasServers && (
<ImportServersBtn tooltipPlacement="top" onImport={setServersImported} onImportError={setErrorImporting} />
)}

View File

@@ -3,9 +3,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
import { Result, SearchField, SimpleCard } from '@shlinkio/shlink-frontend-kit';
import type { FC } from 'react';
import { useEffect, useState } from 'react';
import { useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { Button, Row } from 'reactstrap';
import { Button } from 'reactstrap';
import { NoMenuLayout } from '../common/NoMenuLayout';
import type { FCWithDeps } from '../container/utils';
import { componentFactory, useDependencies } from '../container/utils';
@@ -34,37 +34,32 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
useTimeoutToggle,
ManageServersRow,
} = useDependencies(ManageServers);
const allServers = Object.values(servers);
const [serversList, setServersList] = useState(allServers);
const filterServers = (searchTerm: string) => setServersList(
allServers.filter(({ name, url }) => `${name} ${url}`.toLowerCase().match(searchTerm.toLowerCase())),
const [searchTerm, setSearchTerm] = useState('');
const allServers = useMemo(() => Object.values(servers), [servers]);
const filteredServers = useMemo(
() => allServers.filter(({ name, url }) => `${name} ${url}`.toLowerCase().match(searchTerm.toLowerCase())),
[allServers, searchTerm],
);
const hasAutoConnect = serversList.some(({ autoConnect }) => !!autoConnect);
const hasAutoConnect = allServers.some(({ autoConnect }) => !!autoConnect);
const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
useEffect(() => {
setServersList(Object.values(servers));
}, [servers]);
return (
<NoMenuLayout>
<SearchField className="mb-3" onChange={filterServers} />
<NoMenuLayout className="d-flex flex-column gap-3">
<SearchField onChange={setSearchTerm} />
<Row className="mb-3">
<div className="col-md-6 d-flex d-md-block mb-2 mb-md-0">
<div className="d-flex flex-column flex-md-row gap-2">
<div className="d-flex gap-2">
<ImportServersBtn className="flex-fill" onImportError={setErrorImporting}>Import servers</ImportServersBtn>
{allServers.length > 0 && (
<Button outline className="ms-2 flex-fill" onClick={async () => serversExporter.exportServers()}>
{filteredServers.length > 0 && (
<Button outline className="flex-fill" onClick={async () => serversExporter.exportServers()}>
<FontAwesomeIcon icon={exportIcon} fixedWidth /> Export servers
</Button>
)}
</div>
<div className="col-md-6 text-md-end d-flex d-md-block">
<Button outline color="primary" className="flex-fill" tag={Link} to="/server/create">
<FontAwesomeIcon icon={plusIcon} fixedWidth /> Add a server
</Button>
</div>
</Row>
<Button outline color="primary" className="ms-md-auto" tag={Link} to="/server/create">
<FontAwesomeIcon icon={plusIcon} fixedWidth /> Add a server
</Button>
</div>
<SimpleCard>
<table className="table table-hover responsive-table mb-0">
@@ -77,8 +72,8 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
</tr>
</thead>
<tbody>
{!serversList.length && <tr className="text-center"><td colSpan={4}>No servers found.</td></tr>}
{serversList.map((server) => (
{!filteredServers.length && <tr className="text-center"><td colSpan={4}>No servers found.</td></tr>}
{filteredServers.map((server) => (
<ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} />
))}
</tbody>
@@ -86,7 +81,7 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
</SimpleCard>
{errorImporting && (
<div className="mt-3">
<div>
<Result type="error">The servers could not be imported. Make sure the format is correct.</Result>
</div>
)}

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../utils/mixins/vertical-align';
@import '../utils/mixins/thin-scroll';

View File

@@ -6,9 +6,10 @@ import { useCallback, useRef, useState } from 'react';
import { Button, UncontrolledTooltip } from 'reactstrap';
import type { FCWithDeps } from '../../container/utils';
import { componentFactory, useDependencies } from '../../container/utils';
import type { ServerData, ServersMap } from '../data';
import type { ServerData, ServersMap, ServerWithId } from '../data';
import type { ServersImporter } from '../services/ServersImporter';
import { DuplicatedServersModal } from './DuplicatedServersModal';
import { dedupServers, ensureUniqueIds } from './index';
export type ImportServersBtnProps = PropsWithChildren<{
onImport?: () => void;
@@ -18,7 +19,7 @@ export type ImportServersBtnProps = PropsWithChildren<{
}>;
type ImportServersBtnConnectProps = ImportServersBtnProps & {
createServers: (servers: ServerData[]) => void;
createServers: (servers: ServerWithId[]) => void;
servers: ServersMap;
};
@@ -26,9 +27,6 @@ type ImportServersBtnDeps = {
ServersImporter: ServersImporter
};
const serversInclude = (servers: ServerData[], { url, apiKey }: ServerData) =>
servers.some((server) => server.url === url && server.apiKey === apiKey);
const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBtnDeps> = ({
createServers,
servers,
@@ -43,44 +41,45 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
const [duplicatedServers, setDuplicatedServers] = useState<ServerData[]>([]);
const [isModalOpen,, showModal, hideModal] = useToggle();
const serversToCreate = useRef<ServerData[]>([]);
const create = useCallback((serversData: ServerData[]) => {
const importedServersRef = useRef<ServerWithId[]>([]);
const newServersRef = useRef<ServerWithId[]>([]);
const create = useCallback((serversData: ServerWithId[]) => {
createServers(serversData);
onImport();
}, [createServers, onImport]);
const onFile = useCallback(
async ({ target }: ChangeEvent<HTMLInputElement>) =>
serversImporter.importServersFromFile(target.files?.[0])
.then((newServers) => {
serversToCreate.current = newServers;
.then((importedServers) => {
const { duplicatedServers, newServers } = dedupServers(servers, importedServers);
const existingServers = Object.values(servers);
const dupServers = newServers.filter((server) => serversInclude(existingServers, server));
const hasDuplicatedServers = !!dupServers.length;
importedServersRef.current = ensureUniqueIds(servers, importedServers);
newServersRef.current = ensureUniqueIds(servers, newServers);
if (!hasDuplicatedServers) {
create(newServers);
if (duplicatedServers.length === 0) {
create(importedServersRef.current);
} else {
setDuplicatedServers(dupServers);
setDuplicatedServers(duplicatedServers);
showModal();
}
})
.then(() => {
// Reset input after processing file
(target as { value: string | null }).value = null; // eslint-disable-line no-param-reassign
// Reset file input after processing file
(target as { value: string | null }).value = null;
})
.catch(onImportError),
[create, onImportError, servers, serversImporter, showModal],
);
const createAllServers = useCallback(() => {
create(serversToCreate.current);
create(importedServersRef.current);
hideModal();
}, [create, hideModal, serversToCreate]);
}, [create, hideModal]);
const createNonDuplicatedServers = useCallback(() => {
create(serversToCreate.current.filter((server) => !serversInclude(duplicatedServers, server)));
create(newServersRef.current);
hideModal();
}, [create, duplicatedServers, hideModal]);
}, [create, hideModal]);
return (
<>
@@ -91,7 +90,15 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
You can create servers by importing a CSV file with <b>name</b>, <b>apiKey</b> and <b>url</b> columns.
</UncontrolledTooltip>
<input type="file" accept=".csv" className="d-none" ref={ref} onChange={onFile} aria-hidden />
<input
type="file"
accept=".csv"
className="d-none"
aria-hidden
ref={ref}
onChange={onFile}
data-testid="csv-file-input"
/>
<DuplicatedServersModal
isOpen={isModalOpen}

View File

@@ -1,4 +1,4 @@
@import 'node_modules/@shlinkio/shlink-frontend-kit/dist/base';
@import '../../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.server-error__container {
text-align: center;

View File

@@ -1,6 +1,6 @@
import { InputFormGroup, SimpleCard } from '@shlinkio/shlink-frontend-kit';
import type { FC, PropsWithChildren, ReactNode } from 'react';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { handleEventPreventingDefault } from '../../utils/utils';
import type { ServerData } from '../data';
@@ -11,19 +11,11 @@ type ServerFormProps = PropsWithChildren<{
}>;
export const ServerForm: FC<ServerFormProps> = ({ onSubmit, initialValues, children, title }) => {
const [name, setName] = useState('');
const [url, setUrl] = useState('');
const [apiKey, setApiKey] = useState('');
const [name, setName] = useState(initialValues?.name ?? '');
const [url, setUrl] = useState(initialValues?.url ?? '');
const [apiKey, setApiKey] = useState(initialValues?.apiKey ?? '');
const handleSubmit = handleEventPreventingDefault(() => onSubmit({ name, url, apiKey }));
useEffect(() => {
if (initialValues) {
setName(initialValues.name);
setUrl(initialValues.url);
setApiKey(initialValues.apiKey);
}
}, [initialValues]);
return (
<form className="server-form" name="serverForm" onSubmit={handleSubmit}>
<SimpleCard className="mb-3" title={title}>

View File

@@ -0,0 +1,85 @@
import { groupBy } from '@shlinkio/data-manipulation';
import type { ServerData, ServersMap, ServerWithId } from '../data';
/**
* Builds a potentially unique ID for a server, based on concatenating their name and the hostname of their domain, all
* in lowercase and replacing invalid URL characters with hyphens.
*/
function idForServer(server: ServerData): string {
let urlSegment = server.url;
try {
const { host, pathname } = new URL(urlSegment);
urlSegment = host;
// Remove leading slash from pathname
const normalizedPathname = pathname.substring(1);
// Include pathname in the ID, if not empty
if (normalizedPathname.length > 0) {
urlSegment = `${urlSegment} ${normalizedPathname}`;
}
} catch {
// If the server URL is not valid, use the value as is
}
return `${server.name} ${urlSegment}`.toLowerCase().replace(/[^a-zA-Z0-9-_.~]/g, '-');
}
export function serversListToMap(servers: ServerWithId[]): ServersMap {
const serversMap: ServersMap = {};
servers.forEach((server) => {
serversMap[server.id] = server;
});
return serversMap;
}
const serversInclude = (serversList: ServerData[], { url, apiKey }: ServerData) =>
serversList.some((server) => server.url === url && server.apiKey === apiKey);
export type DedupServersResult = {
/** Servers which already exist in the reference list */
duplicatedServers: ServerData[];
/** Servers which are new based on a reference list */
newServers: ServerData[];
};
/**
* Given a list of new servers, checks which of them already exist in a servers map, and which don't
*/
export function dedupServers(servers: ServersMap, serversToAdd: ServerData[]): DedupServersResult {
const serversList = Object.values(servers);
const { duplicatedServers = [], newServers = [] } = groupBy(
serversToAdd,
(server) => serversInclude(serversList, server) ? 'duplicatedServers' : 'newServers',
);
return { duplicatedServers, newServers };
}
/**
* Given a servers map and a list of servers, return the same list of servers but all with an ID, ensuring the ID is
* unique both among all those servers and existing ones
*/
export function ensureUniqueIds(existingServers: ServersMap, serversList: ServerData[]): ServerWithId[] {
const existingIds = new Set(Object.keys(existingServers));
const serversWithId: ServerWithId[] = [];
serversList.forEach((server) => {
const baseId = idForServer(server);
let id = baseId;
let iterations = 1;
while (existingIds.has(id)) {
id = `${baseId}-${iterations}`;
iterations++;
}
serversWithId.push({ ...server, id });
// Add this server's ID to the list, so that it is taken into consideration for the next ones
existingIds.add(id);
});
return serversWithId;
}

View File

@@ -1,11 +1,14 @@
import type { HttpClient } from '@shlinkio/shlink-js-sdk';
import pack from '../../../package.json';
import { createAsyncThunk } from '../../utils/helpers/redux';
import type { ServerData } from '../data';
import { hasServerData } from '../data';
import { ensureUniqueIds } from '../helpers';
import { createServers } from './servers';
const responseToServersList = (data: any): ServerData[] => (Array.isArray(data) ? data.filter(hasServerData) : []);
const responseToServersList = (data: any) => ensureUniqueIds(
{},
(Array.isArray(data) ? data.filter(hasServerData) : []),
);
export const fetchServers = (httpClient: HttpClient) => createAsyncThunk(
'shlink/remoteServers/fetchServers',

View File

@@ -1,6 +1,7 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import type { ServerData, ServersMap, ServerWithId } from '../data';
import { serversListToMap } from '../helpers';
interface EditServer {
serverId: string;
@@ -14,19 +15,6 @@ interface SetAutoConnect {
const initialState: ServersMap = {};
const serverWithId = (server: ServerWithId | ServerData): ServerWithId => {
if ('id' in server) {
return server;
}
return { ...server, id: crypto.randomUUID() };
};
const serversListToMap = (servers: ServerWithId[]): ServersMap => servers.reduce<ServersMap>(
(acc, server) => ({ ...acc, [server.id]: server }),
{},
);
export const { actions, reducer } = createSlice({
name: 'shlink/servers',
initialState,
@@ -69,10 +57,7 @@ export const { actions, reducer } = createSlice({
},
},
createServers: {
prepare: (servers: ServerData[]) => {
const payload = serversListToMap(servers.map(serverWithId));
return { payload };
},
prepare: (servers: ServerWithId[]) => ({ payload: serversListToMap(servers) }),
reducer: (state, { payload: newServers }: PayloadAction<ServersMap>) => ({ ...state, ...newServers }),
},
},

View File

@@ -22,7 +22,7 @@ export class ServersExporter {
saveCsv(this.window, csv, SERVERS_FILENAME);
} catch (e) {
// FIXME Handle error
console.error(e); // eslint-disable-line no-console
console.error(e);
}
};
}

View File

@@ -1,6 +1,5 @@
import type { ShlinkState } from '../../container/types';
/* eslint-disable no-param-reassign */
export const migrateDeprecatedSettings = (state: Partial<ShlinkState>): Partial<ShlinkState> => {
if (!state.settings) {
return state;

View File

@@ -1,5 +0,0 @@
import type { FC, PropsWithChildren } from 'react';
export const FormText: FC<PropsWithChildren<unknown>> = ({ children }) => (
<small className="form-text text-muted d-block">{children}</small>
);

View File

@@ -39,7 +39,7 @@ describe('ShlinkApiClientBuilder', () => {
const apiKey = 'apiKey';
const apiClient = buildShlinkApiClient(fromPartial({}))(server({ url, apiKey }));
expect(apiClient['serverInfo'].baseUrl).toEqual(url); // eslint-disable-line @typescript-eslint/dot-notation
expect(apiClient['serverInfo'].apiKey).toEqual(apiKey); // eslint-disable-line @typescript-eslint/dot-notation
expect(apiClient['serverInfo'].baseUrl).toEqual(url);
expect(apiClient['serverInfo'].apiKey).toEqual(apiKey);
});
});

View File

@@ -56,7 +56,7 @@ describe('<App />', () => {
it.each([
['/foo', 'shlink-wrapper'],
['/bar', 'shlink-wrapper'],
['/', 'shlink-wrapper d-flex d-md-block align-items-center'],
['/', 'shlink-wrapper d-flex align-items-center pt-3'],
])('renders expected classes on shlink-wrapper based on current pathname', async (pathname, expectedClasses) => {
const { container } = await setUp(pathname);
const shlinkWrapper = container.querySelector('.shlink-wrapper');

View File

@@ -1,6 +1,6 @@
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { screen, waitFor } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import type { ServersMap, ServerWithId } from '../../../src/servers/data';
import type { ServerData, ServersMap, ServerWithId } from '../../../src/servers/data';
import type {
ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
import { ImportServersBtnFactory } from '../../../src/servers/helpers/ImportServersBtn';
@@ -9,6 +9,7 @@ import { checkAccessibility } from '../../__helpers__/accessibility';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<ImportServersBtn />', () => {
const csvFile = new File([''], 'servers.csv', { type: 'text/csv' });
const onImportMock = vi.fn();
const createServersMock = vi.fn();
const importServersFromFile = vi.fn().mockResolvedValue([]);
@@ -54,34 +55,43 @@ describe('<ImportServersBtn />', () => {
});
it('imports servers when file input changes', async () => {
const { container } = setUp();
const input = container.querySelector('[type=file]');
const { user } = setUp();
const input = screen.getByTestId('csv-file-input');
await user.upload(input, csvFile);
if (input) {
fireEvent.change(input, { target: { files: [''] } });
}
expect(importServersFromFile).toHaveBeenCalledTimes(1);
await waitFor(() => expect(createServersMock).toHaveBeenCalledTimes(1));
expect(createServersMock).toHaveBeenCalledTimes(1);
});
it.each([
['Save anyway', true],
['Discard', false],
])('creates expected servers depending on selected option in modal', async (btnName, savesDuplicatedServers) => {
const existingServer = fromPartial<ServerWithId>({ id: 'abc', url: 'existingUrl', apiKey: 'existingApiKey' });
const newServer = fromPartial<ServerWithId>({ url: 'newUrl', apiKey: 'newApiKey' });
const { container, user } = setUp({}, { abc: existingServer });
const input = container.querySelector('[type=file]');
{ btnName: 'Save anyway',savesDuplicatedServers: true },
{ btnName: 'Discard', savesDuplicatedServers: false },
])('creates expected servers depending on selected option in modal', async ({ btnName, savesDuplicatedServers }) => {
const existingServerData: ServerData = {
name: 'existingServer',
url: 'http://s.test/existingUrl',
apiKey: 'existingApiKey',
};
const existingServer: ServerWithId = {
...existingServerData,
id: 'existingserver-s.test',
};
const newServer: ServerData = { name: 'newServer', url: 'http://s.test/newUrl', apiKey: 'newApiKey' };
const { user } = setUp({}, { [existingServer.id]: existingServer });
importServersFromFile.mockResolvedValue([existingServer, newServer]);
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
if (input) {
fireEvent.change(input, { target: { files: [''] } });
}
await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument());
await user.upload(screen.getByTestId('csv-file-input'), csvFile);
expect(screen.getByRole('dialog')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: btnName }));
expect(createServersMock).toHaveBeenCalledWith(savesDuplicatedServers ? [existingServer, newServer] : [newServer]);
expect(createServersMock).toHaveBeenCalledWith(
savesDuplicatedServers
? [expect.objectContaining(existingServerData), expect.objectContaining(newServer)]
: [expect.objectContaining(newServer)],
);
expect(onImportMock).toHaveBeenCalledTimes(1);
});
});

View File

@@ -0,0 +1,69 @@
import { fromPartial } from '@total-typescript/shoehorn';
import type { ServersMap } from '../../../src/servers/data';
import { ensureUniqueIds } from '../../../src/servers/helpers';
describe('index', () => {
describe('ensureUniqueIds', () => {
const servers: ServersMap = {
'the-name-example.com': fromPartial({}),
'another-name-example.com': fromPartial({}),
'short-domain-s.test': fromPartial({}),
};
it('returns expected list of servers when existing IDs conflict', () => {
const result = ensureUniqueIds(servers, [
fromPartial({ name: 'The name', url: 'https://example.com' }),
fromPartial({ name: 'Short domain', url: 'https://s.test' }),
fromPartial({ name: 'The name', url: 'https://example.com' }),
]);
expect(result).toEqual([
expect.objectContaining({ id: 'the-name-example.com-1' }),
expect.objectContaining({ id: 'short-domain-s.test-1' }),
expect.objectContaining({ id: 'the-name-example.com-2' }),
]);
});
it('returns expected list of servers when IDs conflict in provided list of servers', () => {
const result = ensureUniqueIds(servers, [
fromPartial({ name: 'Foo', url: 'https://example.com' }),
fromPartial({ name: 'Bar', url: 'https://s.test' }),
fromPartial({ name: 'Foo', url: 'https://example.com' }),
fromPartial({ name: 'Baz', url: 'https://s.test' }),
]);
expect(result).toEqual([
expect.objectContaining({ id: 'foo-example.com' }),
expect.objectContaining({ id: 'bar-s.test' }),
expect.objectContaining({ id: 'foo-example.com-1' }),
expect.objectContaining({ id: 'baz-s.test' }),
]);
});
it('includes server paths when not empty', () => {
const result = ensureUniqueIds({}, [
fromPartial({ name: 'Foo', url: 'https://example.com' }),
fromPartial({ name: 'Bar', url: 'https://s.test/some/path' }),
fromPartial({ name: 'Baz', url: 'https://s.test/some/other-path-here/123' }),
]);
expect(result).toEqual([
expect.objectContaining({ id: 'foo-example.com' }),
expect.objectContaining({ id: 'bar-s.test-some-path' }),
expect.objectContaining({ id: 'baz-s.test-some-other-path-here-123' }),
]);
});
it('uses server URL verbatim when it is not a valid URL', () => {
const result = ensureUniqueIds({}, [
fromPartial({ name: 'Foo', url: 'invalid' }),
fromPartial({ name: 'Bar', url: 'this is not a URL' }),
]);
expect(result).toEqual([
expect.objectContaining({ id: 'foo-invalid' }),
expect.objectContaining({ id: 'bar-this-is-not-a-url' }),
]);
});
});
});

View File

@@ -9,74 +9,76 @@ describe('remoteServersReducer', () => {
const httpClient = fromPartial<HttpClient>({ jsonRequest });
it.each([
[
[
{
serversArray: [
{
id: '111',
name: 'acel.me from servers.json',
url: 'https://acel.me',
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
},
{
id: '222',
name: 'Local from servers.json',
url: 'http://localhost:8000',
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
},
],
{
111: {
id: '111',
expectedNewServers: {
'acel.me-from-servers.json-acel.me': {
id: 'acel.me-from-servers.json-acel.me',
name: 'acel.me from servers.json',
url: 'https://acel.me',
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
},
222: {
id: '222',
'local-from-servers.json-localhost-8000': {
id: 'local-from-servers.json-localhost-8000',
name: 'Local from servers.json',
url: 'http://localhost:8000',
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
},
},
],
[
[
},
{
serversArray: [
{
id: '111',
name: 'acel.me from servers.json',
url: 'https://acel.me',
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
},
{
id: '222',
name: 'Invalid',
},
{
id: '333',
name: 'Local from servers.json',
url: 'http://localhost:8000',
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
},
],
{
111: {
id: '111',
expectedNewServers: {
'acel.me-from-servers.json-acel.me': {
id: 'acel.me-from-servers.json-acel.me',
name: 'acel.me from servers.json',
url: 'https://acel.me',
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
},
333: {
id: '333',
'local-from-servers.json-localhost-8000': {
id: 'local-from-servers.json-localhost-8000',
name: 'Local from servers.json',
url: 'http://localhost:8000',
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
},
},
],
['<html></html>', {}],
[{}, {}],
])('tries to fetch servers from remote', async (mockedValue, expectedNewServers) => {
jsonRequest.mockResolvedValue(mockedValue);
},
{
serversArray: '<html></html>',
expectedNewServers: {},
},
{
serversArray: {},
expectedNewServers: {},
},
])('tries to fetch servers from remote', async ({ serversArray, expectedNewServers }) => {
jsonRequest.mockResolvedValue(serversArray);
const doFetchServers = fetchServers(httpClient);
await doFetchServers()(dispatch, vi.fn(), {});

View File

@@ -105,15 +105,6 @@ describe('serversReducer', () => {
expect(payload).toEqual(list);
});
it('generates an id for every provided server if they do not have it', () => {
const servers = Object.values(list).map(({ name, autoConnect, url, apiKey }) => (
{ name, autoConnect, url, apiKey }
));
const { payload } = createServers(servers);
expect(Object.values(payload).every(({ id }) => !!id)).toEqual(true);
});
});
describe('setAutoConnect', () => {