Compare commits

..

1571 Commits

Author SHA1 Message Date
Alejandro Celaya
f5e92c6897 Merge pull request #848 from shlinkio/develop
Release 3.10.2
2023-07-09 10:17:23 +02:00
Alejandro Celaya
f1014a4810 Build docker image for linux/arm64/v8 and linux/amd64 only 2023-07-09 10:09:35 +02:00
Alejandro Celaya
1793424658 Merge pull request #847 from acelaya-forks/feature/docker-build-on-tag
Build docker image only on tags
2023-07-09 09:58:55 +02:00
Alejandro Celaya
c94a5b948e Build docker image only on tags 2023-07-09 09:48:54 +02:00
Alejandro Celaya
107cabcd8b Merge pull request #845 from shlinkio/dependabot/npm_and_yarn/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3
2023-07-08 07:50:43 +02:00
Alejandro Celaya
99bc769894 Merge pull request #844 from shlinkio/dependabot/npm_and_yarn/stylelint-15.10.1
Bump stylelint from 14.16.0 to 15.10.1
2023-07-08 07:50:18 +02:00
dependabot[bot]
e8f1964941 Bump tough-cookie from 4.1.2 to 4.1.3
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-08 00:17:47 +00:00
dependabot[bot]
1a491bec1c Bump stylelint from 14.16.0 to 15.10.1
Bumps [stylelint](https://github.com/stylelint/stylelint) from 14.16.0 to 15.10.1.
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/14.16.0...15.10.1)

---
updated-dependencies:
- dependency-name: stylelint
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-07 22:00:52 +00:00
Alejandro Celaya
4ba63cdbf8 Merge pull request #837 from acelaya-forks/feature/vitest-0.32
Feature/vitest 0.32
2023-06-12 09:47:20 +02:00
Alejandro Celaya
b2c2af3ebb Exclude sw helper from code coverage 2023-06-12 08:59:38 +02:00
Alejandro Celaya
9dca19fcb5 Replace coverage-c8 with coverage-v8 2023-06-12 08:51:37 +02:00
Alejandro Celaya
7c2dab43e1 Update to vitest 0.32 2023-06-09 09:07:20 +02:00
Alejandro Celaya
a8c6d9b034 Merge pull request #836 from shlinkio/dependabot/npm_and_yarn/vite-4.3.9
Bump vite from 4.3.1 to 4.3.9
2023-06-06 05:38:06 +02:00
dependabot[bot]
be0cb20fa2 Bump vite from 4.3.1 to 4.3.9
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.3.1 to 4.3.9.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.3.9/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-06 02:03:33 +00:00
Alejandro Celaya
2ac1025e9f Merge pull request #834 from acelaya-forks/feature/vitest-migration
Feature/vitest migration
2023-05-27 14:21:33 +02:00
Alejandro Celaya
27d79b574e Correct test:watch command so that it actually watches 2023-05-27 14:15:38 +02:00
Alejandro Celaya
1b82f42a33 Remove direct dependency on redux and redux-thunk, as those are now required by @reduxjs/toolkit 2023-05-27 14:10:37 +02:00
Alejandro Celaya
f3f9eac67b Fix comments 2023-05-27 13:12:38 +02:00
Alejandro Celaya
2a86a0e540 Fix remaining type errors in tests 2023-05-27 12:45:12 +02:00
Alejandro Celaya
d14aea708e Fix incorrect types between testing library and vitest 2023-05-27 12:29:03 +02:00
Alejandro Celaya
12a05b422d Fix merge conflicts 2023-05-27 12:04:01 +02:00
Alejandro Celaya
a5abe9dbf2 Update test snapshots 2023-05-27 12:02:13 +02:00
Alejandro Celaya
07fcb4e016 Update tests to use vi instead of jest 2023-05-27 11:57:26 +02:00
Alejandro Celaya
e2cbb2713a Replace jest config with vitest config 2023-05-27 11:36:18 +02:00
Alejandro Celaya
706e00ace0 Merge pull request #833 from acelaya-forks/feature/menus
Feature/menus
2023-05-27 10:57:14 +02:00
Alejandro Celaya
655fbf94c1 Normalize and consolidate dropdown menus 2023-05-27 10:40:07 +02:00
Alejandro Celaya
afc574aceb Fixed block and inline dropdown buttons 2023-05-27 09:40:49 +02:00
Alejandro Celaya
3da2b56426 Update actions dependencies and node 2023-05-27 09:40:10 +02:00
Alejandro Celaya
5f91ad8819 Merge pull request #829 from shlinkio/develop
Release 3.10.1
2023-04-23 15:56:15 +02:00
Alejandro Celaya
131a745514 Add v3.10.1 to changelog 2023-04-23 15:24:48 +02:00
Alejandro Celaya
86349f1ad3 Merge pull request #828 from acelaya-forks/feature/short-url-export
Feature/short url export
2023-04-22 12:28:12 +02:00
Alejandro Celaya
72e4a7b062 Fix incorrect type 2023-04-22 12:09:15 +02:00
Alejandro Celaya
0a0165df45 Update changelog 2023-04-22 12:05:31 +02:00
Alejandro Celaya
992b22fd24 Refactor short URL export so that it is compatible with what Shlink expects 2023-04-21 09:36:51 +02:00
Alejandro Celaya
6fbe6c673b Merge pull request #827 from acelaya-forks/feature/vite-latest
Update vite deps
2023-04-21 08:20:42 +02:00
Alejandro Celaya
ff22e54b59 Update vite deps 2023-04-20 22:57:49 +02:00
Alejandro Celaya
578365ab68 Delete outdated stryker config file 2023-04-20 09:28:39 +02:00
Alejandro Celaya
22905a2efc Merge pull request #825 from acelaya-forks/feature/shoehorn
Introduce shoehorn as a possible replacement for ts-mockery
2023-04-14 09:34:45 +02:00
Alejandro Celaya
26bad75a1a Finish replacing ts-mockery with shoehorn 2023-04-14 09:28:53 +02:00
Alejandro Celaya
04e1950591 Migrate more tests to shoehorn 2023-04-13 22:47:13 +02:00
Alejandro Celaya
340f4b8fb5 Introduce shoehorn as a possible replacement for ts-mockery 2023-04-13 21:48:29 +02:00
Alejandro Celaya
457458a894 Merge pull request #820 from shlinkio/develop
Release 3.10.0
2023-03-19 12:00:45 +01:00
Alejandro Celaya
f6334c3618 Merge pull request #819 from acelaya-forks/feature/tags-non-bot-visits
Feature/tags non bot visits
2023-03-19 11:54:54 +01:00
Alejandro Celaya
cf27de965e Remove redundant type 2023-03-19 11:50:06 +01:00
Alejandro Celaya
43b2926063 Update changelog 2023-03-19 11:47:02 +01:00
Alejandro Celaya
1d6464fefb Take into consideration types of visits when increasing tags visits 2023-03-19 11:44:40 +01:00
Alejandro Celaya
927ab76dbd Increase required coverage 2023-03-19 10:46:52 +01:00
Alejandro Celaya
34cfe2077b Test proper amount of visits is displayed in TagsList 2023-03-19 10:44:09 +01:00
Alejandro Celaya
4ebe23e89f Add logic to dynamically exclude bots visits in tags table 2023-03-19 10:32:11 +01:00
Alejandro Celaya
8fa61a6301 Merge pull request #817 from acelaya-forks/feature/tags-stats
Feature/tags stats
2023-03-18 16:36:06 +01:00
Alejandro Celaya
96c20b36a5 Split tagsList and tagsStats methods in ShlinkApiClient for clarity 2023-03-18 16:32:04 +01:00
Alejandro Celaya
a9af5163c1 Update changelog 2023-03-18 16:27:52 +01:00
Alejandro Celaya
b87b108e53 Use /tags/stats endpoint when the server supports it 2023-03-18 16:26:28 +01:00
Alejandro Celaya
ddaec7c6ac Merge pull request #816 from acelaya-forks/feature/decouple-actions
Feature/decouple actions
2023-03-18 16:07:15 +01:00
Alejandro Celaya
4e8e16f16d Refactor of redux tests to avoid covering RTK implementation details 2023-03-18 16:02:06 +01:00
Alejandro Celaya
9cefdb7977 First refactor of redux tests to avoid covering RTK implementation details 2023-03-18 12:09:38 +01:00
Alejandro Celaya
a6d000714b Merge pull request #815 from acelaya-forks/feature/overview-bots
Feature/overview bots
2023-03-18 11:15:01 +01:00
Alejandro Celaya
54758272be Update changelog 2023-03-18 11:10:50 +01:00
Alejandro Celaya
8e9e2c5b61 Create test for VisitsHighlightCard 2023-03-18 11:10:03 +01:00
Alejandro Celaya
934bf495a0 Extend overview to exclude/include bot visits based on config 2023-03-18 10:55:07 +01:00
Alejandro Celaya
1d8189369c Enhance visits overview reducer to handle bot and non-bots visits amounts 2023-03-18 10:54:14 +01:00
Alejandro Celaya
25aa9b9bd7 Enhance types including potential bots on visits summary endpoint 2023-03-18 10:29:49 +01:00
Alejandro Celaya
a1b879a5b4 Add support for a tooltip on HighlightCard component 2023-03-18 10:17:17 +01:00
Alejandro Celaya
b70724f7d6 Update babel-typescript plugin 2023-03-18 10:08:44 +01:00
Alejandro Celaya
a52f96f8e5 Merge pull request #814 from acelaya-forks/feature/update-ts-vite
Update to latest TypeScript and Vite versions
2023-03-17 08:57:11 +01:00
Alejandro Celaya
970c573a12 Update to latest TypeScript and Vite versions 2023-03-17 08:49:47 +01:00
Alejandro Celaya
46749044e2 Merge pull request #813 from acelaya-forks/feature/device-long-urls
Feature/device long urls
2023-03-14 09:11:54 +01:00
Alejandro Celaya
16d748800c Update copy-to-clipboard icons 2023-03-14 09:06:57 +01:00
Alejandro Celaya
3e698b045a Add IconInput test 2023-03-14 09:02:12 +01:00
Alejandro Celaya
999b21577a Removed duplicated CSS from DateInput 2023-03-14 08:50:53 +01:00
Alejandro Celaya
3be5126e2d Add missing ref to IconInput 2023-03-13 18:18:35 +01:00
Alejandro Celaya
2b14c49c80 Update snapshots 2023-03-13 18:04:09 +01:00
Alejandro Celaya
bace2a10e8 Create component to display input with an icon 2023-03-13 18:02:29 +01:00
Alejandro Celaya
006e6b30b7 Update changelog 2023-03-13 09:06:49 +01:00
Alejandro Celaya
4c5d0321d2 Add support for device-specific long URLs when using Shlink 3.5.0 or newer 2023-03-13 09:05:54 +01:00
Alejandro Celaya
fa69c21fa2 Merge pull request #811 from acelaya-forks/feature/feature-flag-hooks
Convert feature flags into hooks
2023-03-11 10:38:26 +01:00
Alejandro Celaya
95439e5602 Convert feature flags into hooks 2023-03-11 10:33:03 +01:00
Alejandro Celaya
bbd8d8ef4e Fix border radius on tags input 2023-03-10 09:17:07 +01:00
Alejandro Celaya
ef269d565c Merge pull request #810 from acelaya-forks/feature/fallback-bots
Make sure the request to get the latest fallback visit respects bots config
2023-03-10 08:58:56 +01:00
Alejandro Celaya
8acf6dda6e Make sure the request to get the latest fallback visit respects bots config 2023-03-10 08:53:05 +01:00
Alejandro Celaya
d18219dc14 Merge pull request #806 from acelaya-forks/feature/preview
Feature/preview
2023-03-08 09:27:57 +01:00
Alejandro Celaya
3f1718f4c5 Fix merge conflicts 2023-03-08 09:21:05 +01:00
Alejandro Celaya
825a749b45 Replace serve with vite preview to check generated build 2023-03-08 09:18:32 +01:00
Alejandro Celaya
c2eb09e664 Merge pull request #804 from acelaya-forks/feature/update-coding-standard
Feature/update coding standard
2023-02-18 11:44:05 +01:00
Alejandro Celaya
adb670dd0c Update coding standard 2023-02-18 11:40:04 +01:00
Alejandro Celaya
5e9ec071dc Remove default exports 2023-02-18 11:37:49 +01:00
Alejandro Celaya
1f41f8da23 Ordered imports alphabetically 2023-02-18 11:15:35 +01:00
Alejandro Celaya
2a5480da79 Add import type whenever possible 2023-02-18 10:40:37 +01:00
Alejandro Celaya
7add854b40 Merge pull request #803 from acelaya-forks/feature/remove-stryker
Remove stryker and mutation testing
2023-02-17 20:31:39 +01:00
Alejandro Celaya
e639cd0bd2 Update changelog 2023-02-17 20:27:48 +01:00
Alejandro Celaya
3503f1f580 Remove stryker and mutation testing 2023-02-17 20:09:31 +01:00
Alejandro Celaya
853dcbd69a Merge pull request #801 from acelaya-forks/feature/vite-4.1
Update to vite 4.1
2023-02-11 13:22:56 +01:00
Alejandro Celaya
c54fff5472 Update to vite 4.1 2023-02-11 13:16:41 +01:00
Alejandro Celaya
699d3d3eaa Fix twitter badge 2023-01-28 11:18:08 +01:00
Alejandro Celaya
0c91f488f0 Merge pull request #794 from acelaya-forks/feature/domain
Replace references to doma.in with s.test
2023-01-18 08:12:25 +01:00
Alejandro Celaya
d3a644877e Replace references to doma.in with s.test 2023-01-17 22:53:49 +01:00
Alejandro Celaya
aac2832eb7 Merge pull request #791 from acelaya-forks/feature/fix-ref-types
Improved types on element ref objects and their usage
2023-01-10 20:11:36 +01:00
Alejandro Celaya
487c832f5b Improved types on element ref objects and their usage 2023-01-10 20:04:47 +01:00
Alejandro Celaya
98e2e57bb2 Merge pull request #790 from shlinkio/dependabot/npm_and_yarn/json5-1.0.2
Bump json5 from 1.0.1 to 1.0.2
2023-01-08 09:04:30 +01:00
dependabot[bot]
c5170df402 Bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-08 06:27:50 +00:00
Alejandro Celaya
4be38dfd0c Merge pull request #789 from shlinkio/develop
Release 3.9.1
2022-12-31 18:22:38 +01:00
Alejandro Celaya
597f2b69e9 Merge pull request #788 from acelaya-forks/feature/fix-base-path
Fixed wrong base path being used in vite config
2022-12-31 18:21:26 +01:00
Alejandro Celaya
c078a5fb55 Fixed wrong base path being used in vite config 2022-12-31 18:15:47 +01:00
Alejandro Celaya
5db0326350 Merge pull request #786 from shlinkio/develop
Release 3.9.0
2022-12-31 17:07:56 +01:00
Alejandro Celaya
7f6c678eaa Merge pull request #785 from acelaya-forks/feature/server-error-fix
Feature/server error fix
2022-12-31 17:02:12 +01:00
Alejandro Celaya
37ac6cebc1 Fixed selectedServer reucer test 2022-12-31 16:56:22 +01:00
Alejandro Celaya
27099aa7fb Updated changelog 2022-12-31 16:43:34 +01:00
Alejandro Celaya
91f4d09608 Ensured a recconnection happens to selected server when its params are edited 2022-12-31 16:42:04 +01:00
Alejandro Celaya
d34b9b1233 Merge pull request #783 from acelaya-forks/feature/visits-async-thunk
Feature/visits async thunk
2022-12-31 10:47:30 +01:00
Alejandro Celaya
2badd2b743 Fixed warning in tests 2022-12-31 10:47:15 +01:00
Alejandro Celaya
4517f38680 Fixed injection of visits loaders 2022-12-31 10:43:03 +01:00
Alejandro Celaya
84f9727836 Updated changelog 2022-12-31 10:35:58 +01:00
Alejandro Celaya
85452cde23 Enhanced visits async thunk so that it wraps both standard async thunk actions and extra ones 2022-12-31 10:34:29 +01:00
Alejandro Celaya
9b19113262 Merge pull request #780 from acelaya-forks/feature/short-urls-filtering
Feature/short urls filtering
2022-12-29 19:26:44 +01:00
Alejandro Celaya
e1bb091363 Updated changelog 2022-12-29 19:21:11 +01:00
Alejandro Celaya
732d664715 Fixed coding styles 2022-12-29 19:19:46 +01:00
Alejandro Celaya
33498ce903 Added support to filter out disabled short URLs 2022-12-29 19:03:17 +01:00
Alejandro Celaya
c25b74de84 Added test for ShortUrlsFilterDropdown 2022-12-29 10:35:50 +01:00
Alejandro Celaya
1c39e3402b Added function to parse optional boolean to string 2022-12-28 23:00:55 +01:00
Alejandro Celaya
a3bd10bc82 Updated ShlinkApiClient to support more filtering options for short URLs list 2022-12-28 22:59:11 +01:00
Alejandro Celaya
d6d237fc52 Merge pull request #779 from shlinkio/feature/tweak-ts
Added --noEmit to tsc as part of production build
2022-12-26 10:31:31 +01:00
Alejandro Celaya
9b7a169110 Added --noEmit to tsc as part of production build 2022-12-26 10:24:53 +01:00
Alejandro Celaya
2b17a24206 Merge pull request #778 from acelaya-forks/feature/chartjs-4
Feature/chartjs 4
2022-12-25 22:52:49 +01:00
Alejandro Celaya
a0d9bd6f09 Fixed type error in AsideMenu 2022-12-25 22:48:47 +01:00
Alejandro Celaya
cd33abd92d Updated changelog 2022-12-25 22:45:21 +01:00
Alejandro Celaya
c83563c0ea Fixed subpath and tests for chartjs 2022-12-25 22:44:43 +01:00
Alejandro Celaya
79515ac960 Updated production deps 2022-12-25 22:31:28 +01:00
Alejandro Celaya
8e8a5f3fd6 Updated to chartjs 4 2022-12-25 09:53:50 +01:00
Alejandro Celaya
51283cc130 Merge pull request #777 from acelaya-forks/feature/fix-visits-filters
Fixed bots filter getting reset when changing date
2022-12-25 09:49:57 +01:00
Alejandro Celaya
4023c077b3 Fixed bots filter getting reset when changing date 2022-12-25 09:44:47 +01:00
Alejandro Celaya
f3cf21ba08 Merge pull request #776 from acelaya-forks/feature/vite
Feature/vite
2022-12-25 09:30:14 +01:00
Alejandro Celaya
bec7b59abf Updated changelog 2022-12-25 09:20:45 +01:00
Alejandro Celaya
3e0abe329f Fixed preview generation, including service worker 2022-12-25 09:19:26 +01:00
Alejandro Celaya
822fe3db9e Small fixes 2022-12-25 09:13:45 +01:00
Alejandro Celaya
408ec82a10 Migrated serice worker generation to vite-plugin-pwa 2022-12-24 19:17:33 +01:00
Alejandro Celaya
ced3fa00ef Ensured service-worker is bundled separately 2022-12-24 18:20:01 +01:00
Alejandro Celaya
595b3c0450 Updated to node 18 and fixed replace-version script for vite structure 2022-12-24 11:34:39 +01:00
Alejandro Celaya
1d1c8153e7 Updated babel plugins for jest 2022-12-24 10:48:03 +01:00
Alejandro Celaya
52f556eb2e Migrated from react-scripts and webpack to vite 2022-12-24 10:18:26 +01:00
Alejandro Celaya
35fcd20123 Merge pull request #775 from acelaya-forks/feature/shlink-updates
Feature/shlink updates
2022-12-23 21:21:06 +01:00
Alejandro Celaya
e518b94fba Fixed tests 2022-12-23 21:16:17 +01:00
Alejandro Celaya
05553ba18a Updated changelog 2022-12-23 21:09:35 +01:00
Alejandro Celaya
4a9e05cf17 Updated prop to make it required as in Shlink v2.8.0 or newer 2022-12-23 21:08:41 +01:00
Alejandro Celaya
60fc351344 Removed references to feature checks for version 2.7 2022-12-23 21:06:59 +01:00
Alejandro Celaya
815e06809a Removed references to feature checks for version 2.8 2022-12-23 20:42:47 +01:00
Alejandro Celaya
bfcdf703e8 Merge pull request #772 from acelaya-forks/feature/exclude-bots
Feature/exclude bots
2022-12-23 20:29:24 +01:00
Alejandro Celaya
ddb2c1e641 Updated changelog 2022-12-23 20:24:55 +01:00
Alejandro Celaya
e790360de9 Added filtering dropdown to short URLs filtering bar 2022-12-23 20:15:52 +01:00
Alejandro Celaya
b00f6fadf8 Added test for parseBooleanToString 2022-12-23 20:03:27 +01:00
Alejandro Celaya
1d6f4bf5db Take into consideration exclñudeBots from query on short URLs row 2022-12-23 20:00:59 +01:00
Alejandro Celaya
80cea91339 Ensured bots exclusion is selected by default in visits filter dropdown, if it was selected in settings 2022-12-23 10:07:23 +01:00
Alejandro Celaya
5942cd6fcf Ensured proper amount of visits is displayed on short URLs based on config 2022-12-22 18:39:09 +01:00
Alejandro Celaya
2859ba6cd2 Simplified reducer logic to update short URLs when new visits come 2022-12-22 18:30:02 +01:00
Alejandro Celaya
b9285fd600 Enrues proper ordering is sent to shlink when ordering by visits 2022-12-22 18:07:44 +01:00
Alejandro Celaya
901df2b90d Added new setting to exclude bots from visits, wherever possible 2022-12-22 12:25:25 +01:00
Alejandro Celaya
662573d940 Merge pull request #771 from acelaya-forks/feature/highlight-disabled
Feature/highlight disabled
2022-12-19 20:49:46 +01:00
Alejandro Celaya
a8dcd3cac7 Updated changelog 2022-12-19 20:45:02 +01:00
Alejandro Celaya
0ac16a1626 Added test for ShortUrlStatus component 2022-12-19 20:43:55 +01:00
Alejandro Celaya
5162fa2a13 Created Tags test 2022-12-19 20:27:33 +01:00
Alejandro Celaya
73a3d1d50f Extended ShortUrlVisitsCount test to cover different contents of the tooltip 2022-12-19 20:18:50 +01:00
Alejandro Celaya
afc272c4d9 Improved ShortUrlsRow test covering new status icon 2022-12-19 20:00:52 +01:00
Alejandro Celaya
f8bcaed3ad Moved short URL status to the last column in the table 2022-12-19 19:40:04 +01:00
Alejandro Celaya
d1a1b7426e Added ShortUrlStatus concept 2022-12-18 19:26:30 +01:00
Alejandro Celaya
99485cc6d8 Removed conept on short URL tags 2022-12-18 13:29:39 +01:00
Alejandro Celaya
187fee46f4 Added extra info and new label to highlight disabled short URLs 2022-12-18 13:17:49 +01:00
Alejandro Celaya
90837546ab Exported some specific component types and improved spacing in short URLs list 2022-12-18 10:12:34 +01:00
Alejandro Celaya
f4cf4850a3 Merge pull request #769 from acelaya-forks/feature/drop-tags-cards
Feature/drop tags cards
2022-12-17 20:07:51 +01:00
Alejandro Celaya
4ef1e491bc Updated changelog 2022-12-17 20:01:31 +01:00
Alejandro Celaya
170f45d46b Removed references to tagsMode setting 2022-12-17 19:59:55 +01:00
Alejandro Celaya
37caa1ad19 Removed references to tags cards 2022-12-17 19:56:58 +01:00
Alejandro Celaya
0312a0911c Fixed build badge in README 2022-12-17 10:54:18 +01:00
Alejandro Celaya
cc88f7678c Merge pull request #768 from shlinkio/develop
Release 3.8.2
2022-12-17 10:07:37 +01:00
Alejandro Celaya
653b470fec Merge pull request #767 from acelaya-forks/feature/fixes
Feature/fixes
2022-12-17 10:03:19 +01:00
Alejandro Celaya
2603f2f987 Added missing application/json content-type when calling Shlink with payload 2022-12-17 09:57:40 +01:00
Alejandro Celaya
b106b3cd0a Updated changelog 2022-12-17 09:29:34 +01:00
Alejandro Celaya
b2b6b3af18 Fixed visits query being lost when switching between sub-sections 2022-12-17 09:28:42 +01:00
Alejandro Celaya
f911f78c95 Merge pull request #763 from shlinkio/dependabot/npm_and_yarn/express-4.18.2
Bump express from 4.17.1 to 4.18.2
2022-12-14 19:06:22 +01:00
dependabot[bot]
a7560443f3 Bump express from 4.17.1 to 4.18.2
Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.18.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-14 17:59:03 +00:00
Alejandro Celaya
ab757b2f67 Merge pull request #759 from shlinkio/develop
Release 3.8.1
2022-12-06 20:21:39 +01:00
Alejandro Celaya
261cc68624 Merge pull request #758 from acelaya-forks/feature/fix-visits-interval
Feature/fix visits interval
2022-12-06 20:20:22 +01:00
Alejandro Celaya
dc2db3a463 Updated changelog 2022-12-06 20:15:44 +01:00
Alejandro Celaya
ae625e4c8a Fixed all visits interval not working after loading the default configured interval unless switching to another one first 2022-12-06 20:13:43 +01:00
Alejandro Celaya
6f5c5b122f Fixed fallback interval not working on visits pages 2022-12-06 18:09:50 +01:00
Alejandro Celaya
5d712d7d78 Created helper curried function to compare two values 2022-12-05 17:29:59 +01:00
Alejandro Celaya
1654784471 Created now function and refactored intervalToDateRange 2022-12-05 17:18:00 +01:00
Alejandro Celaya
7d83e434e6 Merge pull request #755 from shlinkio/develop
Release 3.8.0
2022-12-03 13:34:37 +01:00
Alejandro Celaya
97a54d44c7 Merge pull request #754 from acelaya-forks/feature/visits-filters
Feature/visits filters
2022-12-03 13:29:05 +01:00
Alejandro Celaya
6694ca6918 Updated changelog 2022-12-03 13:24:16 +01:00
Alejandro Celaya
8e61e94fba Added test to check how visits stats persist filters in query string 2022-12-03 13:22:31 +01:00
Alejandro Celaya
69b1c8039e Ensured stryker-tmp folder is ignored by jest 2022-12-03 12:56:25 +01:00
Alejandro Celaya
5bd89efc09 Added test for toDateRange helper function 2022-12-03 12:45:25 +01:00
Alejandro Celaya
e5185f2099 Renamed file containing date range and date interval utils 2022-12-03 12:20:18 +01:00
Alejandro Celaya
d2ebc880a0 Created new hook to handle visits filtering via query string 2022-12-03 12:15:36 +01:00
Alejandro Celaya
165afa436d Minor refactorings and function extractions 2022-11-26 09:11:46 +01:00
Alejandro Celaya
a3f5095dce Merge pull request #751 from acelaya-forks/feature/fix-max-length
Feature/fix max length
2022-11-25 20:14:53 +01:00
Alejandro Celaya
7bda5769fb Updated changelog 2022-11-25 19:20:52 +01:00
Alejandro Celaya
0bf859d485 Simplified DeleteShortUrlModal so that it only requires writing 'delete' 2022-11-25 19:08:40 +01:00
Alejandro Celaya
b79dced185 Fixed broken short URLs table when creating short URL with too long slug 2022-11-25 18:34:27 +01:00
Alejandro Celaya
e368e618f3 Updated changelog 2022-11-22 20:29:01 +01:00
Alejandro Celaya
bc4c69f207 Merge pull request #747 from acelaya-forks/feature/modal-async-delays
Feature/modal async delays
2022-11-22 20:28:30 +01:00
Alejandro Celaya
32f29a84f7 Used TestModalWrapper in DeleteShortUrlModal test 2022-11-22 20:22:03 +01:00
Alejandro Celaya
f0a6420ba9 Extracted helper to test modals 2022-11-22 20:18:11 +01:00
Alejandro Celaya
cf91637848 Updated changelog 2022-11-22 20:09:00 +01:00
Alejandro Celaya
9bdf55374c Ensured DeleteServerModal is not removed from the DOM before close transition has finished 2022-11-22 20:08:08 +01:00
Alejandro Celaya
d21758c410 Fixed DeleteShortUrlModal being removed from the DOM before CSS transition finished 2022-11-22 19:39:07 +01:00
Alejandro Celaya
bc2c945fee Updated changelog 2022-11-20 13:01:03 +01:00
Alejandro Celaya
db2853880d Merge pull request #746 from acelaya-forks/feature/rename-tag-fix
Feature/rename tag fix
2022-11-20 12:59:10 +01:00
Alejandro Celaya
cb76c89a08 Improved HttpClientTest 2022-11-20 12:54:06 +01:00
Alejandro Celaya
059fa37ca7 Updates ShlinkApiClint to use different methods to fetch, and fixed tests 2022-11-20 12:51:07 +01:00
Alejandro Celaya
54cc99448b Merge pull request #742 from shlinkio/dependabot/npm_and_yarn/minimatch-and-recursive-readdir-and-serve-3.1.2
Bump minimatch, recursive-readdir and serve
2022-11-20 09:46:06 +01:00
Alejandro Celaya
a5dd96805d Merge pull request #743 from shlinkio/dependabot/npm_and_yarn/loader-utils-1.4.2
Bump loader-utils from 1.4.1 to 1.4.2
2022-11-20 09:46:00 +01:00
Alejandro Celaya
1e155af948 Ensured stats for renamed tagged are propagated to new name 2022-11-19 09:31:48 +01:00
Alejandro Celaya
dd9ee044eb Ensured JSON decodedoes not happen for endpoints returning empty body 2022-11-19 09:29:29 +01:00
Alejandro Celaya
bd8ea17c84 Ensured bg-warning elements always use dark text 2022-11-19 09:21:51 +01:00
Alejandro Celaya
0236f5132d Merge pull request #745 from acelaya-forks/feature/http-client
Feature/http client
2022-11-17 21:38:28 +01:00
Alejandro Celaya
b8adf5f274 Created test for HttpClient 2022-11-17 21:30:42 +01:00
Alejandro Celaya
c4bce5ec0a Added badge for Mastodon follow 2022-11-17 19:59:26 +01:00
dependabot[bot]
5bfe7dd128 Bump loader-utils from 1.4.1 to 1.4.2
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-16 02:51:35 +00:00
Alejandro Celaya
9b3bdebb28 Wrapped logic to perform HTTP requests with fetch into an HttpClient class 2022-11-15 20:31:35 +01:00
Alejandro Celaya
7575387236 Updated changelog 2022-11-15 17:17:55 +01:00
dependabot[bot]
984a99b24e Bump minimatch, recursive-readdir and serve
Bumps [minimatch](https://github.com/isaacs/minimatch) to 3.1.2 and updates ancestor dependencies [minimatch](https://github.com/isaacs/minimatch), [recursive-readdir](https://github.com/jergason/recursive-readdir) and [serve](https://github.com/vercel/serve). These dependencies need to be updated together.


Updates `minimatch` from 3.0.4 to 3.1.2
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

Updates `recursive-readdir` from 2.2.2 to 2.2.3
- [Release notes](https://github.com/jergason/recursive-readdir/releases)
- [Changelog](https://github.com/jergason/recursive-readdir/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jergason/recursive-readdir/commits/v2.2.3)

Updates `serve` from 14.0.1 to 14.1.1
- [Release notes](https://github.com/vercel/serve/releases)
- [Commits](https://github.com/vercel/serve/compare/14.0.1...14.1.1)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
- dependency-name: recursive-readdir
  dependency-type: indirect
- dependency-name: serve
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-15 16:16:52 +00:00
Alejandro Celaya
a0767417b3 Merge pull request #740 from acelaya-forks/feature/fetch
Feature/fetch
2022-11-15 17:15:43 +01:00
Alejandro Celaya
790c69ba80 Fixed ShlinkApiClient test 2022-11-15 12:19:21 +01:00
Alejandro Celaya
f7ba974d97 Fixed logic to determine if an error is a ProblemDetailError 2022-11-15 12:15:04 +01:00
Alejandro Celaya
1eab5af5c7 Fixed shortUrlDeletion test 2022-11-15 11:50:04 +01:00
Alejandro Celaya
3df0bf79f8 Removed axios from the project 2022-11-15 11:45:28 +01:00
Alejandro Celaya
34aa156d5f Migrated ImageDownloader from axios to fetch 2022-11-15 11:41:05 +01:00
Alejandro Celaya
a88ebc26a9 Merge branch 'develop' into feature/fetch 2022-11-15 11:27:53 +01:00
Alejandro Celaya
d800062159 Extracted helper fetch function and migrated remoteServers redux action from axios to fetch 2022-11-14 23:25:39 +01:00
Alejandro Celaya
e5afe4f767 Migrated ShlinkApiClient from axios to fetch 2022-11-14 23:06:06 +01:00
Alejandro Celaya
ee7a091586 Merge pull request #739 from acelaya-forks/feature/rtk-errors
Changed how errors are serialized by async thunks
2022-11-13 18:36:10 +01:00
Alejandro Celaya
7add83f985 Changed how errors are serialized by async thunks 2022-11-13 18:26:35 +01:00
Alejandro Celaya
16bee43f12 Migrated ShlinkApiClient from axios to fetch 2022-11-13 16:57:16 +01:00
Alejandro Celaya
ba48104c5c Refactored createVisitsReducer so that it expects an object param 2022-11-13 09:59:49 +01:00
Alejandro Celaya
cc620ddf79 Merge pull request #735 from acelaya-forks/feature/visits-rtk
Feature/visits rtk
2022-11-12 20:46:50 +01:00
Alejandro Celaya
6103f6a89b Separated param definition and unpacking for readibility 2022-11-12 20:41:55 +01:00
Alejandro Celaya
4b2c3d2db7 Extracted duplicated code on creating visits reducers to a common helper function 2022-11-12 20:37:04 +01:00
Alejandro Celaya
dac69daf03 Migrated tagVisits reducer to RTK 2022-11-12 20:02:58 +01:00
Alejandro Celaya
3e474a3f2d Migrated shortUrlVisits reducer to RTK 2022-11-12 19:36:12 +01:00
Alejandro Celaya
f81999a4fe Migrated orphanVisits reducer to RTK 2022-11-12 19:15:41 +01:00
Alejandro Celaya
fd80fd65c9 Migrated nonOrphanVisits reducer to RTK 2022-11-12 18:18:16 +01:00
Alejandro Celaya
ab7c52d049 Migrated domainVisits reducer to RTK 2022-11-12 17:51:37 +01:00
Alejandro Celaya
a3cc3d5fc2 Migrated visits-loading actions to payload actions 2022-11-12 10:34:44 +01:00
Alejandro Celaya
a6ed0c811d Updated getShortUrlVisits action so that it expects a signle DTO param 2022-11-12 09:38:24 +01:00
Alejandro Celaya
8e6b9c5afb Updated getOrphanVisits action so that it expects a signle DTO param 2022-11-12 09:32:52 +01:00
Alejandro Celaya
b9efdd69f1 Updated getNonOrphanVisits action so that it expects a signle DTO param 2022-11-12 09:21:23 +01:00
Alejandro Celaya
3b96b89492 Updated getDomainVisits action so that it expects a signle DTO param 2022-11-12 09:18:41 +01:00
Alejandro Celaya
32f7374d92 Migrated progress and fallback visits actions to payload actions 2022-11-12 09:01:43 +01:00
Alejandro Celaya
c6eec8b266 Changed getVisitsWithLoader reducer helper so that it expects an action prefix instead of an action map 2022-11-12 08:49:14 +01:00
Alejandro Celaya
634ae94542 Merge pull request #734 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-11 20:33:05 +01:00
Alejandro Celaya
5095a2c59e Migrated visitsOverview reducer to RTK 2022-11-11 20:23:19 +01:00
Alejandro Celaya
002d2ba8e6 Added tests for selectedServerReducerCreator 2022-11-11 20:01:45 +01:00
Alejandro Celaya
d44fe945d8 Migrated selectedServer reducer to RTK 2022-11-11 19:31:05 +01:00
Alejandro Celaya
6221f9ed05 Migrated selectServer action to RTK and moved loadMercureInfo to an action listener 2022-11-11 19:21:17 +01:00
Alejandro Celaya
2e0e24d87b Migrated fetchServers to RTK 2022-11-11 19:21:17 +01:00
Alejandro Celaya
a1d869900b Merge pull request #733 from acelaya-forks/feature/fix-mercure-integration
Fixed mercure integration
2022-11-11 16:57:40 +01:00
Alejandro Celaya
d90f6c2019 Fixed mercure integration 2022-11-11 16:51:21 +01:00
Alejandro Celaya
ed4c03f154 Merge pull request #732 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-09 19:36:49 +01:00
Alejandro Celaya
7bfccafca8 Migrated shortUrlsList reducer to RTK 2022-11-09 19:13:44 +01:00
Alejandro Celaya
ae49090bad Split short URL edition reducer and async thunk 2022-11-09 18:40:51 +01:00
Alejandro Celaya
979c16eb9c Updated listShortUrls action to use payload 2022-11-09 18:27:05 +01:00
Alejandro Celaya
fe85291772 Changed format on action types and reducer names for those already migrated to RTK 2022-11-09 18:19:07 +01:00
Alejandro Celaya
893c5ace6f Merge pull request #731 from shlinkio/dependabot/npm_and_yarn/loader-utils-1.4.1
Bump loader-utils from 1.4.0 to 1.4.1
2022-11-09 08:31:56 +01:00
Alejandro Celaya
89423737e8 Removed hardcoded action references by improving dependency injection 2022-11-08 22:59:41 +01:00
Alejandro Celaya
f9bfb742da Migrated tagsList reducer to RTK 2022-11-08 22:48:53 +01:00
Alejandro Celaya
b7622b2b38 Migrated filterTags action to use payload 2022-11-08 21:59:17 +01:00
dependabot[bot]
8cfb4cf1e1 Bump loader-utils from 1.4.0 to 1.4.1
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 09:26:38 +00:00
Alejandro Celaya
b9e02cf344 Merge pull request #730 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-07 22:49:33 +01:00
Alejandro Celaya
033df3c3d6 Migrated tagDelete reducer to RTK 2022-11-07 22:41:02 +01:00
Alejandro Celaya
692eaf7dc9 Referenced createNewVisits action directly, instead of its action type 2022-11-07 22:29:15 +01:00
Alejandro Celaya
22b3794154 Migrated tagDeleted action to payload 2022-11-07 22:22:44 +01:00
Alejandro Celaya
dbb08a6ce0 Ensured tags deleted are not removed from list until modal has been hidden 2022-11-07 22:19:44 +01:00
Alejandro Celaya
0571a4a88f Migrated tagEdit reducer to RTK 2022-11-07 22:12:48 +01:00
Alejandro Celaya
648744f440 Migrated tag actions to have a single DTO param 2022-11-07 21:57:01 +01:00
Alejandro Celaya
f8fc1245ca Migrated editTag and tagEdited actions to use payload 2022-11-07 21:45:33 +01:00
Alejandro Celaya
5ecc791b38 Ensured tags list is not updated until the edit modal is closed 2022-11-07 21:32:19 +01:00
Alejandro Celaya
2183b09ffe Merge pull request #728 from acelaya-forks/feature/state-machine-poc
Feature/state machine poc
2022-11-07 19:03:51 +01:00
Alejandro Celaya
085ab521c3 Implemented state machine for short URL creation 2022-11-07 18:55:12 +01:00
Alejandro Celaya
61b274bab9 Replaced inheritance by composition on short URL creation interface 2022-11-07 18:27:41 +01:00
Alejandro Celaya
4ca31fc162 Added flag on short URL creation which tells if the short URL was already saved 2022-11-07 18:24:26 +01:00
Alejandro Celaya
ae1d39bede Merge pull request #725 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-06 19:39:03 +01:00
Alejandro Celaya
f803941fe4 Migrated short URL detail reducer to RTK 2022-11-06 19:32:02 +01:00
Alejandro Celaya
f93bb88d35 Refactored getShortUrlDetail action to have a single DTO param 2022-11-06 19:16:51 +01:00
Alejandro Celaya
ea199dbf8f Removed redundant types 2022-11-06 19:12:41 +01:00
Alejandro Celaya
526d7195bc Updated getShortUrlDetail action to use payload action 2022-11-06 19:06:39 +01:00
Alejandro Celaya
cf4143e4e2 Removed unnecesarry promise references in delete short URL modal 2022-11-06 18:48:47 +01:00
Alejandro Celaya
0f552ae6f4 Removed unnecessary castings to any 2022-11-06 13:21:46 +01:00
Alejandro Celaya
830071278e Migrated shortUrlDeletion reducer to RTK 2022-11-06 13:06:55 +01:00
Alejandro Celaya
d468fb1efe Migrated deleteShortUrl action creator to use PayloadAction and have a single param 2022-11-06 12:46:29 +01:00
Alejandro Celaya
2a268de2cb Migrated editShortUrl reducer to RTK 2022-11-06 12:33:23 +01:00
Alejandro Celaya
77cbb8ebc4 Refactored editShortUrl action to require just one param 2022-11-06 11:59:39 +01:00
Alejandro Celaya
bf84e4a2ed Migrated editShortUrl payload action 2022-11-06 11:53:23 +01:00
Alejandro Celaya
a316366ae9 Migrated shortUrlCreation reducer to RTK 2022-11-06 10:11:44 +01:00
Alejandro Celaya
50823003b4 Migrated settings reducer to RTK 2022-11-06 09:40:23 +01:00
Alejandro Celaya
7c61033bdf Migrated createNewVisits action creator to RTK 2022-11-05 13:05:44 +01:00
Alejandro Celaya
d588d8d9ef Migrated create visit action to use payload 2022-11-05 13:01:00 +01:00
Alejandro Celaya
cd90d3e581 Merge pull request #724 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-05 10:53:12 +01:00
Alejandro Celaya
54407af980 Fixed tests 2022-11-05 10:49:28 +01:00
Alejandro Celaya
a31cdcc9f0 Migrated selectedServer reducer to use payload actions 2022-11-05 10:36:57 +01:00
Alejandro Celaya
10d4419387 Migrated servers reducer to RTK 2022-11-05 10:08:24 +01:00
Alejandro Celaya
6f67f7bbf0 Removed redundant createServer action, leaving just createServers 2022-11-05 09:40:12 +01:00
Alejandro Celaya
90ef41b419 Migrated server list actions to use payload prop 2022-11-05 09:24:12 +01:00
Alejandro Celaya
62ab86aefa Created custom and better typed version of createAsyncThunk 2022-11-05 09:10:30 +01:00
Alejandro Celaya
1dd26fb76f Merge pull request #723 from acelaya-forks/feature/more-rtk
Feature/more rtk
2022-11-04 20:56:30 +01:00
Alejandro Celaya
4a95724425 Migrated mercureInfo reducer to RTK 2022-11-04 20:52:06 +01:00
Alejandro Celaya
f209fa2d58 Migrated sidebar reducer to RTK 2022-11-04 19:45:03 +01:00
Alejandro Celaya
85e2aab4df Migrated appUpdated reducer to RTK 2022-11-04 19:39:15 +01:00
Alejandro Celaya
26c3ea19f4 Merge pull request #722 from acelaya-forks/feature/redux-toolkit-poc
Feature/redux toolkit poc
2022-11-04 19:07:32 +01:00
Alejandro Celaya
a1e2cd7274 Fixed changelog 2022-11-04 18:59:08 +01:00
Alejandro Celaya
6363822ffd Updated to redux/toolkit 1.9 2022-11-04 18:58:21 +01:00
Alejandro Celaya
34f4411aa1 Migrated domainRedirects reducer to redux/toolkit 2022-11-04 18:56:34 +01:00
Alejandro Celaya
b6d08e2203 Updated editDomainRedirects action, to expect a payload DTO instead of multiple args 2022-11-04 17:10:02 +01:00
Alejandro Celaya
4fa6ae493d Removed unnecesary type castings and improved type inference for actions in demainsListReducer 2022-11-04 16:50:03 +01:00
Alejandro Celaya
79645099ba Added explicit import 2022-11-03 20:53:59 +01:00
Alejandro Celaya
18d478e16e Removed unneeded type castings and eslint suppressions in domainsList reducer 2022-11-03 20:51:20 +01:00
Alejandro Celaya
da97b76563 Migrated rest of domainslistreducer-related elements on test to the new ones 2022-11-03 20:29:22 +01:00
Alejandro Celaya
d25dbd5ae6 Replaced domainsList old reducer with new reducer in test 2022-11-03 20:15:28 +01:00
Alejandro Celaya
88e8f3363b Fixed domainsListReducer test so that it works with new payload prop in actions 2022-11-03 19:52:57 +01:00
Alejandro Celaya
24483ec330 Added first redux toolkit based reducer for domains 2022-11-02 20:40:14 +01:00
Alejandro Celaya
15a9fba091 Migrated redux store creation to redux toolkit 2022-11-01 12:52:27 +01:00
Alejandro Celaya
73e2485e09 Merge pull request #720 from acelaya-forks/feature/limit-time
Feature/limit time
2022-10-23 10:58:16 +02:00
Alejandro Celaya
0d94879e49 Updated changelog 2022-10-23 10:51:28 +02:00
Alejandro Celaya
6df12ce194 Moved date-time related utils to the proper folder 2022-10-23 10:49:35 +02:00
Alejandro Celaya
c3b60367f3 Added test covering custom formatting in DateInput 2022-10-23 10:43:01 +02:00
Alejandro Celaya
10d3deff37 Formatted scrollbar in date picker for time component 2022-10-23 10:22:31 +02:00
Alejandro Celaya
3cb79c167e Fixed date picker time styles 2022-10-23 10:13:53 +02:00
Alejandro Celaya
57a17d7e92 Created component for DateTimeInputs 2022-10-18 22:02:09 +02:00
Alejandro Celaya
894934fd08 Merge pull request #716 from acelaya-forks/feature/api3-support
Feature/api3 support
2022-10-12 10:55:16 +02:00
Alejandro Celaya
5a8aae3614 Updated changelog 2022-10-12 10:45:43 +02:00
Alejandro Celaya
3dde1a5b05 Covered short URL deletion when threshold error occurs 2022-10-12 10:43:30 +02:00
Alejandro Celaya
e6c79c19c2 Added support for API v3 error types on different error handlers 2022-10-12 10:35:16 +02:00
Alejandro Celaya
d64abeecdc Use APi v3 by default, and fall back to v2 in case of not found errors 2022-10-12 10:19:54 +02:00
Alejandro Celaya
da6d45a72c Updated to axios 1.1.2 2022-10-11 08:22:20 +02:00
Alejandro Celaya
497a735d80 Merge pull request #714 from acelaya-forks/feature/fix-datepicker-triangle
Feature/fix datepicker triangle
2022-10-08 10:23:06 +02:00
Alejandro Celaya
89f031b338 Updated changelog 2022-10-08 10:18:52 +02:00
Alejandro Celaya
47630dbcd2 Fixed date time picker arrow getting placed on the very edge of the popper 2022-10-08 10:18:08 +02:00
Alejandro Celaya
0d57684565 Merge pull request #712 from acelaya-forks/feature/update-deps
Updated deps
2022-10-05 18:25:20 +02:00
Alejandro Celaya
5880767ac3 Fixed incorrect import 2022-10-05 17:23:41 +02:00
Alejandro Celaya
14c4c29af3 Updated changelog 2022-10-05 17:19:16 +02:00
Alejandro Celaya
9f5614446e Updated bootstrap 2022-10-05 17:17:03 +02:00
Alejandro Celaya
d755e8ffc4 Updated to axios 1.0 2022-10-05 17:12:10 +02:00
Alejandro Celaya
a7a968ab6e Added dependency to history module as react-router-dom no longer depnds on it 2022-10-05 16:35:44 +02:00
Alejandro Celaya
f5757c6081 Fixed incorrectly inferred types 2022-10-04 23:27:11 +02:00
Alejandro Celaya
29fa4fa34d Fixed incorrectly inferred types 2022-10-04 23:24:07 +02:00
Alejandro Celaya
d2de9fb669 Updated dev deps 2022-10-04 23:17:12 +02:00
Alejandro Celaya
e124cd2490 Updated prod deps 2022-10-04 23:09:30 +02:00
Alejandro Celaya
e76c9041b5 Updated @fortawesome/fontawesome-svg-core to v6.2 2022-10-04 23:02:27 +02:00
Alejandro Celaya
755ae23fdb Updated fontawesome deps 2022-10-03 20:06:57 +02:00
Alejandro Celaya
90fde34a45 Merge pull request #711 from shlinkio/develop
Release 3.7.3
2022-09-13 17:48:40 +02:00
Alejandro Celaya
563c60668a Merge pull request #710 from acelaya-forks/feature/fix-loading-large
Feature/fix loading large
2022-09-13 17:45:32 +02:00
Alejandro Celaya
3a657e1e2f Updated changelog 2022-09-13 16:00:27 +02:00
Alejandro Celaya
4466d733b4 Fixed visits not being displayed after a large loading has finished 2022-09-13 15:56:53 +02:00
Alejandro Celaya
dadecdc674 Merge pull request #705 from acelaya-forks/feature/refactor-docker-build
Moved to docker build from reusable workflow
2022-08-19 14:59:09 +02:00
Alejandro Celaya
a2440d3180 Moved to docker build from reusable workflow 2022-08-19 12:48:17 +02:00
Alejandro Celaya
56e6a2a16d Merge pull request #704 from acelaya-forks/feature/ghcr-support
Feature/ghcr support
2022-08-14 17:33:27 +02:00
Alejandro Celaya
c918eaf903 Added GHCR publishing in docker build script 2022-08-14 17:29:01 +02:00
Alejandro Celaya
324eda25e0 Added support to publish docker image in GHCR 2022-08-14 17:27:45 +02:00
Alejandro Celaya
a46116d936 Merge pull request #699 from shlinkio/develop
Release 3.7.2
2022-08-07 18:31:24 +02:00
Alejandro Celaya
8fd419dc72 Merge pull request #698 from acelaya-forks/feature/multi-segment-slugs
Feature/multi segment slugs
2022-08-07 18:25:53 +02:00
Alejandro Celaya
18b27dbd0c Updated changelog 2022-08-07 18:21:24 +02:00
Alejandro Celaya
0c17818a24 Added support for short URLs with multi-segment slugs 2022-08-07 18:19:53 +02:00
Alejandro Celaya
b1749ee2ef Merge pull request #697 from acelaya-forks/feature/case-insensitive-search
Feature/case insensitive search
2022-08-07 13:34:23 +02:00
Alejandro Celaya
27b82c56b1 Updated changelog 2022-08-07 13:29:11 +02:00
Alejandro Celaya
f69bda351d Ensured tags, servers and domains search is case insensitive 2022-08-07 13:26:26 +02:00
Alejandro Celaya
4a92d0ff11 Merge pull request #696 from acelaya-forks/feature/fix-tests
Feature/fix tests
2022-08-07 13:14:56 +02:00
Alejandro Celaya
b37a983bde Updated changelog 2022-08-07 13:09:59 +02:00
Alejandro Celaya
97cf3b26b0 Fixed warning in ImportServersBtnTest 2022-08-07 13:07:25 +02:00
Alejandro Celaya
c490835f9b Ensured menu is displayed before asserting in DateRangeSelector test 2022-08-07 12:59:04 +02:00
Alejandro Celaya
a3ab2c6e1b Fixed invalid DOM in ManageServers test 2022-08-03 17:29:07 +02:00
Alejandro Celaya
ce5108937d Merge pull request #691 from shlinkio/dependabot/npm_and_yarn/terser-5.14.2
Bump terser from 5.12.1 to 5.14.2
2022-07-21 04:13:05 +02:00
dependabot[bot]
9164db181c Bump terser from 5.12.1 to 5.14.2
Bumps [terser](https://github.com/terser/terser) from 5.12.1 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-21 00:07:18 +00:00
Alejandro Celaya
aa14a17ad6 Merge pull request #690 from acelaya-forks/feature/fix-docker-build
Updated react-copy-to-clipboard
2022-07-19 18:48:54 +02:00
Alejandro Celaya
d67b8c0530 Recovered --force on npm ci, as some components still do not officially suport react 18 2022-07-19 18:45:18 +02:00
Alejandro Celaya
d41c1a2a52 Updated react-swipeable 2022-07-19 18:38:29 +02:00
Alejandro Celaya
3b938251d9 Updated react-datepicker 2022-07-19 18:34:48 +02:00
Alejandro Celaya
b8aa068876 Updated react-copy-to-clipboard 2022-07-19 18:28:55 +02:00
Alejandro Celaya
5d288de390 Merge pull request #689 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-17 12:00:07 +02:00
Alejandro Celaya
af851e708b Updated changelog 2022-07-17 11:52:07 +02:00
Alejandro Celaya
72399e7ccd Migrated VisitsTable test to react-testing-library, and removed latest references to enzyme 2022-07-17 11:50:26 +02:00
Alejandro Celaya
1ffd71e81f Migrated VisitsStats test to react testing library 2022-07-17 10:24:34 +02:00
Alejandro Celaya
d627de8e83 Migrated TagsSelector test to react testing library 2022-07-17 10:01:35 +02:00
Alejandro Celaya
fc4fdb4fc7 Migrated DropdownBtnMenu test to react testing library 2022-07-17 09:29:50 +02:00
Alejandro Celaya
126537185b Migrated DateRangeRow test to react testing library 2022-07-17 09:15:36 +02:00
Alejandro Celaya
24de0773d8 Migrated EditTagModal test to react testing library 2022-07-17 09:11:29 +02:00
Alejandro Celaya
cc77af6142 Merge pull request #687 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-17 08:42:52 +02:00
Alejandro Celaya
c16460af82 Migrated TagsTableRow test to react testing library 2022-07-16 10:59:18 +02:00
Alejandro Celaya
4c7bed90a3 Normalized mocks 2022-07-16 10:52:45 +02:00
Alejandro Celaya
491b2f2c07 Migrated TagsTable test to react testing library 2022-07-16 10:43:44 +02:00
Alejandro Celaya
a038f5e618 Migrated ShortUrlsRow test to react testing library 2022-07-16 10:28:14 +02:00
Alejandro Celaya
9ba74328ff Merge pull request #686 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-16 10:01:41 +02:00
Alejandro Celaya
90a643761a Migrated ShortUrlsRowMenu test to react testing library 2022-07-15 22:11:13 +02:00
Alejandro Celaya
6236d36372 Migrated DeleteShortUrlModal test to react testing library 2022-07-15 22:00:30 +02:00
Alejandro Celaya
065c908153 Migrated QrCodeModal test to react testing library 2022-07-15 21:42:16 +02:00
Alejandro Celaya
a14e612a38 Migrated DateRangeSelector test to react testing library 2022-07-14 22:14:42 +02:00
Alejandro Celaya
0b155b1d20 Merge pull request #685 from acelaya-forks/feature/testing-lib
Migrated SortableBarChartCard test to react testing library
2022-07-14 21:55:29 +02:00
Alejandro Celaya
9b9cfd0543 Migrated SortableBarChartCard test to react testing library 2022-07-11 18:26:52 +02:00
Alejandro Celaya
3d067371d3 Merge pull request #684 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-10 20:49:32 +02:00
Alejandro Celaya
381eb5a502 Migrated DropdownBtn test to react testing library 2022-07-10 20:42:58 +02:00
Alejandro Celaya
4a88f30d13 Migrated Message test to react testing library 2022-07-10 20:29:56 +02:00
Alejandro Celaya
bdf181adec Migrated PaginationDropdown test to react testing library 2022-07-10 20:11:01 +02:00
Alejandro Celaya
f97fce873b Migrated ShortUrlDetailLink test to react testing library 2022-07-10 19:58:27 +02:00
Alejandro Celaya
879017ecca Migrated ShortUrlFormCheckboxGroup test to react testing library 2022-07-10 19:51:21 +02:00
Alejandro Celaya
83150331e5 Renamed test helpers folder 2022-07-10 19:44:49 +02:00
Alejandro Celaya
7249ec4968 Merge branch 'feature/testing-lib' into develop 2022-07-09 23:19:18 +02:00
Alejandro Celaya
3ac148f7cd Merge pull request #683 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-09 23:18:49 +02:00
Alejandro Celaya
a73472f7e5 Removed debug line in logs 2022-07-09 23:18:09 +02:00
Alejandro Celaya
08ca59f990 Migrated DeleteTagConfirmModal test to react testing library 2022-07-09 23:13:15 +02:00
Alejandro Celaya
d07f7e757e Moved common test set-up code to helper function 2022-07-09 23:03:21 +02:00
Alejandro Celaya
cb13e82b9c Migrated ShortUrlsList test to react testing library 2022-07-09 22:37:26 +02:00
Alejandro Celaya
fd7aa570ed Merge pull request #681 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-08 15:38:42 +02:00
Alejandro Celaya
c00053f6e1 Migrated DateIntervalSelector test to react testing library 2022-07-08 15:11:51 +02:00
Alejandro Celaya
2e0e7f361c Migrated DateIntervalDropdownItems test to react testing library 2022-07-08 15:03:48 +02:00
Alejandro Celaya
21101d4da8 Migrated Result test to react testing library 2022-07-08 11:24:19 +02:00
Alejandro Celaya
65f739499f Migrated InfoTooltip test to react testing library 2022-07-08 11:03:58 +02:00
Alejandro Celaya
91ee4a32cd Migrated Tag test to react testing library 2022-07-08 10:48:29 +02:00
Alejandro Celaya
498668929f Merge pull request #680 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-07 19:06:01 +02:00
Alejandro Celaya
935b12763b Migrated TagsModeDropdown test to react testing library 2022-07-07 19:01:17 +02:00
Alejandro Celaya
28b15e4a85 Migrated TagsCards test to react testing library 2022-07-07 18:53:28 +02:00
Alejandro Celaya
6af49a9945 Migrated ShortUrlVisitsCount test to react testing library 2022-07-07 18:44:00 +02:00
Alejandro Celaya
c80ad70e3b Migrated ExportShortUrlsBtn test to react testing library 2022-07-06 18:59:30 +02:00
Alejandro Celaya
1a20065053 Migrated CreateShortUrlResult test to react testing library 2022-07-06 18:30:33 +02:00
Alejandro Celaya
edef36bae8 Merge pull request #679 from acelaya-forks/feature/testing-lib
Feature/testing lib
2022-07-05 21:12:04 +02:00
Alejandro Celaya
3cd25dc2df Migrated ShortUrlsTable test to react testing library 2022-07-05 20:46:31 +02:00
Alejandro Celaya
43840d7656 Migrated ShortUrlForm test to react testing library 2022-07-05 20:30:23 +02:00
Alejandro Celaya
a1bdb75036 Merge pull request #678 from acelaya-forks/feature/testing-lib
Migrated VisitsFilterDropdown test to react testing library
2022-07-04 16:36:20 +02:00
Alejandro Celaya
ac0107d450 Migrated VisitsFilterDropdown test to react testing library 2022-06-21 19:23:05 +02:00
Alejandro Celaya
d3d2cf72b9 Merge pull request #673 from acelaya-forks/feature/tests
Feature/tests
2022-06-20 08:06:11 +02:00
Alejandro Celaya
eb9ec4ec31 Migrated QrFormatDropdown test to react testing library 2022-06-13 21:38:39 +02:00
Alejandro Celaya
3201830b27 Migrated QrErrorCorrectionDropdown test to react testing library 2022-06-13 21:32:19 +02:00
Alejandro Celaya
58ddec6aff Merge pull request #672 from acelaya-forks/feature/rtl
Feature/rtl
2022-06-12 20:47:12 +02:00
Alejandro Celaya
59fd58b824 Migrated EditShortUrl test to react testing library 2022-06-12 20:41:40 +02:00
Alejandro Celaya
efa07f0368 Updated changelog 2022-06-12 20:19:48 +02:00
Alejandro Celaya
1dd6a8e2e4 Added proper color-schema to root element based on selected theme 2022-06-12 20:18:31 +02:00
Alejandro Celaya
bcd3fa8ce4 Merge pull request #670 from acelaya-forks/feature/rtl
Feature/rtl
2022-06-11 18:40:40 +02:00
Alejandro Celaya
6ff3cf544b Updated snapshot 2022-06-11 18:12:29 +02:00
Alejandro Celaya
ab21f923c6 Migrated OpenMapModalBtn test to react testing library 2022-06-11 18:10:08 +02:00
Alejandro Celaya
b75fd2e03a Migrated MapModal test to react testing library 2022-06-11 17:38:12 +02:00
Alejandro Celaya
ec7c7d521f Migrated TableOrderIcon test to react testing library 2022-06-11 17:28:47 +02:00
Alejandro Celaya
f9909713d9 Merge pull request #669 from acelaya-forks/feature/rtl
Feature/rtl
2022-06-11 17:12:29 +02:00
Alejandro Celaya
59087ced8a Migrated NavPills test to react testing library 2022-06-11 09:14:51 +02:00
Alejandro Celaya
84435714f5 Migrated ShortUrlVisitsHeader test to react testing library 2022-06-11 08:53:48 +02:00
Alejandro Celaya
6bd628712e Migrated TagVisitsHeader test to react testing library 2022-06-11 08:37:10 +02:00
Alejandro Celaya
997f4a6bdc Merge pull request #668 from acelaya-forks/feature/moar
Feature/moar
2022-06-10 21:42:37 +02:00
Alejandro Celaya
b1fec831c5 Migrated VisitsHeader test to react testing library 2022-06-10 21:35:42 +02:00
Alejandro Celaya
54fe849efd Migrated more tests to react testing lib 2022-06-10 21:31:13 +02:00
Alejandro Celaya
8bf1a9d023 Merge pull request #667 from acelaya-forks/feature/tests-and-more-tests
Feature/tests and more tests
2022-06-10 20:53:24 +02:00
Alejandro Celaya
07cedd0bdb Migrated DateInput test to react testing library 2022-06-10 20:48:53 +02:00
Alejandro Celaya
44a93ae556 Migrated CopyToClipboard test to react testing library 2022-06-10 20:29:42 +02:00
Alejandro Celaya
72f790b28c Merge pull request #666 from acelaya-forks/feature/tests
Migrated Paginator test to react testing library
2022-06-10 20:20:52 +02:00
Alejandro Celaya
a63f7e741a Ensured npm ci is run with --force until we get rid of enzyme 2022-06-10 20:09:38 +02:00
Alejandro Celaya
58f952df8a Migrated Paginator test to react testing library 2022-06-09 22:17:33 +02:00
Alejandro Celaya
2acd0ec95d Merge pull request #665 from acelaya-forks/feature/rtl-why-not
Feature/rtl why not
2022-06-09 07:31:26 +02:00
Alejandro Celaya
105254d053 Migrated CreateShortUrl test to react testing library 2022-06-08 18:28:16 +02:00
Alejandro Celaya
e538f2a3bb Migrated VisitsSettings test to react testing library 2022-06-08 18:24:21 +02:00
Alejandro Celaya
98ea491469 Merge pull request #664 from acelaya-forks/feature/teststs
Feature/teststs
2022-06-07 20:28:59 +02:00
Alejandro Celaya
10e50efb33 Migrated UserInterfaceSettings test to react testing library 2022-06-07 20:22:30 +02:00
Alejandro Celaya
d60023f585 Migrated TagSettings test to react testing library 2022-06-07 20:11:45 +02:00
Alejandro Celaya
c0d5feb433 Added comment 2022-06-06 22:46:53 +02:00
Alejandro Celaya
2451167296 Merge pull request #663 from acelaya-forks/feature/rtl-again
Feature/rtl again
2022-06-06 22:42:28 +02:00
Alejandro Celaya
4a70e4ecd3 Migrated ShortUrlsListSettings test to react testing library 2022-06-06 22:38:07 +02:00
Alejandro Celaya
a90c3da7b6 Migrated RealTimeUpdatesSettings test to react testing library 2022-06-06 22:23:21 +02:00
Alejandro Celaya
53e15b041d Merge pull request #662 from acelaya-forks/feature/tests-all-over
Feature/tests all over
2022-06-06 20:52:14 +02:00
Alejandro Celaya
7669254a0c Created helper function to convert mutable refs from useRef into element refs for the ref prop 2022-06-06 20:46:51 +02:00
Alejandro Celaya
b450e4093e Migrated Settings test to react testing library 2022-06-05 11:16:11 +02:00
Alejandro Celaya
a012d6206f Migrated ImportServersBtn test to react testing library 2022-06-05 11:06:26 +02:00
Alejandro Celaya
30f502a51b Migrated HighlightCard test to react testing library 2022-06-05 10:19:08 +02:00
Alejandro Celaya
4defeaf017 Merge pull request #661 from acelaya-forks/feature/here-we-go-again
Feature/here we go again
2022-06-04 19:18:18 +02:00
Alejandro Celaya
7f35fb0ada Migrated ServerError test to react testing library 2022-06-04 19:13:00 +02:00
Alejandro Celaya
cd1a926292 Migrated ServerForm test to react testing library 2022-06-04 19:02:20 +02:00
Alejandro Celaya
e46506b264 Migrated DuplicatedServersModal test to react testing library 2022-06-04 18:54:34 +02:00
Alejandro Celaya
807c5c3fb4 Merge pull request #659 from acelaya-forks/feature/moar-rtl
Feature/moar rtl
2022-06-04 10:25:17 +02:00
Alejandro Celaya
64efb1d43d Merge pull request #660 from shlinkio/dependabot/npm_and_yarn/eventsource-1.1.1
Bump eventsource from 1.1.0 to 1.1.1
2022-06-04 10:22:55 +02:00
Alejandro Celaya
49e1f82b03 Migrated ManageServersRowDropdown test to react testing library 2022-06-04 10:20:24 +02:00
Alejandro Celaya
1bd8636c19 Migrated ServersListGroup test to react testing library 2022-06-04 09:59:19 +02:00
Alejandro Celaya
cfe84e1275 Migrated ManageServersRow test to react testing library 2022-06-04 09:46:49 +02:00
Alejandro Celaya
5dda4731a0 Migrated ManageServers test to react testing library 2022-06-04 09:34:46 +02:00
dependabot[bot]
ce830ea6d3 Bump eventsource from 1.1.0 to 1.1.1
Bumps [eventsource](https://github.com/EventSource/eventsource) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/EventSource/eventsource/releases)
- [Changelog](https://github.com/EventSource/eventsource/blob/master/HISTORY.md)
- [Commits](https://github.com/EventSource/eventsource/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: eventsource
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-01 22:45:25 +00:00
Alejandro Celaya
b217b70dfe Migrated DeleteServerModal test to react testing library 2022-05-29 20:45:19 +02:00
Alejandro Celaya
ceee26ad25 Migrated Time test to react testing library 2022-05-29 20:32:34 +02:00
Alejandro Celaya
876018390d Merge pull request #658 from acelaya-forks/feature/rtl
Migrated CreateServer test to react testing library
2022-05-29 16:13:17 +02:00
Alejandro Celaya
0366f3544b Merge pull request #656 from shlinkio/dependabot/npm_and_yarn/async-2.6.4
Bump async from 2.6.3 to 2.6.4
2022-05-29 16:12:31 +02:00
Alejandro Celaya
b964ba5317 Merge pull request #643 from shlinkio/dependabot/npm_and_yarn/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8
2022-05-29 16:12:00 +02:00
Alejandro Celaya
494e36c842 Migrated CreateServer test to react testing library 2022-05-29 12:18:21 +02:00
Alejandro Celaya
9c611a5b13 Merge pull request #657 from acelaya-forks/feature/mar-tests
Feature/mar tests
2022-05-28 12:58:39 +02:00
Alejandro Celaya
357c478640 Migrated LineChartCard test to react testing library 2022-05-28 12:54:33 +02:00
Alejandro Celaya
89f830d9bb Migrated DoughnutChartLegend test to react testing library 2022-05-28 12:33:50 +02:00
Alejandro Celaya
56150e8707 Migrated TagCard test to react testing library 2022-05-28 12:16:17 +02:00
Alejandro Celaya
1d60db25bd Removed all default export except for services and reducers 2022-05-28 11:16:59 +02:00
Alejandro Celaya
2cac1d9fd2 More default exports removals 2022-05-28 10:47:39 +02:00
Alejandro Celaya
e70724f058 Refactored some default exports to regular ones 2022-05-28 10:34:12 +02:00
Alejandro Celaya
27a05e55c9 Migrated TagsList to react testing library 2022-05-27 13:42:30 +02:00
Alejandro Celaya
0a0de86ecd Merge pull request #655 from shlinkio/develop
Release 3.7.1
2022-05-25 20:44:29 +02:00
dependabot[bot]
ec025b7d0f Bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 18:34:47 +00:00
Alejandro Celaya
744cea1f11 Merge pull request #654 from acelaya-forks/feature/fix-nan
Feature/fix nan
2022-05-25 20:32:41 +02:00
Alejandro Celaya
073617b6d3 Fixed rendering of values greater than 1000 2022-05-25 20:26:34 +02:00
Alejandro Celaya
8d69945e8e Switched visits buttons order 2022-05-25 18:26:34 +02:00
Alejandro Celaya
3f34a1fb87 Updated to node 16 2022-05-25 18:13:32 +02:00
Alejandro Celaya
7bbc7250dd Merge pull request #652 from acelaya-forks/feature/and-moar-rtl
Feature/and moar rtl
2022-05-17 22:36:39 +02:00
Alejandro Celaya
63433864d3 Migrated ServersDropdown to react testing library 2022-05-17 22:31:02 +02:00
Alejandro Celaya
e53f90fc5c Migrated EditDomainRedirectsModal to react testing library 2022-05-17 22:18:01 +02:00
Alejandro Celaya
33adb08105 Merge pull request #651 from acelaya-forks/featue/rtl-more
Migrated DeleteServerButton to react testing library
2022-05-16 20:46:53 +02:00
Alejandro Celaya
4a610d182c Migrated DeleteServerButton to react testing library 2022-05-16 20:42:00 +02:00
Alejandro Celaya
8655d9be87 Merge pull request #650 from acelaya-forks/feature/esm-scripts
Feature/esm scripts
2022-05-15 08:42:28 +02:00
Alejandro Celaya
9962ddcd36 Updated changelog 2022-05-15 08:37:18 +02:00
Alejandro Celaya
e117429373 Updated replace-version script to use ESM and updated to node 16.14 2022-05-15 08:35:59 +02:00
Alejandro Celaya
dd0f5f961c Updated create-dist-file script to use ESM 2022-05-15 08:32:36 +02:00
Alejandro Celaya
f0b5505770 Merge pull request #649 from acelaya-forks/feature/downgrade-chalk
Downgraded to chalk 4
2022-05-14 17:32:16 +02:00
Alejandro Celaya
c63b4f9f21 Downgraded to chalk 4 2022-05-14 17:12:50 +02:00
Alejandro Celaya
6ed19af295 Merge pull request #647 from shlinkio/develop
Release 3.7.0
2022-05-14 16:59:31 +02:00
Alejandro Celaya
46f7a67b14 Tagged v3.7.0 in changelog 2022-05-14 16:51:59 +02:00
Alejandro Celaya
6f2639fd1f Merge pull request #646 from acelaya-forks/feature/short-url-filtering
Feature/short url filtering
2022-05-14 16:48:18 +02:00
Alejandro Celaya
f1568eb43b Updated changelog 2022-05-14 16:43:00 +02:00
Alejandro Celaya
aefc632ed7 Removed some default imports 2022-05-14 16:41:09 +02:00
Alejandro Celaya
bd3555db94 Fixed coding styles 2022-05-14 16:38:25 +02:00
Alejandro Celaya
ed366fa4cc Updated ShortUrlsFilteringBar test 2022-05-14 16:36:45 +02:00
Alejandro Celaya
30aeba0af2 Fixed ordering dropdown to be shorter in short URLs filter 2022-05-14 14:15:21 +02:00
Alejandro Celaya
b4c3bd16b1 Fixed colors and styles in tags selector 2022-05-14 13:05:23 +02:00
Alejandro Celaya
4b97abaf72 Improved tags filtering for short URLs, allowing to select from any existing tag 2022-05-14 12:53:02 +02:00
Alejandro Celaya
e387706a7b Updated to ExternalLink 2.0 2022-05-14 12:51:36 +02:00
Alejandro Celaya
a7cc8786c3 Migrated ExportBtn test to react testing library, and changed icon 2022-05-14 11:15:48 +02:00
Alejandro Celaya
5c0573deb7 Merge pull request #645 from acelaya-forks/feature/moar-rtl-tests
Feature/moar rtl tests
2022-05-13 20:29:59 +02:00
Alejandro Celaya
bc8956db4a Fixed coding styles 2022-05-13 20:25:32 +02:00
Alejandro Celaya
d44be88b3f Fixed ilegal rendering of trinside div in DomainRow test 2022-05-13 20:21:20 +02:00
Alejandro Celaya
64ee9a39cc Migrated HorizontalBarChart test to react testing library 2022-05-13 20:18:40 +02:00
Alejandro Celaya
4999f982e4 Migrated ChartCard test to react testing library 2022-05-13 19:59:30 +02:00
Alejandro Celaya
f3f0dbac19 Added shlinkio css coding styles 2022-05-12 22:44:12 +02:00
Alejandro Celaya
c2818645c4 Merge pull request #644 from acelaya-forks/feature/new-css-style
Feature/new css style
2022-05-11 22:37:02 +02:00
Alejandro Celaya
b0a4aee175 Updated changelog 2022-05-11 22:33:02 +02:00
Alejandro Celaya
67c45f444b Replaced adidas coding styles for CSS with a custom one based on stylelint recommended 2022-05-11 22:32:17 +02:00
dependabot[bot]
a8c6e916cf Bump ini from 1.3.5 to 1.3.8
Bumps [ini](https://github.com/npm/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/npm/ini/releases)
- [Changelog](https://github.com/npm/ini/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/ini/compare/v1.3.5...v1.3.8)

---
updated-dependencies:
- dependency-name: ini
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-11 19:43:12 +00:00
Alejandro Celaya
f3570d0c9d Removed no-longer needed deps 2022-05-11 21:41:19 +02:00
Alejandro Celaya
653be14e77 Merge pull request #628 from shlinkio/dependabot/npm_and_yarn/ejs-3.1.7
Bump ejs from 3.1.6 to 3.1.7
2022-05-11 19:38:16 +02:00
Alejandro Celaya
71c8b596e7 Merge pull request #633 from shlinkio/dependabot/npm_and_yarn/kind-of-6.0.3
Bump kind-of from 6.0.2 to 6.0.3
2022-05-11 19:38:09 +02:00
Alejandro Celaya
ba45b6a7a6 Merge pull request #634 from shlinkio/dependabot/npm_and_yarn/trim-newlines-3.0.1
Bump trim-newlines from 3.0.0 to 3.0.1
2022-05-11 19:38:01 +02:00
Alejandro Celaya
cd311aeaa5 Merge pull request #635 from shlinkio/dependabot/npm_and_yarn/dns-packet-1.3.4
Bump dns-packet from 1.3.1 to 1.3.4
2022-05-11 19:37:53 +02:00
Alejandro Celaya
4f7a6d5c96 Merge pull request #636 from shlinkio/dependabot/npm_and_yarn/ansi-regex-3.0.1
Bump ansi-regex from 3.0.0 to 3.0.1
2022-05-11 19:37:42 +02:00
Alejandro Celaya
a4fb439dd4 Merge pull request #641 from acelaya-forks/feature/user-event
Feature/user event
2022-05-11 19:29:39 +02:00
Alejandro Celaya
3870752bba Replaced firEvent with userEvent as much as possible 2022-05-11 19:18:43 +02:00
Alejandro Celaya
7f059c3f3b Migrated to testing-library/user-event for complex events in tests 2022-05-10 20:54:14 +02:00
Alejandro Celaya
686fe5abbe Merge pull request #640 from acelaya-forks/feature/more-rtl-tests
Feature/more rtl tests
2022-05-09 19:53:46 +02:00
Alejandro Celaya
1f47658c3c Fixed coding styles 2022-05-09 19:47:41 +02:00
Alejandro Celaya
d582a0f9e5 Migrated DomainStatusIcon test to react testing library 2022-05-09 19:45:09 +02:00
Alejandro Celaya
b1d51a4103 Migrated ManageDomains test to react testing library 2022-05-09 19:23:35 +02:00
Alejandro Celaya
fb0adf74f3 Migrated DomainsSelector test to react testing library 2022-05-09 19:03:19 +02:00
Alejandro Celaya
0b16300a70 Migrated DomainRow test to react testing library 2022-05-09 18:38:14 +02:00
Alejandro Celaya
43302ef5a8 Migrated ShlinkLogo test to react testing library 2022-05-06 21:24:16 +02:00
Alejandro Celaya
3846ca293c Migrated SimplePaginator test to react testing library 2022-05-06 21:20:14 +02:00
Alejandro Celaya
00f154ef4e Migrated ShlinkVersionsContainer test to react testing library 2022-05-06 21:01:44 +02:00
Alejandro Celaya
4ea826ed2c Migrated ShlinkVersions test to react testing library 2022-05-06 20:25:48 +02:00
Alejandro Celaya
d327142d00 Migrated ScrollToTop test to react testing library 2022-05-06 20:13:51 +02:00
Alejandro Celaya
37adcb52cf Migrated NotFound test to react testing library 2022-05-06 19:55:25 +02:00
Alejandro Celaya
fcbb9cda12 Migrated HorizontalBarChart test to react testing library + snapshots for the events on the canvas 2022-05-06 19:46:47 +02:00
Alejandro Celaya
116c36febc Merge pull request #639 from acelaya-forks/feature/more-rtl-tests
Feature/more rtl tests
2022-05-06 19:16:07 +02:00
Alejandro Celaya
43a409fb30 Updated to stryker v6 2022-05-06 19:02:03 +02:00
Alejandro Celaya
63f26d0089 Migrated MenuLayout test to react testing library 2022-05-06 18:54:00 +02:00
Alejandro Celaya
218ea09d23 Removed no longer needed module mocking 2022-05-03 20:39:09 +02:00
Alejandro Celaya
a322886710 Migrated MainHeader test to react testing library 2022-05-03 20:36:24 +02:00
Alejandro Celaya
29182ae349 Migrated Home test to react testing library 2022-05-03 20:15:22 +02:00
Alejandro Celaya
bc3bc8dd8a Migrated ErrorHandler test to react testing library 2022-05-03 20:01:40 +02:00
Alejandro Celaya
e128b847be Migrated AsideMenu test to react testing library 2022-05-03 18:03:14 +02:00
Alejandro Celaya
f72251c125 Migrated AppUpdateBanner test to react testing library 2022-05-03 17:49:42 +02:00
Alejandro Celaya
9784cbb3ac Migrated App test to react testing library 2022-05-03 17:36:34 +02:00
Alejandro Celaya
e6f9003fb6 Merge pull request #638 from acelaya-forks/feature/more-rtl-tests
Feature/more rtl tests
2022-05-02 19:39:30 +02:00
Alejandro Celaya
e8a5eadd2b Migrated ShlinkApiError test from enzyme to react testing library 2022-05-02 19:34:33 +02:00
Alejandro Celaya
337bfc47c1 Deleted ForServerVersion component, which is no longer used 2022-05-02 19:28:07 +02:00
Alejandro Celaya
677f1da8df Removed last occurrence of ForServerVersion component, replaced by feature check 2022-05-02 19:24:57 +02:00
Alejandro Celaya
8918b1ac96 Migrated Overview test from enzyme to react testing library 2022-05-02 19:19:47 +02:00
Alejandro Celaya
0de8eb1568 Migrated ForServerVersion test from enzyme to react testing library 2022-05-02 18:58:57 +02:00
Alejandro Celaya
c00aaa9018 Migrated UseExistingIfFoundInfoIcon test from enzyme to react testing library 2022-05-02 18:54:19 +02:00
Alejandro Celaya
e837ee5225 Migrated EditServer test from enzyme to react testing library 2022-05-02 18:47:18 +02:00
dependabot[bot]
fc589a0b29 Bump ejs from 3.1.6 to 3.1.7
Bumps [ejs](https://github.com/mde/ejs) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/mde/ejs/releases)
- [Changelog](https://github.com/mde/ejs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mde/ejs/compare/v3.1.6...v3.1.7)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:38:29 +00:00
dependabot[bot]
b0769d1cf8 Bump ansi-regex from 3.0.0 to 3.0.1
Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: ansi-regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:38:13 +00:00
dependabot[bot]
5befd67270 Bump dns-packet from 1.3.1 to 1.3.4
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

---
updated-dependencies:
- dependency-name: dns-packet
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:38:12 +00:00
dependabot[bot]
59bdeb67bc Bump trim-newlines from 3.0.0 to 3.0.1
Bumps [trim-newlines](https://github.com/sindresorhus/trim-newlines) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/sindresorhus/trim-newlines/releases)
- [Commits](https://github.com/sindresorhus/trim-newlines/commits)

---
updated-dependencies:
- dependency-name: trim-newlines
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:38:10 +00:00
dependabot[bot]
2d1de2cac8 Bump kind-of from 6.0.2 to 6.0.3
Bumps [kind-of](https://github.com/jonschlinkert/kind-of) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/jonschlinkert/kind-of/releases)
- [Changelog](https://github.com/jonschlinkert/kind-of/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonschlinkert/kind-of/compare/6.0.2...6.0.3)

---
updated-dependencies:
- dependency-name: kind-of
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:38:09 +00:00
Alejandro Celaya
d3f180f270 Merge pull request #632 from acelaya-forks/feature/jest-28
Feature/jest 28
2022-05-02 13:36:58 +02:00
Alejandro Celaya
5482766d03 Updated changelog 2022-05-02 13:24:44 +02:00
Alejandro Celaya
dfbe43ef02 Added missing configs to fixt tests with Jest 28 2022-05-02 13:22:38 +02:00
Alejandro Celaya
ed7bb20bbb Updated to jest 28 2022-05-02 12:08:47 +02:00
Alejandro Celaya
57a2a03469 Merge pull request #631 from acelaya-forks/feature/react-chartjs-4
Feature/react chartjs 4
2022-05-02 11:57:04 +02:00
Alejandro Celaya
df9c1a88fc Updated changelog 2022-05-02 11:52:16 +02:00
Alejandro Celaya
c8b78d04e2 Fixed jest config to transform react-chartjs-2 lib 2022-05-02 11:51:17 +02:00
Alejandro Celaya
c516969686 Updated to react-chartjs 4 2022-05-02 11:35:05 +02:00
Alejandro Celaya
fd4295ade8 Merge pull request #630 from acelaya-forks/feature/react-testing-lib
Feature/react testing lib
2022-05-02 11:04:12 +02:00
Alejandro Celaya
39d4f8c73d Migrated Checkbox test to rteact testing library 2022-05-02 10:21:18 +02:00
Alejandro Celaya
d9b55f1d95 Updated changelog 2022-05-02 10:03:27 +02:00
Alejandro Celaya
66d8a32f49 Migrated SimpleCard test to react testing library 2022-05-02 10:01:29 +02:00
Alejandro Celaya
8b091a7b23 Migrated ShortUrlCreationSetting test to react testing library 2022-05-02 09:48:49 +02:00
Alejandro Celaya
8edb3dc923 Migrated NonOrphanVisits test to react testing library 2022-05-01 16:52:33 +02:00
Alejandro Celaya
a93d1e821d Merge pull request #629 from acelaya-forks/feature/shlink-2.6
Feature/shlink 2.6
2022-05-01 11:07:42 +02:00
Alejandro Celaya
9c5cad7571 Updated changelog 2022-05-01 11:01:57 +02:00
Alejandro Celaya
b970b38c29 Removed check on title support 2022-05-01 11:00:46 +02:00
Alejandro Celaya
763ef207f1 Removed conditional orphan visits section 2022-05-01 10:50:06 +02:00
Alejandro Celaya
a949ec9e8e Removed checks for QR code features that were not supported on versions older than 2.6 2022-05-01 10:44:12 +02:00
Alejandro Celaya
9518ad9bb4 Dropped support to send tags to the PATCH endpoint 2022-05-01 10:30:51 +02:00
Alejandro Celaya
5a0d67e409 Merge pull request #624 from acelaya-forks/feature/domain-visits
Feature/domain visits
2022-04-30 12:07:24 +02:00
Alejandro Celaya
e6932e7353 Created DomainVisits test 2022-04-30 12:01:50 +02:00
Alejandro Celaya
ddb08f4d2e Removed non-needed components which were just wrapping another component that could directly be used instead 2022-04-30 11:00:19 +02:00
Alejandro Celaya
368f7acd2d Updated react and react-dom to v18.1 2022-04-30 09:24:53 +02:00
Alejandro Celaya
6714f90c37 Fixed linting issues 2022-04-30 09:19:43 +02:00
Alejandro Celaya
bbaa4d0f05 Improved domainVisits reducer covering new visits for different domains and default domain 2022-04-30 09:18:53 +02:00
Alejandro Celaya
3aa990a1b0 Created domainVisits reducer test 2022-04-30 09:11:30 +02:00
Alejandro Celaya
464ee11d0d Added react testing library and add test for DomainDropdown 2022-04-30 09:05:12 +02:00
Alejandro Celaya
f909d38130 Updated changelog 2022-04-24 18:55:34 +02:00
Alejandro Celaya
77e59c886d Added test for ShlinkApiClient.getDomainVisits 2022-04-24 18:54:44 +02:00
Alejandro Celaya
05254326cb Implemented domain visits section 2022-04-24 18:36:25 +02:00
Alejandro Celaya
932dec3bde Added dropdown in domains section, to allow multiple options over domains 2022-04-24 13:10:04 +02:00
Alejandro Celaya
e976a0c716 Merge pull request #621 from acelaya-forks/feature/react-18
Feature/react 18
2022-04-24 11:34:17 +02:00
Alejandro Celaya
71b68562db Fixed types in Overview component test 2022-04-24 11:28:32 +02:00
Alejandro Celaya
460d2d23ce Updated changelog 2022-04-24 11:23:09 +02:00
Alejandro Celaya
6aee08b866 Ensured react-leaflet is transformed with jest, until updated to jest 28 2022-04-24 11:21:01 +02:00
Alejandro Celaya
271b19a4ec Fixed no longer implicit children prop in FunctionalComponent type 2022-04-24 10:39:11 +02:00
Alejandro Celaya
d5b1dc5bff Updated to stable packages with support for react 18 2022-04-23 11:52:39 +02:00
Alejandro Celaya
965e69c525 Fixed reference error 2022-04-03 10:10:10 +02:00
Alejandro Celaya
bd549c8642 Updated to latest react-redux beta 2022-04-03 09:43:22 +02:00
Alejandro Celaya
66edaed3a0 Updated to react 18 2022-04-02 08:58:48 +02:00
Alejandro Celaya
79831322fd Merge pull request #618 from acelaya-forks/feature/latest-error
Fixed call to an invalid function in prod envs
2022-04-02 08:41:07 +02:00
Alejandro Celaya
ed1c5a2197 Fixed call to an invalid function in prod envs 2022-04-02 08:32:54 +02:00
Alejandro Celaya
6d32379b67 Merge pull request #615 from acelaya-forks/feature/csvjson-update
Feature/csvjson update
2022-03-31 20:36:13 +02:00
Alejandro Celaya
56a62ae505 Added tests for new CSV-JSON helper functions 2022-03-31 20:32:39 +02:00
Alejandro Celaya
50072f5997 Updated changelog 2022-03-31 20:20:02 +02:00
Alejandro Celaya
e875e05538 Replaced unmaintained dependency 2022-03-31 20:18:05 +02:00
Alejandro Celaya
e2c8551baf Merge pull request #614 from shlinkio/acelaya-patch-1
Removed comment
2022-03-27 17:45:51 +02:00
Alejandro Celaya
1b0a2811e0 Removed comment 2022-03-27 17:41:29 +02:00
Alejandro Celaya
9cac4d23a7 Merge pull request #611 from acelaya-forks/feature/new-coding-style
Feature/new coding style
2022-03-27 09:48:39 +02:00
Alejandro Celaya
b323ddbd33 Temporarily disabled som a11y linting rules 2022-03-27 09:44:47 +02:00
Alejandro Celaya
98450ebec3 Removed no longer needed eslint disable comments 2022-03-26 13:07:58 +01:00
Alejandro Celaya
28a5166f56 Updated changelog 2022-03-26 12:59:54 +01:00
Alejandro Celaya
4f128b3fe8 Fixed tests 2022-03-26 12:46:32 +01:00
Alejandro Celaya
fd5060b996 Updated to latest eslint 2022-03-26 12:26:46 +01:00
Alejandro Celaya
a2df486280 Updated to airbnb coding styles 2022-03-26 12:17:42 +01:00
Alejandro Celaya
4e9b19afd1 Merge pull request #609 from acelaya-forks/feature/uneject
Feature/uneject
2022-03-25 17:48:04 +01:00
Alejandro Celaya
4d78949b8d Removed test script and used jest directly instead 2022-03-25 17:43:15 +01:00
Alejandro Celaya
13bafdc924 Disabled false positive eslint rule 2022-03-25 17:40:18 +01:00
Alejandro Celaya
ea95e8e7b5 Disabled linting while building 2022-03-25 17:27:41 +01:00
Alejandro Celaya
eaa1a2f2ca Added explicit dependency on webpack 5.70 2022-03-25 17:13:36 +01:00
Alejandro Celaya
9d6121903e Fixed some dependency references 2022-03-25 16:59:37 +01:00
Alejandro Celaya
2795bf050e Dejected project back to react-scripts, where posible 2022-03-24 21:27:33 +01:00
Alejandro Celaya
0e4e430673 Fixed margin in button 2022-03-24 20:23:46 +01:00
Alejandro Celaya
3e58d861ec Merge pull request #608 from shlinkio/develop
Release 3.6.0
2022-03-17 20:41:27 +01:00
Alejandro Celaya
2d8c2f92c4 Added v3.6.0 to changelog 2022-03-17 20:38:38 +01:00
Alejandro Celaya
56fa114f3c Merge pull request #607 from acelaya-forks/feature/export-urls
Feature/export urls
2022-03-17 20:36:11 +01:00
Alejandro Celaya
0a57390c46 Created ExportShortUrlsBtn test 2022-03-17 20:28:47 +01:00
Alejandro Celaya
ea7345b872 Updated changelog 2022-03-13 19:09:06 +01:00
Alejandro Celaya
e44520b2c2 Enhanced ReportExporter test 2022-03-13 19:07:33 +01:00
Alejandro Celaya
92ddcad753 Implemented short URLs exporting 2022-03-13 18:56:42 +01:00
Alejandro Celaya
e632c5b04f Abstracted logic to parse tags from string to array and back for the query 2022-03-13 11:14:30 +01:00
Alejandro Celaya
47d30aaa34 Created ExportBtn test 2022-03-13 11:00:45 +01:00
Alejandro Celaya
a26019ca78 Re-positioned components in short urls list for consistency with other sections 2022-03-13 10:43:57 +01:00
Alejandro Celaya
ef8db5e2cd Moved short URL ordering dropdown to ShortUrlsFilteringBar to simplify positioning 2022-03-13 10:32:27 +01:00
Alejandro Celaya
18f952f4fc Merge branch 'develop' into feature/export-urls 2022-03-13 09:56:59 +01:00
Alejandro Celaya
389f4efa4d Merge pull request #602 from acelaya-forks/feature/font-awesome-6
Updated to fontawesome 6
2022-03-13 08:44:39 +01:00
Alejandro Celaya
d1e6b052d9 Updated to fontawesome 6 2022-03-13 08:40:52 +01:00
Alejandro Celaya
7fd360495b Created button to use when anything needs to be exported 2022-03-12 20:51:30 +01:00
Alejandro Celaya
187e26810d Merge pull request #600 from acelaya-forks/feature/update-react-datepicker
Updated to latest react-datepicker major version
2022-03-11 17:27:23 +01:00
Alejandro Celaya
8a1edfe7cf Fixed usage of old module in InfoTooltip test 2022-03-11 17:23:43 +01:00
Alejandro Celaya
81d405d7be Updated to latest react-datepicker major version 2022-03-11 17:16:24 +01:00
Alejandro Celaya
c4148f0494 Fixed reactstrap 9 deprecated warnings 2022-03-11 16:37:41 +01:00
Alejandro Celaya
a8f996bec7 Merge pull request #599 from acelaya-forks/feature/update-ts
Updated to latest typescript
2022-03-11 16:25:57 +01:00
Alejandro Celaya
faa81ea1a5 Merge pull request #598 from acelaya-forks/feature/footer-alignment
Feature/footer alignment
2022-03-11 16:22:00 +01:00
Alejandro Celaya
ec360d3a28 Updated to latest typescript 2022-03-11 16:20:38 +01:00
Alejandro Celaya
749074604f Added missing parentheses 2022-03-11 16:17:44 +01:00
Alejandro Celaya
c60a6a78c8 Updated changelog 2022-03-11 16:13:54 +01:00
Alejandro Celaya
f15b803851 Created sidebar reducer test 2022-03-11 16:12:54 +01:00
Alejandro Celaya
c949359d6f Renamed sidebar actions as they make more sense 2022-03-11 16:07:17 +01:00
Alejandro Celaya
73d4707420 Ensured versions footer has proper classes based on sidebar status, not selected server 2022-03-11 16:03:15 +01:00
Alejandro Celaya
4f731d9de8 Mitigated wrong footer alignment on some server sections 2022-03-10 19:13:39 +01:00
Alejandro Celaya
2b400beb31 Merge pull request #597 from shlinkio/dependabot/npm_and_yarn/urijs-1.19.10
Bump urijs from 1.19.9 to 1.19.10
2022-03-09 07:13:12 +01:00
dependabot[bot]
a3616b56f5 Bump urijs from 1.19.9 to 1.19.10
Bumps [urijs](https://github.com/medialize/URI.js) from 1.19.9 to 1.19.10.
- [Release notes](https://github.com/medialize/URI.js/releases)
- [Changelog](https://github.com/medialize/URI.js/blob/gh-pages/CHANGELOG.md)
- [Commits](https://github.com/medialize/URI.js/compare/v1.19.9...v1.19.10)

---
updated-dependencies:
- dependency-name: urijs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-08 23:43:05 +00:00
Alejandro Celaya
65a162bdd2 Fixed linting errors 2022-03-07 20:28:46 +01:00
Alejandro Celaya
0e7c2f00d1 Merge pull request #596 from acelaya-forks/feature/update-deps
Feature/update deps
2022-03-07 18:07:02 +01:00
Alejandro Celaya
2b59d02ed9 Silenced ts errors on chart tests 2022-03-07 18:06:28 +01:00
Alejandro Celaya
45c6d3996e Updated changelog 2022-03-07 17:44:48 +01:00
Alejandro Celaya
bb7545824a Updated to compare-versions 4 2022-03-07 17:44:07 +01:00
Alejandro Celaya
feb2154257 Updated to react-datepicker 4.3 2022-03-07 17:41:59 +01:00
Alejandro Celaya
8551fcf08f Updated to react-chartjs-2 3.3 2022-03-07 17:39:03 +01:00
Alejandro Celaya
61b094ee7d Updated remaining dev deps 2022-03-07 17:29:38 +01:00
Alejandro Celaya
42714066bf Updated some dev packages 2022-03-07 17:09:54 +01:00
Alejandro Celaya
94350683bd Updated more deps 2022-03-07 16:58:16 +01:00
Alejandro Celaya
3d7950bb51 Updated some deps 2022-03-07 16:53:41 +01:00
Alejandro Celaya
ec4b777429 Merge pull request #591 from acelaya-forks/feature/bootstrap5
Feature/bootstrap5
2022-03-07 16:34:19 +01:00
Alejandro Celaya
61b61bce1c Fixed styles 2022-03-07 16:28:21 +01:00
Alejandro Celaya
dcfb5ab054 Fixed tests after bootstrap 5 update 2022-03-07 16:27:25 +01:00
Alejandro Celaya
6346f82a0a Updated target in tsconfig to es2019 2022-03-07 14:26:35 +01:00
Alejandro Celaya
31f1d5b530 Updated babel packages and extracted babel config 2022-03-07 14:21:09 +01:00
Alejandro Celaya
fc71c0f5c8 Fixed text decoration for anchors with btn class 2022-03-07 11:25:42 +01:00
Alejandro Celaya
7ab368a424 Fixed ShortUrlCreationSettings test 2022-03-07 11:17:40 +01:00
Alejandro Celaya
1cee36ec9f Updated changelog 2022-03-07 11:05:49 +01:00
Alejandro Celaya
74635281de Fixed table rendering issues 2022-03-07 11:03:41 +01:00
Alejandro Celaya
0f43ad59a0 Updated jest packages 2022-03-07 10:30:57 +01:00
Alejandro Celaya
b97ea17950 Fixed smooth scrolling which feels weird with client-side routing 2022-03-07 09:13:23 +01:00
Alejandro Celaya
3f48ca401d Fixed responsive table headers 2022-03-07 09:09:30 +01:00
Alejandro Celaya
3ecad0161b Fixed gaps in sticky tables 2022-03-07 08:55:00 +01:00
Alejandro Celaya
9ff331e2db Fixed styles in tag edition modal 2022-03-07 08:46:43 +01:00
Alejandro Celaya
27e3b6f0d0 Fixed short URL creation and modal close buttons 2022-03-06 11:16:31 +01:00
Alejandro Celaya
6a739b7a25 Fixed styles in main header 2022-03-06 10:58:30 +01:00
Alejandro Celaya
56313e5db8 Fixed home page styles for bootstrap 5 2022-03-06 10:38:26 +01:00
Alejandro Celaya
d8e4a4b891 More improvements to form controls with bootstrap 5 2022-03-05 19:57:48 +01:00
Alejandro Celaya
dee1932a64 Fixed form labels 2022-03-05 19:43:10 +01:00
Alejandro Celaya
661b9b2cc1 Fixed more rendering issues after BS5 migration 2022-03-05 16:11:01 +01:00
Alejandro Celaya
f24fb61e20 Fixed horizontal scroll 2022-03-05 15:46:26 +01:00
Alejandro Celaya
0993b43c79 Created namespace for form controls 2022-03-05 14:43:43 +01:00
Alejandro Celaya
ec403d7b1f Fixed links and some form styles 2022-03-05 14:04:01 +01:00
Alejandro Celaya
f4fa1582a7 Fixed overwritting of default bootstrap color 2022-03-05 13:32:47 +01:00
Alejandro Celaya
e5a84b1505 Updated margin, padding and alignment classes to the new bootstrap 5 approach 2022-03-05 13:26:28 +01:00
Alejandro Celaya
ce871fe2a2 Updated to latest bootstrap and reactstrap 2022-03-05 13:14:26 +01:00
Alejandro Celaya
5a713fe92f Merge pull request #588 from shlinkio/dependabot/npm_and_yarn/urijs-1.19.9
Bump urijs from 1.19.8 to 1.19.9
2022-03-04 00:57:11 +01:00
dependabot[bot]
819df9cf3d Bump urijs from 1.19.8 to 1.19.9
Bumps [urijs](https://github.com/medialize/URI.js) from 1.19.8 to 1.19.9.
- [Release notes](https://github.com/medialize/URI.js/releases)
- [Changelog](https://github.com/medialize/URI.js/blob/gh-pages/CHANGELOG.md)
- [Commits](https://github.com/medialize/URI.js/compare/v1.19.8...v1.19.9)

---
updated-dependencies:
- dependency-name: urijs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-03 23:34:50 +00:00
Alejandro Celaya
a67e0b052f Merge pull request #587 from acelaya-forks/feature/split-scripts
Split dist file creation and version replacing from main build script
2022-02-27 20:15:03 +01:00
Alejandro Celaya
c088259e46 Split dist file creation and version replacing from main build script 2022-02-27 20:10:10 +01:00
Alejandro Celaya
82f8636af5 Merge pull request #586 from acelaya-forks/feature/jest-config
Feature/jest config
2022-02-27 19:26:05 +01:00
Alejandro Celaya
f0ad4dad9f Removed ts-jest, which is not actually used 2022-02-27 19:18:59 +01:00
Alejandro Celaya
acf19823b0 Simplified jest config and removed unneeded packages 2022-02-27 19:12:30 +01:00
Alejandro Celaya
c02fba8d82 Merge pull request #578 from shlinkio/dependabot/npm_and_yarn/follow-redirects-1.14.8
Bump follow-redirects from 1.14.5 to 1.14.8
2022-02-27 13:01:53 +01:00
Alejandro Celaya
a4f36f8620 Merge pull request #569 from acelaya-forks/feature/tags-mode
Added support for tag mode on short URLs list
2022-02-26 12:06:57 +01:00
Alejandro Celaya
987c27a221 Updated changelog 2022-02-26 11:59:52 +01:00
Alejandro Celaya
248f887fb3 Added missing tests on ShortUrlsFilteringBar test 2022-02-26 11:55:35 +01:00
Alejandro Celaya
8fd07070b8 Created TooltipToggleSwitch test 2022-02-26 11:25:40 +01:00
Alejandro Celaya
45c918f4ee Merge branch 'develop' into feature/tags-mode 2022-02-26 10:48:42 +01:00
Alejandro Celaya
4f267a0275 Merge pull request #584 from shlinkio/dependabot/npm_and_yarn/url-parse-1.5.10
Bump url-parse from 1.5.7 to 1.5.10
2022-02-26 06:42:15 +01:00
dependabot[bot]
ad1caaf5dd Bump url-parse from 1.5.7 to 1.5.10
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.7 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.7...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-26 05:34:34 +00:00
Alejandro Celaya
1e0528fca0 Merge pull request #583 from shlinkio/dependabot/npm_and_yarn/urijs-1.19.8
Bump urijs from 1.19.2 to 1.19.8
2022-02-26 06:32:48 +01:00
dependabot[bot]
b30df582f2 Bump urijs from 1.19.2 to 1.19.8
Bumps [urijs](https://github.com/medialize/URI.js) from 1.19.2 to 1.19.8.
- [Release notes](https://github.com/medialize/URI.js/releases)
- [Changelog](https://github.com/medialize/URI.js/blob/gh-pages/CHANGELOG.md)
- [Commits](https://github.com/medialize/URI.js/compare/v1.19.2...v1.19.8)

---
updated-dependencies:
- dependency-name: urijs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-26 03:31:29 +00:00
Alejandro Celaya
f0b42cdc09 Added missing prop 2022-02-22 19:23:57 +01:00
Alejandro Celaya
308660287e Merged develop 2022-02-22 19:16:04 +01:00
Alejandro Celaya
c80a8e9601 Merge pull request #581 from shlinkio/dependabot/npm_and_yarn/url-parse-1.5.7
Bump url-parse from 1.4.7 to 1.5.7
2022-02-19 13:46:55 +01:00
dependabot[bot]
059d17f8d6 Bump url-parse from 1.4.7 to 1.5.7
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 12:42:32 +00:00
Alejandro Celaya
de027eccad Merge pull request #580 from acelaya-forks/feature/simple-color-picker
Feature/simple color picker
2022-02-16 20:14:22 +01:00
Alejandro Celaya
643494a54b Updated changelog 2022-02-16 20:08:48 +01:00
Alejandro Celaya
71a010d5d7 Replaced rect-color with react-colorful 2022-02-16 20:07:10 +01:00
dependabot[bot]
b419586504 Bump follow-redirects from 1.14.5 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.5 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.5...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 19:41:02 +00:00
Alejandro Celaya
78a519c649 Merge pull request #574 from shlinkio/dependabot/npm_and_yarn/postcss-8.2.13
Bump postcss from 8.1.7 to 8.2.13
2022-02-14 20:39:08 +01:00
Alejandro Celaya
23ee3d18a6 Merge pull request #577 from acelaya-forks/feature/enhanced-settings
Feature/enhanced settings
2022-02-14 20:37:36 +01:00
Alejandro Celaya
a6b2f1b385 Update changelog 2022-02-14 20:30:58 +01:00
Alejandro Celaya
30a71ac8b7 Improved settings section names 2022-02-14 20:29:53 +01:00
Alejandro Celaya
ae9e5a0566 Fixed tests 2022-02-14 20:04:38 +01:00
Alejandro Celaya
f24c8052a9 Improved NavPills component and added test 2022-02-14 19:58:20 +01:00
Alejandro Celaya
b0fa14fcfe Extracted nav pills to their own component for reusability 2022-02-13 20:20:20 +01:00
Alejandro Celaya
338c2a1191 Fixed conflicts 2022-02-08 19:40:51 +01:00
Alejandro Celaya
405a150a2b Merge pull request #575 from shlinkio/dependabot/npm_and_yarn/ws-6.2.2
Bump ws from 6.2.1 to 6.2.2
2022-02-07 23:15:47 +01:00
dependabot[bot]
3c402f8787 Bump ws from 6.2.1 to 6.2.2
Bumps [ws](https://github.com/websockets/ws) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/6.2.1...6.2.2)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 22:10:18 +00:00
dependabot[bot]
7d10efc286 Bump postcss from 8.1.7 to 8.2.13
Bumps [postcss](https://github.com/postcss/postcss) from 8.1.7 to 8.2.13.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.1.7...8.2.13)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 22:09:44 +00:00
Alejandro Celaya
cf5205e976 Merge pull request #573 from acelaya-forks/feature/react-router-6
Feature/react router 6
2022-02-07 23:08:30 +01:00
Alejandro Celaya
eab072831d Fixed VisitsStats test 2022-02-07 22:55:32 +01:00
Alejandro Celaya
c4e928ff09 Fixed most tests using react-router-dom hooks 2022-02-07 22:17:57 +01:00
Alejandro Celaya
97024d828e Ensured short URLs section is active regardless the page 2022-02-06 21:17:10 +01:00
Alejandro Celaya
c6e500ba71 Updated source code to react-router 6 2022-02-06 20:07:18 +01:00
Alejandro Celaya
eb39d97cc5 Fixed merge conflicts 2022-02-05 16:48:55 +01:00
Alejandro Celaya
071eaddfd1 Merge pull request #571 from acelaya-forks/feature/non-orphan-visits
Feature/non orphan visits
2022-02-05 16:47:42 +01:00
Alejandro Celaya
0eec9b185f Added test for non-orphan visits reducer 2022-02-05 16:40:48 +01:00
Alejandro Celaya
5edb62e76b Created tests for non-orphan visits components 2022-02-05 16:37:01 +01:00
Alejandro Celaya
9bc5a050eb Updated changelog 2022-02-05 13:53:54 +01:00
Alejandro Celaya
4a80f224d8 Created components and reducer to handle non-orphan visits 2022-02-05 13:53:07 +01:00
Alejandro Celaya
0608d3cf19 Improved icon in HighlightedCard 2022-02-05 13:46:24 +01:00
Alejandro Celaya
8fbe6bb17d Added changes to load orphan visits and fixed tests 2022-02-05 13:37:49 +01:00
Alejandro Celaya
60929342fb Added some feedback to know which cardsin overview pages are clickable 2022-02-05 10:46:46 +01:00
Alejandro Celaya
e0d43020dc Extracted cards in overview to their own component 2022-02-05 10:04:34 +01:00
Alejandro Celaya
2de0276195 Added support for tag mode on short URLs list 2022-01-31 10:15:25 +01:00
Alejandro Celaya
1011b062ae Merge pull request #568 from acelaya-forks/feature/delete-error-code
Improved error code check on short URL deletion
2022-01-25 19:55:21 +01:00
Alejandro Celaya
c8b530cc1a Improved error code check on short URL deletion 2022-01-25 19:51:08 +01:00
Alejandro Celaya
6e72c343ab Merge pull request #566 from acelaya-forks/feature/nil-optimization
Fixed unintended usage of false where only null or undefined should m…
2022-01-08 15:14:29 +01:00
Alejandro Celaya
1c37186461 Fixed unintended usage of false where only null or undefined should match 2022-01-08 15:09:56 +01:00
Alejandro Celaya
34a59db4cf Merge pull request #558 from Roy-Orbison/tag-legibility
Make text of light tags legible
2022-01-08 12:45:14 +01:00
Alejandro Celaya
12f61d03be Created Tag component test 2022-01-08 12:41:32 +01:00
Alejandro Celaya
aca9218f9d Added test covering ColorGenerator.isColorLightForKey 2022-01-08 12:16:31 +01:00
Alejandro Celaya
b727a704a6 Changed classes to use BEM, and fixed TS compilation errors 2022-01-08 12:06:28 +01:00
Roy-Orbison
1e03eed6c0 Make text of light tags legible 2022-01-08 11:59:38 +01:00
Alejandro Celaya
e9fcdcb049 Merge pull request #563 from shlinkio/develop
Release 3.5.1
2022-01-08 11:25:22 +01:00
Alejandro Celaya
5b7f1ef18a Merge pull request #562 from acelaya-forks/feature/autocomplete-new-tags
Fixed new tags added to new short URLs, not appearing on tags autosug…
2022-01-08 11:21:32 +01:00
Alejandro Celaya
715128a653 Fixed new tags added to new short URLs, not appearing on tags autosuggest 2022-01-08 11:14:11 +01:00
Alejandro Celaya
83fbdbb135 Merge pull request #561 from acelaya-forks/feature/overview-list
Fixed short URLs list in overview page
2022-01-08 10:55:02 +01:00
Alejandro Celaya
2e963bdc8e Fixed short URLs list in overview page 2022-01-08 10:51:34 +01:00
Alejandro Celaya
8d6e93ea4f Merge pull request #560 from acelaya-forks/feature/logo-alignment
Feature/logo alignment
2022-01-08 10:30:26 +01:00
Alejandro Celaya
112a8cdf2f Updated changelog 2022-01-08 10:24:07 +01:00
Alejandro Celaya
27476d8b23 Added missing border in welcome screen title 2022-01-08 10:22:51 +01:00
Alejandro Celaya
2ad2d69b2b Fixed Shlink logo not being vertically aligned in welcome screen 2022-01-08 10:19:20 +01:00
Alejandro Celaya
a3d6944fc1 Added Twitter follow badge to readme 2022-01-07 16:16:53 +01:00
Alejandro Celaya
552169ee77 Merge pull request #553 from shlinkio/develop
Release 3.5.0
2022-01-01 12:50:47 +01:00
Alejandro Celaya
4f03ab18e5 Fixed typo in CHANGELOG 2022-01-01 12:47:54 +01:00
Alejandro Celaya
184d5d97e7 Merge pull request #552 from acelaya-forks/feature/duplicated-servers
Feature/duplicated servers
2022-01-01 12:43:31 +01:00
Alejandro Celaya
ba667a0768 Updated changelog 2022-01-01 12:38:00 +01:00
Alejandro Celaya
15b3424d7f Improved DuplicatedServersModal test 2022-01-01 12:35:06 +01:00
Alejandro Celaya
98398a048b Added logic to detect duplicated servers when importing a servers list 2022-01-01 12:20:09 +01:00
Alejandro Celaya
3cb066f5f5 Reduced unnecesary lines in test 2022-01-01 09:46:21 +01:00
Alejandro Celaya
053b38bee3 Created DuplicatedServerModal test 2022-01-01 09:46:21 +01:00
Alejandro Celaya
1f9356cc21 Created modal to warn when creating a duplicated server 2022-01-01 09:46:21 +01:00
Alejandro Celaya
f07e7fd31c Simplified server-related styles and removed default export from NoMenuLayout 2022-01-01 09:46:21 +01:00
Alejandro Celaya
7794876d7c Merge pull request #551 from acelaya-forks/feature/white-screen
Ensured settings migration function does not crash if settings are no…
2022-01-01 09:45:10 +01:00
Alejandro Celaya
e77b4d7a82 Ensured settings migration function does not crash if settings are not set 2022-01-01 09:40:26 +01:00
Alejandro Celaya
af0d2d3cdc Merge pull request #550 from acelaya-forks/feature/domain-health-checks
Feature/domain health checks
2021-12-28 23:33:33 +01:00
Alejandro Celaya
7e132be686 Fixed DomainStatusIcon test 2021-12-28 23:22:55 +01:00
Alejandro Celaya
aba1972d0d Added dynamic tooltip placement in DomainStatusIcon based on media query 2021-12-28 23:15:34 +01:00
Alejandro Celaya
0268bb6930 Improved icon used for failing status domains 2021-12-28 22:54:17 +01:00
Alejandro Celaya
ecd6e6a066 Created DomainStatusIcon test 2021-12-28 22:48:35 +01:00
Alejandro Celaya
6411c6169b Added tooltips to domain icons 2021-12-27 22:27:13 +01:00
Alejandro Celaya
a78467065a Added logic in ManageDomains and DomainRow components to check if the domains status 2021-12-26 13:53:17 +01:00
Alejandro Celaya
c05c74f009 Extended domainsList reducer, adding functionality to verify domains statuses 2021-12-26 13:38:17 +01:00
Alejandro Celaya
ace29ca4a4 Created helper function to replace the authority on a URL 2021-12-26 13:21:09 +01:00
Alejandro Celaya
4f90d147a4 Merge pull request #548 from acelaya-forks/feature/remove-extra-check
Removed error check which is no longer needed for currently supported…
2021-12-26 10:45:52 +01:00
Alejandro Celaya
9348f211f0 Removed error check which is no longer needed for currently supported Shlink versions 2021-12-26 10:42:25 +01:00
Alejandro Celaya
729d9e4a39 Merge pull request #546 from acelaya-forks/feature/order-by-to-query
Feature/order by to query
2021-12-25 20:04:40 +01:00
Alejandro Celaya
3274088b54 Added tests for new ordering helper functions and updated changelog 2021-12-25 19:58:54 +01:00
Alejandro Celaya
49c841ca07 Added short URLs orderBy handling to the query state 2021-12-25 19:51:25 +01:00
Alejandro Celaya
91f319df65 Merge pull request #545 from acelaya-forks/feature/refactorings
Feature/refactorings
2021-12-25 10:53:44 +01:00
Alejandro Celaya
dbf4b0926e Added Settings suffix to all settings sub-components 2021-12-25 10:49:12 +01:00
Alejandro Celaya
994f31b7e5 Renamed SortingDropdown to OrderingDropdown, for consistency 2021-12-25 10:32:33 +01:00
Alejandro Celaya
6213067f35 Removed default export in SortingDropdown 2021-12-25 10:26:38 +01:00
Alejandro Celaya
76fb45c97e Renamed constants holding orderable fields for short URLs and tags 2021-12-25 10:24:37 +01:00
Alejandro Celaya
2bf5f276f5 Merge pull request #544 from acelaya-forks/feature/ordering-settings
Feature/ordering settings
2021-12-24 15:21:04 +01:00
Alejandro Celaya
eaadd6f7af Removed params param when dispatching list short RULs action, as it was used by a reducer that has been deleted 2021-12-24 15:05:15 +01:00
Alejandro Celaya
86c6acb7b8 Updated changelog 2021-12-24 14:16:42 +01:00
Alejandro Celaya
de32d899bc Added new settings card to customize short URLs lists 2021-12-24 14:15:28 +01:00
Alejandro Celaya
d4356ba6e6 Moved types from old shortUrlsListParams reducer, to the data index file 2021-12-24 13:47:27 +01:00
Alejandro Celaya
275aee4de2 Removed shortUrlsListParams reducer, as the state is now handled internally in the component 2021-12-24 13:39:57 +01:00
Alejandro Celaya
57075c581d Updated Short URLs list so that it allows setting default orderBy from settings 2021-12-24 13:14:13 +01:00
Alejandro Celaya
d8442e435d Added option to customize ordering in tags list 2021-12-24 11:06:02 +01:00
Alejandro Celaya
e954a860bf Added test for migrateDeprecatedSettings function 2021-12-23 17:59:18 +01:00
Alejandro Celaya
5598fe0f53 Created new settings card for tags-related options 2021-12-23 17:53:14 +01:00
Alejandro Celaya
e77508edcc Merge pull request #541 from acelaya-forks/feature/not-empty-resultsets
Feature/not empty resultsets
2021-12-23 10:57:45 +01:00
Alejandro Celaya
c517c0521c Renamed doFallbackRange to doIntervalFallback to make it more descriptive 2021-12-23 10:51:13 +01:00
Alejandro Celaya
e22856ff74 Added logic in reducers to fallback to a different date interval if default one returns no visits 2021-12-23 10:38:02 +01:00
Alejandro Celaya
a30687e4ea Updated changelog 2021-12-22 20:34:56 +01:00
Alejandro Celaya
64ba346566 Updated VisitsStats components to react to the fallbackInterval 2021-12-22 20:23:26 +01:00
Alejandro Celaya
3745b297db Updated visits components to support the doFallbackRange flag 2021-12-22 20:19:54 +01:00
Alejandro Celaya
401418c049 Extended DateRangeSelector to allow updating its value via props after rendering 2021-12-22 20:14:26 +01:00
Alejandro Celaya
7adb40489d Added some helper function to deal with dates 2021-12-22 20:08:28 +01:00
Alejandro Celaya
482314b9f4 Merge pull request #540 from acelaya-forks/feature/extended-basic-creation-form
Added custom slug field to the basic creation form in Overview page
2021-12-19 12:56:21 +01:00
Alejandro Celaya
138e40315d Added custom slug field to the basic creation form in Overview page 2021-12-19 12:52:49 +01:00
Alejandro Celaya
7d6afd47b1 Removed unecesary check 2021-12-14 23:12:39 +01:00
Alejandro Celaya
ed1f650fc6 Merge pull request #539 from acelaya-forks/feature/dash-order-by
Switched to the <field>-<dir> notation in orderBy param for short URL…
2021-12-14 23:09:36 +01:00
Alejandro Celaya
17e4e06fcc Switched to the <field>-<dir> notation in orderBy param for short URLs list 2021-12-14 23:02:16 +01:00
Alejandro Celaya
654b36ab08 Merge pull request #536 from acelaya-forks/feature/default-domain-edition
Feature/default domain edition
2021-12-09 13:49:14 +01:00
Alejandro Celaya
9abbfc5b1e Updated changelog 2021-12-09 13:45:24 +01:00
Alejandro Celaya
c9d906316f Updated domain components to use defaultRedirects prop when present (Shlink 2.10 or newer) 2021-12-09 13:44:29 +01:00
Alejandro Celaya
8d476e0729 Added support to fetch full response from list domains endpoint 2021-12-09 13:16:28 +01:00
Alejandro Celaya
7a320c9574 Merge branch 'develop' of github.com:acelaya/shlink-web-client-react into develop 2021-12-09 13:08:50 +01:00
Alejandro Celaya
3f1392ce62 Fixed changelog 2021-12-09 13:08:19 +01:00
Alejandro Celaya
79e54ea230 Updated changelog 2021-12-08 08:53:10 +01:00
Alejandro Celaya
e2473207ba Merge pull request #534 from shlinkio/dependabot/npm_and_yarn/axios-0.21.2
Bump axios from 0.21.1 to 0.21.2
2021-12-08 08:50:53 +01:00
dependabot[bot]
fb961dd47b Bump axios from 0.21.1 to 0.21.2
Bumps [axios](https://github.com/axios/axios) from 0.21.1 to 0.21.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.21.1...v0.21.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-07 23:57:30 +00:00
Alejandro Celaya
ff1821666e Merge pull request #533 from shlinkio/develop
Release 3.4.2
2021-12-07 20:52:41 +01:00
Alejandro Celaya
9a62bcd8fb Merge branch 'develop' of github.com:shlinkio/shlink-web-client into develop 2021-12-07 20:51:45 +01:00
Alejandro Celaya
9c6c1b43c8 Merge pull request #532 from acelaya-forks/feature/invalid-selector-fix
Feature/invalid selector fix
2021-12-07 20:48:11 +01:00
Alejandro Celaya
4986dbcb91 Fixed tests 2021-12-07 20:41:07 +01:00
Alejandro Celaya
527d4acf17 Updated changelog 2021-12-07 20:32:48 +01:00
Alejandro Celaya
0237253caf Fixed crash in domains when using a domain with port as element ID 2021-12-07 20:24:59 +01:00
Alejandro Celaya
47f5f47867 Merge pull request #529 from shlinkio/develop
Release 3.4.1
2021-11-20 10:11:57 +01:00
Alejandro Celaya
70d4572797 Merge pull request #528 from acelaya-forks/feature/adr
Added first Architecture Decision Records
2021-11-20 10:07:29 +01:00
Alejandro Celaya
8bfa14386b Added first Architecture Decision Records 2021-11-20 10:06:43 +01:00
Alejandro Celaya
9f6401c30b Merge pull request #527 from acelaya-forks/feature/omit-auto-connect-on-export
Fixed export servers to ensure autoConnect is not included
2021-11-20 09:50:37 +01:00
Alejandro Celaya
14b2ee53b5 Fixed export servers to ensure autoConnect is not included 2021-11-20 09:44:12 +01:00
Alejandro Celaya
7db9974e8d Merge pull request #523 from acelaya-forks/feature/home-alignment
Updated landing page to be vertically aligned on mobile devices
2021-11-13 23:08:44 +01:00
Alejandro Celaya
7d29129ca1 Updated landing page to be vertically aligned on mobile devices 2021-11-13 23:04:59 +01:00
Alejandro Celaya
42152c6872 Merge pull request #519 from shlinkio/develop
Release 3.4.0
2021-11-11 21:44:39 +01:00
Alejandro Celaya
b7e9afd54a Added v3.4.0 to changelog 2021-11-11 21:42:58 +01:00
Alejandro Celaya
3bc9bd2ef8 Merge pull request #517 from acelaya-forks/feature/reset-page
Feature/reset page
2021-11-11 21:42:27 +01:00
Alejandro Celaya
7bc3819ebe Fixed TS error in SearchBar test 2021-11-11 21:38:37 +01:00
Alejandro Celaya
0642443aa9 Updated changelog 2021-11-11 21:32:28 +01:00
Alejandro Celaya
2e77cd1969 Removed handling of most short URLs list params from a reducer 2021-11-11 21:28:17 +01:00
Alejandro Celaya
21b8e05e35 Moved dates handling in short URLs list to query 2021-11-10 22:25:56 +01:00
Alejandro Celaya
ed038b9799 Fixed ShortUrlsList test 2021-11-08 23:41:17 +01:00
Alejandro Celaya
5f33059de1 Improved SearchBar test 2021-11-08 23:23:45 +01:00
Alejandro Celaya
3bc5b4c154 Extended ShortUrlsPaginator so that it allows appending current query string 2021-11-08 22:13:37 +01:00
Alejandro Celaya
a2421ee2d3 Created helper function to evolve a query string based on an object 2021-11-07 11:22:29 +01:00
Alejandro Celaya
109baef828 Minor changes on tags filtering for short URLs 2021-11-07 11:03:31 +01:00
Alejandro Celaya
303900756d Added TableOrderIcon test 2021-11-06 22:46:40 +01:00
Alejandro Celaya
fe81e023e8 Moved table sorting icon to its own component wrapping the logic 2021-11-06 22:34:29 +01:00
Alejandro Celaya
5906921eec Merge pull request #516 from acelaya-forks/feature/consistent-tags-sorting
Feature/consistent tags sorting
2021-11-06 12:36:19 +01:00
Alejandro Celaya
ee826458be Updated sorting dropdown to accept an order object instead of two individual props 2021-11-06 12:26:20 +01:00
Alejandro Celaya
7169c6e083 Updated changelog 2021-11-06 12:05:49 +01:00
Alejandro Celaya
0bb5c7d8af Simplified branches while resolving server Id 2021-11-06 12:04:26 +01:00
Alejandro Celaya
a6892b8a12 Covered ordering use cases on TagsList test 2021-11-06 11:58:59 +01:00
Alejandro Celaya
765c4713a2 Fixed all tests to work with new tags sorting approach 2021-11-06 11:30:42 +01:00
Alejandro Celaya
e6737ff1f2 Moved logic to render sorting icon to tags list, as it's too specific 2021-11-06 11:11:09 +01:00
Alejandro Celaya
7a2d0e5dee Added sorting dropdown for tags, that can be used regardless the display mode 2021-11-06 11:03:56 +01:00
Alejandro Celaya
daf076a57e Moved logic to sort tags to TagsList component, to allow sorting on any context 2021-11-06 10:55:01 +01:00
Alejandro Celaya
af08b53002 Merge pull request #514 from acelaya-forks/feature/sticky-tags-header
Feature/sticky tags header
2021-11-01 14:16:00 +01:00
Alejandro Celaya
39d5853fe3 Added tests for ordering logic in TagsTable 2021-11-01 14:10:57 +01:00
Alejandro Celaya
9cbeef1cb4 Moved test to the right place 2021-11-01 13:57:53 +01:00
Alejandro Celaya
2857e59273 Updated changelog 2021-11-01 13:45:30 +01:00
Alejandro Celaya
04571ea634 Added logic to order tags list 2021-11-01 13:42:53 +01:00
Alejandro Celaya
5241925acc Added not-enabled sorting on tags table 2021-11-01 12:48:11 +01:00
Alejandro Celaya
844cf51d04 Added missing prettify on number of visits to export and selected visits 2021-11-01 11:19:20 +01:00
Alejandro Celaya
b0c1549005 Added sticky header to tags table 2021-11-01 11:13:51 +01:00
Alejandro Celaya
16d2e437b6 Merge pull request #513 from acelaya-forks/feature/update-test-deps
Feature/update test deps
2021-10-31 12:44:22 +01:00
Alejandro Celaya
944b166e43 Added explicit any type on caught errors where needed 2021-10-31 12:38:42 +01:00
Alejandro Celaya
e5f99d0893 Removed remaining instances of setImmediate in tests 2021-10-31 12:33:17 +01:00
Alejandro Celaya
57e73dcba6 Fixed unhandled promise in remoteServers.test 2021-10-31 12:20:02 +01:00
Alejandro Celaya
80f0f9bd08 Updated test libs 2021-10-31 12:07:38 +01:00
Alejandro Celaya
1486d1fba5 Updated enzyme deps 2021-10-31 10:34:10 +01:00
Alejandro Celaya
e28f74169d Merge pull request #512 from acelaya-forks/feature/server-auto-connect
Feature/server auto connect
2021-10-31 00:16:54 +02:00
Alejandro Celaya
2375882c73 Fixed TS compile error in Home component test 2021-10-31 00:12:03 +02:00
Alejandro Celaya
7b344998ea Updated changelog 2021-10-31 00:08:47 +02:00
Alejandro Celaya
e8ea3b4abe Updated to node 16 and allowed to auto-connect to the first server marked as auto-connect 2021-10-31 00:07:38 +02:00
Alejandro Celaya
bd0fca23cf Merge pull request #511 from acelaya-forks/feature/push-visits-in-date
Feature/push visits in date
2021-10-24 22:44:52 +02:00
Alejandro Celaya
6d392ba403 Added more tests covering how real-time visits are filtered out based on date intervals 2021-10-24 22:37:14 +02:00
Alejandro Celaya
e135dd92ec Ensured new visits are pushed to the state only if they match selected date range 2021-10-24 10:31:32 +02:00
Alejandro Celaya
36af3c3dd0 Merge pull request #510 from acelaya-forks/feature/improved-servers-management
Feature/improved servers management
2021-10-23 11:43:11 +02:00
Alejandro Celaya
c0e33d6a6a Updated changelog 2021-10-23 11:34:39 +02:00
Alejandro Celaya
41398f659e Created ManageServers test 2021-10-23 11:33:32 +02:00
Alejandro Celaya
8618519b6b Created ManageServersRowDropdown test 2021-10-23 10:55:52 +02:00
Alejandro Celaya
c7c32b494e Created ManageServersRow test 2021-10-23 10:34:20 +02:00
Alejandro Celaya
ec9fd67b8a Extracted ManageServersRowDropdown to its own component 2021-10-22 20:26:11 +02:00
Alejandro Celaya
7637ce3107 Added logic to toggle auto-connect on servers 2021-10-22 20:13:23 +02:00
Alejandro Celaya
ada5488a6c Ensured export servers btn is not displayed when there are no servers 2021-10-22 19:03:12 +02:00
Alejandro Celaya
478209f50d Improvements on ManageServers 2021-10-22 18:53:00 +02:00
Alejandro Celaya
7f4263966e Created new section to manage servers 2021-10-17 19:13:06 +02:00
Alejandro Celaya
002f280364 Extracted common dropdown-item style 2021-10-17 18:58:38 +02:00
Alejandro Celaya
d8a6676d30 Merge pull request #507 from acelaya-forks/feature/code-coverage
Increased minimum required branch code coverage to 80
2021-10-17 13:47:30 +02:00
Alejandro Celaya
beff6668de Increased minimum required branch code coverage to 80 2021-10-17 13:43:37 +02:00
Alejandro Celaya
4baa901f1c Fixed merge conflicts 2021-10-17 12:41:23 +02:00
Alejandro Celaya
f19746cd58 Merge pull request #505 from acelaya-forks/feature/resettable-title
Ensured short URL title can be resetted after creation
2021-10-17 12:39:45 +02:00
Alejandro Celaya
85161915b1 Ensured short URL title can be resetted after creation 2021-10-17 12:35:11 +02:00
Alejandro Celaya
29bf53bf88 Ensured CI is run on develop branch 2021-10-16 18:12:18 +02:00
Alejandro Celaya
d2284cd181 Merge pull request #504 from acelaya-forks/feature/reusable-workflow
Replaced local ci workflow with one from external repo
2021-10-16 18:10:55 +02:00
Alejandro Celaya
88305a57bf Replaced local ci workflow with one from external repo 2021-10-16 18:05:06 +02:00
Alejandro Celaya
f4908cacc3 Merge pull request #502 from acelaya-forks/feature/forward-query
Feature/forward query
2021-10-13 23:17:52 +02:00
Alejandro Celaya
2925752fde Updated changelog 2021-10-13 23:11:17 +02:00
Alejandro Celaya
1bf3569774 Allowed to customize initial state for forward query 2021-10-13 23:10:22 +02:00
Alejandro Celaya
9e6907deb4 Added forward query component to short URL form 2021-10-13 22:50:48 +02:00
Alejandro Celaya
eaa6efe803 Merge pull request #501 from acelaya-forks/feature/allow-all-default
Feature/allow all default
2021-10-03 21:18:37 +02:00
Alejandro Celaya
d38020e2d1 Updated changelog 2021-10-03 21:12:06 +02:00
Alejandro Celaya
4c1d285d04 Ensured the 'all' item is selected when custom date ranges are unselected 2021-10-03 21:09:48 +02:00
Alejandro Celaya
c71e0919e9 Allowed to select 'all' as the default interval for visits 2021-10-03 21:07:07 +02:00
Alejandro Celaya
a295734c13 Merge pull request #499 from shlinkio/develop
Release 3.3.1
2021-09-27 22:57:46 +02:00
Alejandro Celaya
d00b6165b3 Merge pull request #498 from acelaya-forks/feature/fix-multi-dots
Ensured all dots are replaced from domain when generating its domain ID
2021-09-27 22:54:06 +02:00
Alejandro Celaya
0cbba1182f Ensured all dots are replaced from domain when generating its domain ID 2021-09-27 22:50:12 +02:00
Alejandro Celaya
785806b7a1 Merge pull request #495 from shlinkio/develop
Release 3.3.0
2021-09-25 11:59:18 +02:00
Alejandro Celaya
15b7fd5c93 Merge pull request #494 from acelaya-forks/feature/remove-old-shlink
Feature/remove old shlink
2021-09-25 11:54:26 +02:00
Alejandro Celaya
9b32bd2817 Updated changelog 2021-09-25 11:48:25 +02:00
Alejandro Celaya
8b5b035568 Removed rest of version checks for versions older than 2.4 2021-09-25 11:47:18 +02:00
Alejandro Celaya
f7cc90bb77 Removed some version checks for versions older than 2.4.0 2021-09-25 11:40:16 +02:00
Alejandro Celaya
7b0cda7191 Merge pull request #493 from acelaya-forks/feature/tags-list
Feature/tags list
2021-09-25 11:03:13 +02:00
Alejandro Celaya
9791486341 Created TagsTableRow test 2021-09-25 10:57:42 +02:00
Alejandro Celaya
40ef51a348 Created TagsTable test 2021-09-25 10:37:13 +02:00
Alejandro Celaya
a90287ed02 Updated changelog 2021-09-25 10:07:42 +02:00
Alejandro Celaya
12f6a132bd Added pagination to tags table 2021-09-25 09:34:38 +02:00
Alejandro Celaya
1da7119c5c Added new setting to determine default display mode for tags 2021-09-25 08:20:56 +02:00
Alejandro Celaya
01f6f11ee2 Created new tags components 2021-09-24 20:25:28 +02:00
Alejandro Celaya
57d4db5daa Created TagsModeDropdown component 2021-09-24 20:21:02 +02:00
Alejandro Celaya
c7559e78a2 Created DropdownBtnMenu test 2021-09-24 20:04:16 +02:00
Alejandro Celaya
2f76c5381f Added some tests for new tags components 2021-09-24 19:55:26 +02:00
Alejandro Celaya
304a7431ad Created new component to handle buttons displaying a dropdown menu 2021-09-24 19:10:03 +02:00
Alejandro Celaya
691dabcfbc Merge pull request #489 from acelaya-forks/feature/coverage-80
Feature/coverage 80
2021-09-20 22:13:18 +02:00
Alejandro Celaya
2dd35dcd44 Fixed import statement order 2021-09-20 22:05:24 +02:00
Alejandro Celaya
44930b8c5f Replaced usages of test with it, and updated changelog 2021-09-20 22:00:34 +02:00
Alejandro Celaya
310913b222 Adjusted required code coverage to current values 2021-09-20 21:52:46 +02:00
Alejandro Celaya
b877aa8e5b Improved branching coverage in some parts 2021-09-20 21:51:51 +02:00
Alejandro Celaya
27e3d65143 Created PaginationDropdown test 2021-09-20 21:31:14 +02:00
Alejandro Celaya
b462169e1e Created missing tests for settings components 2021-09-20 21:23:39 +02:00
Alejandro Celaya
dc2f30c73b Recovered test 2021-09-20 20:52:57 +02:00
Alejandro Celaya
8df1ba4671 Added toApiParams test 2021-09-20 20:48:52 +02:00
Alejandro Celaya
56a3dbd07f Created EditTagModal test 2021-09-20 20:32:54 +02:00
Alejandro Celaya
856ee6d65c Created MainHeader test 2021-09-19 11:17:56 +02:00
Alejandro Celaya
9518a5e442 Created ImageDownloader test 2021-09-19 10:57:36 +02:00
Alejandro Celaya
3a8c7a7bf4 Added required code coverage for jest 2021-09-19 10:31:53 +02:00
Alejandro Celaya
7fb0658349 Merge pull request #488 from acelaya-forks/feature/split-charts
Feature/split charts
2021-09-18 19:18:34 +02:00
Alejandro Celaya
6d79851d18 Removed last reference to graph instead of chart 2021-09-18 19:09:31 +02:00
Alejandro Celaya
f89e4244ea Moved LineChartCard with the rest of the charts 2021-09-18 19:07:50 +02:00
Alejandro Celaya
3c23016028 Refactored components used to render charts for visits 2021-09-18 19:05:28 +02:00
Alejandro Celaya
27c4bd792b Merge pull request #487 from acelaya-forks/feature/chartjs-3
Feature/chartjs 3
2021-09-18 13:26:41 +02:00
Alejandro Celaya
1b158b3df4 Fixed links to issues defined as PRs in changelog 2021-09-18 13:22:11 +02:00
Alejandro Celaya
19f0dc2920 Updated changelog 2021-09-18 13:18:48 +02:00
Alejandro Celaya
a15917b1ae Fixed tests 2021-09-18 13:17:04 +02:00
Alejandro Celaya
7e5397dd38 Created PieChartLegend test 2021-09-18 12:59:54 +02:00
Alejandro Celaya
382d7b1c9f Improved comment 2021-09-18 12:34:14 +02:00
Alejandro Celaya
58ee123cef Memoized DefaultChart to make sure it does not change unless its props also change 2021-09-18 12:29:15 +02:00
Alejandro Celaya
039a56f410 Fixed tooltips in bar charts 2021-09-18 12:07:05 +02:00
Alejandro Celaya
6780aa623b Merged develop 2021-09-12 12:28:01 +02:00
Alejandro Celaya
7752140c9d Fixed merge conflicts 2021-09-12 10:33:10 +02:00
Alejandro Celaya
8bfd38d861 Merge pull request #485 from shlinkio/hotfix/v3.2.1
Release v3.2.1
2021-09-12 10:30:10 +02:00
Alejandro Celaya
27b6676edc Merge pull request #484 from acelaya-forks/feature/wrong-end-dates
ClFeature/wrong end dates
2021-09-12 10:22:30 +02:00
Alejandro Celaya
66c91722fc Updated changelog 2021-09-12 10:17:24 +02:00
Alejandro Celaya
178f15b7d3 Ensured end dates are set at the end of the date when filtering visits 2021-09-12 10:16:05 +02:00
Alejandro Celaya
0e47f9b502 Merge pull request #483 from acelaya-forks/feature/import-servers-win
Feature/import servers win
2021-09-12 10:04:33 +02:00
Alejandro Celaya
d2ad1cd54b Updated changelog 2021-09-12 09:58:24 +02:00
Alejandro Celaya
91e003153b Updated logic to import servers, to not check the file type 2021-09-12 09:56:53 +02:00
Alejandro Celaya
c6cca9c91f Fixed indentation 2021-09-12 09:56:29 +02:00
Alejandro Celaya
7330fd85ff Updated function signaure 2021-09-12 09:34:51 +02:00
Alejandro Celaya
b61d863356 Fixed merge conflicts 2021-09-12 09:03:31 +02:00
Alejandro Celaya
f54460e8f8 First attempt to fix click event on charts 2021-09-05 16:51:18 +02:00
Alejandro Celaya
036c8aafcb Extracted PieChartLegend to its own component 2021-09-05 16:51:18 +02:00
Alejandro Celaya
d55160e8f6 Recovered function to render pie chart labels 2021-09-05 16:51:18 +02:00
Alejandro Celaya
0572bc2854 First iteration to migrate to Chart.js 3. Making it compile 2021-09-05 16:51:18 +02:00
Alejandro Celaya
aceb2350cf Merge pull request #479 from acelaya-forks/feature/tag-special-chars
Fixed tags including special chars being broken when used in URLs
2021-09-01 10:59:45 +02:00
Alejandro Celaya
923575b38b Fixed tags including special chars being broken when used in URLs 2021-09-01 10:54:33 +02:00
Alejandro Celaya
f41a8473f8 Fixed path on preview env 2021-08-29 11:31:33 +02:00
Alejandro Celaya
b94cdb2680 Fixed action version 2021-08-29 10:45:30 +02:00
Alejandro Celaya
0cdae72ebd Migrated to external deploy-preview action 2021-08-29 10:33:55 +02:00
Alejandro Celaya
75931edc33 Merge pull request #473 from acelaya-forks/feature/manage-domains
Feature/manage domains
2021-08-24 20:31:38 +02:00
Alejandro Celaya
d1fcd10c04 Fixed TS errors in tests 2021-08-24 20:26:57 +02:00
Alejandro Celaya
06f4cff97e Fixed missing initial values when editing one domain redirects 2021-08-24 20:24:34 +02:00
Alejandro Celaya
0804322a9f Updated changelog 2021-08-24 20:15:05 +02:00
Alejandro Celaya
53ba14e6f6 Created ManageDomains test 2021-08-24 20:13:54 +02:00
Alejandro Celaya
ead5f2033b Created DomainRow test 2021-08-24 19:53:28 +02:00
Alejandro Celaya
74ac122787 Created EditDomainRedirectsModal test 2021-08-23 19:12:41 +02:00
Alejandro Celaya
13785c7beb Removed styles from one section that ended up in generic component 2021-08-23 18:31:40 +02:00
Alejandro Celaya
9887cae4fd Added InfoTooltip test 2021-08-23 18:26:15 +02:00
Alejandro Celaya
410d372755 Extracted InfoTooltip to its own component 2021-08-22 11:05:07 +02:00
Alejandro Celaya
e7a969a78d Merge branch 'feature/manage-domains' of github.com:acelaya/shlink-web-client-react into feature/manage-domains 2021-08-22 10:47:00 +02:00
Alejandro Celaya
b1d6f58619 Added responsiveness to manage domains table 2021-08-22 10:46:47 +02:00
Alejandro Celaya
f49b74229c Enhanced tooltip 2021-08-22 09:34:56 +02:00
Alejandro Celaya
d88f822125 Extended ShlinkApiClient test covering editDomainRedirects 2021-08-22 09:11:14 +02:00
Alejandro Celaya
dce1cefd49 Created domainRedirects reducer test 2021-08-22 09:06:18 +02:00
Alejandro Celaya
8e71b2e2b1 Improved domainsList reducer test 2021-08-22 09:00:58 +02:00
Alejandro Celaya
69cb3bd619 Implemented logic to edit domain redirects 2021-08-21 17:53:06 +02:00
Alejandro Celaya
bf29158a8a Added missing alignment 2021-08-20 17:31:42 +02:00
Alejandro Celaya
a28a4846bc Created base structure to manage domains 2021-08-20 17:30:07 +02:00
Alejandro Celaya
5eee86003d Merge pull request #471 from acelaya-forks/feature/qr-code-error-correction
Feature/qr code error correction
2021-08-16 17:48:46 +02:00
Alejandro Celaya
37a3a2022b Added missing props on qrCodes test 2021-08-16 17:44:11 +02:00
Alejandro Celaya
c6be8bd96f Created tests for new QR code dropdowns 2021-08-16 17:38:25 +02:00
Alejandro Celaya
5166340779 Extracted some QR code modal components to external components 2021-08-16 17:26:54 +02:00
Alejandro Celaya
520e52595f Updated changelog 2021-08-16 17:14:57 +02:00
Alejandro Celaya
461c0e0bc9 Added new component for QR codes error correction when consuming Shlink 2.8 2021-08-16 17:13:31 +02:00
Alejandro Celaya
0ecb771b23 Created lint:fix global command 2021-08-16 13:21:53 +02:00
Alejandro Celaya
c89e2b5d25 Merge pull request #470 from acelaya-forks/feature/download-qr-code
Feature/download qr code
2021-08-16 13:20:00 +02:00
Alejandro Celaya
aa8f2a0cbc Updated changelog 2021-08-16 13:15:16 +02:00
Alejandro Celaya
eb90aa2274 Added support to download QR codes to the QR code modal 2021-08-16 13:13:41 +02:00
Alejandro Celaya
2b5420a429 Merge pull request #468 from acelaya-forks/feature/tags-global-search
Feature/tags global search
2021-08-15 18:27:16 +02:00
Alejandro Celaya
3484e74559 Fixed coding styles 2021-08-15 18:21:36 +02:00
Alejandro Celaya
edd536cc1e Updated changelog 2021-08-15 18:17:05 +02:00
Alejandro Celaya
322396a366 Allowed to dynamically determine how short URL suggestions are calculated 2021-08-15 18:13:13 +02:00
Alejandro Celaya
9f02bc6496 Added new settings to determine how to search on tags during short URL creation, and how many suggestions to display 2021-08-15 10:58:26 +02:00
Alejandro Celaya
590393dcfd Merge pull request #467 from acelaya-forks/feature/comma-separated-tags
Feature/comma separated tags
2021-08-15 09:54:57 +02:00
Alejandro Celaya
8029823271 Updated changelog 2021-08-15 09:50:27 +02:00
Alejandro Celaya
4417a17d5c Improved TagsSelector component test, covering different logic while adding tags 2021-08-15 09:49:01 +02:00
Alejandro Celaya
b8a7dccf92 Ensured TagsSelector does not allow duplicated tags, and allows adding multiple coma-separated tags at once 2021-08-15 09:45:14 +02:00
Alejandro Celaya
cbe5f98aa3 Merge pull request #466 from acelaya-forks/feature/tags-title
Added dynamic title on hover for tags with a very long title
2021-08-14 19:45:29 +02:00
Alejandro Celaya
6c2f5b99ac Added dynamic title on hover for tags with a very long title 2021-08-14 19:40:53 +02:00
Alejandro Celaya
fa64c950ca Merge pull request #453 from shlinkio/develop
Release 3.2.0
2021-07-12 16:44:20 +02:00
Alejandro Celaya
0e4667e59c Added v3.2.0 to changelog 2021-07-12 16:40:36 +02:00
Alejandro Celaya
56d9dcf562 Merge pull request #452 from acelaya-forks/feature/auto-pwa-restart
Feature/auto pwa restart
2021-07-12 16:39:27 +02:00
Alejandro Celaya
d5e8f81076 Created AppUpdateBanner test 2021-07-12 16:34:58 +02:00
Alejandro Celaya
69905c4b38 Added logic to allow refreshing the PWA without closing the tabs 2021-07-12 16:16:18 +02:00
Alejandro Celaya
08694d7693 Extracted update banner to a separated component 2021-07-12 12:24:04 +02:00
Alejandro Celaya
8045fa8886 Added more improvements to landing page 2021-07-12 12:05:33 +02:00
Alejandro Celaya
0789494a40 Removed deprecated env var for publish release 2021-07-11 22:30:53 +02:00
Alejandro Celaya
34837f2917 Merge pull request #451 from acelaya-forks/feature/improve-landing
Feature/improve landing
2021-07-11 22:29:45 +02:00
Alejandro Celaya
9e8c743d53 Updated changelog 2021-07-11 22:26:11 +02:00
Alejandro Celaya
239cc4ab84 Improved landing page design 2021-07-11 22:25:36 +02:00
Alejandro Celaya
b3e79f4219 Merge pull request #447 from acelaya-forks/feature/visits-filter-reducer
Feature/visits filter reducer
2021-07-02 20:10:36 +02:00
Alejandro Celaya
7c11a6d1ab Allowed to deselect orphan visits type 2021-07-02 20:05:51 +02:00
Alejandro Celaya
635ee6c5eb Updated changelog 2021-07-02 19:57:25 +02:00
Alejandro Celaya
f79bd39de7 Moved logic to filter visits to reducers 2021-06-30 03:23:45 +02:00
Alejandro Celaya
5c6979122d Extracted VisitsFilter type from component for general usage 2021-06-30 02:36:13 +02:00
Alejandro Celaya
402efac12e Merge pull request #446 from acelaya-forks/feature/tags-input
Feature/tags input
2021-06-26 17:50:12 +02:00
Alejandro Celaya
770ba624c2 Created TagsSelector test 2021-06-26 17:44:26 +02:00
Alejandro Celaya
d4236b914d Updated changelog 2021-06-26 17:07:59 +02:00
Alejandro Celaya
2cc92b5b41 Ensured tags are added onBlur 2021-06-26 17:06:39 +02:00
Alejandro Celaya
f0598ba47f Changed min query length for tags input to 1 2021-06-26 10:44:17 +02:00
Alejandro Celaya
66c5c7ebf1 Replaced tags component by one which is better maintained 2021-06-26 10:17:07 +02:00
Alejandro Celaya
741bc21a55 Merge pull request #445 from acelaya-forks/feature/moment-js-migration
Feature/moment js migration
2021-06-25 20:09:12 +02:00
Alejandro Celaya
fb1ced5e3f Created test for Time component 2021-06-25 20:05:06 +02:00
Alejandro Celaya
3999d14bab Created abstraction function to parse dates 2021-06-25 19:52:50 +02:00
Alejandro Celaya
99c77622cd Updated changelog 2021-06-25 19:41:25 +02:00
Alejandro Celaya
bc5c25deb0 Fixed issue due to immutability 2021-06-25 19:33:18 +02:00
Alejandro Celaya
0275908f69 Removed last references to moment.js from the project 2021-06-25 19:15:19 +02:00
Alejandro Celaya
4be1a295d8 Replaced most of the usages of moment with date-fns 2021-06-24 20:13:06 +02:00
Alejandro Celaya
ee65c0c050 Merge pull request #444 from acelaya-forks/feature/crawlable-option
Feature/crawlable option
2021-06-23 20:03:37 +02:00
Alejandro Celaya
d718329b52 Updated changelog 2021-06-23 19:59:47 +02:00
Alejandro Celaya
55716a8f7f Created ShortUrlFormCheckboxGroup test 2021-06-23 19:59:06 +02:00
Alejandro Celaya
5ef719c592 Added support to set crawlable short URLs during creation and edition 2021-06-23 19:52:23 +02:00
Alejandro Celaya
3a57416525 Merge pull request #443 from acelaya-forks/feature/visits-filtering
Feature/visits filtering
2021-06-22 21:17:35 +02:00
Alejandro Celaya
5bd57e71fd Improved DropdownBtn test 2021-06-22 21:12:06 +02:00
Alejandro Celaya
c4ed838510 Updated changelog 2021-06-22 21:06:29 +02:00
Alejandro Celaya
affe2309b0 Ensured filter for bots does not show for Shlink older than 2.7.0 2021-06-22 21:03:47 +02:00
Alejandro Celaya
638ce89780 Improved dropdown to filter visits, adding support to filter out bots 2021-06-22 20:46:28 +02:00
Alejandro Celaya
a0ab9533cb Merge pull request #441 from acelaya-forks/feature/bots-support
Feature/bots support
2021-06-13 11:58:58 +02:00
Alejandro Celaya
7b80948eea Fixed TS errors in tests 2021-06-13 11:54:51 +02:00
Alejandro Celaya
1cf96c7212 Improved VisitsTable test 2021-06-13 11:49:53 +02:00
Alejandro Celaya
151175dc70 Updated changelog 2021-06-13 11:41:41 +02:00
Alejandro Celaya
a30376344e Added tests covering visits table with potential bots 2021-06-13 11:38:13 +02:00
Alejandro Celaya
db0c43dcdd Added column to display if a visit is a potential bot in the visits table 2021-06-13 11:07:32 +02:00
Alejandro Celaya
a3550f8e52 Updated docker images 2021-06-13 09:55:07 +02:00
Alejandro Celaya
3a3babadeb Renamed script 2021-06-13 09:51:10 +02:00
Alejandro Celaya
e22ad2c822 Merge pull request #439 from acelaya-forks/feature/fix-horizontal-scroll
Fixed horizontal scroll
2021-06-13 07:59:19 +02:00
Alejandro Celaya
342dda3ec9 Fixed horizontal scroll 2021-06-13 07:52:53 +02:00
Alejandro Celaya
b7af07c043 Fixed docker build script so that it can work with develop branch 2021-06-06 19:27:43 +02:00
Alejandro Celaya
6b338275d3 Updated branch where the docker image builds unstable versions 2021-06-06 19:24:57 +02:00
Alejandro Celaya
a72d3b2720 Updated changelog 2021-06-06 19:14:18 +02:00
Alejandro Celaya
18042dba6e Merge branch 'main' into develop 2021-06-06 19:13:29 +02:00
Alejandro Celaya
6e09d1372f Merge pull request #436 from acelaya-forks/feature/recover-pwa
Feature/recover pwa
2021-06-06 19:11:37 +02:00
Alejandro Celaya
ce02d29ca3 Ensure review environment does not contain a service worker 2021-06-06 19:06:24 +02:00
Alejandro Celaya
e193c700d6 Fixed TS error in App test 2021-06-06 18:58:05 +02:00
Alejandro Celaya
bfeb282aa9 Added appUpdates reducer test 2021-06-06 18:49:38 +02:00
Alejandro Celaya
5caa648112 Added banner to be displayed when the service worker has updated the app in the background 2021-06-06 18:41:10 +02:00
Alejandro Celaya
4546b74b6f Added missing webpack config that generates service worker 2021-06-06 12:54:32 +02:00
Alejandro Celaya
2fb5507803 Added service worker back to the project to recover PWA capabilities 2021-06-06 12:27:02 +02:00
Alejandro Celaya
93329c5a12 erge branch 'develop' of github.com:shlinkio/shlink-web-client into develop 2021-05-30 17:51:16 +02:00
Alejandro Celaya
5a91b668dc Updated changelog 2021-05-30 17:50:54 +02:00
Alejandro Celaya
66aac4771c Merge pull request #434 from matiasgarciaisaia/patch-1
Update server.json alternative Docker configs in README.md
2021-05-29 18:27:27 +02:00
Matías García Isaía
ce04b8eb58 Update server.json alternative Docker configs in README.md
See #432 & #433
2021-05-29 11:11:24 -03:00
Alejandro Celaya
e0c20c704e Merge pull request #432 from matiasgarciaisaia/feature/conf-volume
Support servers.json in a conf.d directory
2021-05-29 11:58:41 +02:00
Alejandro Celaya
d5fadc56af Removed new empty line added by mistake 2021-05-29 11:54:08 +02:00
Alejandro Celaya
bbc3342c00 Moved servers.json config on nginx above another less restrictive but conflicting rule 2021-05-29 11:53:06 +02:00
Matias Garcia Isaia
76ebbd318a Support servers.json in a conf.d directory
In Cattle (and maybe other Docker environments) you can't mount specific files, but
have to mount a whole volume as a directory.

We now allow the servers.json to be looked for inside a specific folder to support
that use case.
2021-05-29 11:41:32 +02:00
Alejandro Celaya
24801b068b Updated changelog 2021-05-29 11:40:14 +02:00
Alejandro Celaya
4c21ad0a89 Merge pull request #433 from matiasgarciaisaia/feature/server-from-env
Single-server servers.json from environment variables in Docker image
2021-05-29 11:35:27 +02:00
Alejandro Celaya
f626f9b046 Renamed env vars 2021-05-29 11:30:35 +02:00
Matias Garcia Isaia
ccffa0fe12 Allow Docker image to generate servers.json from environment
In the Docker image, generate the servers.json with a single server
by reading environment variables.
2021-05-28 22:01:39 -03:00
Alejandro Celaya
d5530b4614 Merge pull request #429 from acelaya-forks/feature/stryker5
Updated to stryker 5
2021-05-15 12:08:26 +02:00
Alejandro Celaya
7c327099bb Updated changelog 2021-05-15 12:04:25 +02:00
Alejandro Celaya
577d7e79da Updated to stryker 5 2021-05-15 12:02:43 +02:00
Alejandro Celaya
31736fad1e Ensured proper ref is checked out on preview env 2021-05-09 21:09:24 +02:00
Alejandro Celaya
6319a81ddb Fixed event name 2021-05-09 21:02:32 +02:00
Alejandro Celaya
0ca6ff6906 Ensured checkout is done from remote remo 2021-05-09 20:52:15 +02:00
Alejandro Celaya
eb69165781 Changed event for preview deployments to use pull_request_target 2021-05-09 14:39:13 +02:00
Alejandro Celaya
4e3d311bef Changed token used for preview deployment 2021-05-09 14:25:10 +02:00
Alejandro Celaya
54b7aeed20 Added github token to preview env deployment 2021-05-09 14:14:56 +02:00
Alejandro Celaya
2ba8db1fd3 Ensured preview envs are generated on PRs only 2021-05-09 14:03:59 +02:00
Alejandro Celaya
f74270a767 Ensured branch slug is generated before building project on preview env deployment 2021-05-09 13:53:36 +02:00
Alejandro Celaya
9a245fbf13 Created new workflow to generate preview envs 2021-05-09 13:34:39 +02:00
Alejandro Celaya
f16e9565e2 Added v3.1.1 to changelog 2021-05-08 11:04:21 +02:00
Alejandro Celaya
e65f9a7b89 Merge pull request #419 from acelaya-forks/feature/edit-feedback
Feature/edit feedback
2021-05-08 11:02:17 +02:00
Alejandro Celaya
0141a1e0ed Updated changelog 2021-05-08 10:57:12 +02:00
Alejandro Celaya
937876ce67 Improved feedback when editing a short URL 2021-05-08 10:56:20 +02:00
Alejandro Celaya
b52120e0d3 Updated changelog 2021-05-07 20:37:41 +02:00
Alejandro Celaya
62b65334b5 Merge pull request #418 from antwonw/patch-1
Update QrCodeModal.tsx
2021-05-07 20:36:25 +02:00
antwonw
76dae535d9 Update QrCodeModal.tsx
Remove indivisible class to fix hyperlink extending outside modal.
2021-05-06 16:56:53 -07:00
Alejandro Celaya
23ba140ff4 Merge pull request #416 from acelaya-forks/feature/prepend-visits
Feature/prepend visits
2021-05-01 16:44:21 +02:00
Alejandro Celaya
76ff7d81b9 Updated changelog 2021-05-01 16:40:22 +02:00
Alejandro Celaya
66deba29f5 Ensured new visits are prepended and not appended, ensuring they keep the proper order 2021-05-01 16:39:13 +02:00
Alejandro Celaya
e44527e9c9 Merge pull request #415 from acelaya-forks/feature/update-url-on-list
Feature/update url on list
2021-04-24 18:06:02 +02:00
Alejandro Celaya
aec629b95c Updated changelog 2021-04-24 18:01:41 +02:00
Alejandro Celaya
fa4664e583 Ensured edited short URLs are reflected in redux state when needed 2021-04-24 17:58:37 +02:00
Alejandro Celaya
2952ac8892 Merge pull request #406 from acelaya-forks/feature/reduce-margins
Feature/reduce margins
2021-03-29 21:26:49 +02:00
Alejandro Celaya
cf4fc4fa30 Updated changelog 2021-03-29 21:22:28 +02:00
Alejandro Celaya
2d61748aac Fixed styles in disabled days in date picker 2021-03-29 21:21:53 +02:00
Alejandro Celaya
7f61825768 Reduced and standardized overall vertical spacing 2021-03-29 21:08:48 +02:00
Alejandro Celaya
c3d6c83ec4 Merge pull request #405 from acelaya-forks/feature/orphan-visits-improvements
Feature/orphan visits improvements
2021-03-28 21:07:52 +02:00
Alejandro Celaya
c3e38fd580 Improved VisitsParser test 2021-03-28 21:03:46 +02:00
Alejandro Celaya
db778a73f7 Updated changelog 2021-03-28 20:57:19 +02:00
Alejandro Celaya
f0a04ced75 Added graph with orphan visits grouped by visited URL 2021-03-28 20:56:16 +02:00
Alejandro Celaya
d6bb718672 Added filtering by type to orphan visits 2021-03-28 17:45:47 +02:00
Alejandro Celaya
6d887ec4a8 Replaced custom reducers with ramda's countBy 2021-03-28 16:27:31 +02:00
Alejandro Celaya
859cd9e5e3 Improved VisitsTable test 2021-03-28 16:06:37 +02:00
Alejandro Celaya
eabd7d9ecb Added visited URL column on visits table for orphan visits 2021-03-28 15:57:22 +02:00
Alejandro Celaya
205e3ffb90 Merge pull request #404 from acelaya-forks/feature/edit-title
Feature/edit title
2021-03-27 19:01:02 +01:00
Alejandro Celaya
8c7a91c7b8 Memoized initial state for editing short URL, to ensure the form values are not reset while saving 2021-03-27 18:56:24 +01:00
Alejandro Celaya
56aab349db Updated ShortUrlForm to ensure it does not render empty cards 2021-03-27 18:39:55 +01:00
Alejandro Celaya
6628a4059e Updated changelog 2021-03-27 17:58:17 +01:00
Alejandro Celaya
10c9f7dabd Added header to EditShortUrl and created EditSHortUrl test 2021-03-27 17:56:46 +01:00
Alejandro Celaya
d703e5e182 Deleted reducers for short URL tags and short URL meta 2021-03-27 14:13:10 +01:00
Alejandro Celaya
3ad0c4d009 Deleted modals that were used to edit short URLs, since now there's a dedicated section 2021-03-27 10:49:23 +01:00
Alejandro Celaya
1403538660 Removed children from ShortUrlForm 2021-03-27 10:41:13 +01:00
Alejandro Celaya
ca670d810d Added error/loading handling to edit short URL 2021-03-27 10:27:46 +01:00
Alejandro Celaya
d5e20f445d Ensured title is not sent when its value is empty during short URL creation/edition 2021-03-27 10:19:35 +01:00
Alejandro Celaya
eea76d88c3 Ensured all data can be set when editing a short URL 2021-03-27 09:49:47 +01:00
Alejandro Celaya
a019bd30df Created view to edit short URLs 2021-03-20 16:32:12 +01:00
Alejandro Celaya
631b46393b Added title to short URL form 2021-03-20 11:18:00 +01:00
Alejandro Celaya
98aa85ca14 Created reusable component to have a short URL form 2021-03-19 19:11:27 +01:00
Alejandro Celaya
ea01d22369 Merge pull request #403 from acelaya-forks/feature/export-stats
Feature/export stats
2021-03-14 18:18:29 +01:00
Alejandro Celaya
ff1d2f63c8 Updated changelog 2021-03-14 18:14:10 +01:00
Alejandro Celaya
71468379bd Fixed headers when exporting visits to CSV 2021-03-14 18:12:10 +01:00
Alejandro Celaya
843f646264 Improved styling of the export visits button 2021-03-14 13:31:58 +01:00
Alejandro Celaya
508623f89f Improved styling of the export visits button 2021-03-14 13:30:50 +01:00
Alejandro Celaya
482489599e Created VisitsExporter test 2021-03-14 13:16:24 +01:00
Alejandro Celaya
03f63e3ee3 Added button to export visits as CSV 2021-03-14 12:53:01 +01:00
Alejandro Celaya
3f3523b80f Extracted helper function to generate a Csv file 2021-03-14 11:47:23 +01:00
Alejandro Celaya
1594717f33 Merge pull request #402 from acelaya-forks/feature/visits-default-value
Feature/visits default value
2021-03-06 17:38:08 +01:00
Alejandro Celaya
ed92b9c949 Updated changelog 2021-03-06 17:33:34 +01:00
Alejandro Celaya
e76b22b2ae Ensured consistent heights in settings cards 2021-03-06 17:30:21 +01:00
Alejandro Celaya
e380ddb40f Replaced test by it in tests 2021-03-06 17:25:09 +01:00
Alejandro Celaya
426d000a59 Added tests for new visits settings 2021-03-06 17:21:23 +01:00
Alejandro Celaya
fee62484b5 Created section to set default date interval for visits 2021-03-06 16:54:43 +01:00
Alejandro Celaya
d3f9650e82 Added new visits settings 2021-03-06 10:56:49 +01:00
Alejandro Celaya
ad46927750 Merge pull request #401 from acelaya-forks/feature/feature-improvements
Feature/feature improvements
2021-03-06 10:21:56 +01:00
Alejandro Celaya
bd79230007 Fixed version definition 2021-03-06 10:16:13 +01:00
Alejandro Celaya
5224e7b4ef Created new feature checkers 2021-03-06 09:58:29 +01:00
Alejandro Celaya
70ce099913 Added stricter types for SemVer versions 2021-03-06 09:38:48 +01:00
Alejandro Celaya
b4c2fb5b8f Merge pull request #400 from acelaya-forks/feature/improve-reducer
Feature/improve reducer
2021-03-05 16:31:18 +01:00
Alejandro Celaya
6fbf65c873 Updated changelog 2021-03-05 16:26:29 +01:00
Alejandro Celaya
13d3a95a06 Improved short URL detail redux action so that it avoids API calls when the URL is found in local state 2021-03-05 16:25:20 +01:00
Alejandro Celaya
56b3523c5b Moved short URL detail reducer to short-urls module 2021-03-05 16:04:02 +01:00
Alejandro Celaya
8a69adfbc9 Merge pull request #399 from acelaya-forks/feature/title-in-list
Feature/title in list
2021-03-05 15:48:59 +01:00
Alejandro Celaya
87a32b412f Added short URL title to visits header 2021-03-05 15:44:15 +01:00
Alejandro Celaya
df87ad5867 Updated changelog 2021-03-05 15:24:38 +01:00
Alejandro Celaya
f15bbcd027 Improved ShortUrlsRow test 2021-03-05 15:23:38 +01:00
Alejandro Celaya
3c9c0fe994 Added support for title field in short URL table 2021-03-05 14:20:49 +01:00
Alejandro Celaya
a665e96908 Updated to coding-standard v1.2.2 2021-03-05 11:14:58 +01:00
Alejandro Celaya
fddba80b08 Merge pull request #396 from acelaya-forks/feature/updated-deps
Feature/updated deps
2021-02-28 19:11:02 +01:00
Alejandro Celaya
caa3a09827 Fixed TS error in test 2021-02-28 19:00:11 +01:00
Alejandro Celaya
fa70520f38 Fixed props interface definition 2021-02-28 18:57:27 +01:00
Alejandro Celaya
b789f64a54 Updated changelog 2021-02-28 18:51:18 +01:00
Alejandro Celaya
ce0fc1094e Enabled @typescript-eslint/no-unsafe-return eslint rule again 2021-02-28 18:48:36 +01:00
Alejandro Celaya
ad0a889548 Enabled @typescript-eslint/no-base-to-string eslint rule again 2021-02-28 18:22:44 +01:00
Alejandro Celaya
1fe76500e8 Enabled @typescript-eslint/no-unsafe-call eslint rule again 2021-02-28 17:43:41 +01:00
Alejandro Celaya
86544f4b24 Enabled @typescript-eslint/unbound-method eslint rule again 2021-02-28 17:21:26 +01:00
Alejandro Celaya
c8f8416c06 No longer continue on error when linting fails during CI 2021-02-28 17:02:47 +01:00
Alejandro Celaya
3d2228441a Enabled @typescript-eslint/ban-ts-comment eslint rule 2021-02-28 13:11:27 +01:00
Alejandro Celaya
3f616d5482 Updated to @shlinkio/eslint-config-js-coding-standard@1.2.1 2021-02-28 13:01:11 +01:00
Alejandro Celaya
47fb26368b Updated dependencies and fixed coding styles 2021-02-28 12:56:56 +01:00
Alejandro Celaya
fb2194d2d1 Updated dependencies 2021-02-28 11:13:07 +01:00
Alejandro Celaya
8ec49b8cfc Merge pull request #394 from acelaya-forks/feature/orphan-visits-stats
Feature/orphan visits stats
2021-02-28 11:00:33 +01:00
Alejandro Celaya
4d77c3abf9 Updated changelog 2021-02-28 10:46:57 +01:00
Alejandro Celaya
d921c44d3b Created orphanVisitsReducer test 2021-02-28 10:45:14 +01:00
Alejandro Celaya
eb0ab92472 Created OrphanVisits test 2021-02-28 10:36:56 +01:00
Alejandro Celaya
9904ac757b Updated mercure integration so that the hook accepts a list of topics to subscribe 2021-02-28 10:12:30 +01:00
Alejandro Celaya
71ee886e24 Updated overview page cards to be links to other sections when suitable 2021-02-28 09:50:01 +01:00
Alejandro Celaya
25e53bf627 Created MenuLayout test 2021-02-28 09:28:46 +01:00
Alejandro Celaya
d7edd69e60 Created OrphanVisitsTitle test 2021-02-28 08:52:31 +01:00
Alejandro Celaya
115038f80f Created visits type helpers test 2021-02-27 20:13:18 +01:00
Alejandro Celaya
5479210366 Created section to display orphan visits stats 2021-02-27 20:03:51 +01:00
Alejandro Celaya
46d012b6ff Merge pull request #393 from acelaya-forks/feature/patch-tags
Feature/patch tags
2021-02-27 10:03:36 +01:00
Alejandro Celaya
80dcbf0668 Updated changelog 2021-02-27 09:51:31 +01:00
Alejandro Celaya
d0825089d0 Enhanced edit tags action so that it calls PATCH endpoint 2021-02-27 09:49:56 +01:00
Alejandro Celaya
f653739d50 Merge pull request #391 from acelaya-forks/feature/dark-theme
Feature/dark theme
2021-02-27 09:02:58 +01:00
Alejandro Celaya
2553b27d7d Rolled-back blurred modal 2021-02-27 08:52:10 +01:00
Alejandro Celaya
3cd30b61e4 More style fixes for dark theme 2021-02-27 08:34:44 +01:00
Alejandro Celaya
ae4921b865 Improved contrast in input border colors for dark theme 2021-02-26 23:10:19 +01:00
Alejandro Celaya
c89bcab770 Improved contrast in border colors for dark theme 2021-02-26 23:03:14 +01:00
Alejandro Celaya
f97ef8df83 Added proper blurred background for modals 2021-02-21 21:05:59 +01:00
Alejandro Celaya
e7466ced18 Added dark theme styles for date picker 2021-02-21 21:05:59 +01:00
Alejandro Celaya
0ee899f309 Updated changelog 2021-02-21 21:05:59 +01:00
Alejandro Celaya
36c97ad804 Updated styles in tags section to make it more dark-theme friendly 2021-02-21 21:05:30 +01:00
Alejandro Celaya
d6633f7555 More dark theme styles for visits page 2021-02-21 21:05:30 +01:00
Alejandro Celaya
61af43f9d9 Fixed visits table styles for dark theme 2021-02-21 21:05:30 +01:00
Alejandro Celaya
9523277311 Added icon to show which theme is selected 2021-02-21 21:05:30 +01:00
Alejandro Celaya
9703eba6ec Fixed styles for disabled inputs in dark theme 2021-02-21 21:05:30 +01:00
Alejandro Celaya
83791157ce Fixed inputs colors in dark theme when they are outside of cards 2021-02-21 21:05:30 +01:00
Alejandro Celaya
7f6c71e8d7 Created UserInterface test 2021-02-21 21:05:30 +01:00
Alejandro Celaya
9dbf790cc8 Added components and logic to dynamically change theme 2021-02-21 21:05:30 +01:00
Alejandro Celaya
f313a39b81 Added brand color and input styles to dark theme 2021-02-21 21:05:30 +01:00
Alejandro Celaya
53f16ac8b5 Added primary color alfa and tables color 2021-02-21 21:05:30 +01:00
Alejandro Celaya
13c681dc39 Added first bits of the dark theme styles 2021-02-21 21:05:30 +01:00
Alejandro Celaya
f35be007c1 Merge pull request #392 from acelaya-forks/feature/orphan-visits-card
Feature/orphan visits card
2021-02-21 21:04:37 +01:00
Alejandro Celaya
e2d26e8bdd Updated changelog 2021-02-21 20:57:57 +01:00
Alejandro Celaya
5a373fd7ae Added new card in overview to display orphan visits 2021-02-21 20:55:39 +01:00
Alejandro Celaya
3c53f7d0fc Merge pull request #389 from acelaya-forks/feature/validate-urls-setting
Feature/validate urls setting
2021-02-14 17:38:08 +01:00
Alejandro Celaya
57e3db1e1c Updated changelog 2021-02-14 17:34:20 +01:00
Alejandro Celaya
5afd3869dd Created ShortUrlCreation test 2021-02-14 17:33:01 +01:00
Alejandro Celaya
c3ebb0d10f Added test for setShortUrlCreationSettings action 2021-02-14 13:28:17 +01:00
Alejandro Celaya
4885088d59 Added option to customize initial state fo the 'Validate URL' option 2021-02-14 13:23:42 +01:00
Alejandro Celaya
872890e674 Merge pull request #388 from acelaya-forks/feature/qr-code-margin
Feature/qr code margin
2021-02-14 10:34:18 +01:00
Alejandro Celaya
8a2e39a935 Added subtle shadow in QR code image, so that it's easier to notice the margin 2021-02-14 10:21:10 +01:00
Alejandro Celaya
f8edcda665 Updated changelog 2021-02-14 10:17:34 +01:00
Alejandro Celaya
c95cb144a8 Added margin option to QR code component 2021-02-14 10:16:30 +01:00
Alejandro Celaya
f9da22c5a1 Added support for margin param in buildQrCodeUrl function 2021-02-14 09:50:26 +01:00
Alejandro Celaya
be085f50e0 Updated to bootstrap 4.6 2021-02-14 09:29:24 +01:00
Alejandro Celaya
1122f4e560 Merge pull request #381 from acelaya-forks/feature/qr-code-improvements
Feature/qr code improvements
2021-01-24 18:38:51 +01:00
Alejandro Celaya
ecefa22204 Replace nested ternary conditions with ramda's cond 2021-01-24 18:21:04 +01:00
Alejandro Celaya
e2ba63ff58 Updated changelog 2021-01-24 18:14:19 +01:00
Alejandro Celaya
277069a0af Fixed warnings in SortingDropdown 2021-01-24 18:12:16 +01:00
Alejandro Celaya
0c9434b555 Created CopyToClipboardIcon test 2021-01-24 18:06:11 +01:00
Alejandro Celaya
0fce6dd821 Fixed warnings in DropdownBtn test 2021-01-24 18:05:37 +01:00
Alejandro Celaya
4b8e5bf3fc Added qrCode helper test 2021-01-24 17:47:03 +01:00
Alejandro Celaya
3546a17575 Improved QR code modal, to allow selecting size, format and copy URL 2021-01-24 17:37:31 +01:00
Alejandro Celaya
556495ea7e Improved QR code component 2021-01-21 16:51:54 +01:00
Alejandro Celaya
e9cef8a029 Merge pull request #375 from acelaya-forks/feature/servers-import-error
Feature/servers import error
2020-12-30 21:04:59 +01:00
Alejandro Celaya
e577eb48d6 Changed env for github workflows from ubuntu-latest to ubuntu-20.04 2020-12-30 20:58:36 +01:00
Alejandro Celaya
d08a69954a Updated changelog 2020-12-30 20:53:14 +01:00
Alejandro Celaya
fe81bfccef Fixed importing servers in android due to wrong mime type 2020-12-30 20:52:05 +01:00
Alejandro Celaya
4869435aca Changed linting order 2020-12-30 20:10:37 +01:00
Alejandro Celaya
0822cebb10 Merge pull request #374 from acelaya-forks/feature/responsive-table
Feature/responsive table
2020-12-30 20:09:42 +01:00
Alejandro Celaya
01a18f2342 Updated changelog 2020-12-30 20:05:53 +01:00
Alejandro Celaya
a22274f382 Increased breakpoint in which short URLs table collapses 2020-12-30 20:05:04 +01:00
Alejandro Celaya
c0098ac7fd Merge pull request #373 from acelaya-forks/feature/ui-fixes
Fixed minor UI glitches in visits section
2020-12-30 19:52:24 +01:00
Alejandro Celaya
ba5a99dc2a Fixed minor UI glitches in visits section 2020-12-30 19:48:02 +01:00
Alejandro Celaya
1927ad2d3a Merge pull request #370 from acelaya-forks/feature/stryker-updates
Updated stryker
2020-12-25 19:13:57 +01:00
Alejandro Celaya
0356a0204d Updated stryker 2020-12-25 19:10:35 +01:00
Alejandro Celaya
3bf64bee1e Merge pull request #369 from acelaya-forks/feature/consistent-dropdowns
Feature/consistent dropdowns
2020-12-25 11:25:48 +01:00
Alejandro Celaya
da484374a1 Renamed Dropdnown.scss to DropdownBtn.scss for consistency with component 2020-12-25 11:21:39 +01:00
Alejandro Celaya
7b9447b717 Updated changelog 2020-12-25 11:17:57 +01:00
Alejandro Celaya
e583eb2759 Ensured sorting dropdown for short URLs is not enclosed inside card 2020-12-25 11:15:49 +01:00
Alejandro Celaya
93b4de60f6 Improved sorting dropdown to display order field and order dir 2020-12-25 11:06:10 +01:00
Alejandro Celaya
16f4f7eac8 Reused dropdown-btn styles in sorting dropdown 2020-12-25 10:54:49 +01:00
Alejandro Celaya
90d4fe72db Renamed Dropdown component to DropdownBtn 2020-12-25 10:43:36 +01:00
Alejandro Celaya
e1298cfa81 Created Dropdown test 2020-12-25 10:39:54 +01:00
Alejandro Celaya
6be3a1223f Created common Dropdown component for style consistency 2020-12-25 10:29:25 +01:00
Alejandro Celaya
81d24432a9 Updated app gif 2020-12-24 10:58:59 +01:00
Alejandro Celaya
1d193f1187 Updated nginx version in docker image 2020-12-22 10:23:27 +01:00
Alejandro Celaya
c56994c813 Merge pull request #363 from acelaya-forks/feature/refactorings
Feature/refactorings
2020-12-22 10:17:59 +01:00
Alejandro Celaya
44862073bb Added v3 to changelog 2020-12-22 10:06:24 +01:00
Alejandro Celaya
9eb9182c21 Created ShlinkApiError test 2020-12-22 10:05:32 +01:00
Alejandro Celaya
b2abfd543e Moved Shlink API services to api module 2020-12-22 09:57:09 +01:00
Alejandro Celaya
8c6eaf2f1d Moved API types and type helpers to api module 2020-12-22 09:49:18 +01:00
Alejandro Celaya
811544d7df Moved api utils to subfolder 2020-12-22 09:24:33 +01:00
Alejandro Celaya
9fdfdf865e Merge pull request #361 from acelaya-forks/feature/errors-improvements
Feature/errors improvements
2020-12-22 00:00:04 +01:00
Alejandro Celaya
6a354c277c Set API response as per Shlink v2 2020-12-21 23:55:54 +01:00
Alejandro Celaya
89f6c6c283 Updated changelog 2020-12-21 23:53:15 +01:00
Alejandro Celaya
d534a4e441 Moved logic to parse API errors to a helper function 2020-12-21 23:51:49 +01:00
Alejandro Celaya
4c3772d5c8 Added meaningful error messages for the rest of API calls 2020-12-21 23:41:50 +01:00
Alejandro Celaya
ee95d5a1b7 Improved handling of errors in several API interactions 2020-12-21 21:26:45 +01:00
Alejandro Celaya
51379eb2a0 Created component holding the logic to render Shlink API errors 2020-12-21 21:19:02 +01:00
Alejandro Celaya
f69f791790 Improved handling of short URL deletion errors 2020-12-21 21:02:30 +01:00
Alejandro Celaya
54b1ab12cd Passed API error while creating URLs to display proper error messages 2020-12-21 20:55:52 +01:00
Alejandro Celaya
18d417e78c Merge pull request #359 from acelaya-forks/feature/message-improvements
Feature/message improvements
2020-12-21 18:31:21 +01:00
Alejandro Celaya
7a48a06442 Normalized import 2020-12-21 18:20:59 +01:00
Alejandro Celaya
195aaa8be6 Updated changelog 2020-12-21 18:15:09 +01:00
Alejandro Celaya
94d2f3167b Created Result test 2020-12-21 18:14:11 +01:00
Alejandro Celaya
344f5e9b0d Updated Result component so that it has the text centered by default 2020-12-21 17:58:46 +01:00
Alejandro Celaya
b211a29fc5 Created new Result component to display operation result messages consistently 2020-12-21 17:54:20 +01:00
Alejandro Celaya
c25355c531 Added Message test 2020-12-21 09:57:46 +01:00
Alejandro Celaya
5cf0c86a14 Normalized Message component, making it autocontained 2020-12-21 09:22:13 +01:00
Alejandro Celaya
852e791c80 Merge pull request #357 from acelaya-forks/feature/routable-visits-sections
Feature/routable visits sections
2020-12-20 20:01:04 +01:00
Alejandro Celaya
f5d03ed3a2 Created query helper test 2020-12-20 19:51:43 +01:00
Alejandro Celaya
4642e07fd3 Reduced duplication when defining routes in visits section 2020-12-20 19:42:37 +01:00
Alejandro Celaya
83221c1066 Added routes to subsections in visits 2020-12-20 19:28:14 +01:00
Alejandro Celaya
214b952e84 Merge pull request #356 from acelaya-forks/feature/welcome-ui
Feature/welcome UI
2020-12-20 12:39:18 +01:00
Alejandro Celaya
42adbb3739 Updated changelog 2020-12-20 12:32:54 +01:00
Alejandro Celaya
9e63c463ca Styled scroll in servers list for home page 2020-12-20 12:25:17 +01:00
Alejandro Celaya
260a6c4940 Improved welcome screen 2020-12-20 12:17:12 +01:00
Alejandro Celaya
fa949cde12 Simplified onTagClick handling in ShortUrlsTable 2020-12-20 09:09:22 +01:00
Alejandro Celaya
23da0328ec Added Shlink logo as react component 2020-12-20 08:56:46 +01:00
Alejandro Celaya
7da634e772 Fixed tags filtering from overview page 2020-12-19 22:49:11 +01:00
Alejandro Celaya
79f7459d77 Merge pull request #354 from acelaya-forks/feature/ci-migration
Replaced scrutinizer with codecov
2020-12-19 12:58:43 +01:00
Alejandro Celaya
4002392b12 Replaced scrutinizer with codecov 2020-12-19 12:55:30 +01:00
Alejandro Celaya
e9e53bb69b Added border on top of overview section cards 2020-12-17 18:42:43 +01:00
Alejandro Celaya
623deec973 Merge pull request #353 from acelaya-forks/feature/more-ui-improvements
Feature/more UI improvements
2020-12-15 19:04:04 +01:00
Alejandro Celaya
3453d4ffd5 Fixed coding styles 2020-12-15 18:59:14 +01:00
Alejandro Celaya
f9ef7eccf8 Updated changelog 2020-12-15 18:53:41 +01:00
Alejandro Celaya
3cdcffaac3 Fixed mutation checks step in ci workflow 2020-12-15 18:45:15 +01:00
Alejandro Celaya
0f23cdcd21 Updated initial interval for visits to be last 30 days 2020-12-15 18:40:36 +01:00
Alejandro Celaya
9dc6c756f2 Fixed rendering of cards in overview page 2020-12-15 18:12:15 +01:00
Alejandro Celaya
0491694839 Set fixed width to aside menu 2020-12-15 17:57:24 +01:00
Alejandro Celaya
f1f3c3f98b Merge pull request #350 from acelaya-forks/feature/ui-improvements
Feature/UI improvements
2020-12-15 10:05:16 +01:00
Alejandro Celaya
ec3ad8412c Fixed mutation tests in ci workflow 2020-12-15 10:01:15 +01:00
Alejandro Celaya
d39512732a Fixed DateRangeSelector focus state 2020-12-15 09:54:45 +01:00
Alejandro Celaya
95abf4f898 Updated changelog 2020-12-14 23:36:58 +01:00
Alejandro Celaya
61a1087d91 Added date range selector to short URLs list 2020-12-14 23:35:31 +01:00
Alejandro Celaya
3f245a757e Created DateRangeSelector test 2020-12-14 23:15:06 +01:00
Alejandro Celaya
4e236a80de Created new dropdown component to select relative or absolute date ranges 2020-12-14 22:58:15 +01:00
Alejandro Celaya
288f6e2cf8 Fixed rendering of ShlinkVersions component to match current layout 2020-12-14 19:05:25 +01:00
Alejandro Celaya
9b6d4a4d97 Added max-width to internal container 2020-12-14 18:39:19 +01:00
Alejandro Celaya
f2a8865679 Added new card styles to error pages 2020-12-13 20:57:00 +01:00
Alejandro Celaya
017db18e70 Removed unneeded step in ci workflow 2020-12-13 10:38:03 +01:00
Alejandro Celaya
19c4a61524 Added github and docker logos to badges 2020-12-13 09:32:37 +01:00
Alejandro Celaya
f01c9bd5c8 Fixed build badge 2020-12-13 06:47:46 +01:00
Alejandro Celaya
2a5fa54ae1 Merge pull request #348 from acelaya-forks/feature/github-actions
Created workflow for ci in github actions
2020-12-12 21:48:23 +01:00
Alejandro Celaya
7a1b6367a8 Changed build badges to point to github action 2020-12-12 21:43:16 +01:00
Alejandro Celaya
058860737e Removed travis-specific env vars from github action 2020-12-12 21:39:51 +01:00
Alejandro Celaya
20f2fd1080 Created workflow for ci in github actions 2020-12-12 21:29:25 +01:00
Alejandro Celaya
16ce1d24af Merge pull request #347 from acelaya-forks/feature/visits-improvements
Feature/visits improvements
2020-12-12 21:15:16 +01:00
Alejandro Celaya
a51db38749 Updated changelog 2020-12-12 21:07:32 +01:00
Alejandro Celaya
6090f97347 Updated tabs in visits section to be sticky 2020-12-12 21:05:54 +01:00
Alejandro Celaya
c74355e363 Improved visits section so that charts are grouped in sub tabs 2020-12-12 20:45:23 +01:00
Alejandro Celaya
a013d40bf1 More standardization color changes 2020-12-12 16:55:01 +01:00
Alejandro Celaya
7f7473c348 Merge pull request #346 from acelaya-forks/feature/drop-shlink-1-support
Dropped support for Shlink 1
2020-12-12 13:50:38 +01:00
Alejandro Celaya
df6f1b984f Dropped support for Shlink 1 2020-12-12 13:43:16 +01:00
Alejandro Celaya
b9905c8bf4 Ensured visits amount card displays warning for old shlink versions 2020-12-12 13:22:11 +01:00
Alejandro Celaya
32957835b3 Merge pull request #345 from acelaya-forks/feature/restyle
Feature/restyle
2020-12-12 12:13:52 +01:00
Alejandro Celaya
2efc5feb3f Updated changelog 2020-12-12 12:07:51 +01:00
Alejandro Celaya
526fa14dce Improved NoMenuLayout, using a container-xl style 2020-12-12 12:04:20 +01:00
Alejandro Celaya
4d969b994e Improved server form 2020-12-12 11:43:16 +01:00
Alejandro Celaya
d62edb2249 Moved 'add server' button inside servers dropdown 2020-12-12 11:29:15 +01:00
Alejandro Celaya
bc82e7e7fd Fixed colors in visits table 2020-12-12 11:11:36 +01:00
Alejandro Celaya
1e460d3ef7 Updated edit URL modal to be large 2020-12-12 11:07:05 +01:00
Alejandro Celaya
143a05cab1 Restyled cards, background and shadows 2020-12-12 10:56:10 +01:00
Alejandro Celaya
bf1b59c0d8 Merge pull request #343 from acelaya-forks/feature/overview-page
Feature/overview page
2020-12-08 19:44:25 +01:00
Alejandro Celaya
5ab38027bf Updated changelog 2020-12-08 19:38:35 +01:00
Alejandro Celaya
3e6aee47e5 Fixed TS compilation in tests 2020-12-08 19:36:47 +01:00
Alejandro Celaya
60282281a3 Grouped basic components in 'create' form in its own card 2020-12-08 19:21:31 +01:00
Alejandro Celaya
2017ee7456 Created SimpleCard component to reduce duplicated code when rendering cards 2020-12-08 19:10:29 +01:00
Alejandro Celaya
e60d241fcf Changed 'create' page, grouping components and adding more explanations 2020-12-08 18:52:18 +01:00
Alejandro Celaya
43af6fdaba Added redirect from server base path to overview page, to ease changing default page 2020-12-08 18:27:36 +01:00
Alejandro Celaya
f359a16004 Ensured tags input looks as a large input 2020-12-08 18:18:16 +01:00
Alejandro Celaya
1b413fb0b7 Created Overview component test 2020-12-08 17:51:49 +01:00
Alejandro Celaya
20a9259109 Minor style improvements in overview page 2020-12-08 11:39:16 +01:00
Alejandro Celaya
8d5f7e942d Implemented reducers for actions affecting short URLs list 2020-12-08 10:57:27 +01:00
Alejandro Celaya
17d5c4327b Added form to create short URLs to overview page 2020-12-07 20:37:03 +01:00
Alejandro Celaya
9b30a82a79 Created visitsOverview reducer test 2020-12-07 19:19:37 +01:00
Alejandro Celaya
a0ec3c0293 Improved wording 2020-12-07 13:03:47 +01:00
Alejandro Celaya
d9e39eee2b Added new reducer for visits overview, and added it to overview page 2020-12-07 12:12:39 +01:00
Alejandro Celaya
032e9c53f3 Extracted short URLs table into reusable component to use both on list section and overview section 2020-12-07 11:17:19 +01:00
Alejandro Celaya
dba0ac6442 Created Overview page as default page after connecting to a server 2020-12-06 18:37:22 +01:00
Alejandro Celaya
920effb4c6 Merge pull request #341 from acelaya-forks/feature/validate-flag
Feature/validate flag
2020-12-06 13:21:08 +01:00
Alejandro Celaya
bd6e455cd6 Fixed import 2020-12-06 13:20:16 +01:00
Alejandro Celaya
b9fc906537 Fixed alignment and margins for checkboxes in create form 2020-12-06 13:14:43 +01:00
Alejandro Celaya
1415f196bb Updated changelog 2020-12-06 13:09:06 +01:00
Alejandro Celaya
8f7e356e54 Added support to enable/disable validating the URL while it is created 2020-12-06 13:07:44 +01:00
Alejandro Celaya
0ed88079ad Skip install step when building docker image in travis 2020-12-06 11:57:14 +01:00
Alejandro Celaya
5182f9d147 Merge pull request #339 from acelaya-forks/feature/domains-dropdown
Feature/domains dropdown
2020-11-28 12:48:20 +01:00
Alejandro Celaya
4e1579832e Updated changelog 2020-11-28 12:38:16 +01:00
Alejandro Celaya
ff48c0cd45 Added DomainSelector test 2020-11-28 12:36:40 +01:00
Alejandro Celaya
02c7125236 Created domainsList reducer test 2020-11-28 12:22:52 +01:00
Alejandro Celaya
dc397d4b82 Improved existing tests 2020-11-28 11:45:04 +01:00
Alejandro Celaya
2a206f11b9 Renamed DomainsDropdown to DomainSelector 2020-11-28 09:58:05 +01:00
Alejandro Celaya
369fcf2f6a Improved design on domains dropdown 2020-11-28 09:34:41 +01:00
Alejandro Celaya
983e4db3b1 Created component to allow selecting from existing domains list 2020-11-25 21:05:27 +01:00
Alejandro Celaya
2a7c2474cd Merge pull request #336 from acelaya-forks/feature/fix-visits
Feature/fix visits
2020-11-14 13:09:51 +01:00
Alejandro Celaya
c890124e67 Updated changelog 2020-11-14 13:02:28 +01:00
Alejandro Celaya
3e21cccb14 Fixed visits getting accumulated every time the visits page is opened 2020-11-14 13:01:35 +01:00
Alejandro Celaya
dafebc3df9 Merge pull request #332 from acelaya-forks/feature/update-deps
Feature/update deps
2020-11-14 12:21:49 +01:00
Alejandro Celaya
6619e7cdb6 Updated changelog 2020-11-14 12:13:28 +01:00
Alejandro Celaya
c54f314424 Updated react-datepicker to latest version 2020-11-14 12:10:42 +01:00
Alejandro Celaya
4964f28169 Updated more production dependencies 2020-11-14 11:00:41 +01:00
Alejandro Celaya
dead22c332 Updated reactstrap 2020-11-14 10:33:32 +01:00
Alejandro Celaya
aba65346b4 Updated react-dev-utils 2020-11-14 10:24:15 +01:00
Alejandro Celaya
4621246cec Updated color-picker and fixed error when left open and modal is closed 2020-11-14 09:16:26 +01:00
Alejandro Celaya
f83280068b Updated more dev dependencies 2020-11-14 08:59:20 +01:00
Alejandro Celaya
0671fa6567 Updated to stryker v4 2020-11-13 23:06:03 +01:00
Alejandro Celaya
5c80e853c6 #325 Updated to Typescript 4 2020-11-13 22:46:17 +01:00
Alejandro Celaya
6c90d7072f #325 Updated to react 17 2020-11-13 22:44:26 +01:00
Alejandro Celaya
18bccab27a Moved to official docker github actions for docker-image-build 2020-11-10 19:25:20 +01:00
Alejandro Celaya
b9213952d3 Added npm ci when generating release 2020-11-01 10:39:09 +01:00
Alejandro Celaya
f1ae68a300 Allow empty changelog when publishing release 2020-11-01 10:34:53 +01:00
Alejandro Celaya
3f0409f25a Merge pull request #331 from acelaya-forks/feature/automatic-release
Feature/automatic release
2020-11-01 10:32:41 +01:00
Alejandro Celaya
6f568a16bf Moved tag releasing from travis to github workflow 2020-11-01 10:27:33 +01:00
Alejandro Celaya
39ae3b4762 Updated chanegelog to more strictly endorse to keepachangelog spec 2020-11-01 10:21:44 +01:00
Alejandro Celaya
14e31ed2c3 Merge pull request #330 from acelaya-forks/feature/fix-switch-alignment
Removed hardcoded display: inline for BooleanControls
2020-10-31 17:28:19 +01:00
Alejandro Celaya
ff1fb0dd12 Removed hardcoded display: inline for BooleanControls 2020-10-31 17:18:51 +01:00
Alejandro Celaya
2e6a35181d Merge pull request #329 from acelaya-forks/feature/fix-too-long-cache
Feature/fix too long cache
2020-10-31 13:47:43 +01:00
Alejandro Celaya
22cca598ca Updated changelog 2020-10-31 13:38:37 +01:00
Alejandro Celaya
de906bf370 Added proper caching rules to nginx config included in docker image 2020-10-31 13:36:53 +01:00
Alejandro Celaya
498594c31b Deleted service worker 2020-10-31 13:22:39 +01:00
Alejandro Celaya
cfbd246cfc Merge pull request #327 from acelaya-forks/feature/dart-sass
Feature/dart sass
2020-10-31 13:07:52 +01:00
Alejandro Celaya
3f91c556e4 Explicitly installed node 14 in scrutinizer env 2020-10-31 13:00:09 +01:00
Alejandro Celaya
4d1622607c Enabled all platforms back on docker image builds 2020-10-31 12:34:42 +01:00
Alejandro Celaya
eacdee293c Replaced node-sass with dart-sass 2020-10-31 12:27:24 +01:00
Alejandro Celaya
f4b115cffd Merge pull request #326 from acelaya-forks/feature/node-14
Updated to node 14
2020-10-31 12:08:35 +01:00
Alejandro Celaya
7dcd623513 Updated to node 14 2020-10-31 11:58:07 +01:00
Alejandro Celaya
8b00d1aaae Updated reference from travis-ci.org to travis-ci.com 2020-10-31 09:11:43 +01:00
Alejandro Celaya
facfd33e96 Merge pull request #319 from acelaya-forks/feature/calendar-z-index
Feature/calendar z index
2020-10-03 11:28:20 +02:00
Alejandro Celaya
a841dc7531 Updated changelog 2020-10-03 11:23:08 +02:00
Alejandro Celaya
28ebd55b69 Fixed z-index in react-datepicker 2020-10-03 11:22:21 +02:00
Alejandro Celaya
3eade5a0c0 Merge pull request #318 from acelaya-forks/feature/manifest-basic-auth
Feature/manifest basic auth
2020-10-03 11:10:57 +02:00
Alejandro Celaya
caf74cd87b Updated changelog 2020-10-03 11:03:17 +02:00
Alejandro Celaya
049510f513 Added crossorigin=use-credentials to manifest.json, so that credentials are passed and it is propery downloaded 2020-10-03 11:00:56 +02:00
Alejandro Celaya
b151b7eedb Added missing condition for github release to work on travis build 2020-09-20 12:46:51 +02:00
Alejandro Celaya
4e22e9c092 Added script step to publish release travis job 2020-09-20 12:38:47 +02:00
Alejandro Celaya
793883148a Added v2.6 to changelog 2020-09-20 12:07:16 +02:00
Alejandro Celaya
8acb7bea24 Merge pull request #310 from acelaya-forks/feature/line-chart-highlights
Feature/line chart highlights
2020-09-20 12:05:06 +02:00
Alejandro Celaya
335cceeb82 Fixed coding styles 2020-09-20 11:58:40 +02:00
Alejandro Celaya
bf7455ad6e Updated changelog 2020-09-20 11:49:19 +02:00
Alejandro Celaya
421cc5b718 Put together all chart-related helper functions 2020-09-20 11:46:07 +02:00
Alejandro Celaya
78d97a64aa Added visits highlightning capabilities to line chart 2020-09-20 11:43:24 +02:00
Alejandro Celaya
749c757cbd Removed unneeded condition on travis deploy step, as the same condition is on the parent job 2020-09-20 10:43:21 +02:00
Alejandro Celaya
faf9554286 Added lines between job definitions in travis config 2020-09-19 18:52:49 +02:00
Alejandro Celaya
b7a0be3872 Allowed mutation testing step to fail without failing the whole build 2020-09-19 18:08:16 +02:00
Alejandro Celaya
cff8046ff8 Merge pull request #308 from acelaya-forks/feature/contributing
Added CONTRIBUTING.md file
2020-09-19 17:42:28 +02:00
Alejandro Celaya
af1289752d Added reference to the CONTRIBUTING file from the README file 2020-09-19 17:42:06 +02:00
Alejandro Celaya
b06d9d3bc7 Added CONTRIBUTING.md file 2020-09-19 17:32:54 +02:00
Alejandro Celaya
b2904189ef Merge pull request #307 from acelaya-forks/feature/parallel-builds
Feature/parallel builds
2020-09-19 17:04:52 +02:00
Alejandro Celaya
5c639d241b Disabled docker image build in arm archs, as it fails with node-sass 2020-09-19 16:58:01 +02:00
Alejandro Celaya
984e9f32a5 Split all scripts in travis build into individual jobs 2020-09-19 16:57:35 +02:00
Alejandro Celaya
59d23b584a Merge pull request #304 from acelaya-forks/feature/gh-action-docker-build
Feature/gh action docker build
2020-09-19 16:35:29 +02:00
Alejandro Celaya
a7d865228a Updated name of branch in which docker build action needs to run 2020-09-19 16:25:33 +02:00
Alejandro Celaya
260ff716d7 Updated changelog 2020-09-19 16:24:43 +02:00
Alejandro Celaya
9001a3da37 Moved docker build to github actions, enabling multi-arch support 2020-09-19 16:23:39 +02:00
Alejandro Celaya
46db1e39f3 Merge pull request #303 from acelaya-forks/feature/cancel-tags-visits
Feature/cancel tags visits
2020-09-19 11:23:54 +02:00
Alejandro Celaya
6bf3fc0fd5 Updated changelog 2020-09-19 10:51:41 +02:00
Alejandro Celaya
a136543551 Fixed tags visits loading not being cancelled when the visits component gets unmounted 2020-09-19 10:50:49 +02:00
Alejandro Celaya
23046c149c Fixed visits normalization not converting empty strings into null 2020-09-19 10:31:23 +02:00
Alejandro Celaya
2951d0d75e Merge pull request #302 from acelaya-forks/feature/number-formatting
Feature/number formatting
2020-09-19 10:16:54 +02:00
Alejandro Celaya
b52e40edd3 Updated changelog 2020-09-17 18:11:03 +02:00
Alejandro Celaya
51556d76ac Fixed tests 2020-09-17 18:05:26 +02:00
Alejandro Celaya
871868f0a4 Moved common rendering chart labels code to external module for reuse 2020-09-15 22:30:31 +02:00
Alejandro Celaya
67495fa302 Added number formatting to charts 2020-09-15 22:22:56 +02:00
Alejandro Celaya
fc9341f631 Added number formatting to visits line chart 2020-09-13 11:11:17 +02:00
Alejandro Celaya
3fea8b5505 Ensured page numbers in paginators are prettified 2020-09-13 10:03:02 +02:00
Alejandro Celaya
89e3114ef3 Merge pull request #300 from acelaya-forks/feature/default-ordering
Feature/default ordering
2020-09-13 09:54:20 +02:00
Alejandro Celaya
4dc5fad8b8 Fixed coding standards 2020-09-13 09:47:29 +02:00
Alejandro Celaya
2567bdfdf0 Updated changelog 2020-09-13 09:32:02 +02:00
Alejandro Celaya
f36cf1e7b9 Updated short URL list params so that it requests dateCreated DESC ordering by default 2020-09-12 17:59:58 +02:00
Alejandro Celaya
bd88e56331 Merge pull request #299 from acelaya-forks/feature/updates-interval
Feature/updates interval
2020-09-12 13:18:23 +02:00
Alejandro Celaya
fe3e08de0f Fixed event source not being properly closed with new boundToMercureHub HOC 2020-09-12 12:06:53 +02:00
Alejandro Celaya
cfb165d240 Fixed boundToMercureHub HOC so that it clears updates intervals when unmounted 2020-09-12 11:55:49 +02:00
Alejandro Celaya
fa074f91be Updated changelog 2020-09-12 11:35:12 +02:00
Alejandro Celaya
6fc4963663 Replaced redux action to create one visit by action that allows multiple visits at once 2020-09-12 11:31:44 +02:00
Alejandro Celaya
ad437f655e Added support to dispatch all UI actions based on mercure bindings on a specific schedule instead of real time 2020-09-12 08:52:03 +02:00
Alejandro Celaya
9b45513684 Added form controls to set real time updates interval 2020-09-09 19:16:04 +02:00
Alejandro Celaya
5d6d802d64 Moved mercure hub binding from custom hook to HOC 2020-09-06 19:41:15 +02:00
Alejandro Celaya
536d49aac9 Merge pull request #298 from acelaya-forks/feature/always-visible-versions
Feature/always visible versions
2020-09-06 13:20:17 +02:00
Alejandro Celaya
796c9ca140 Fixed changelog 2020-09-06 13:11:33 +02:00
Alejandro Celaya
1b1a1f3230 Created component decorator that resets selected server and used it on Settings 2020-09-06 13:10:30 +02:00
Alejandro Celaya
98d856700c Added missing row wrapping Message component 2020-09-06 12:47:14 +02:00
Alejandro Celaya
b814f500de Moved shlink versions to the outer element so that's always visible 2020-09-06 12:36:17 +02:00
Alejandro Celaya
90abf29db9 Merge pull request #296 from acelaya-forks/feature/typescript
Feature/typescript
2020-09-06 10:29:55 +02:00
Alejandro Celaya
d064eb5f9e Fixed inconsistent type 2020-09-06 10:22:21 +02:00
Alejandro Celaya
58c9ef9b51 Updated dependencies 2020-09-06 10:17:46 +02:00
Alejandro Celaya
125b13e059 Added stryker mutator for TS 2020-09-06 09:46:07 +02:00
Alejandro Celaya
dcdee8b308 Simplified eslint config 2020-09-06 09:32:16 +02:00
Alejandro Celaya
f33d1fca39 Updated pattern for code coverage collection 2020-09-06 09:18:02 +02:00
Alejandro Celaya
7e907ba9b6 Updated changelog 2020-09-05 09:03:40 +02:00
Alejandro Celaya
3cec2efbbd Removed no longer used dependencies 2020-09-05 08:57:50 +02:00
Alejandro Celaya
d4094e66b3 Finished TS migration 2020-09-05 08:49:18 +02:00
Alejandro Celaya
73b854037d Migrated to TS all visits components except the biggest two 2020-09-04 19:33:16 +02:00
Alejandro Celaya
f2e7a2161d Removed duplicated code on mercure-bound components 2020-09-04 19:05:41 +02:00
Alejandro Celaya
260ed3041a Finished migrating visits helpers to TS 2020-09-04 18:43:26 +02:00
Alejandro Celaya
8a146021dd Migrated first charts to TS 2020-09-03 20:34:22 +02:00
Alejandro Celaya
4083592212 Fixed coding styles and ensured linting command applies to ts and tsx files 2020-09-02 20:27:50 +02:00
Alejandro Celaya
f9c57ca659 Migrated first visits helper components to TS 2020-09-02 20:13:31 +02:00
Alejandro Celaya
d0d664ef79 Migrated VisitsParser to TS 2020-09-02 19:32:07 +02:00
Alejandro Celaya
16d96efa4a Finished migrating all remaining utils to TS 2020-08-31 18:38:27 +02:00
Alejandro Celaya
f8ea1ae3d5 Migrated remaining tags-related elements to TS 2020-08-30 20:48:09 +02:00
Alejandro Celaya
18883caa6d Migrated tags helpers to TS 2020-08-30 20:31:31 +02:00
Alejandro Celaya
84fc82b74e Fixed custom slug field not being disabled when selecting a short code length 2020-08-30 19:52:40 +02:00
Alejandro Celaya
8a9c694fbc Migrated all remaining short-url elements to TS 2020-08-30 19:45:17 +02:00
Alejandro Celaya
4b33d39d44 Finished migrating ll short-url helpers to TS 2020-08-30 09:59:14 +02:00
Alejandro Celaya
c0f5d9c12c Finished migrating servers module to TS 2020-08-29 20:20:45 +02:00
Alejandro Celaya
ef630af154 Migrated ShlinkApiClient to TS 2020-08-29 19:51:14 +02:00
Alejandro Celaya
ebd7a76896 Migrated to TS main services except ShlinkApiClient 2020-08-29 18:51:03 +02:00
Alejandro Celaya
64a968711c Migrated all servers services to TS 2020-08-29 14:16:37 +02:00
Alejandro Celaya
aee4c2d02f Migrated to TS all servers helpers 2020-08-29 13:51:53 +02:00
Alejandro Celaya
8cc0695ee9 Refactored ServerError to infer error message based on provided server type guards 2020-08-29 10:53:02 +02:00
Alejandro Celaya
f40ad91ea9 Migrated some common components and their dependencies to TS 2020-08-29 09:19:15 +02:00
Alejandro Celaya
a96539129d Migrated more common components to TS 2020-08-28 20:05:01 +02:00
Alejandro Celaya
dcf72e6818 Finished migrating remaining reducers to TS 2020-08-28 18:33:37 +02:00
Alejandro Celaya
54290d4c9a Migrated ShlinkApiClientBuilder to TS 2020-08-27 22:09:16 +02:00
Alejandro Celaya
eb3775859a Migrated tags reducers to typescripts 2020-08-27 19:12:09 +02:00
Alejandro Celaya
83531666de Migrated to typescript the most complex reducer in the project 2020-08-27 18:31:56 +02:00
Alejandro Celaya
f3a2535e2f Defined visits TS types 2020-08-27 17:56:48 +02:00
Alejandro Celaya
f283dc8569 Migrated short URL helper modal components to TS 2020-08-26 20:37:36 +02:00
Alejandro Celaya
b19bbee7fc More components migrated to TS 2020-08-26 20:03:23 +02:00
Alejandro Celaya
1b03d04318 Migrated more short-url reducers to TS 2020-08-26 18:55:40 +02:00
Alejandro Celaya
6696fb13d6 Created redux test 2020-08-25 20:23:12 +02:00
Alejandro Celaya
f04aece7df Removed dependency on redux-actions for all reducers already migrated to typescript 2020-08-25 19:42:15 +02:00
Alejandro Celaya
d8f3952920 Migrated first short URL reducers to typescript 2020-08-24 18:52:52 +02:00
Alejandro Celaya
fefa4e7848 Migrated settings module to TS 2020-08-24 17:32:20 +02:00
Alejandro Celaya
0b4a348969 Migrated remoteServers reducer to TS 2020-08-23 11:58:43 +02:00
Alejandro Celaya
3e2fee0df5 Migrated selectedServer test to typescript 2020-08-23 10:58:43 +02:00
Alejandro Celaya
294888454d Renamed NewServerData to ServerData, as it's used in other contexts too 2020-08-23 10:52:37 +02:00
Alejandro Celaya
1b7e1e2b5b Tweaked server types and data 2020-08-23 10:51:42 +02:00
Alejandro Celaya
dc78138066 Migrate servers reducer to typescript 2020-08-23 10:20:31 +02:00
Alejandro Celaya
87e64e5899 Migrated first reducer to typescript, adding also type for the shared app state 2020-08-23 09:52:09 +02:00
Alejandro Celaya
e193a692e8 Migrated all service providers to typescript 2020-08-23 09:03:44 +02:00
Alejandro Celaya
2eba607874 More elements migrated to typescript 2020-08-22 19:03:25 +02:00
Alejandro Celaya
62df46d648 Refactored many helpers to Typescript 2020-08-22 18:32:48 +02:00
Alejandro Celaya
7c67fa4149 Migrate CreateServer component to Typescript 2020-08-22 17:58:44 +02:00
Alejandro Celaya
2db85c2783 Migrated to typescript first component getting another component with props injected 2020-08-22 13:41:54 +02:00
Alejandro Celaya
39663ba936 Migrated to TS first component where some dependency was being injected 2020-08-22 11:20:27 +02:00
Alejandro Celaya
eefea0c37b Added babel plugins to support latest TS functionalities 2020-08-22 11:00:11 +02:00
Alejandro Celaya
d65a6ba970 Migrated to Typescript a file which is imported in JS files 2020-08-22 09:48:55 +02:00
Alejandro Celaya
524b0a74c6 Migrated first component and test to typescript 2020-08-22 09:15:05 +02:00
Alejandro Celaya
72de9d4ff8 Added first Typescript files 2020-08-22 08:47:19 +02:00
Alejandro Celaya
a91f1b3bd4 Fixed coding styles 2020-08-22 08:10:31 +02:00
Alejandro Celaya
343a93b984 Installed TS and updated linter 2020-08-22 08:06:41 +02:00
Alejandro Celaya
8be17cce8a Merge pull request #291 from acelaya-forks/feature/toggle-switch
Feature/toggle switch
2020-07-14 16:23:23 +02:00
Alejandro Celaya
d2f818c1ea Moved common code between Checkbox and ToggleSwitch to child component 2020-07-14 16:14:16 +02:00
Alejandro Celaya
a675d60d59 Added new ToggleSwitch component 2020-07-14 16:05:00 +02:00
Alejandro Celaya
2d96c21b50 Updated changelog 2020-07-09 17:46:44 +02:00
Alejandro Celaya
6f6ba9e34d Merge pull request #290 from MartinH0/patch-1
Added Links to Version Info
2020-07-09 17:42:39 +02:00
Alejandro Celaya
e6efda5563 Fixed wrong use of quotes 2020-07-09 17:36:26 +02:00
Alejandro Celaya
b1df1652bf Fixed ShlinkVersions test 2020-07-09 17:34:29 +02:00
Alejandro Celaya
474239c151 Moved version link to common component, and fixed coding styles 2020-07-09 17:17:19 +02:00
MartinH0
feeb212259 Update ShlinkVersions.js 2020-07-09 15:54:45 +02:00
MartinH0
90245016a0 Update ShlinkVersions.js
Hope this works now, but tests obviously fails bc it does not expect a Link
2020-07-09 15:47:09 +02:00
MartinH0
8c7616c3a7 Update ShlinkVersions.js 2020-07-09 15:33:58 +02:00
MartinH0
ea84ce9c41 Update ShlinkVersions.js 2020-07-09 15:25:53 +02:00
MartinH0
c4730ec92d Update ShlinkVersions.js 2020-07-09 15:18:48 +02:00
MartinH0
76b3d573c0 Update ShlinkVersions.js 2020-07-09 15:15:01 +02:00
MartinH0
b96f4b7a90 Update ShlinkVersions.js
Changed back ExternalLink against docs to normal closing Tag.
2020-07-09 15:04:14 +02:00
MartinH0
2a0def262d Update ShlinkVersions.js 2020-07-09 14:53:15 +02:00
MartinH0
897e35f0b8 Update ShlinkVersions.js 2020-07-09 14:43:53 +02:00
MartinH0
1c335506d8 Update ShlinkVersions.js 2020-07-09 12:58:10 +02:00
MartinH0
d46acdbd70 Added Links to Version Info
Actually it would be better if the link is just added if version info is provided. Now the Link is given always.
2020-07-07 22:10:35 +02:00
Alejandro Celaya
026bb4140e Merge branch 'main' of github.com:shlinkio/shlink-web-client into main 2020-07-06 09:31:37 +02:00
Alejandro Celaya
d80f3da55d Updated comment on issue templates 2020-07-06 09:31:11 +02:00
Alejandro Celaya
f18495a4b1 Updated comment fixing line breaks 2020-06-27 09:11:42 +02:00
Alejandro Celaya
f908da78f6 Merge pull request #287 from acelaya-forks/feature/servers-warning
Added warning to pre-configuring servers section
2020-06-22 22:04:55 +02:00
Alejandro Celaya
bc16381c90 Added warning to pre-configuring servers section 2020-06-22 21:57:58 +02:00
Alejandro Celaya
4cb7aa64cf Removed references to master branch 2020-06-20 20:03:00 +02:00
Alejandro Celaya
da6d7aea8b Merge pull request #284 from acelaya-forks/feature/simplify-travis
Removed all conditional checks in travis
2020-06-10 18:50:23 +02:00
Alejandro Celaya
b310d79110 Removed all conditional checks in travis 2020-06-10 18:43:11 +02:00
Alejandro Celaya
e26cdc11c3 Merge pull request #283 from acelaya-forks/feature/chart-legend
Feature/chart legend
2020-06-06 12:27:01 +02:00
Alejandro Celaya
fa54aa3128 Updated changelog 2020-06-06 12:17:45 +02:00
Alejandro Celaya
e31e70039d Created GraphCard test 2020-06-06 12:16:19 +02:00
Alejandro Celaya
cb761dea8f Increased default height for doughnut charts 2020-06-06 12:08:21 +02:00
Alejandro Celaya
949e0da105 Added custom responsive legend to doughnut charts 2020-06-06 11:58:25 +02:00
Alejandro Celaya
770cc59448 Extracted logic to render graph from GraphCard to DefatlChart component 2020-06-06 10:35:13 +02:00
Alejandro Celaya
72dd2bd0a7 Merge pull request #282 from acelaya-forks/feature/mercure-dup-code
Feature/mercure dup code
2020-06-06 09:47:15 +02:00
Alejandro Celaya
54733eaa18 Updated changelog 2020-06-06 09:30:39 +02:00
Alejandro Celaya
52c56f7918 Created custom react hook that binds to mercure topic 2020-06-06 09:29:43 +02:00
Alejandro Celaya
c46d5187c1 Removed duplicated code when binding to mercure by checking if enabled first 2020-06-06 09:24:05 +02:00
Alejandro Celaya
05e3e87653 Merge pull request #281 from acelaya-forks/feature/docker-version
Fixed version not properly provided to docker image
2020-06-06 08:58:41 +02:00
Alejandro Celaya
8b9289ff08 Fixed version not properly provided to docker image 2020-06-06 08:50:37 +02:00
Alejandro Celaya
16ffbcfbc0 Merge pull request #278 from acelaya-forks/feature/fix-default-grouping
Feature/fix default grouping
2020-05-31 20:30:32 +02:00
Alejandro Celaya
d825b6e174 Updated changelog 2020-05-31 20:17:59 +02:00
Alejandro Celaya
73e55cc742 Replaced if/else by functional matcher 2020-05-31 20:16:15 +02:00
Alejandro Celaya
32cc1cc580 Improved logic to determine default grouping for line chart based on how old the visits are 2020-05-31 20:03:59 +02:00
Alejandro Celaya
e00574553f Moved some helper components for visits to visits/helpers 2020-05-31 17:51:52 +02:00
700 changed files with 43503 additions and 31824 deletions

View File

@@ -5,3 +5,4 @@
./test
./shlink-web-client.gif
./dist
./docs

View File

@@ -1,45 +1,16 @@
{
"root": true,
"extends": [
"adidas-env/browser",
"adidas-env/module",
"adidas-env/node",
"adidas-es6",
"adidas-babel",
"adidas-react"
"@shlinkio/js-coding-standard"
],
"plugins": ["jest"],
"env": {
"jest/globals": true
},
"globals": {
"process": true,
"setImmediate": true
},
"settings": {
"react": {
"version": "16.3"
}
"parserOptions": {
"project": "./tsconfig.json"
},
"ignorePatterns": ["src/service*.ts"],
"rules": {
"comma-dangle": ["error", "always-multiline"],
"no-invalid-this": "off",
"no-console": "warn",
"template-curly-spacing": ["error", "never"],
"no-warning-comments": "off",
"no-magic-numbers": "off",
"no-undefined": "off",
"no-inline-comments": "off",
"lines-around-comment": "off",
"indent": ["error", 2, {
"SwitchCase": 1
}
],
"react/jsx-curly-spacing": ["error", "never"],
"react/jsx-indent-props": ["error", 2],
"react/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
"react/jsx-closing-bracket-location": ["error", "tag-aligned"],
"react/no-array-index-key": "off",
"react/no-did-update-set-state": "off",
"react/display-name": "off"
"jsx-a11y/control-has-associated-label": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off"
}
}

View File

@@ -1,6 +1,7 @@
<!--
Before opening an issue, just take into account that this is a completely free of charge open source project.
I'm always happy to help and provide support, but some understanding will be required.
Before opening an issue, just take into account that this is a completely free of charge and open source project.
I'm always happy to help and provide support, but some understanding will be expected.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
You may also be asked to provide tests or ways to reproduce reported bugs.
Try to be polite, and understand it is impossible for an OSS project to cover all use cases.
-->

View File

@@ -5,9 +5,10 @@ labels: bug
---
<!--
Before opening an issue, just take into account that this is a completely free of charge open source project.
I'm always happy to help and provide support, but some understanding will be required.
Before opening an issue, just take into account that this is a completely free of charge and open source project.
I'm always happy to help and provide support, but some understanding will be expected.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
You may also be asked to provide tests or ways to reproduce reported bugs.
Try to be polite, and understand it is impossible for an OSS project to cover all use cases.
With that said, please fill in the information requested next. More information might be requested once the issue is open.

View File

@@ -5,9 +5,10 @@ labels: feature
---
<!--
Before opening an issue, just take into account that this is a completely free of charge open source project.
I'm always happy to help and provide support, but some understanding will be required.
Before opening an issue, just take into account that this is a completely free of charge and open source project.
I'm always happy to help and provide support, but some understanding will be expected.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
You may also be asked to provide tests or ways to reproduce reported bugs.
Try to be polite, and understand it is impossible for an OSS project to cover all use cases.
With that said, please fill in the information requested next. More information might be requested once the issue is open.

View File

@@ -5,9 +5,10 @@ labels: question
---
<!--
Before opening an issue, just take into account that this is a completely free of charge open source project.
I'm always happy to help and provide support, but some understanding will be required.
Before opening an issue, just take into account that this is a completely free of charge and open source project.
I'm always happy to help and provide support, but some understanding will be expected.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
You may also be asked to provide tests or ways to reproduce reported bugs.
Try to be polite, and understand it is impossible for an OSS project to cover all use cases.
With that said, please fill in the information requested next. More information might be requested once the issue is open.

16
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Continuous integration
on:
pull_request: null
push:
branches:
- main
- develop
jobs:
ci:
uses: shlinkio/github-actions/.github/workflows/web-app-ci.yml@main
with:
node-version: 20.2
publish-coverage: true
force-install: true

28
.github/workflows/deploy-preview.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Deploy preview
on:
pull_request_target: null
jobs:
deploy:
runs-on: ubuntu-20.04
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v3
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
with:
node-version: 20.2
- name: Build
run: |
npm ci --force && \
node ./scripts/set-homepage.js /shlink-web-client/${GITHUB_HEAD_REF#refs/heads/} && \
npm run build
- name: Deploy preview
uses: shlinkio/deploy-preview-action@v1.0.1
with:
folder: build

View File

@@ -0,0 +1,15 @@
name: Build and publish docker image
on:
push:
tags:
- 'v*'
jobs:
build:
uses: shlinkio/github-actions/.github/workflows/docker-build-and-publish.yml@main
secrets: inherit
with:
image-name: shlinkio/shlink-web-client
version-arg-name: VERSION
platforms: 'linux/arm64/v8,linux/amd64'

27
.github/workflows/publish-release.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Publish release
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Use node.js
uses: actions/setup-node@v3
with:
node-version: 20.2
- name: Generate release assets
run: npm ci --force && VERSION=${GITHUB_REF#refs/tags/v} npm run build:dist
- name: Publish release with assets
uses: docker://antonyurchenko/git-release:latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ALLOW_EMPTY_CHANGELOG: "true"
with:
args: |
dist/shlink-web-client_*_dist.zip

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
# testing
/coverage
/.stryker-tmp
/reports
# production

View File

@@ -1,6 +0,0 @@
build:
environment:
node: v12.14.1
tools:
external_code_coverage:
timeout: 1200

View File

@@ -1,11 +1,5 @@
{
"extends": [
"stylelint-config-adidas",
"stylelint-config-adidas-bem",
"stylelint-config-recommended-scss"
],
"syntax": "scss",
"plugins": [
"stylelint-scss"
"@shlinkio/stylelint-config-css-coding-standard"
]
}

View File

@@ -1,58 +0,0 @@
dist: bionic
language: node_js
jobs:
fast_finish: true
include:
- name: "Docker publish"
node_js: '12.16.3'
if: NOT type = pull_request
env:
- DOCKER_PUBLISH="true"
- name: "CI"
node_js: '12.16.3'
env:
- DOCKER_PUBLISH="false"
allow_failures:
- name: "Docker publish"
cache:
directories:
- node_modules
services:
- docker
install:
- if [[ ${DOCKER_PUBLISH} == 'true' ]]; then sudo bash ./scripts/docker/install-docker ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then npm ci ; fi
before_script:
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then echo "Building commit range ${TRAVIS_COMMIT_RANGE}" ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then export MUTATION_FILES=$(git diff ${TRAVIS_COMMIT_RANGE:-origin/master} --name-only | grep -E 'src\/(.*).(js|ts|jsx|tsx)$' | paste -sd ",") ; fi
script:
- if [[ ${DOCKER_PUBLISH} == 'true' ]]; then bash ./scripts/docker/build ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then npm run lint ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then npm run test:ci ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then docker build -t shlink-web-client:test . ; fi
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then npm run mutate:ci ; fi
after_success:
- if [[ ${DOCKER_PUBLISH} == 'false' ]]; then node_modules/.bin/ocular coverage/clover.xml ; fi
# Before deploying, build dist file for current travis tag
before_deploy:
- if [[ ! -z $TRAVIS_TAG && ${DOCKER_PUBLISH} == 'false' ]]; then npm run build ${TRAVIS_TAG#?} ; fi
deploy:
- provider: releases
api_key:
secure: jBvPwC7EAbViaNR83rwMSt5XQDK0Iu9rgvEMa7GoyShbHcvUCCPd73Tu9quNpKi6NKsDY3INHgtch3vgonjGNGDGJ+yDyIBzXcvsAX2x3UcHpRbgY12uiINVmQxBI1+OVQB016Nm+cKC/i5Z36K4EmDbYfo+MrKndngM6AjcQFTwI8EwniIMaQgg4gNes//K8NhP5u0c3gwG+Q6jEGnq6uH3kcRgh6/epIZYpQyxjqWqKwF77sgcYj+X2Nf6XxtB5neuCi301UKLoLx8G0skh/Lm6KAIO4s9iIhIFa3UpoF21Ka0TxLpd2JxalLryCnFGlWWE6lxC9Htmc0TeRowJQlGdJXCskJ37xT9MljKY0fwNMu06VS/FUgykuCv+jP3zQu51pKu7Ew7+WeNPjautoOTu54VkdGyHcf2ThBNEyJQuiEwAQe4u7yAxY6R5ovEdvHBSIg4w1E5/Mxy5SMTCUlIAv6H7QQ1X9Z/zJm9HH5KeKz5tsHvQ/RIdSpgHXq/tC8o4Yup/LCFucXfrgvy/8pJoO1UpOlmvm62974NFfo0EG5YWwv6brUqz3QXpMjb8sWqgjltYMYJX3J7WZ34rIc+zt4NAmfhqgczaOC4pUGCiJ8jX3rMWIaQRn1AJ+5V337jL9fNDpTHny4phQjHrMJ1e0HZuNp0Xb5Q8wgqDPM=
file: "./dist/shlink-web-client_${TRAVIS_TAG#?}_dist.zip"
skip_cleanup: true
on:
all_branches: true
condition: ${DOCKER_PUBLISH} == 'false'
tags: true

File diff suppressed because it is too large Load Diff

72
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,72 @@
# Contributing
This file will guide you through the process of getting to project up and running, in case you want to provide coding contributions.
You will also see how to ensure the code fulfills the expected code checks, and how to create a pull request.
## System dependencies
The project can be run inside a docker container through provided docker-compose configuration.
Because of this, the only actual dependencies are [docker](https://docs.docker.com/get-docker/) and [docker-compose](https://docs.docker.com/compose/install/).
## Setting up the project
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:
* 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).
## 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 is the basic project structure:
```
shlink-web-client
├── config
├── public
├── scripts
├── src
├── test
├── package.json
└── README.md
```
* `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).
* `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.
## Running code checks
> 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).
## 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.
## Pull request process
In order to provide pull requests to this project, you should always start by creating a new branch, where you will make all desired changes.
The base branch should always be `main`, and the target branch for the pull request should also be `main`.
Before your branch can be merged, all the checks described in [Running code checks](#running-code-checks) have to be passing. You can verify that manually, or wait for the build to be run automatically after the pull request is created.

View File

@@ -1,12 +1,12 @@
FROM node:12.16.3-alpine as node
FROM node:20.2-alpine as node
COPY . /shlink-web-client
ARG VERSION="latest"
ENV VERSION ${VERSION}
RUN cd /shlink-web-client && \
npm install && npm run build -- ${VERSION} --no-dist
RUN cd /shlink-web-client && npm ci --force && npm run build
FROM nginx:1.17.10-alpine
FROM nginx:1.23-alpine
LABEL maintainer="Alejandro Celaya <alejandro@alejandrocelaya.com>"
RUN rm -r /usr/share/nginx/html && rm /etc/nginx/conf.d/default.conf
COPY config/docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY scripts/docker/servers_from_env.sh /docker-entrypoint.d/30-shlink-servers-json.sh
COPY --from=node /shlink-web-client/build /usr/share/nginx/html

View File

@@ -1,17 +1,20 @@
# shlink-web-client
[![Build Status](https://img.shields.io/travis/shlinkio/shlink-web-client.svg?style=flat-square)](https://travis-ci.org/shlinkio/shlink-web-client)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/shlinkio/shlink-web-client.svg?style=flat-square)](https://scrutinizer-ci.com/g/shlinkio/shlink-web-client/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/shlinkio/shlink-web-client.svg?style=flat-square)](https://scrutinizer-ci.com/g/shlinkio/shlink-web-client/?branch=master)
[![Build Status](https://img.shields.io/github/actions/workflow/status/shlinkio/shlink-web-client/ci.yml?branch=develop&logo=github&style=flat-square)](https://github.com/shlinkio/shlink-web-client/actions/workflows/ci.yml?query=workflow%3A%22Continuous+integration%22)
[![Code Coverage](https://img.shields.io/codecov/c/gh/shlinkio/shlink-web-client/develop?style=flat-square)](https://app.codecov.io/gh/shlinkio/shlink-web-client)
[![GitHub release](https://img.shields.io/github/release/shlinkio/shlink-web-client.svg?style=flat-square)](https://github.com/shlinkio/shlink-web-client/releases/latest)
[![Docker pulls](https://img.shields.io/docker/pulls/shlinkio/shlink-web-client.svg?style=flat-square)](https://hub.docker.com/r/shlinkio/shlink-web-client/)
[![GitHub license](https://img.shields.io/github/license/shlinkio/shlink-web-client.svg?style=flat-square)](https://github.com/shlinkio/shlink-web-client/blob/master/LICENSE)
[![Docker pulls](https://img.shields.io/docker/pulls/shlinkio/shlink-web-client.svg?logo=docker&style=flat-square)](https://hub.docker.com/r/shlinkio/shlink-web-client/)
[![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)
[![Twitter](https://img.shields.io/badge/follow-shlinkio-blue.svg?style=flat-square&logo=twitter&color=blue)](https://twitter.com/shlinkio)
[![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)
[![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).
![shlink-web-client](shlink-web-client.gif)
> If you are trying to find out how to run the project in development mode or how to provide contributions, read the [CONTRIBUTING](CONTRIBUTING.md) doc.
## Installation
There are three ways in which you can use this application.
@@ -51,7 +54,7 @@ Those servers can be exported and imported in other browsers, but if for some re
[
{
"name": "Main server",
"url": "https://doma.in",
"url": "https://s.test",
"apiKey": "09c972b7-506b-49f1-a19a-d729e22e599c"
},
{
@@ -67,6 +70,33 @@ Those servers can be exported and imported in other browsers, but if for some re
If you are using the shlink-web-client docker image, you can mount the `servers.json` file in a volume inside `/usr/share/nginx/html`, which is the app's document root inside the container.
docker run --name shlink-web-client -p 8000:80 -v ${PWD}/servers.json:/usr/share/nginx/html/servers.json shlinkio/shlink-web-client
Alternatively, you can mount a `conf.d` directory, which in turn contains the `servers.json` file, in a volume inside `/usr/share/nginx/html`. *(since shlink-web-client 3.2.0)*.
docker run --name shlink-web-client -p 8000:80 -v ${PWD}/my-config/:/usr/share/nginx/html/conf.d/ shlinkio/shlink-web-client
If you want to pre-configure a single server, you can provide its config via env vars. When the container starts up, it will build the `servers.json` file dynamically based on them. *(since shlink-web-client 3.2.0)*.
* `SHLINK_SERVER_URL`: The fully qualified URL for the Shlink server.
* `SHLINK_SERVER_API_KEY`: The API key.
* `SHLINK_SERVER_NAME`: The name to be displayed. Defaults to **Shlink** if not provided.
```shell
docker run \
--name shlink-web-client \
-p 8000:80 \
-e SHLINK_SERVER_URL=https://s.test \
-e SHLINK_SERVER_API_KEY=6aeb82c6-e275-4538-a747-31f9abfba63c \
shlinkio/shlink-web-client
```
> **Be extremely careful when using this feature.**
>
> Due to shlink-web-client's client-side nature, the file needs to be accessible from the browser.
>
> Because of that, make sure you use this only when you self-host shlink-web-client, and you know only trusted people will have access to it.
>
> Failing to do this could cause your API keys to end up being exposed.
## Serve project in subpath

View File

@@ -4,11 +4,31 @@ server {
root /usr/share/nginx/html;
index index.html;
# Expire rules for static content
# HTML files should never be cached. There's only one here, which is the entry point (index.html)
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
}
# Images and other binary assets can be saved for a month
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
add_header Cache-Control "public";
}
# JS and CSS files can be saved for a year, as they are always hashed. New versions will include a new hash anyway, forcing the download
location ~* \.(?:css|js)$ {
expires 1y;
add_header Cache-Control "public";
}
# servers.json may be on the root, or in conf.d directory
location = /servers.json {
try_files /servers.json /conf.d/servers.json;
}
# When requesting static paths with extension, try them, and return a 404 if not found
location ~* .+\.(css|js|html|png|jpe?g|gif|bmp|ico|json|csv|otf|eot|svg|svgz|ttf|woff|woff2|ijmap|pdf|tif|map) {
try_files $uri $uri/ =404;
}
# When requesting a path without extension, try it, and return the index if not found
# This allows HTML5 history paths to be handled by the client application
location / {

View File

@@ -1,100 +0,0 @@
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
// Make sure that including paths.js after env.js will read .env variables.
delete require.cache[require.resolve('./paths')];
const { NODE_ENV } = process.env;
if (!NODE_ENV) {
throw new Error(
'The NODE_ENV environment variable is required but was not specified.'
);
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
paths.dotenv,
].filter(Boolean);
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set. Variable expansion is supported in .env files.
// https://github.com/motdotla/dotenv
// https://github.com/motdotla/dotenv-expand
dotenvFiles.forEach((dotenvFile) => {
if (fs.existsSync(dotenvFile)) {
require('dotenv-expand')(
require('dotenv').config({
path: dotenvFile,
})
);
}
});
// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
// https://github.com/facebook/create-react-app/issues/253.
// It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd());
process.env.NODE_PATH = (process.env.NODE_PATH || '')
.split(path.delimiter)
.filter((folder) => folder && !path.isAbsolute(folder))
.map((folder) => path.resolve(appDirectory, folder))
.join(path.delimiter);
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;
function getClientEnvironment(publicUrl) {
const raw = Object.keys(process.env)
.filter((key) => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
// Useful for determining whether were running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl,
}
);
// Stringify all values so we can feed into Webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
}, {}),
};
return { raw, stringified };
}
module.exports = getClientEnvironment;

View File

@@ -1,13 +0,0 @@
// This is a custom Jest transformer turning style imports into empty objects.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process() {
return 'module.exports = {};';
},
getCacheKey() {
// The output is always the same.
return 'cssTransform';
},
};

View File

@@ -1,29 +0,0 @@
const path = require('path');
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));
if (filename.match(/\.svg$/)) {
return `module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: (props) => ({
$$typeof: Symbol.for('react.element'),
type: 'svg',
ref: null,
key: null,
props: Object.assign({}, props, {
children: ${assetFilename}
})
}),
};`;
}
return `module.exports = ${assetFilename};`;
},
};

View File

@@ -1,87 +0,0 @@
const path = require('path');
const fs = require('fs');
const url = require('url');
// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
const envPublicUrl = process.env.PUBLIC_URL;
function ensureSlash(inputPath, needsSlash) {
const hasSlash = inputPath.endsWith('/');
if (hasSlash && !needsSlash) {
return inputPath.substr(0, inputPath.length - 1);
} else if (!hasSlash && needsSlash) {
return `${inputPath}/`;
}
return inputPath;
}
const getPublicUrl = (appPackageJson) =>
envPublicUrl || require(appPackageJson).homepage;
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
// Webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
function getServedPath(appPackageJson) {
const publicUrl = getPublicUrl(appPackageJson);
const servedUrl =
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
return ensureSlash(servedUrl, true);
}
const moduleFileExtensions = [
'web.mjs',
'mjs',
'web.js',
'js',
'web.ts',
'ts',
'web.tsx',
'tsx',
'json',
'web.jsx',
'jsx',
];
// Resolve file paths in the same order as webpack
const resolveModule = (resolveFn, filePath) => {
const extension = moduleFileExtensions.find((extension) =>
fs.existsSync(resolveFn(`${filePath}.${extension}`)));
if (extension) {
return resolveFn(`${filePath}.${extension}`);
}
return resolveFn(`${filePath}.js`);
};
// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp('build'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
publicUrl: getPublicUrl(resolveApp('package.json')),
servedPath: getServedPath(resolveApp('package.json')),
};
module.exports.moduleFileExtensions = moduleFileExtensions;

View File

@@ -1,4 +0,0 @@
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });

27
config/test/setupTests.ts Normal file
View File

@@ -0,0 +1,27 @@
import 'vitest-canvas-mock';
import 'chart.js/auto';
import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers';
import matchers from '@testing-library/jest-dom/matchers';
import { cleanup } from '@testing-library/react';
import ResizeObserver from 'resize-observer-polyfill';
import { afterEach, expect } from 'vitest';
// Workaround for TypeScript error: https://github.com/testing-library/jest-dom/issues/439#issuecomment-1536524120
declare module 'vitest' {
interface Assertion<T = any> extends jest.Matchers<void, T>, TestingLibraryMatchers<T, void> {}
}
// Extends Vitest's expect method with methods from react-testing-library
expect.extend(matchers);
afterEach(() => {
// Clears all mocks after every test
vi.clearAllMocks();
// Run a cleanup after each test case (e.g. clearing jsdom)
cleanup();
});
(global as any).ResizeObserver = ResizeObserver;
(global as any).scrollTo = () => {};
(global as any).prompt = () => {};
(global as any).matchMedia = (media: string) => ({ matches: false, media });

View File

@@ -1,678 +0,0 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const getClientEnvironment = require('./env');
const paths = require('./paths');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
/* eslint-disable complexity */
module.exports = (webpackEnv) => {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = publicPath === './';
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && 'cheap-module-source-map',
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
entry: [
// Include an alternative client for WebpackDevServer. A client's job is to
// connect to WebpackDevServer by a socket and get notified about changes.
// When you save a file, the client will either apply hot updates (in case
// of CSS changes), or refresh the page (in case of JS changes). When you
// make a syntax error, this client will display a syntax error overlay.
// Note: instead of the default WebpackDevServer client, we use a custom one
// to bring better experience for Create React App users. You can replace
// the line below with these two lines if you prefer the stock client:
// require.resolve('webpack-dev-server/client') + '?/',
// require.resolve('webpack/hot/dev-server'),
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
// Finally, this is your app's code:
paths.appIndexJs,
// We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[chunkhash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[chunkhash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? (info) =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// Automatically split vendor and commons
// https://twitter.com/wSokra/status/969633336732905474
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
splitChunks: {
chunks: 'all',
name: false,
},
// Keep the runtime chunk separated to enable long term caching
// https://twitter.com/wSokra/status/969679223278505985
runtimeChunk: true,
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253
modules: [ 'node_modules' ].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebook/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: paths.moduleFileExtensions
.map((ext) => `.${ext}`)
.filter((ext) => useTypeScript || !ext.includes('ts')),
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
plugins: [
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
// guards against forgotten dependencies and such.
PnpWebpackPlugin,
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [ paths.appPackageJson ]),
],
},
resolveLoader: {
plugins: [
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
// from the current package.
PnpWebpackPlugin.moduleLoader(module),
],
},
module: {
strictExportPresence: true,
rules: [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|mjs|jsx)$/,
enforce: 'pre',
use: [
{
options: {
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [ /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/ ],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent:
'@svgr/webpack?-prettier,-svgo![path]',
},
},
},
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
{
test: /\.(js|mjs)$/,
exclude: /@babel(?:\/|\\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// If an error happens in a package, it's possible to be
// because it was compiled. Thus, we don't want the browser
// debugger to show the original code. Instead, the code
// being evaluated would be much more helpful.
sourceMaps: false,
},
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [ /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/ ],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [ /runtime~.+[.]js/ ]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [ /\.map$/, /asset-manifest\.json$/ ],
importWorkboxFrom: 'cdn',
navigateFallback: `${publicUrl}/index.html`,
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: false,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
compilerOptions: {
module: 'esnext',
moduleResolution: 'node',
resolveJsonModule: true,
isolatedModules: true,
noEmit: true,
jsx: 'preserve',
},
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
formatter: typescriptFormatter,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};

View File

@@ -1,115 +0,0 @@
const fs = require('fs');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const paths = require('./paths');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const host = process.env.HOST || '0.0.0.0';
module.exports = function(proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebook/create-react-app/issues/2271
// https://github.com/facebook/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
disableHostCheck:
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
// Enable gzip compression of generated files.
compress: true,
// Silence WebpackDevServer's own logs since they're generally not useful.
// It will still show compile warnings and errors with this setting.
clientLogLevel: 'none',
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files wont automatically be available in
// production build folder unless we copy them. However, copying the whole
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
// for files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through Webpack. If you just want to
// use an image, put it in `src` and `import` it from JavaScript instead.
contentBase: paths.appPublic,
// By default files from `contentBase` will not trigger a page reload.
watchContentBase: true,
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
// for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point
// in the Webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser.
hot: true,
// It is important to tell WebpackDevServer to use the same "root" path
// as we specified in the config. In development, we always serve from /.
publicPath: '/',
// WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
quiet: true,
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebook/create-react-app/issues/293
// src/node_modules is not ignored to support absolute imports
// https://github.com/facebook/create-react-app/issues/1065
watchOptions: {
ignored: ignoredFiles(paths.appSrc),
},
// Enable HTTPS if the HTTPS environment variable is set to 'true'
https: protocol === 'https',
host,
overlay: false,
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true,
},
public: allowedHost,
proxy,
before(app, server) {
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(app);
}
// This lets us fetch source contents from webpack for the error overlay
app.use(evalSourceMapMiddleware(server));
// This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware());
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware());
},
};
};

View File

@@ -3,11 +3,11 @@ version: '3'
services:
shlink_web_client_node:
container_name: shlink_web_client_node
image: node:12.16.3-alpine
command: /bin/sh -c "cd /home/shlink/www && npm install && npm run start"
image: node:20.2-alpine
command: /bin/sh -c "cd /home/shlink/www && npm install --force && npm run start"
volumes:
- ./:/home/shlink/www
ports:
- "3000:3000"
- "56745:56745"
- "5000:5000"
- "4173:4173"

View File

@@ -0,0 +1,51 @@
# How to handle setting auto-connect on servers
* Status: Accepted
* Date: 2021-10-31
## Context and problem statement
A new feature has been requested, to allow auto-connecting to servers. The request specifically mentioned doing it automatically when there's only one server configured, but it can be extended a bit to allow setting an "auto-connect" server, regardless the number of configured servers.
At all times, no more than one server can be set to "auto-connect" simultaneously. Setting a new one will effectively unset the previous one, if any.
## Considered option
* Auto-connect only of there's a single server configured.
* Allow to set the server as "auto-connect" during server creation, edition or import.
* Allow to set the server as "auto-connect" on a separated flow, where the full list of servers can be handled.
## Decision outcome
In order to make it more flexible, any server will be allowed to be set as "auto-connect", regardless the amount of configured servers.
Auto-connect will be handled from the new "Manage servers" section.
## Pros and Cons of the Options
### Only one server
* Good:
* Does not require extending models, and the logic to auto-connect is based on the amount of configured servers.
* Bad:
* It's not flexible enough.
* Makes the app behave differently depending on the amount of configured servers, making it confusing.
### Auto-connect configured on existing creation/edition/import
* Good:
* Does not require creating a new section to handle "auto-connect".
* Bad:
* Requires extending the server model with a new prop.
* It's much harder to ensure data consistency, as we need to ensure only one server is set to "auto-connect".
* On import, many servers might have been set to "auto-connect". The expected behavior there can be unclear.
### Auto-connect configured on new section
* Good:
* It's much easier to ensure data consistency.
* It's much more clear and predictable, as the UI shows which is the server configured as auto-connect.
* We have controls in a single place to set/unset auto connect on servers, allowing only the proper option based on current state for every server.
* Bad:
* Requires extending the server model with a new prop.
* Requires creating a new section to handle "auto-connect".

5
docs/adr/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Architectural Decision Records
Here listed you will find the different architectural decisions taken in the project, including all the reasoning behind it, options considered, and final outcome.
* [2021-10-31 How to handle setting auto-connect on servers](2021-10-31-how-to-handle-setting-auto-connect-on-servers.md)

90
index.html Normal file
View File

@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#4696e5">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
<!-- FavIcon itself -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/svg+xml" href="/favicon.svg" sizes="any">
<link rel="icon" type="image/png" href="/favicon.png">
<link rel="icon" type="image/gif" href="/favicon.gif">
<!-- Apple Touch -->
<link rel="apple-touch-icon" sizes="16x16" href="/icons/icon-16x16.png">
<link rel="apple-touch-icon" sizes="24x24" href="/icons/icon-24x24.png">
<link rel="apple-touch-icon" sizes="32x32" href="/icons/icon-32x32.png">
<link rel="apple-touch-icon" sizes="40x40" href="/icons/icon-40x40.png">
<link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png">
<link rel="apple-touch-icon" sizes="60x60" href="/icons/icon-60x60.png">
<link rel="apple-touch-icon" sizes="64x64" href="/icons/icon-64x64.png">
<link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/icons/icon-76x76.png">
<link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png">
<link rel="apple-touch-icon" sizes="114x114" href="/icons/icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/icons/icon-120x120.png">
<link rel="apple-touch-icon" sizes="128x128" href="/icons/icon-128x128.png">
<link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png">
<link rel="apple-touch-icon" sizes="150x150" href="/icons/icon-150x150.png">
<link rel="apple-touch-icon" sizes="152x152" href="/icons/icon-152x152.png">
<link rel="apple-touch-icon" sizes="160x160" href="/icons/icon-160x160.png">
<link rel="apple-touch-icon" sizes="167x167" href="/icons/icon-167x167.png">
<link rel="apple-touch-icon" sizes="180x180" href="/icons/icon-180x180.png">
<link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png">
<link rel="apple-touch-icon" sizes="196x196" href="/icons/icon-196x196.png">
<link rel="apple-touch-icon" sizes="228x228" href="/icons/icon-228x228.png">
<link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png">
<link rel="apple-touch-icon" sizes="310x310" href="/icons/icon-310x310.png">
<link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png">
<link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png">
<link rel="apple-touch-icon" sizes="1024x1024" href="/icons/icon-1024x1024.png">
<!-- Normal -->
<link rel="icon" type="image/png" sizes="1024x1024" href="/icons/icon-1024x1024.png">
<link rel="icon" type="image/png" sizes="512x512" href="/icons/icon-512x512.png">
<link rel="icon" type="image/png" sizes="384x384" href="/icons/icon-384x384.png">
<link rel="icon" type="image/png" sizes="310x310" href="/icons/icon-310x310.png">
<link rel="icon" type="image/png" sizes="256x256" href="/icons/icon-256x256.png">
<link rel="icon" type="image/png" sizes="228x228" href="/icons/icon-228x228.png">
<link rel="icon" type="image/png" sizes="196x196" href="/icons/icon-196x196.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/icon-192x192.png">
<link rel="icon" type="image/png" sizes="180x180" href="/icons/icon-180x180.png">
<link rel="icon" type="image/png" sizes="167x167" href="/icons/icon-167x167.png">
<link rel="icon" type="image/png" sizes="160x160" href="/icons/icon-160x160.png">
<link rel="icon" type="image/png" sizes="152x152" href="/icons/icon-152x152.png">
<link rel="icon" type="image/png" sizes="150x150" href="/icons/icon-150x150.png">
<link rel="icon" type="image/png" sizes="144x144" href="/icons/icon-144x144.png">
<link rel="icon" type="image/png" sizes="128x128" href="/icons/icon-128x128.png">
<link rel="icon" type="image/png" sizes="120x120" href="/icons/icon-120x120.png">
<link rel="icon" type="image/png" sizes="114x114" href="/icons/icon-114x114.png">
<link rel="icon" type="image/png" sizes="96x96" href="/icons/icon-96x96.png">
<link rel="icon" type="image/png" sizes="76x76" href="/icons/icon-76x76.png">
<link rel="icon" type="image/png" sizes="72x72" href="/icons/icon-72x72.png">
<link rel="icon" type="image/png" sizes="64x64" href="/icons/icon-64x64.png">
<link rel="icon" type="image/png" sizes="60x60" href="/icons/icon-60x60.png">
<link rel="icon" type="image/png" sizes="48x48" href="/icons/icon-48x48.png">
<link rel="icon" type="image/png" sizes="40x40" href="/icons/icon-40x40.png">
<link rel="icon" type="image/png" sizes="32x32" href="/icons/icon-32x32.png">
<link rel="icon" type="image/png" sizes="24x24" href="/icons/icon-24x24.png">
<link rel="icon" type="image/png" sizes="16x16" href="/icons/icon-16x16.png">
<!-- MS -->
<meta name="msapplication-TileImage" content="/icons/icon-144x144.png">
<meta name="msapplication-square70x70logo" content="/icons/icon-70x70.png">
<meta name="msapplication-square144x144logo" content="/icons/icon-144x144.png">
<meta name="msapplication-square150x150logo" content="/icons/icon-150x150.png">
<meta name="msapplication-square310x310logo" content="/icons/icon-310x310.png">
<title>Shlink — The URL shortener</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

View File

@@ -1,44 +0,0 @@
module.exports = {
coverageDirectory: '<rootDir>/coverage',
collectCoverageFrom: [
'src/**/*.js',
'!src/registerServiceWorker.js',
'!src/index.js',
'!src/reducers/index.js',
'!src/**/provideServices.js',
'!src/container/*.js',
],
resolver: 'jest-pnp-resolver',
setupFiles: [
'react-app-polyfill/jsdom',
'<rootDir>/config/setupEnzyme.js',
],
testMatch: [ '<rootDir>/test/**/*.test.{js,jsx,ts,tsx}' ],
testEnvironment: 'jsdom',
testURL: 'http://localhost',
transform: {
'^.+\\.(js|jsx|mjs)$': '<rootDir>/node_modules/babel-jest',
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
'^(?!.*\\.(js|jsx|mjs|css|json)$)': '<rootDir>/config/jest/fileTransform.js',
},
transformIgnorePatterns: [
'[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$',
'^.+\\.module\\.(css|sass|scss)$',
],
moduleNameMapper: {
'^react-native$': 'react-native-web',
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
},
moduleFileExtensions: [
'web.js',
'js',
'web.ts',
'ts',
'web.tsx',
'tsx',
'json',
'web.jsx',
'jsx',
'node',
],
};

145
manifest.ts Normal file
View File

@@ -0,0 +1,145 @@
export const manifest = {
short_name: 'Shlink',
name: 'Shlink',
start_url: '/',
display: 'standalone',
theme_color: '#4696e5',
background_color: '#4696e5',
icons: [
{
src: './icons/icon-16x16.png',
type: 'image/png',
sizes: '16x16',
},
{
src: './icons/icon-24x24.png',
type: 'image/png',
sizes: '24x24',
},
{
src: './icons/icon-32x32.png',
type: 'image/png',
sizes: '32x32',
},
{
src: './icons/icon-40x40.png',
type: 'image/png',
sizes: '40x40',
},
{
src: './icons/icon-48x48.png',
type: 'image/png',
sizes: '48x48',
},
{
src: './icons/icon-60x60.png',
type: 'image/png',
sizes: '60x60',
},
{
src: './icons/icon-64x64.png',
type: 'image/png',
sizes: '64x64',
},
{
src: './icons/icon-72x72.png',
type: 'image/png',
sizes: '72x72',
},
{
src: './icons/icon-76x76.png',
type: 'image/png',
sizes: '76x76',
},
{
src: './icons/icon-96x96.png',
type: 'image/png',
sizes: '96x96',
},
{
src: './icons/icon-114x114.png',
type: 'image/png',
sizes: '114x114',
},
{
src: './icons/icon-120x120.png',
type: 'image/png',
sizes: '120x120',
},
{
src: './icons/icon-128x128.png',
type: 'image/png',
sizes: '128x128',
},
{
src: './icons/icon-144x144.png',
type: 'image/png',
sizes: '144x144',
},
{
src: './icons/icon-150x150.png',
type: 'image/png',
sizes: '150x150',
},
{
src: './icons/icon-152x152.png',
type: 'image/png',
sizes: '152x152',
},
{
src: './icons/icon-160x160.png',
type: 'image/png',
sizes: '160x160',
},
{
src: './icons/icon-167x167.png',
type: 'image/png',
sizes: '167x167',
},
{
src: './icons/icon-180x180.png',
type: 'image/png',
sizes: '180x180',
},
{
src: './icons/icon-192x192.png',
type: 'image/png',
sizes: '192x192',
},
{
src: './icons/icon-196x196.png',
type: 'image/png',
sizes: '196x196',
},
{
src: './icons/icon-228x228.png',
type: 'image/png',
sizes: '228x228',
},
{
src: './icons/icon-256x256.png',
type: 'image/png',
sizes: '256x256',
},
{
src: './icons/icon-310x310.png',
type: 'image/png',
sizes: '310x310',
},
{
src: './icons/icon-384x384.png',
type: 'image/png',
sizes: '384x384',
},
{
src: './icons/icon-512x512.png',
type: 'image/png',
sizes: '512x512',
},
{
src: './icons/icon-1024x1024.png',
type: 'image/png',
sizes: '1024x1024',
},
],
};

32591
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,145 +6,97 @@
"repository": "https://github.com/shlinkio/shlink-web-client",
"license": "MIT",
"scripts": {
"lint": "npm run lint:js && npm run lint:css",
"lint:js": "eslint src test scripts config",
"lint:js:fix": "npm run lint:js -- --fix",
"lint": "npm run lint:css && npm run lint:js",
"lint:css": "stylelint src/*.scss src/**/*.scss",
"lint:js": "eslint --ext .js,.ts,.tsx src test",
"lint:fix": "npm run lint:css:fix && npm run lint:js:fix",
"lint:css:fix": "npm run lint:css -- --fix",
"start": "node scripts/start.js",
"serve:build": "serve ./build",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom --colors",
"test:ci": "npm run test -- --coverage --coverageReporters=text --coverageReporters=text-summary --coverageReporters=clover",
"test:pretty": "npm run test -- --coverage --coverageReporters=text --coverageReporters=text-summary --coverageReporters=html",
"mutate": "./node_modules/.bin/stryker run",
"mutate:ci": "npm run mutate -- --mutate=$MUTATION_FILES",
"check": "npm run test & npm run lint & wait"
"lint:js:fix": "npm 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",
"test": "vitest run --run",
"test:watch": "vitest --watch",
"test:ci": "npm run test -- --coverage",
"test:verbose": "npm run test -- --verbose"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.11.2",
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-regular-svg-icons": "^5.11.2",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/react-fontawesome": "^0.1.5",
"array-filter": "^1.0.0",
"array-map": "^0.0.0",
"array-reduce": "^0.0.0",
"axios": "^0.19.0",
"bootstrap": "^4.3.1",
"bottlejs": "^1.7.2",
"bowser": "^2.9.0",
"chart.js": "^2.8.0",
"classnames": "^2.2.6",
"compare-versions": "^3.5.1",
"csvjson": "^5.1.0",
"event-source-polyfill": "^1.0.12",
"leaflet": "^1.5.1",
"moment": "^2.24.0",
"promise": "^8.0.3",
"prop-types": "^15.7.2",
"qs": "^6.9.0",
"ramda": "^0.26.1",
"react": "^16.13.1",
"react-autosuggest": "^9.4.3",
"react-chartjs-2": "^2.8.0",
"react-color": "^2.17.3",
"react-copy-to-clipboard": "^5.0.1",
"react-datepicker": "~1.5.0",
"react-dom": "^16.13.1",
"react-external-link": "^1.0.0",
"react-leaflet": "^2.4.0",
"react-moment": "^0.9.5",
"react-redux": "^7.1.1",
"react-router-dom": "^5.1.2",
"react-swipeable": "^5.4.0",
"react-tagsinput": "^3.19.0",
"reactstrap": "^8.0.1",
"redux": "^4.0.4",
"redux-actions": "^2.6.5",
"redux-localstorage-simple": "^2.2.0",
"redux-thunk": "^2.3.0",
"uuid": "^3.3.3"
"@fortawesome/fontawesome-free": "^6.3.0",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-brands-svg-icons": "^6.3.0",
"@fortawesome/free-regular-svg-icons": "^6.3.0",
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@json2csv/plainjs": "^6.1.2",
"@reduxjs/toolkit": "^1.9.1",
"bootstrap": "^5.2.3",
"bottlejs": "^2.0.1",
"bowser": "^2.11.0",
"chart.js": "^4.1.1",
"classnames": "^2.3.2",
"compare-versions": "^5.0.3",
"csvtojson": "^2.0.10",
"date-fns": "^2.29.3",
"event-source-polyfill": "^1.0.31",
"history": "^5.3.0",
"leaflet": "^1.9.3",
"qs": "^6.11.0",
"ramda": "^0.27.2",
"react": "^18.2.0",
"react-chartjs-2": "^5.1.0",
"react-colorful": "^5.6.1",
"react-copy-to-clipboard": "^5.1.0",
"react-datepicker": "^4.8.0",
"react-dom": "^18.2.0",
"react-external-link": "^2.2.0",
"react-leaflet": "^4.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.6.1",
"react-swipeable": "^7.0.0",
"react-tag-autocomplete": "^6.3.0",
"reactstrap": "^9.1.5",
"redux-localstorage-simple": "^2.5.1",
"uuid": "^8.3.2",
"workbox-core": "^6.5.4",
"workbox-expiration": "^6.5.4",
"workbox-precaching": "^6.5.4",
"workbox-routing": "^6.5.4",
"workbox-strategies": "^6.5.4"
},
"devDependencies": {
"@babel/core": "^7.6.2",
"@stryker-mutator/core": "^3.2.4",
"@stryker-mutator/javascript-mutator": "^3.2.4",
"@stryker-mutator/jest-runner": "^3.2.4",
"@svgr/webpack": "^4.3.3",
"adm-zip": "^0.4.13",
"autoprefixer": "^9.6.3",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"babel-loader": "^8.0.6",
"babel-plugin-named-asset-import": "^0.3.4",
"babel-preset-react-app": "^9.0.2",
"babel-runtime": "^6.26.0",
"bfj": "^7.0.1",
"case-sensitive-paths-webpack-plugin": "^2.2.0",
"chalk": "^2.4.2",
"css-loader": "^3.2.0",
"dotenv": "^8.1.0",
"dotenv-expand": "^5.1.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"eslint": "^5.11.1",
"eslint-config-adidas-babel": "^1.1.0",
"eslint-config-adidas-env": "^1.1.0",
"eslint-config-adidas-es6": "^1.2.0",
"eslint-config-adidas-react": "^1.1.1",
"eslint-loader": "^3.0.2",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^22.17.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.16.0",
"file-loader": "^4.2.0",
"fork-ts-checker-webpack-plugin-alt": "^0.4.14",
"fs-extra": "^8.1.0",
"html-webpack-plugin": "^4.0.0-beta.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.9.0",
"jest-pnp-resolver": "^1.2.1",
"jest-resolve": "^24.9.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.12.0",
"object-assign": "^4.1.1",
"ocular.js": "^0.1.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"pnp-webpack-plugin": "^1.5.0",
"postcss": "^7.0.18",
"postcss-flexbugs-fixes": "^4.1.0",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"postcss-safe-parser": "^4.0.1",
"raf": "^3.4.1",
"react-app-polyfill": "^1.0.4",
"react-dev-utils": "^9.1.0",
"resolve": "^1.12.0",
"sass-loader": "^8.0.0",
"serve": "^11.2.0",
"stryker-cli": "^1.0.0",
"style-loader": "^1.0.0",
"stylelint": "^9.10.1",
"stylelint-config-adidas": "^1.2.1",
"stylelint-config-adidas-bem": "^1.2.0",
"stylelint-config-recommended-scss": "^4.0.0",
"stylelint-scss": "^3.11.1",
"sw-precache-webpack-plugin": "^0.11.5",
"terser-webpack-plugin": "^2.1.2",
"url-loader": "^2.2.0",
"webpack": "^4.41.0",
"webpack-dev-server": "^3.8.2",
"webpack-manifest-plugin": "^2.2.0",
"whatwg-fetch": "^3.0.0",
"workbox-webpack-plugin": "^4.3.1"
},
"babel": {
"presets": [
"react-app"
]
"@shlinkio/eslint-config-js-coding-standard": "~2.1.0",
"@shlinkio/stylelint-config-css-coding-standard": "~1.0.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@total-typescript/shoehorn": "^0.1.0",
"@types/json2csv": "^5.0.3",
"@types/leaflet": "^1.9.0",
"@types/qs": "^6.9.7",
"@types/ramda": "^0.28.15",
"@types/react": "^18.0.26",
"@types/react-color": "^3.0.6",
"@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-datepicker": "^4.8.0",
"@types/react-dom": "^18.0.10",
"@types/react-tag-autocomplete": "^6.3.0",
"@types/uuid": "^8.3.4",
"@vitejs/plugin-react": "^4.0.0",
"@vitest/coverage-v8": "^0.32.0",
"adm-zip": "^0.5.10",
"chalk": "^5.2.0",
"eslint": "^8.30.0",
"jsdom": "^22.0.0",
"resize-observer-polyfill": "^1.5.1",
"sass": "^1.57.1",
"stylelint": "^15.10.1",
"typescript": "^5.0.2",
"vite": "^4.3.9",
"vite-plugin-pwa": "^0.14.4",
"vitest": "^0.32.0",
"vitest-canvas-mock": "^0.2.2"
},
"browserslist": [
">0.2%",

View File

@@ -1,109 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#4696e5">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- FavIcon itself -->
<link rel="icon" type="image/x-icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="icon" type="image/svg+xml" href="%PUBLIC_URL%/favicon.svg" sizes="any">
<link rel="icon" type="image/png" href="%PUBLIC_URL%/favicon.png">
<link rel="icon" type="image/gif" href="%PUBLIC_URL%/favicon.gif">
<!-- Apple Touch -->
<link rel="apple-touch-icon" sizes="16x16" href="%PUBLIC_URL%/icons/icon-16x16.png">
<link rel="apple-touch-icon" sizes="24x24" href="%PUBLIC_URL%/icons/icon-24x24.png">
<link rel="apple-touch-icon" sizes="32x32" href="%PUBLIC_URL%/icons/icon-32x32.png">
<link rel="apple-touch-icon" sizes="40x40" href="%PUBLIC_URL%/icons/icon-40x40.png">
<link rel="apple-touch-icon" sizes="48x48" href="%PUBLIC_URL%/icons/icon-48x48.png">
<link rel="apple-touch-icon" sizes="60x60" href="%PUBLIC_URL%/icons/icon-60x60.png">
<link rel="apple-touch-icon" sizes="64x64" href="%PUBLIC_URL%/icons/icon-64x64.png">
<link rel="apple-touch-icon" sizes="72x72" href="%PUBLIC_URL%/icons/icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="%PUBLIC_URL%/icons/icon-76x76.png">
<link rel="apple-touch-icon" sizes="96x96" href="%PUBLIC_URL%/icons/icon-96x96.png">
<link rel="apple-touch-icon" sizes="114x114" href="%PUBLIC_URL%/icons/icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="%PUBLIC_URL%/icons/icon-120x120.png">
<link rel="apple-touch-icon" sizes="128x128" href="%PUBLIC_URL%/icons/icon-128x128.png">
<link rel="apple-touch-icon" sizes="144x144" href="%PUBLIC_URL%/icons/icon-144x144.png">
<link rel="apple-touch-icon" sizes="150x150" href="%PUBLIC_URL%/icons/icon-150x150.png">
<link rel="apple-touch-icon" sizes="152x152" href="%PUBLIC_URL%/icons/icon-152x152.png">
<link rel="apple-touch-icon" sizes="160x160" href="%PUBLIC_URL%/icons/icon-160x160.png">
<link rel="apple-touch-icon" sizes="167x167" href="%PUBLIC_URL%/icons/icon-167x167.png">
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/icons/icon-180x180.png">
<link rel="apple-touch-icon" sizes="192x192" href="%PUBLIC_URL%/icons/icon-192x192.png">
<link rel="apple-touch-icon" sizes="196x196" href="%PUBLIC_URL%/icons/icon-196x196.png">
<link rel="apple-touch-icon" sizes="228x228" href="%PUBLIC_URL%/icons/icon-228x228.png">
<link rel="apple-touch-icon" sizes="256x256" href="%PUBLIC_URL%/icons/icon-256x256.png">
<link rel="apple-touch-icon" sizes="310x310" href="%PUBLIC_URL%/icons/icon-310x310.png">
<link rel="apple-touch-icon" sizes="384x384" href="%PUBLIC_URL%/icons/icon-384x384.png">
<link rel="apple-touch-icon" sizes="512x512" href="%PUBLIC_URL%/icons/icon-512x512.png">
<link rel="apple-touch-icon" sizes="1024x1024" href="%PUBLIC_URL%/icons/icon-1024x1024.png">
<!-- Normal -->
<link rel="icon" type="image/png" sizes="1024x1024" href="%PUBLIC_URL%/icons/icon-1024x1024.png">
<link rel="icon" type="image/png" sizes="512x512" href="%PUBLIC_URL%/icons/icon-512x512.png">
<link rel="icon" type="image/png" sizes="384x384" href="%PUBLIC_URL%/icons/icon-384x384.png">
<link rel="icon" type="image/png" sizes="310x310" href="%PUBLIC_URL%/icons/icon-310x310.png">
<link rel="icon" type="image/png" sizes="256x256" href="%PUBLIC_URL%/icons/icon-256x256.png">
<link rel="icon" type="image/png" sizes="228x228" href="%PUBLIC_URL%/icons/icon-228x228.png">
<link rel="icon" type="image/png" sizes="196x196" href="%PUBLIC_URL%/icons/icon-196x196.png">
<link rel="icon" type="image/png" sizes="192x192" href="%PUBLIC_URL%/icons/icon-192x192.png">
<link rel="icon" type="image/png" sizes="180x180" href="%PUBLIC_URL%/icons/icon-180x180.png">
<link rel="icon" type="image/png" sizes="167x167" href="%PUBLIC_URL%/icons/icon-167x167.png">
<link rel="icon" type="image/png" sizes="160x160" href="%PUBLIC_URL%/icons/icon-160x160.png">
<link rel="icon" type="image/png" sizes="152x152" href="%PUBLIC_URL%/icons/icon-152x152.png">
<link rel="icon" type="image/png" sizes="150x150" href="%PUBLIC_URL%/icons/icon-150x150.png">
<link rel="icon" type="image/png" sizes="144x144" href="%PUBLIC_URL%/icons/icon-144x144.png">
<link rel="icon" type="image/png" sizes="128x128" href="%PUBLIC_URL%/icons/icon-128x128.png">
<link rel="icon" type="image/png" sizes="120x120" href="%PUBLIC_URL%/icons/icon-120x120.png">
<link rel="icon" type="image/png" sizes="114x114" href="%PUBLIC_URL%/icons/icon-114x114.png">
<link rel="icon" type="image/png" sizes="96x96" href="%PUBLIC_URL%/icons/icon-96x96.png">
<link rel="icon" type="image/png" sizes="76x76" href="%PUBLIC_URL%/icons/icon-76x76.png">
<link rel="icon" type="image/png" sizes="72x72" href="%PUBLIC_URL%/icons/icon-72x72.png">
<link rel="icon" type="image/png" sizes="64x64" href="%PUBLIC_URL%/icons/icon-64x64.png">
<link rel="icon" type="image/png" sizes="60x60" href="%PUBLIC_URL%/icons/icon-60x60.png">
<link rel="icon" type="image/png" sizes="48x48" href="%PUBLIC_URL%/icons/icon-48x48.png">
<link rel="icon" type="image/png" sizes="40x40" href="%PUBLIC_URL%/icons/icon-40x40.png">
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/icons/icon-32x32.png">
<link rel="icon" type="image/png" sizes="24x24" href="%PUBLIC_URL%/icons/icon-24x24.png">
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/icons/icon-16x16.png">
<!-- MS -->
<meta name="msapplication-TileImage" content="%PUBLIC_URL%/icons/icon-144x144.png">
<meta name="msapplication-square70x70logo" content="%PUBLIC_URL%/icons/icon-70x70.png">
<meta name="msapplication-square144x144logo" content="%PUBLIC_URL%/icons/icon-144x144.png">
<meta name="msapplication-square150x150logo" content="%PUBLIC_URL%/icons/icon-150x150.png">
<meta name="msapplication-square310x310logo" content="%PUBLIC_URL%/icons/icon-310x310.png">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Shlink — The URL shortener</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@@ -1,145 +0,0 @@
{
"short_name": "Shlink",
"name": "Shlink",
"start_url": "/",
"display": "standalone",
"theme_color": "#4696e5",
"background_color": "#4696e5",
"icons": [
{
"src": "./icons/icon-16x16.png",
"type": "image/png",
"sizes": "16x16"
},
{
"src": "./icons/icon-24x24.png",
"type": "image/png",
"sizes": "24x24"
},
{
"src": "./icons/icon-32x32.png",
"type": "image/png",
"sizes": "32x32"
},
{
"src": "./icons/icon-40x40.png",
"type": "image/png",
"sizes": "40x40"
},
{
"src": "./icons/icon-48x48.png",
"type": "image/png",
"sizes": "48x48"
},
{
"src": "./icons/icon-60x60.png",
"type": "image/png",
"sizes": "60x60"
},
{
"src": "./icons/icon-64x64.png",
"type": "image/png",
"sizes": "64x64"
},
{
"src": "./icons/icon-72x72.png",
"type": "image/png",
"sizes": "72x72"
},
{
"src": "./icons/icon-76x76.png",
"type": "image/png",
"sizes": "76x76"
},
{
"src": "./icons/icon-96x96.png",
"type": "image/png",
"sizes": "96x96"
},
{
"src": "./icons/icon-114x114.png",
"type": "image/png",
"sizes": "114x114"
},
{
"src": "./icons/icon-120x120.png",
"type": "image/png",
"sizes": "120x120"
},
{
"src": "./icons/icon-128x128.png",
"type": "image/png",
"sizes": "128x128"
},
{
"src": "./icons/icon-144x144.png",
"type": "image/png",
"sizes": "144x144"
},
{
"src": "./icons/icon-150x150.png",
"type": "image/png",
"sizes": "150x150"
},
{
"src": "./icons/icon-152x152.png",
"type": "image/png",
"sizes": "152x152"
},
{
"src": "./icons/icon-160x160.png",
"type": "image/png",
"sizes": "160x160"
},
{
"src": "./icons/icon-167x167.png",
"type": "image/png",
"sizes": "167x167"
},
{
"src": "./icons/icon-180x180.png",
"type": "image/png",
"sizes": "180x180"
},
{
"src": "./icons/icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "./icons/icon-196x196.png",
"type": "image/png",
"sizes": "196x196"
},
{
"src": "./icons/icon-228x228.png",
"type": "image/png",
"sizes": "228x228"
},
{
"src": "./icons/icon-256x256.png",
"type": "image/png",
"sizes": "256x256"
},
{
"src": "./icons/icon-310x310.png",
"type": "image/png",
"sizes": "310x310"
},
{
"src": "./icons/icon-384x384.png",
"type": "image/png",
"sizes": "384x384"
},
{
"src": "./icons/icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
},
{
"src": "./icons/icon-1024x1024.png",
"type": "image/png",
"sizes": "1024x1024"
}
]
}

View File

@@ -1,227 +0,0 @@
/* eslint-disable no-console */
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', (err) => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const chalk = require('chalk');
const fs = require('fs-extra');
const webpack = require('webpack');
const bfj = require('bfj');
const AdmZip = require('adm-zip');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
const printBuildError = require('react-dev-utils/printBuildError');
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const { measureFileSizesBeforeBuild, printFileSizesAfterBuild } = FileSizeReporter;
// These sizes are pretty large. We'll warn for bundles exceeding them.
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; // eslint-disable-line
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; // eslint-disable-line
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([ paths.appHtml, paths.appIndexJs ])) {
process.exit(1);
}
// Process CLI arguments
const argvSliceStart = 2;
const argv = process.argv.slice(argvSliceStart);
const writeStatsJson = argv.indexOf('--stats') !== -1;
const withoutDist = argv.indexOf('--no-dist') !== -1;
const { version, hasVersion } = getVersionFromArgs(argv);
// Generate configuration
const config = configFactory('production');
checkBrowsers(paths.appPath, isInteractive)
.then(() =>
// First, read the current file sizes in build directory.
// This lets us display how much they changed later.
measureFileSizesBeforeBuild(paths.appBuild))
.then((previousFileSizes) => {
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
fs.emptyDirSync(paths.appBuild);
// Merge with the public folder
copyPublicFolder();
// Start the webpack build
return build(previousFileSizes);
})
.then(
({ stats, previousFileSizes, warnings }) => {
if (warnings.length) {
console.log(chalk.yellow('Compiled with warnings.\n'));
console.log(warnings.join('\n\n'));
console.log(
`\nSearch for the ${
chalk.underline(chalk.yellow('keywords'))
} to learn more about each warning.`
);
console.log(
`To ignore, add ${
chalk.cyan('// eslint-disable-next-line')
} to the line before.\n`
);
} else {
console.log(chalk.green('Compiled successfully.\n'));
hasVersion && replaceVersionPlaceholder(version);
}
console.log('File sizes after gzip:\n');
printFileSizesAfterBuild(
stats,
previousFileSizes,
paths.appBuild,
WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE
);
console.log();
},
(err) => {
console.log(chalk.red('Failed to compile.\n'));
printBuildError(err);
process.exit(1);
}
)
.then(() => hasVersion && !withoutDist && zipDist(version))
.catch((err) => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
// Create the production build and print the deployment instructions.
function build(previousFileSizes) {
console.log('Creating an optimized production build...');
const compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
let messages;
if (err) {
if (!err.message) {
return reject(err);
}
messages = formatWebpackMessages({
errors: [ err.message ],
warnings: [],
});
} else {
messages = formatWebpackMessages(
stats.toJson({ all: false, warnings: true, errors: true })
);
}
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors.join('\n\n')));
}
if (
process.env.CI &&
(typeof process.env.CI !== 'string' ||
process.env.CI.toLowerCase() !== 'false') &&
messages.warnings.length
) {
console.log(
chalk.yellow(
'\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n'
)
);
return reject(new Error(messages.warnings.join('\n\n')));
}
const resolveArgs = {
stats,
previousFileSizes,
warnings: messages.warnings,
};
if (writeStatsJson) {
return bfj // eslint-disable-line promise/no-promise-in-callback
.write(`${paths.appBuild}/bundle-stats.json`, stats.toJson())
.then(() => resolve(resolveArgs))
.catch((error) => reject(new Error(error)));
}
return resolve(resolveArgs);
});
});
}
function copyPublicFolder() {
fs.copySync(paths.appPublic, paths.appBuild, {
dereference: true,
filter: (file) => file !== paths.appHtml,
});
}
function zipDist(version) {
const versionFileName = `./dist/shlink-web-client_${version}_dist.zip`;
console.log(chalk.cyan(`Generating dist file for version ${chalk.bold(version)}...`));
const zip = new AdmZip();
try {
if (fs.existsSync(versionFileName)) {
fs.unlink(versionFileName);
}
zip.addLocalFolder('./build', `shlink-web-client_${version}_dist`);
zip.writeZip(versionFileName);
console.log(chalk.green('Dist file properly generated'));
} catch (e) {
console.log(chalk.red('An error occurred while generating dist file'));
console.log(e);
}
console.log();
}
function getVersionFromArgs(argv) {
const [ version ] = argv;
return { version, hasVersion: !!version };
}
function replaceVersionPlaceholder(version) {
const staticJsFilesPath = './build/static/js';
const versionPlaceholder = '%_VERSION_%';
const isMainFile = (file) => file.startsWith('main.') && file.endsWith('.js');
const [ mainJsFile ] = fs.readdirSync(staticJsFilesPath).filter(isMainFile);
const filePath = `${staticJsFilesPath}/${mainJsFile}`;
const fileContent = fs.readFileSync(filePath, 'utf-8');
const replaced = fileContent.replace(versionPlaceholder, version);
fs.writeFileSync(filePath, replaced, 'utf-8');
}

View File

@@ -0,0 +1,34 @@
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
import chalk from 'chalk';
import AdmZip from 'adm-zip';
import fs from 'fs';
function zipDist(version) {
const versionFileName = `./dist/shlink-web-client_${version}_dist.zip`;
console.log(chalk.cyan(`Generating dist file for version ${chalk.bold(version)}...`));
const zip = new AdmZip();
try {
if (fs.existsSync(versionFileName)) {
fs.unlink(versionFileName);
}
zip.addLocalFolder('./build', `shlink-web-client_${version}_dist`);
zip.writeZip(versionFileName);
console.log(chalk.green('Dist file properly generated'));
} catch (e) {
console.log(chalk.red('An error occurred while generating dist file'));
console.log(e);
}
console.log();
}
const version = process.env.VERSION;
if (version) {
zipDist(version);
}

View File

@@ -1,33 +0,0 @@
#!/bin/bash
set -e
#PLATFORMS="linux/arm/v7,linux/arm64/v8,linux/amd64"
PLATFORMS="linux/amd64"
DOCKER_IMAGE="shlinkio/shlink-web-client"
BUILDX_VER=v0.4.1
export DOCKER_CLI_EXPERIMENTAL=enabled
mkdir -vp ~/.docker/cli-plugins/ ~/dockercache
curl --silent -L "https://github.com/docker/buildx/releases/download/${BUILDX_VER}/buildx-${BUILDX_VER}.linux-amd64" > ~/.docker/cli-plugins/docker-buildx
chmod a+x ~/.docker/cli-plugins/docker-buildx
docker buildx create --use
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
if [[ -z $TRAVIS_TAG ]]; then
docker buildx build --push \
--platform ${PLATFORMS} \
-t ${DOCKER_IMAGE}:latest .
else
TAGS="-t ${DOCKER_IMAGE}:${TRAVIS_TAG#?}"
# Push stable tag only if this is not an alpha or beta release
[[ $TRAVIS_TAG != *"alpha"* && $TRAVIS_TAG != *"beta"* ]] && TAGS="${TAGS} -t ${DOCKER_IMAGE}:stable"
docker buildx build --push \
--build-arg SHLINK_VERSION=${TRAVIS_TAG#?} \
--platform ${PLATFORMS} \
${TAGS} .
fi

View File

@@ -1,12 +0,0 @@
#!/usr/bin/env bash
set -ex
# install latest docker version
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
# enable multiarch execution
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

View File

@@ -0,0 +1,16 @@
#!/bin/sh
set -e
ME=$(basename $0)
setup_single_shlink_server() {
[ -n "$SHLINK_SERVER_URL" ] || return 0
[ -n "$SHLINK_SERVER_API_KEY" ] || return 0
local name="${SHLINK_SERVER_NAME:-Shlink}"
echo "[{\"name\":\"${name}\",\"url\":\"${SHLINK_SERVER_URL}\",\"apiKey\":\"${SHLINK_SERVER_API_KEY}\"}]" > /usr/share/nginx/html/servers.json
}
setup_single_shlink_server
exit 0

View File

@@ -0,0 +1,20 @@
import fs from 'fs';
function replaceVersionPlaceholder(version) {
const staticJsFilesPath = './build/assets';
const versionPlaceholder = '%_VERSION_%';
const isMainFile = (file) => file.startsWith('index-') && file.endsWith('.js');
const [mainJsFile] = fs.readdirSync(staticJsFilesPath).filter(isMainFile);
const filePath = `${staticJsFilesPath}/${mainJsFile}`;
const fileContent = fs.readFileSync(filePath, 'utf-8');
const replaced = fileContent.replace(versionPlaceholder, version);
fs.writeFileSync(filePath, replaced, 'utf-8');
}
const version = process.env.VERSION;
if (version) {
replaceVersionPlaceholder(version);
}

13
scripts/set-homepage.js Normal file
View File

@@ -0,0 +1,13 @@
const argv = process.argv.slice(2);
const [ homepage ] = argv;
if (!homepage) {
throw new Error('Homepage has to be provided as the first arg for this script');
}
const packageJsonPath = `${__dirname}/../package.json`;
const packageJson = require(packageJsonPath);
const fs = require('fs');
packageJson.homepage = homepage;
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));

View File

@@ -1,125 +0,0 @@
/* eslint-disable no-console */
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', (err) => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const fs = require('fs');
const chalk = require('chalk');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const {
choosePort,
createCompiler,
prepareProxy,
prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const createDevServerConfig = require('../config/webpackDevServer.config');
const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([ paths.appHtml, paths.appIndexJs ])) {
process.exit(1);
}
// Tools like Cloud9 rely on this.
const DEFAULT_PORT = 3000;
const PORT = parseInt(process.env.PORT) || DEFAULT_PORT;
const HOST = process.env.HOST || '0.0.0.0';
if (process.env.HOST) {
console.log(
chalk.cyan(
`Attempting to bind to HOST environment variable: ${chalk.yellow(
chalk.bold(process.env.HOST)
)}`
)
);
console.log(
'If this was unintentional, check that you haven\'t mistakenly set it in your shell.'
);
console.log(
`Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`
);
console.log();
}
checkBrowsers(paths.appPath, isInteractive)
.then(() =>
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
choosePort(HOST, PORT))
.then((port) => {
if (port === null) {
// We have not found a port.
return;
}
const config = configFactory('development');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const urls = prepareUrls(protocol, HOST, port);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler({ webpack, config, appName, urls, useYarn });
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
// Serve webpack assets generated by the compiler over a web server.
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(port, HOST, (err) => {
if (err) {
return console.log(err);
}
if (isInteractive) {
clearConsole();
}
console.log(chalk.cyan('Starting the development server...\n'));
return openBrowser(urls.localUrlForBrowser);
});
[ 'SIGINT', 'SIGTERM' ].forEach((sig) => {
process.on(sig, () => {
devServer.close();
process.exit();
});
});
})
.catch((err) => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});

View File

@@ -1,23 +0,0 @@
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', (err) => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
// Make tests to be matched inside tests folder
const jest = require('jest');
const argumentsToRemove = 2;
const argv = process.argv.slice(argumentsToRemove);
jest.run(argv);

17
shlink-web-client.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
// eslint-disable-next-line max-classes-per-file
declare module 'event-source-polyfill' {
declare class EventSourcePolyfill {
public onmessage?: ({ data }: { data: string }) => void;
public onerror?: ({ status }: { status: number }) => void;
public close: () => void;
public constructor(hubUrl: URL, options?: any);
}
}
declare module '@json2csv/plainjs' {
export class Parser {
parse: <T>(data: T[]) => string;
}
}
declare module '*.png'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -1,40 +0,0 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { Route, Switch } from 'react-router-dom';
import NotFound from './common/NotFound';
import './App.scss';
const propTypes = {
fetchServers: PropTypes.func,
servers: PropTypes.object,
};
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer, Settings) => ({ fetchServers, servers }) => {
// On first load, try to fetch the remote servers if the list is empty
useEffect(() => {
if (Object.keys(servers).length === 0) {
fetchServers();
}
}, []);
return (
<div className="container-fluid app-container">
<MainHeader />
<div className="app">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/settings" component={Settings} />
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} />
<Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} />
</Switch>
</div>
</div>
);
};
App.propTypes = propTypes;
export default App;

View File

@@ -1,10 +0,0 @@
@import './utils/base';
.app-container {
height: 100%;
}
.app {
padding-top: $headerHeight;
height: 100%;
}

View File

@@ -0,0 +1,18 @@
import type { ProblemDetailsError } from './types/errors';
import { isInvalidArgumentError } from './utils';
export interface ShlinkApiErrorProps {
errorData?: ProblemDetailsError;
fallbackMessage?: string;
}
export const ShlinkApiError = ({ errorData, fallbackMessage }: ShlinkApiErrorProps) => (
<>
{errorData?.detail ?? fallbackMessage}
{isInvalidArgumentError(errorData) && (
<p className="mb-0">
Invalid elements: [{errorData.invalidElements.join(', ')}]
</p>
)}
</>
);

View File

@@ -0,0 +1,149 @@
import { isEmpty, isNil, reject } from 'ramda';
import type { HttpClient } from '../../common/services/HttpClient';
import type { ShortUrl, ShortUrlData } from '../../short-urls/data';
import { orderToString } from '../../utils/helpers/ordering';
import { stringifyQuery } from '../../utils/helpers/query';
import type { OptionalString } from '../../utils/utils';
import type {
ShlinkDomainRedirects,
ShlinkDomainsResponse,
ShlinkEditDomainRedirects,
ShlinkHealth,
ShlinkMercureInfo,
ShlinkShortUrlData,
ShlinkShortUrlsListNormalizedParams,
ShlinkShortUrlsListParams,
ShlinkShortUrlsResponse,
ShlinkTags,
ShlinkTagsResponse,
ShlinkTagsStatsResponse,
ShlinkVisits,
ShlinkVisitsOverview,
ShlinkVisitsParams,
} from '../types';
import { isRegularNotFound, parseApiError } from '../utils';
const buildShlinkBaseUrl = (url: string, version: 2 | 3) => `${url}/rest/v${version}`;
const rejectNilProps = reject(isNil);
const normalizeListParams = (
{ orderBy = {}, excludeMaxVisitsReached, excludePastValidUntil, ...rest }: ShlinkShortUrlsListParams,
): ShlinkShortUrlsListNormalizedParams => ({
...rest,
excludeMaxVisitsReached: excludeMaxVisitsReached === true ? 'true' : undefined,
excludePastValidUntil: excludePastValidUntil === true ? 'true' : undefined,
orderBy: orderToString(orderBy),
});
export class ShlinkApiClient {
private apiVersion: 2 | 3;
public constructor(
private readonly httpClient: HttpClient,
private readonly baseUrl: string,
private readonly apiKey: string,
) {
this.apiVersion = 3;
}
public readonly listShortUrls = async (params: ShlinkShortUrlsListParams = {}): Promise<ShlinkShortUrlsResponse> =>
this.performRequest<{ shortUrls: ShlinkShortUrlsResponse }>('/short-urls', 'GET', normalizeListParams(params))
.then(({ shortUrls }) => shortUrls);
public readonly createShortUrl = async (options: ShortUrlData): Promise<ShortUrl> => {
const filteredOptions = reject((value) => isEmpty(value) || isNil(value), options as any);
return this.performRequest<ShortUrl>('/short-urls', 'POST', {}, filteredOptions);
};
public readonly getShortUrlVisits = async (shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits> =>
this.performRequest<{ visits: ShlinkVisits }>(`/short-urls/${shortCode}/visits`, 'GET', query)
.then(({ visits }) => visits);
public readonly getTagVisits = async (tag: string, query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> =>
this.performRequest<{ visits: ShlinkVisits }>(`/tags/${tag}/visits`, 'GET', query).then(({ visits }) => visits);
public readonly getDomainVisits = async (domain: string, query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> =>
this.performRequest<{ visits: ShlinkVisits }>(`/domains/${domain}/visits`, 'GET', query).then(({ visits }) => visits);
public readonly getOrphanVisits = async (query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> =>
this.performRequest<{ visits: ShlinkVisits }>('/visits/orphan', 'GET', query).then(({ visits }) => visits);
public readonly getNonOrphanVisits = async (query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> =>
this.performRequest<{ visits: ShlinkVisits }>('/visits/non-orphan', 'GET', query).then(({ visits }) => visits);
public readonly getVisitsOverview = async (): Promise<ShlinkVisitsOverview> =>
this.performRequest<{ visits: ShlinkVisitsOverview }>('/visits').then(({ visits }) => visits);
public readonly getShortUrl = async (shortCode: string, domain?: OptionalString): Promise<ShortUrl> =>
this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'GET', { domain });
public readonly deleteShortUrl = async (shortCode: string, domain?: OptionalString): Promise<void> =>
this.performEmptyRequest(`/short-urls/${shortCode}`, 'DELETE', { domain });
public readonly updateShortUrl = async (
shortCode: string,
domain: OptionalString,
edit: ShlinkShortUrlData,
): Promise<ShortUrl> =>
this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'PATCH', { domain }, edit);
public readonly listTags = async (): Promise<ShlinkTags> =>
this.performRequest<{ tags: ShlinkTagsResponse }>('/tags', 'GET', { withStats: 'true' })
.then(({ tags }) => tags)
.then(({ data, stats }) => ({ tags: data, stats }));
public readonly tagsStats = async (): Promise<ShlinkTags> =>
this.performRequest<{ tags: ShlinkTagsStatsResponse }>('/tags/stats', 'GET')
.then(({ tags }) => tags)
.then(({ data }) => ({ tags: data.map(({ tag }) => tag), stats: data }));
public readonly deleteTags = async (tags: string[]): Promise<{ tags: string[] }> =>
this.performEmptyRequest('/tags', 'DELETE', { tags }).then(() => ({ tags }));
public readonly editTag = async (oldName: string, newName: string): Promise<{ oldName: string; newName: string }> =>
this.performEmptyRequest('/tags', 'PUT', {}, { oldName, newName }).then(() => ({ oldName, newName }));
public readonly health = async (): Promise<ShlinkHealth> => this.performRequest<ShlinkHealth>('/health', 'GET');
public readonly mercureInfo = async (): Promise<ShlinkMercureInfo> =>
this.performRequest<ShlinkMercureInfo>('/mercure-info', 'GET');
public readonly listDomains = async (): Promise<ShlinkDomainsResponse> =>
this.performRequest<{ domains: ShlinkDomainsResponse }>('/domains').then(({ domains }) => domains);
public readonly editDomainRedirects = async (
domainRedirects: ShlinkEditDomainRedirects,
): Promise<ShlinkDomainRedirects> =>
this.performRequest<ShlinkDomainRedirects>('/domains/redirects', 'PATCH', {}, domainRedirects);
private readonly performRequest = async <T>(url: string, method = 'GET', query = {}, body?: object): Promise<T> =>
this.httpClient.fetchJson<T>(...this.toFetchParams(url, method, query, body)).catch(
this.handleFetchError(() => this.httpClient.fetchJson<T>(...this.toFetchParams(url, method, query, body))),
);
private readonly performEmptyRequest = async (url: string, method = 'GET', query = {}, body?: object): Promise<void> =>
this.httpClient.fetchEmpty(...this.toFetchParams(url, method, query, body)).catch(
this.handleFetchError(() => this.httpClient.fetchEmpty(...this.toFetchParams(url, method, query, body))),
);
private readonly toFetchParams = (url: string, method: string, query = {}, body?: object): [string, RequestInit] => {
const normalizedQuery = stringifyQuery(rejectNilProps(query));
const stringifiedQuery = isEmpty(normalizedQuery) ? '' : `?${normalizedQuery}`;
return [`${buildShlinkBaseUrl(this.baseUrl, this.apiVersion)}${url}${stringifiedQuery}`, {
method,
body: body && JSON.stringify(body),
headers: { 'X-Api-Key': this.apiKey },
}];
};
private readonly handleFetchError = (retryFetch: Function) => (e: unknown) => {
if (!isRegularNotFound(parseApiError(e))) {
throw e;
}
// If we capture a not found error, let's assume this Shlink version does not support API v3, so we decrease to
// v2 and retry
this.apiVersion = 2;
return retryFetch();
};
}

View File

@@ -0,0 +1,33 @@
import type { HttpClient } from '../../common/services/HttpClient';
import type { GetState } from '../../container/types';
import type { ServerWithId } from '../../servers/data';
import { hasServerData } from '../../servers/data';
import { ShlinkApiClient } from './ShlinkApiClient';
const apiClients: Record<string, ShlinkApiClient> = {};
const isGetState = (getStateOrSelectedServer: GetState | ServerWithId): getStateOrSelectedServer is GetState =>
typeof getStateOrSelectedServer === 'function';
const getSelectedServerFromState = (getState: GetState): ServerWithId => {
const { selectedServer } = getState();
if (!hasServerData(selectedServer)) {
throw new Error('There\'s no selected server or it is not found');
}
return selectedServer;
};
export const buildShlinkApiClient = (httpClient: HttpClient) => (getStateOrSelectedServer: GetState | ServerWithId) => {
const { url, apiKey } = isGetState(getStateOrSelectedServer)
? getSelectedServerFromState(getStateOrSelectedServer)
: getStateOrSelectedServer;
const clientKey = `${url}_${apiKey}`;
if (!apiClients[clientKey]) {
apiClients[clientKey] = new ShlinkApiClient(httpClient, url, apiKey);
}
return apiClients[clientKey];
};
export type ShlinkApiClientBuilder = ReturnType<typeof buildShlinkApiClient>;

View File

@@ -0,0 +1,6 @@
import type Bottle from 'bottlejs';
import { buildShlinkApiClient } from './ShlinkApiClientBuilder';
export const provideServices = (bottle: Bottle) => {
bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'HttpClient');
};

54
src/api/types/errors.ts Normal file
View File

@@ -0,0 +1,54 @@
export enum ErrorTypeV2 {
INVALID_ARGUMENT = 'INVALID_ARGUMENT',
INVALID_SHORT_URL_DELETION = 'INVALID_SHORT_URL_DELETION',
DOMAIN_NOT_FOUND = 'DOMAIN_NOT_FOUND',
FORBIDDEN_OPERATION = 'FORBIDDEN_OPERATION',
INVALID_URL = 'INVALID_URL',
INVALID_SLUG = 'INVALID_SLUG',
INVALID_SHORTCODE = 'INVALID_SHORTCODE',
TAG_CONFLICT = 'TAG_CONFLICT',
TAG_NOT_FOUND = 'TAG_NOT_FOUND',
MERCURE_NOT_CONFIGURED = 'MERCURE_NOT_CONFIGURED',
INVALID_AUTHORIZATION = 'INVALID_AUTHORIZATION',
INVALID_API_KEY = 'INVALID_API_KEY',
NOT_FOUND = 'NOT_FOUND',
}
export enum ErrorTypeV3 {
INVALID_ARGUMENT = 'https://shlink.io/api/error/invalid-data',
INVALID_SHORT_URL_DELETION = 'https://shlink.io/api/error/invalid-short-url-deletion',
DOMAIN_NOT_FOUND = 'https://shlink.io/api/error/domain-not-found',
FORBIDDEN_OPERATION = 'https://shlink.io/api/error/forbidden-tag-operation',
INVALID_URL = 'https://shlink.io/api/error/invalid-url',
INVALID_SLUG = 'https://shlink.io/api/error/non-unique-slug',
INVALID_SHORTCODE = 'https://shlink.io/api/error/short-url-not-found',
TAG_CONFLICT = 'https://shlink.io/api/error/tag-conflict',
TAG_NOT_FOUND = 'https://shlink.io/api/error/tag-not-found',
MERCURE_NOT_CONFIGURED = 'https://shlink.io/api/error/mercure-not-configured',
INVALID_AUTHORIZATION = 'https://shlink.io/api/error/missing-authentication',
INVALID_API_KEY = 'https://shlink.io/api/error/invalid-api-key',
NOT_FOUND = 'https://shlink.io/api/error/not-found',
}
export interface ProblemDetailsError {
type: string;
detail: string;
title: string;
status: number;
[extraProps: string]: any;
}
export interface InvalidArgumentError extends ProblemDetailsError {
type: ErrorTypeV2.INVALID_ARGUMENT | ErrorTypeV3.INVALID_ARGUMENT;
invalidElements: string[];
}
export interface InvalidShortUrlDeletion extends ProblemDetailsError {
type: 'INVALID_SHORTCODE_DELETION' | ErrorTypeV2.INVALID_SHORT_URL_DELETION | ErrorTypeV3.INVALID_SHORT_URL_DELETION;
threshold: number;
}
export interface RegularNotFound extends ProblemDetailsError {
type: ErrorTypeV2.NOT_FOUND | ErrorTypeV3.NOT_FOUND;
status: 404;
}

133
src/api/types/index.ts Normal file
View File

@@ -0,0 +1,133 @@
import type { ShortUrl, ShortUrlMeta } from '../../short-urls/data';
import type { Order } from '../../utils/helpers/ordering';
import type { OptionalString } from '../../utils/utils';
import type { Visit } from '../../visits/types';
export interface ShlinkShortUrlsResponse {
data: ShortUrl[];
pagination: ShlinkPaginator;
}
export interface ShlinkMercureInfo {
token: string;
mercureHubUrl: string;
}
export interface ShlinkHealth {
status: 'pass' | 'fail';
version: string;
}
export interface ShlinkTagsStats {
tag: string;
shortUrlsCount: number;
visitsSummary?: ShlinkVisitsSummary; // Optional only before Shlink 3.5.0
/** @deprecated */
visitsCount: number;
}
export interface ShlinkTags {
tags: string[];
stats: ShlinkTagsStats[];
}
export interface ShlinkTagsResponse {
data: string[];
/** @deprecated Present only when withStats=true is provided, which is deprecated */
stats: ShlinkTagsStats[];
}
export interface ShlinkTagsStatsResponse {
data: ShlinkTagsStats[];
}
export interface ShlinkPaginator {
currentPage: number;
pagesCount: number;
totalItems: number;
}
export interface ShlinkVisitsSummary {
total: number;
nonBots: number;
bots: number;
}
export interface ShlinkVisits {
data: Visit[];
pagination: ShlinkPaginator;
}
export interface ShlinkVisitsOverview {
nonOrphanVisits?: ShlinkVisitsSummary; // Optional only before Shlink 3.5.0
orphanVisits?: ShlinkVisitsSummary; // Optional only before Shlink 3.5.0
/** @deprecated */
visitsCount: number;
/** @deprecated */
orphanVisitsCount: number;
}
export interface ShlinkVisitsParams {
domain?: OptionalString;
page?: number;
itemsPerPage?: number;
startDate?: string;
endDate?: string;
excludeBots?: boolean;
}
export interface ShlinkShortUrlData extends ShortUrlMeta {
longUrl?: string;
title?: string;
validateUrl?: boolean;
tags?: string[];
}
export interface ShlinkDomainRedirects {
baseUrlRedirect: string | null;
regular404Redirect: string | null;
invalidShortUrlRedirect: string | null;
}
export interface ShlinkEditDomainRedirects extends Partial<ShlinkDomainRedirects> {
domain: string;
}
export interface ShlinkDomain {
domain: string;
isDefault: boolean;
redirects?: ShlinkDomainRedirects; // Optional only for Shlink older than 2.8
}
export interface ShlinkDomainsResponse {
data: ShlinkDomain[];
defaultRedirects?: ShlinkDomainRedirects; // Optional only for Shlink older than 2.10
}
export type TagsFilteringMode = 'all' | 'any';
type ShlinkShortUrlsOrderableFields = 'dateCreated' | 'shortCode' | 'longUrl' | 'title' | 'visits' | 'nonBotVisits';
export type ShlinkShortUrlsOrder = Order<ShlinkShortUrlsOrderableFields>;
export interface ShlinkShortUrlsListParams {
page?: string;
itemsPerPage?: number;
searchTerm?: string;
tags?: string[];
tagsMode?: TagsFilteringMode;
orderBy?: ShlinkShortUrlsOrder;
startDate?: string;
endDate?: string;
excludeMaxVisitsReached?: boolean;
excludePastValidUntil?: boolean;
}
export interface ShlinkShortUrlsListNormalizedParams extends
Omit<ShlinkShortUrlsListParams, 'orderBy' | 'excludeMaxVisitsReached' | 'excludePastValidUntil'> {
orderBy?: string;
excludeMaxVisitsReached?: 'true';
excludePastValidUntil?: 'true';
}

25
src/api/utils/index.ts Normal file
View File

@@ -0,0 +1,25 @@
import type {
InvalidArgumentError,
InvalidShortUrlDeletion,
ProblemDetailsError,
RegularNotFound } from '../types/errors';
import {
ErrorTypeV2,
ErrorTypeV3,
} from '../types/errors';
const isProblemDetails = (e: unknown): e is ProblemDetailsError =>
!!e && typeof e === 'object' && ['type', 'detail', 'title', 'status'].every((prop) => prop in e);
export const parseApiError = (e: unknown): ProblemDetailsError | undefined => (isProblemDetails(e) ? e : undefined);
export const isInvalidArgumentError = (error?: ProblemDetailsError): error is InvalidArgumentError =>
error?.type === ErrorTypeV2.INVALID_ARGUMENT || error?.type === ErrorTypeV3.INVALID_ARGUMENT;
export const isInvalidDeletionError = (error?: ProblemDetailsError): error is InvalidShortUrlDeletion =>
error?.type === 'INVALID_SHORTCODE_DELETION'
|| error?.type === ErrorTypeV2.INVALID_SHORT_URL_DELETION
|| error?.type === ErrorTypeV3.INVALID_SHORT_URL_DELETION;
export const isRegularNotFound = (error?: ProblemDetailsError): error is RegularNotFound =>
(error?.type === ErrorTypeV2.NOT_FOUND || error?.type === ErrorTypeV3.NOT_FOUND) && error?.status === 404;

26
src/app/App.scss Normal file
View File

@@ -0,0 +1,26 @@
@import '../utils/base';
.app-container {
height: 100%;
}
.app {
padding-top: $headerHeight;
height: 100%;
}
.shlink-wrapper {
min-height: 100%;
padding-bottom: $footer-height + $footer-margin;
margin-bottom: -($footer-height + $footer-margin);
}
.shlink-footer {
height: $footer-height;
margin-top: $footer-margin;
padding: 0;
@media (min-width: $mdMin) {
padding: 0 15px;
}
}

68
src/app/App.tsx Normal file
View File

@@ -0,0 +1,68 @@
import classNames from 'classnames';
import type { FC } from 'react';
import { useEffect } from 'react';
import { Route, Routes, useLocation } from 'react-router-dom';
import { AppUpdateBanner } from '../common/AppUpdateBanner';
import { NotFound } from '../common/NotFound';
import type { ServersMap } from '../servers/data';
import type { Settings } from '../settings/reducers/settings';
import { forceUpdate } from '../utils/helpers/sw';
import { changeThemeInMarkup } from '../utils/theme';
import './App.scss';
interface AppProps {
fetchServers: () => void;
servers: ServersMap;
settings: Settings;
resetAppUpdate: () => void;
appUpdated: boolean;
}
export const App = (
MainHeader: FC,
Home: FC,
MenuLayout: FC,
CreateServer: FC,
EditServer: FC,
SettingsComp: FC,
ManageServers: FC,
ShlinkVersionsContainer: FC,
) => ({ fetchServers, servers, settings, appUpdated, resetAppUpdate }: AppProps) => {
const location = useLocation();
const isHome = location.pathname === '/';
useEffect(() => {
// On first load, try to fetch the remote servers if the list is empty
if (Object.keys(servers).length === 0) {
fetchServers();
}
changeThemeInMarkup(settings.ui?.theme ?? 'light');
}, []);
return (
<div className="container-fluid app-container">
<MainHeader />
<div className="app">
<div className={classNames('shlink-wrapper', { 'd-flex d-md-block align-items-center': isHome })}>
<Routes>
<Route index element={<Home />} />
<Route path="/settings/*" element={<SettingsComp />} />
<Route path="/manage-servers" element={<ManageServers />} />
<Route path="/server/create" element={<CreateServer />} />
<Route path="/server/:serverId/edit" element={<EditServer />} />
<Route path="/server/:serverId/*" element={<MenuLayout />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
<div className="shlink-footer">
<ShlinkVersionsContainer />
</div>
</div>
<AppUpdateBanner isOpen={appUpdated} toggle={resetAppUpdate} forceUpdate={forceUpdate} />
</div>
);
};

View File

@@ -0,0 +1,14 @@
import { createSlice } from '@reduxjs/toolkit';
const { actions, reducer } = createSlice({
name: 'shlink/appUpdates',
initialState: false,
reducers: {
appUpdateAvailable: () => true,
resetAppUpdate: () => false,
},
});
export const { appUpdateAvailable, resetAppUpdate } = actions;
export const appUpdatesReducer = reducer;

View File

@@ -0,0 +1,25 @@
import type Bottle from 'bottlejs';
import type { ConnectDecorator } from '../../container/types';
import { App } from '../App';
import { appUpdateAvailable, resetAppUpdate } from '../reducers/appUpdates';
export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
// Components
bottle.serviceFactory(
'App',
App,
'MainHeader',
'Home',
'MenuLayout',
'CreateServer',
'EditServer',
'Settings',
'ManageServers',
'ShlinkVersionsContainer',
);
bottle.decorator('App', connect(['servers', 'settings', 'appUpdated'], ['fetchServers', 'resetAppUpdate']));
// Actions
bottle.serviceFactory('appUpdateAvailable', () => appUpdateAvailable);
bottle.serviceFactory('resetAppUpdate', () => resetAppUpdate);
};

View File

@@ -0,0 +1,17 @@
@import '../utils/base';
@import '../utils/mixins/horizontal-align';
.app-update-banner.app-update-banner {
@include horizontal-align();
position: fixed;
top: $headerHeight - 25px;
padding: 0 4rem 0 0;
z-index: 1040;
margin: 0;
color: var(--text-color);
text-align: center;
width: 700px;
max-width: calc(100% - 30px);
box-shadow: 0 0 1rem var(--brand-color);
}

View File

@@ -0,0 +1,34 @@
import { faSyncAlt as reloadIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { FC, MouseEventHandler } from 'react';
import { Alert, Button } from 'reactstrap';
import { useToggle } from '../utils/helpers/hooks';
import { SimpleCard } from '../utils/SimpleCard';
import './AppUpdateBanner.scss';
interface AppUpdateBannerProps {
isOpen: boolean;
toggle: MouseEventHandler<any>;
forceUpdate: Function;
}
export const AppUpdateBanner: FC<AppUpdateBannerProps> = ({ isOpen, toggle, forceUpdate }) => {
const [isUpdating,, setUpdating] = useToggle();
const update = () => {
setUpdating();
forceUpdate();
};
return (
<Alert className="app-update-banner" isOpen={isOpen} toggle={toggle} tag={SimpleCard} color="secondary">
<h4 className="mb-4">This app has just been updated!</h4>
<p className="mb-0">
Restart it to enjoy the new features.
<Button role="button" disabled={isUpdating} className="ms-2" color="secondary" size="sm" onClick={update}>
{!isUpdating && <>Restart now <FontAwesomeIcon icon={reloadIcon} className="ms-1" /></>}
{isUpdating && <>Restarting...</>}
</Button>
</p>
</Alert>
);
};

View File

@@ -1,81 +0,0 @@
import {
faList as listIcon,
faLink as createIcon,
faTags as tagsIcon,
faPen as editIcon,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react';
import { NavLink } from 'react-router-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { serverType } from '../servers/prop-types';
import './AsideMenu.scss';
const AsideMenuItem = ({ children, to, className, ...rest }) => (
<NavLink
className={classNames('aside-menu__item', className)}
activeClassName="aside-menu__item--selected"
to={to}
{...rest}
>
{children}
</NavLink>
);
AsideMenuItem.propTypes = {
children: PropTypes.node.isRequired,
to: PropTypes.string.isRequired,
className: PropTypes.string,
};
const propTypes = {
selectedServer: serverType,
className: PropTypes.string,
showOnMobile: PropTypes.bool,
};
const AsideMenu = (DeleteServerButton) => {
const AsideMenu = ({ selectedServer, className, showOnMobile }) => {
const serverId = selectedServer ? selectedServer.id : '';
const asideClass = classNames('aside-menu', className, {
'aside-menu--hidden': !showOnMobile,
});
const shortUrlsIsActive = (match, location) => location.pathname.match('/list-short-urls');
const buildPath = (suffix) => `/server/${serverId}${suffix}`;
return (
<aside className={asideClass}>
<nav className="nav flex-column aside-menu__nav">
<AsideMenuItem to={buildPath('/list-short-urls/1')} isActive={shortUrlsIsActive}>
<FontAwesomeIcon icon={listIcon} />
<span className="aside-menu__item-text">List short URLs</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/create-short-url')}>
<FontAwesomeIcon icon={createIcon} flip="horizontal" />
<span className="aside-menu__item-text">Create short URL</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/manage-tags')}>
<FontAwesomeIcon icon={tagsIcon} />
<span className="aside-menu__item-text">Manage tags</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/edit')} className="aside-menu__item--push">
<FontAwesomeIcon icon={editIcon} />
<span className="aside-menu__item-text">Edit this server</span>
</AsideMenuItem>
<DeleteServerButton
className="aside-menu__item aside-menu__item--danger"
textClassName="aside-menu__item-text"
server={selectedServer}
/>
</nav>
</aside>
);
};
AsideMenu.propTypes = propTypes;
return AsideMenu;
};
export default AsideMenu;

View File

@@ -1,10 +1,10 @@
@import '../utils/base';
@import '../utils/mixins/vertical-align';
$asideMenuMobileWidth: 280px;
.aside-menu {
background-color: #f7f7f7;
width: $asideMenuWidth;
background-color: var(--primary-color);
box-shadow: rgb(0 0 0 / .05) 0 8px 15px;
position: fixed !important;
padding-top: 13px;
padding-bottom: 10px;
@@ -18,20 +18,18 @@ $asideMenuMobileWidth: 280px;
@media (min-width: $mdMin) {
padding: 30px 15px 15px;
border-right: 1px solid #eee;
}
@media (max-width: $smMax) {
width: $asideMenuMobileWidth !important;
transition: left 300ms;
top: $headerHeight - 3px;
box-shadow: -10px 0 50px 11px rgba(0, 0, 0, .55);
box-shadow: -10px 0 50px 11px rgb(0 0 0 / .55);
}
}
.aside-menu--hidden {
@media (max-width: $smMax) {
left: -($asideMenuMobileWidth + 35px);
left: -($asideMenuWidth + 35px);
}
}
@@ -44,24 +42,24 @@ $asideMenuMobileWidth: 280px;
margin: 0 -15px;
text-decoration: none !important;
cursor: pointer;
@media (max-width: $smMax) {
margin: 0;
}
}
.aside-menu__item:hover {
background-color: $lightHoverColor;
}
.aside-menu__item--selected {
color: #fff;
background-color: $mainColor;
background-color: var(--secondary-color);
}
.aside-menu__item--selected,
.aside-menu__item--selected:hover {
color: #fff;
background-color: $mainColor;
color: #ffffff;
background-color: var(--brand-color);
}
.aside-menu__item--divider {
border-bottom: 1px solid #eee;
border-bottom: 1px solid #eeeeee;
margin: 20px 0;
}
@@ -74,7 +72,7 @@ $asideMenuMobileWidth: 280px;
}
.aside-menu__item--danger:hover {
color: #fff;
color: #ffffff;
background-color: $dangerColor;
}

90
src/common/AsideMenu.tsx Normal file
View File

@@ -0,0 +1,90 @@
import {
faGlobe as domainsIcon,
faHome as overviewIcon,
faLink as createIcon,
faList as listIcon,
faPen as editIcon,
faTags as tagsIcon,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import type { FC } from 'react';
import type { NavLinkProps } from 'react-router-dom';
import { NavLink, useLocation } from 'react-router-dom';
import type { SelectedServer } from '../servers/data';
import { isServerWithId } from '../servers/data';
import type { DeleteServerButtonProps } from '../servers/DeleteServerButton';
import './AsideMenu.scss';
export interface AsideMenuProps {
selectedServer: SelectedServer;
showOnMobile?: boolean;
}
interface AsideMenuItemProps extends NavLinkProps {
to: string;
className?: string;
}
const AsideMenuItem: FC<AsideMenuItemProps> = ({ children, to, className, ...rest }) => (
<NavLink
className={({ isActive }) => classNames('aside-menu__item', className, { 'aside-menu__item--selected': isActive })}
to={to}
{...rest}
>
{children}
</NavLink>
);
export const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
{ selectedServer, showOnMobile = false }: AsideMenuProps,
) => {
const hasId = isServerWithId(selectedServer);
const serverId = hasId ? selectedServer.id : '';
const { pathname } = useLocation();
const asideClass = classNames('aside-menu', {
'aside-menu--hidden': !showOnMobile,
});
const buildPath = (suffix: string) => `/server/${serverId}${suffix}`;
return (
<aside className={asideClass}>
<nav className="nav flex-column aside-menu__nav">
<AsideMenuItem to={buildPath('/overview')}>
<FontAwesomeIcon fixedWidth icon={overviewIcon} />
<span className="aside-menu__item-text">Overview</span>
</AsideMenuItem>
<AsideMenuItem
to={buildPath('/list-short-urls/1')}
className={classNames({ 'aside-menu__item--selected': pathname.match('/list-short-urls') !== null })}
>
<FontAwesomeIcon fixedWidth icon={listIcon} />
<span className="aside-menu__item-text">List short URLs</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/create-short-url')}>
<FontAwesomeIcon fixedWidth icon={createIcon} flip="horizontal" />
<span className="aside-menu__item-text">Create short URL</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/manage-tags')}>
<FontAwesomeIcon fixedWidth icon={tagsIcon} />
<span className="aside-menu__item-text">Manage tags</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/manage-domains')}>
<FontAwesomeIcon fixedWidth icon={domainsIcon} />
<span className="aside-menu__item-text">Manage domains</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/edit')} className="aside-menu__item--push">
<FontAwesomeIcon fixedWidth icon={editIcon} />
<span className="aside-menu__item-text">Edit this server</span>
</AsideMenuItem>
{hasId && (
<DeleteServerButton
className="aside-menu__item aside-menu__item--danger"
textClassName="aside-menu__item-text"
server={selectedServer}
/>
)}
</nav>
</aside>
);
};

View File

@@ -1,43 +0,0 @@
import React from 'react';
import * as PropTypes from 'prop-types';
import './ErrorHandler.scss';
import { Button } from 'reactstrap';
// FIXME Replace with typescript: (window, console)
const ErrorHandler = ({ location }, { error }) => class ErrorHandler extends React.Component {
static propTypes = {
children: PropTypes.node.isRequired,
};
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(e) {
if (process.env.NODE_ENV !== 'development') {
error(e);
}
}
render() {
if (this.state.hasError) {
return (
<div className="error-handler">
<h1>Oops! This is awkward :S</h1>
<p>It seems that something went wrong. Try refreshing the page or just click this button.</p>
<br />
<Button outline color="primary" onClick={() => location.reload()}>Take me back</Button>
</div>
);
}
return this.props.children;
}
};
export default ErrorHandler;

View File

@@ -1,9 +0,0 @@
@import '../utils/mixins/vertical-align.scss';
.error-handler {
@include vertical-align();
padding: 20px;
text-align: center;
width: 100%;
}

View File

@@ -0,0 +1,47 @@
import type { ReactNode } from 'react';
import { Component } from 'react';
import { Button } from 'reactstrap';
import { SimpleCard } from '../utils/SimpleCard';
interface ErrorHandlerState {
hasError: boolean;
}
export const ErrorHandler = (
{ location }: Window,
{ error }: Console,
) => class extends Component<any, ErrorHandlerState> {
public constructor(props: object) {
super(props);
this.state = { hasError: false };
}
public static getDerivedStateFromError(): ErrorHandlerState {
return { hasError: true };
}
public componentDidCatch(e: Error): void {
if (process.env.NODE_ENV !== 'development') {
error(e);
}
}
public render(): ReactNode {
const { hasError } = this.state;
if (hasError) {
return (
<div className="home">
<SimpleCard className="p-4">
<h1>Oops! This is awkward :S</h1>
<p>It seems that something went wrong. Try refreshing the page or just click this button.</p>
<br />
<Button outline color="primary" onClick={() => location.reload()}>Take me back</Button>
</SimpleCard>
</div>
);
}
const { children } = this.props;
return children;
}
};

View File

@@ -1,34 +0,0 @@
import React, { useEffect } from 'react';
import { isEmpty, values } from 'ramda';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import './Home.scss';
import ServersListGroup from '../servers/ServersListGroup';
const propTypes = {
resetSelectedServer: PropTypes.func,
servers: PropTypes.object,
};
const Home = ({ resetSelectedServer, servers }) => {
const serversList = values(servers);
const hasServers = !isEmpty(serversList);
useEffect(() => {
resetSelectedServer();
}, []);
return (
<div className="home">
<h1 className="home__title">Welcome to Shlink</h1>
<ServersListGroup servers={serversList}>
{hasServers && <span>Please, select a server.</span>}
{!hasServers && <span>Please, <Link to="/server/create">add a server</Link>.</span>}
</ServersListGroup>
</div>
);
};
Home.propTypes = propTypes;
export default Home;

View File

@@ -1,18 +1,58 @@
@import '../utils/base';
@import '../utils/mixins/vertical-align';
$mainCardWidth: 720px;
$fiveColumnsSize: .4167; // 12 / 5 -> Can't use "/" operator in latest dart-sass
.home {
text-align: center;
height: calc(100vh - #{$headerHeight});
display: flex;
align-items: center;
justify-content: center;
flex-flow: column;
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);
}
.home__title {
text-align: center;
font-size: 1.75rem;
margin: 0;
@media (min-width: $mdMin) {
font-size: 2.2rem;
}
}
.home__servers-container {
@media (min-width: $mdMin) {
border-left: 1px solid var(--border-color);
}
}

67
src/common/Home.tsx Normal file
View File

@@ -0,0 +1,67 @@
import { faExternalLinkAlt, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { isEmpty, values } from 'ramda';
import { useEffect } from 'react';
import { ExternalLink } from 'react-external-link';
import { Link, useNavigate } from 'react-router-dom';
import { Card, Row } from 'reactstrap';
import type { ServersMap } from '../servers/data';
import { ServersListGroup } from '../servers/ServersListGroup';
import { ShlinkLogo } from './img/ShlinkLogo';
import './Home.scss';
interface HomeProps {
servers: ServersMap;
}
export const Home = ({ servers }: HomeProps) => {
const navigate = useNavigate();
const serversList = values(servers);
const hasServers = !isEmpty(serversList);
useEffect(() => {
// Try to redirect to the first server marked as auto-connect
const autoConnectServer = serversList.find(({ autoConnect }) => autoConnect);
autoConnectServer && navigate(`/server/${autoConnectServer.id}`);
}, []);
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>
</div>
<div className="col-md-7 home__servers-container">
<div className="home__title-wrapper">
<h1 className="home__title">Welcome!</h1>
</div>
<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>
<Link to="/server/create" className="btn btn-outline-primary btn-lg me-2">
<FontAwesomeIcon icon={faPlus} /> <span className="ms-1">Add a server</span>
</Link>
</p>
<p className="mb-0 mt-5">
<ExternalLink href="https://shlink.io/documentation">
<small>
<span className="me-1">Learn more about Shlink</span> <FontAwesomeIcon icon={faExternalLinkAlt} />
</small>
</ExternalLink>
</p>
</div>
)}
</ServersListGroup>
</div>
</Row>
</Card>
</div>
);
};

View File

@@ -1,61 +0,0 @@
import { faPlus as plusIcon, faChevronDown as arrowIcon, faCogs as cogsIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { useToggle } from '../utils/helpers/hooks';
import shlinkLogo from './shlink-logo-white.png';
import './MainHeader.scss';
const propTypes = {
location: PropTypes.object,
};
const MainHeader = (ServersDropdown) => {
const MainHeaderComp = ({ location }) => {
const [ isOpen, toggleOpen, , close ] = useToggle();
const { pathname } = location;
useEffect(close, [ location ]);
const createServerPath = '/server/create';
const settingsPath = '/settings';
const toggleClass = classNames('main-header__toggle-icon', { 'main-header__toggle-icon--opened': isOpen });
return (
<Navbar color="primary" dark fixed="top" className="main-header" expand="md">
<NavbarBrand tag={Link} to="/">
<img src={shlinkLogo} alt="Shlink" className="main-header__brand-logo" /> Shlink
</NavbarBrand>
<NavbarToggler onClick={toggleOpen}>
<FontAwesomeIcon icon={arrowIcon} className={toggleClass} />
</NavbarToggler>
<Collapse navbar isOpen={isOpen}>
<Nav navbar className="ml-auto">
<NavItem>
<NavLink tag={Link} to={settingsPath} active={pathname === settingsPath}>
<FontAwesomeIcon icon={cogsIcon} />&nbsp; Settings
</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} to={createServerPath} active={pathname === createServerPath}>
<FontAwesomeIcon icon={plusIcon} />&nbsp; Add server
</NavLink>
</NavItem>
<ServersDropdown />
</Nav>
</Collapse>
</Navbar>
);
};
MainHeaderComp.propTypes = propTypes;
return MainHeaderComp;
};
export default MainHeader;

View File

@@ -1,8 +1,8 @@
@import '../utils/base';
.main-header.main-header {
background-color: $mainColor !important;
color: white;
background-color: var(--brand-color) !important;
.navbar-brand {
color: inherit !important;

44
src/common/MainHeader.tsx Normal file
View File

@@ -0,0 +1,44 @@
import { faChevronDown as arrowIcon, faCogs as cogsIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import type { FC } from 'react';
import { useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
import { useToggle } from '../utils/helpers/hooks';
import { ShlinkLogo } from './img/ShlinkLogo';
import './MainHeader.scss';
export const MainHeader = (ServersDropdown: FC) => () => {
const [isOpen, toggleOpen, , close] = useToggle();
const location = useLocation();
const { pathname } = location;
useEffect(close, [location]);
const settingsPath = '/settings';
const toggleClass = classNames('main-header__toggle-icon', { 'main-header__toggle-icon--opened': isOpen });
return (
<Navbar color="primary" dark fixed="top" className="main-header" expand="md">
<NavbarBrand tag={Link} to="/">
<ShlinkLogo className="main-header__brand-logo" color="white" /> Shlink
</NavbarBrand>
<NavbarToggler onClick={toggleOpen}>
<FontAwesomeIcon icon={arrowIcon} className={toggleClass} />
</NavbarToggler>
<Collapse navbar isOpen={isOpen}>
<Nav navbar className="ms-auto">
<NavItem>
<NavLink tag={Link} to={settingsPath} active={pathname.startsWith(settingsPath)}>
<FontAwesomeIcon icon={cogsIcon} />&nbsp; Settings
</NavLink>
</NavItem>
<ServersDropdown />
</Nav>
</Collapse>
</Navbar>
);
};

View File

@@ -1,98 +0,0 @@
import React, { useEffect } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Swipeable } from 'react-swipeable';
import { faBars as burgerIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import * as PropTypes from 'prop-types';
import { serverType } from '../servers/prop-types';
import { withSelectedServer } from '../servers/helpers/withSelectedServer';
import { useToggle } from '../utils/helpers/hooks';
import { versionMatch } from '../utils/helpers/version';
import NotFound from './NotFound';
import './MenuLayout.scss';
const propTypes = {
match: PropTypes.object,
location: PropTypes.object,
selectedServer: serverType,
};
const MenuLayout = (
TagsList,
ShortUrls,
AsideMenu,
CreateShortUrl,
ShortUrlVisits,
TagVisits,
ShlinkVersions,
ServerError
) => {
const MenuLayoutComp = ({ match, location, selectedServer }) => {
const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle();
const { params: { serverId } } = match;
useEffect(() => hideSidebar(), [ location ]);
if (selectedServer.serverNotReachable) {
return <ServerError type="not-reachable" />;
}
const addTagsVisitsRoute = versionMatch(selectedServer.version, { minVersion: '2.2.0' });
const burgerClasses = classNames('menu-layout__burger-icon', {
'menu-layout__burger-icon--active': sidebarVisible,
});
const swipeMenuIfNoModalExists = (callback) => (e) => {
const swippedOnVisitsTable = e.event.path.some(
({ classList }) => classList && classList.contains('visits-table')
);
if (swippedOnVisitsTable || document.querySelector('.modal')) {
return;
}
callback();
};
return (
<React.Fragment>
<FontAwesomeIcon icon={burgerIcon} className={burgerClasses} onClick={toggleSidebar} />
<Swipeable
delta={40}
className="menu-layout__swipeable"
onSwipedLeft={swipeMenuIfNoModalExists(hideSidebar)}
onSwipedRight={swipeMenuIfNoModalExists(showSidebar)}
>
<div className="row menu-layout__swipeable-inner">
<AsideMenu className="col-lg-2 col-md-3" selectedServer={selectedServer} showOnMobile={sidebarVisible} />
<div className="col-lg-10 offset-lg-2 col-md-9 offset-md-3" onClick={() => hideSidebar()}>
<div className="menu-layout__container">
<Switch>
<Route exact path="/server/:serverId/list-short-urls/:page" component={ShortUrls} />
<Route exact path="/server/:serverId/create-short-url" component={CreateShortUrl} />
<Route exact path="/server/:serverId/short-code/:shortCode/visits" component={ShortUrlVisits} />
{addTagsVisitsRoute && <Route exact path="/server/:serverId/tag/:tag/visits" component={TagVisits} />}
<Route exact path="/server/:serverId/manage-tags" component={TagsList} />
<Route
render={() => <NotFound to={`/server/${serverId}/list-short-urls/1`}>List short URLs</NotFound>}
/>
</Switch>
</div>
<div className="menu-layout__footer text-center text-md-right">
<ShlinkVersions />
</div>
</div>
</div>
</Swipeable>
</React.Fragment>
);
};
MenuLayoutComp.propTypes = propTypes;
return withSelectedServer(MenuLayoutComp, ServerError);
};
export default MenuLayout;

View File

@@ -1,13 +1,7 @@
@import '../utils/base';
.menu-layout__swipeable {
$offset: 15px;
height: 100%;
margin-right: -$offset;
margin-left: -$offset;
padding-left: $offset;
padding-right: $offset;
}
.menu-layout__swipeable-inner {
@@ -22,7 +16,7 @@
z-index: 1035;
font-size: 1.5rem;
cursor: pointer;
color: rgba(255, 255, 255, .5);
color: rgb(255 255 255 / .5);
@media (max-width: $smMax) {
display: inline-block;
@@ -33,25 +27,11 @@
color: white;
}
$footer-height: 2.3rem;
$footer-margin: .8rem;
.menu-layout__container {
padding: 20px 0 ($footer-height + $footer-margin);
.menu-layout__container.menu-layout__container {
padding: 20px 0 0;
min-height: 100%;
margin-bottom: -($footer-height + $footer-margin);
@media (min-width: $mdMin) {
padding: 30px 15px ($footer-height + $footer-margin);
}
}
.menu-layout__footer {
height: $footer-height;
margin-top: $footer-margin;
padding: 0;
@media (min-width: $mdMin) {
padding: 0 15px;
padding: 30px 0 0 $asideMenuWidth;
}
}

87
src/common/MenuLayout.tsx Normal file
View File

@@ -0,0 +1,87 @@
import { faBars as burgerIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import type { FC } from 'react';
import { useEffect } from 'react';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import { isReachableServer } from '../servers/data';
import { withSelectedServer } from '../servers/helpers/withSelectedServer';
import { useFeature } from '../utils/helpers/features';
import { useSwipeable, useToggle } from '../utils/helpers/hooks';
import type { AsideMenuProps } from './AsideMenu';
import { NotFound } from './NotFound';
import './MenuLayout.scss';
interface MenuLayoutProps {
sidebarPresent: Function;
sidebarNotPresent: Function;
}
export const MenuLayout = (
TagsList: FC,
ShortUrlsList: FC,
AsideMenu: FC<AsideMenuProps>,
CreateShortUrl: FC,
ShortUrlVisits: FC,
TagVisits: FC,
DomainVisits: FC,
OrphanVisits: FC,
NonOrphanVisits: FC,
ServerError: FC,
Overview: FC,
EditShortUrl: FC,
ManageDomains: FC,
) => withSelectedServer<MenuLayoutProps>(({ selectedServer, sidebarNotPresent, sidebarPresent }) => {
const location = useLocation();
const [sidebarVisible, toggleSidebar, showSidebar, hideSidebar] = useToggle();
const showContent = isReachableServer(selectedServer);
useEffect(() => hideSidebar(), [location]);
useEffect(() => {
showContent && sidebarPresent();
return () => sidebarNotPresent();
}, []);
if (!showContent) {
return <ServerError />;
}
const addNonOrphanVisitsRoute = useFeature('nonOrphanVisits', selectedServer);
const addDomainVisitsRoute = useFeature('domainVisits', selectedServer);
const burgerClasses = classNames('menu-layout__burger-icon', { 'menu-layout__burger-icon--active': sidebarVisible });
const swipeableProps = useSwipeable(showSidebar, hideSidebar);
return (
<>
<FontAwesomeIcon icon={burgerIcon} className={burgerClasses} onClick={toggleSidebar} />
<div {...swipeableProps} className="menu-layout__swipeable">
<div className="menu-layout__swipeable-inner">
<AsideMenu selectedServer={selectedServer} showOnMobile={sidebarVisible} />
<div className="menu-layout__container" onClick={() => hideSidebar()}>
<div className="container-xl">
<Routes>
<Route index element={<Navigate replace to="overview" />} />
<Route path="/overview" element={<Overview />} />
<Route path="/list-short-urls/:page" element={<ShortUrlsList />} />
<Route path="/create-short-url" element={<CreateShortUrl />} />
<Route path="/short-code/:shortCode/visits/*" element={<ShortUrlVisits />} />
<Route path="/short-code/:shortCode/edit" element={<EditShortUrl />} />
<Route path="/tag/:tag/visits/*" element={<TagVisits />} />
{addDomainVisitsRoute && <Route path="/domain/:domain/visits/*" element={<DomainVisits />} />}
<Route path="/orphan-visits/*" element={<OrphanVisits />} />
{addNonOrphanVisitsRoute && <Route path="/non-orphan-visits/*" element={<NonOrphanVisits />} />}
<Route path="/manage-tags" element={<TagsList />} />
<Route path="/manage-domains" element={<ManageDomains />} />
<Route
path="*"
element={<NotFound to={`/server/${selectedServer.id}/list-short-urls/1`}>List short URLs</NotFound>}
/>
</Routes>
</div>
</div>
</div>
</div>
</>
);
}, ServerError);

View File

@@ -1,13 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import './NoMenuLayout.scss';
const propTypes = {
children: PropTypes.node,
};
const NoMenuLayout = ({ children }) => <div className="no-menu-wrapper">{children}</div>;
NoMenuLayout.propTypes = propTypes;
export default NoMenuLayout;

View File

@@ -1,3 +1,9 @@
@import '../utils/base';
.no-menu-wrapper {
padding: 40px 20px;
padding: 15px 0 0;
@media (min-width: $mdMin) {
padding: 30px 20px 20px;
}
}

View File

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

View File

@@ -1,24 +0,0 @@
import React from 'react';
import { Link } from 'react-router-dom';
import * as PropTypes from 'prop-types';
const propTypes = {
to: PropTypes.string,
children: PropTypes.node,
};
const NotFound = ({ to = '/', children = 'Home' }) => (
<div className="home">
<h2>Oops! We could not find requested route.</h2>
<p>
Use your browser&apos;s back button to navigate to the page you have previously come from, or just press this
button.
</p>
<br />
<Link to={to} className="btn btn-outline-primary btn-lg">{children}</Link>
</div>
);
NotFound.propTypes = propTypes;
export default NotFound;

19
src/common/NotFound.tsx Normal file
View File

@@ -0,0 +1,19 @@
import type { FC, PropsWithChildren } from 'react';
import { Link } from 'react-router-dom';
import { SimpleCard } from '../utils/SimpleCard';
type NotFoundProps = PropsWithChildren<{ to?: string }>;
export const NotFound: FC<NotFoundProps> = ({ to = '/', children = 'Home' }) => (
<div className="home">
<SimpleCard className="p-4">
<h2>Oops! We could not find requested route.</h2>
<p>
Use your browser&apos;s back button to navigate to the page you have previously come from, or just press this
button.
</p>
<br />
<Link to={to} className="btn btn-outline-primary btn-lg">{children}</Link>
</SimpleCard>
</div>
);

View File

@@ -1,23 +0,0 @@
import { useEffect } from 'react';
import PropTypes from 'prop-types';
const propTypes = {
location: PropTypes.object,
children: PropTypes.node,
};
const ScrollToTop = () => {
const ScrollToTopComp = ({ location, children }) => {
useEffect(() => {
scrollTo(0, 0);
}, [ location ]);
return children;
};
ScrollToTopComp.propTypes = propTypes;
return ScrollToTopComp;
};
export default ScrollToTop;

View File

@@ -0,0 +1,13 @@
import type { FC, PropsWithChildren } from 'react';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export const ScrollToTop: FC<PropsWithChildren<unknown>> = ({ children }) => {
const location = useLocation();
useEffect(() => {
scrollTo(0, 0);
}, [location]);
return <>{children}</>;
};

View File

@@ -1,29 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { pipe } from 'ramda';
import { serverType } from '../servers/prop-types';
import { versionToPrintable, versionToSemVer } from '../utils/helpers/version';
const SHLINK_WEB_CLIENT_VERSION = '%_VERSION_%';
const propTypes = {
selectedServer: serverType,
className: PropTypes.string,
clientVersion: PropTypes.string,
};
const ShlinkVersions = ({ selectedServer, className, clientVersion = SHLINK_WEB_CLIENT_VERSION }) => {
const { printableVersion: serverVersion } = selectedServer;
const normalizedClientVersion = pipe(versionToSemVer(), versionToPrintable)(clientVersion);
return (
<small className={classNames('text-muted', className)}>
Client: <b>{normalizedClientVersion}</b> - Server: <b>{serverVersion}</b>
</small>
);
};
ShlinkVersions.propTypes = propTypes;
export default ShlinkVersions;

View File

@@ -0,0 +1,32 @@
import { pipe } from 'ramda';
import { ExternalLink } from 'react-external-link';
import type { SelectedServer } from '../servers/data';
import { isReachableServer } from '../servers/data';
import { versionToPrintable, versionToSemVer } from '../utils/helpers/version';
const SHLINK_WEB_CLIENT_VERSION = '%_VERSION_%';
const normalizeVersion = pipe(versionToSemVer(), versionToPrintable);
export interface ShlinkVersionsProps {
selectedServer: SelectedServer;
clientVersion?: string;
}
const VersionLink = ({ project, version }: { project: 'shlink' | 'shlink-web-client'; version: string }) => (
<ExternalLink href={`https://github.com/shlinkio/${project}/releases/${version}`} className="text-muted">
<b>{version}</b>
</ExternalLink>
);
export const ShlinkVersions = ({ selectedServer, clientVersion = SHLINK_WEB_CLIENT_VERSION }: ShlinkVersionsProps) => {
const normalizedClientVersion = normalizeVersion(clientVersion);
return (
<small className="text-muted">
{isReachableServer(selectedServer) && (
<>Server: <VersionLink project="shlink" version={selectedServer.printableVersion} /> - </>
)}
Client: <VersionLink project="shlink-web-client" version={normalizedClientVersion} />
</small>
);
};

View File

@@ -0,0 +1,9 @@
@import '../utils/base';
.shlink-versions-container--with-sidebar {
margin-left: 0;
@media (min-width: $mdMin) {
margin-left: $asideMenuWidth;
}
}

View File

@@ -0,0 +1,22 @@
import classNames from 'classnames';
import type { SelectedServer } from '../servers/data';
import type { Sidebar } from './reducers/sidebar';
import { ShlinkVersions } from './ShlinkVersions';
import './ShlinkVersionsContainer.scss';
export interface ShlinkVersionsContainerProps {
selectedServer: SelectedServer;
sidebar: Sidebar;
}
export const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsContainerProps) => {
const classes = classNames('text-center', {
'shlink-versions-container--with-sidebar': sidebar.sidebarPresent,
});
return (
<div className={classes}>
<ShlinkVersions selectedServer={selectedServer} />
</div>
);
};

View File

@@ -1,23 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import type { FC } from 'react';
import { Pagination, PaginationItem, PaginationLink } from 'reactstrap';
import { isPageDisabled, keyForPage, progressivePagination } from '../utils/helpers/pagination';
import type {
NumberOrEllipsis } from '../utils/helpers/pagination';
import {
keyForPage,
pageIsEllipsis,
prettifyPageNumber,
progressivePagination,
} from '../utils/helpers/pagination';
import './SimplePaginator.scss';
const propTypes = {
pagesCount: PropTypes.number.isRequired,
currentPage: PropTypes.number.isRequired,
setCurrentPage: PropTypes.func.isRequired,
centered: PropTypes.bool,
};
interface SimplePaginatorProps {
pagesCount: number;
currentPage: number;
setCurrentPage: (currentPage: number) => void;
centered?: boolean;
}
const SimplePaginator = ({ pagesCount, currentPage, setCurrentPage, centered = true }) => {
export const SimplePaginator: FC<SimplePaginatorProps> = (
{ pagesCount, currentPage, setCurrentPage, centered = true },
) => {
if (pagesCount < 2) {
return null;
}
const onClick = (page) => () => setCurrentPage(page);
const onClick = (page: NumberOrEllipsis) => () => !pageIsEllipsis(page) && setCurrentPage(page);
return (
<Pagination listClassName={classNames('flex-wrap mb-0 simple-paginator', { 'justify-content-center': centered })}>
@@ -27,10 +35,12 @@ const SimplePaginator = ({ pagesCount, currentPage, setCurrentPage, centered = t
{progressivePagination(currentPage, pagesCount).map((pageNumber, index) => (
<PaginationItem
key={keyForPage(pageNumber, index)}
disabled={isPageDisabled(pageNumber)}
disabled={pageIsEllipsis(pageNumber)}
active={currentPage === pageNumber}
>
<PaginationLink tag="span" onClick={onClick(pageNumber)}>{pageNumber}</PaginationLink>
<PaginationLink role="link" tag="span" onClick={onClick(pageNumber)}>
{prettifyPageNumber(pageNumber)}
</PaginationLink>
</PaginationItem>
))}
<PaginationItem disabled={currentPage >= pagesCount}>
@@ -39,7 +49,3 @@ const SimplePaginator = ({ pagesCount, currentPage, setCurrentPage, centered = t
</Pagination>
);
};
SimplePaginator.propTypes = propTypes;
export default SimplePaginator;

View File

@@ -0,0 +1,25 @@
import { MAIN_COLOR } from '../../utils/theme';
export interface ShlinkLogoProps {
color?: string;
className?: string;
}
export const ShlinkLogo = ({ color = MAIN_COLOR, className }: ShlinkLogoProps) => (
<svg className={className} viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g fill={color}>
<path
d=" M 23.71 85.08 C 17.22 49.81 49.44 14.86 85.08 18.12 C 118.83 19.21 145.72 53.33 139.45 86.37 C 155.64 102.30 171.32 118.83 187.87 134.36 C 198.32 111.73 208.84 89.12 219.57 66.62 C 226.05 53.84 243.47 48.74 255.73 56.27 C 263.76 62.10 270.34 69.69 277.25 76.75 C 286.28 86.61 285.72 102.89 276.31 112.31 C 223.38 165.37 170.38 218.37 117.35 271.34 C 107.72 280.99 91.01 281.25 81.11 271.86 C 74.39 264.94 66.82 258.69 61.24 250.77 C 53.72 238.52 58.85 221.07 71.64 214.62 C 94.11 203.87 116.72 193.38 139.33 182.91 C 123.81 166.36 107.30 150.68 91.37 134.49 C 60.20 140.28 27.37 116.78 23.71 85.08 Z"
/>
<path
d=" M 205.21 201.23 C 225.32 181.36 260.88 181.11 281.14 200.86 C 299.25 218.75 317.37 236.65 335.10 254.93 C 356.73 278.01 352.01 318.70 326.03 336.56 C 320.07 330.47 313.73 324.65 308.12 318.28 C 323.86 309.39 328.76 286.18 316.63 272.39 C 301.73 256.95 286.30 242.03 271.24 226.75 C 264.49 219.65 256.80 212.00 246.37 211.52 C 224.65 208.64 205.52 233.36 214.49 253.58 C 221.09 266.81 234.22 275.12 243.62 286.24 C 240.43 295.96 238.09 306.13 238.29 316.46 C 225.55 304.29 213.16 291.73 200.89 279.09 C 180.97 257.57 183.10 220.45 205.21 201.23 Z"
/>
<path
d=" M 273.90 352.07 C 252.28 328.99 256.98 288.31 282.96 270.46 C 288.93 276.54 295.26 282.36 300.88 288.72 C 285.14 297.62 280.23 320.82 292.38 334.61 C 307.27 350.05 322.70 364.96 337.75 380.25 C 344.51 387.35 352.20 395.00 362.64 395.48 C 384.35 398.37 403.49 373.64 394.51 353.42 C 387.92 340.18 374.78 331.88 365.38 320.76 C 368.56 311.04 370.91 300.86 370.71 290.54 C 383.45 302.70 395.84 315.27 408.11 327.91 C 428.03 349.43 425.90 386.55 403.78 405.77 C 383.68 425.64 348.13 425.89 327.86 406.14 C 309.75 388.25 291.60 370.37 273.90 352.07 Z"
/>
<path
d=" M 422.11 403.83 C 431.96 394.07 441.60 384.06 451.66 374.51 C 460.90 383.74 471.89 392.70 474.89 406.11 C 480.16 429.97 484.08 454.13 488.76 478.12 C 490.00 483.41 484.47 488.29 479.35 486.63 C 454.66 481.52 429.55 478.12 405.14 471.84 C 393.17 467.97 385.20 457.75 376.55 449.27 C 386.39 439.49 396.13 429.60 406.06 419.91 C 416.37 433.45 435.74 414.00 422.11 403.83 Z"
/>
</g>
</svg>
);

View File

@@ -0,0 +1,159 @@
@import '../utils/base';
.react-tags {
position: relative;
padding: 5px 0 0 6px;
border-radius: .5rem;
background-color: var(--primary-color);
border: 1px solid var(--input-border-color);
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
/* shared font styles */
font-size: 1em;
line-height: 1.2;
/* clicking anywhere will focus the input */
cursor: text;
}
.input-group > .react-tags {
flex: 1 1 auto;
width: 1%;
min-width: 0;
}
.card .react-tags {
background-color: var(--input-color);
}
.react-tags.is-focused {
box-shadow: 0 0 0 .2rem rgb(70 150 229 / 25%);
}
.react-tags__tag {
font-size: 100%;
}
.react-tags__selected {
display: inline;
vertical-align: 2px;
}
.react-tags__selected-tag {
display: inline-block;
box-sizing: border-box;
margin: 0 6px 6px 0;
padding: 6px 8px;
border: 1px solid var(--input-border-color);
border-radius: .25rem;
background: #f1f1f1;
/* match the font styles */
font-size: inherit;
line-height: inherit;
}
.react-tags__selected-tag:after {
content: '\2715';
color: #aaaaaa;
margin-left: 8px;
}
.react-tags__selected-tag:hover,
.react-tags__selected-tag:focus {
border-color: var(--input-border-color);
}
.react-tags__search {
display: inline-block;
/* match tag layout */
padding: 6px 2px;
margin-bottom: 5px;
/* prevent autoresize overflowing the container */
max-width: 100%;
}
@media screen and (min-width: $smMin) {
.react-tags__search {
/* this will become the offsetParent for suggestions */
position: relative;
}
}
.react-tags__search-input {
font-size: 1.25rem;
line-height: inherit;
color: var(--input-text-color);
background-color: inherit;
/* prevent autoresize overflowing the container */
max-width: 100%;
/* remove styles and layout from this element */
margin: 0 0 0 7px;
padding: 0;
border: 0;
outline: none;
}
.react-tags__search-input::placeholder {
color: #6c757d;
}
.react-tags__search-input::-ms-clear {
display: none;
}
.react-tags__suggestions {
position: absolute;
top: 100%;
left: 0;
width: 100%;
z-index: 10;
}
@media screen and (min-width: $smMin) {
.react-tags__suggestions {
width: 240px;
}
}
.react-tags__suggestions ul {
margin: 4px -1px;
padding: 0;
list-style: none;
background: var(--primary-color);
border: 1px solid var(--border-color);
border-radius: .25rem;
box-shadow: 0 2px 6px rgb(0 0 0 / .2);
}
.react-tags__suggestions li {
padding: 8px 10px;
}
.react-tags__suggestions li:not(:last-child) {
border-bottom: 1px solid var(--border-color);
}
.react-tags__suggestions li mark {
text-decoration: underline;
background: none;
font-weight: 600;
}
.react-tags__suggestions li:hover {
cursor: pointer;
background-color: var(--active-color);
}
.react-tags__suggestions li.is-active {
background-color: var(--active-color);
}
.react-tags__suggestions li.is-disabled {
opacity: .5;
cursor: auto;
}

View File

@@ -1,46 +0,0 @@
.react-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
border-radius: .25rem;
overflow: hidden;
min-height: 2.6rem;
padding: 6px 0 0 6px;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.react-tagsinput--focused {
border-color: #80bdff;
box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25);
}
.react-tagsinput-tag {
font-size: 1rem;
background-color: #f1f1f1;
border-radius: 4px;
display: inline-block;
font-weight: 400;
margin: 0 5px 6px 0;
padding: 6px 8px;
line-height: 1;
color: #fff;
}
.react-tagsinput-remove {
cursor: pointer;
font-weight: 700;
margin-left: 8px;
}
.react-tagsinput-tag span:before {
content: '\2715';
color: #fff;
}
.react-tagsinput-input {
background: transparent;
border: 0;
outline: none;
padding: 3px 5px;
width: 100%;
margin-bottom: 6px;
}

View File

@@ -0,0 +1,22 @@
import { createSlice } from '@reduxjs/toolkit';
export interface Sidebar {
sidebarPresent: boolean;
}
const initialState: Sidebar = {
sidebarPresent: false,
};
const { actions, reducer } = createSlice({
name: 'shlink/sidebar',
initialState,
reducers: {
sidebarPresent: () => ({ sidebarPresent: true }),
sidebarNotPresent: () => ({ sidebarPresent: false }),
},
});
export const { sidebarPresent, sidebarNotPresent } = actions;
export const sidebarReducer = reducer;

View File

@@ -0,0 +1,42 @@
import type { Fetch } from '../../utils/types';
const applicationJsonHeader = { 'Content-Type': 'application/json' };
const withJsonContentType = (options?: RequestInit): RequestInit | undefined => {
if (!options?.body) {
return options;
}
return options ? {
...options,
headers: {
...(options.headers ?? {}),
...applicationJsonHeader,
},
} : {
headers: applicationJsonHeader,
};
};
export class HttpClient {
constructor(private readonly fetch: Fetch) {}
public readonly fetchJson = <T>(url: string, options?: RequestInit): Promise<T> =>
this.fetch(url, withJsonContentType(options)).then(async (resp) => {
const json = await resp.json();
if (!resp.ok) {
throw json;
}
return json as T;
});
public readonly fetchEmpty = (url: string, options?: RequestInit): Promise<void> =>
this.fetch(url, withJsonContentType(options)).then(async (resp) => {
if (!resp.ok) {
throw await resp.json();
}
});
public readonly fetchBlob = (url: string): Promise<Blob> => this.fetch(url).then((resp) => resp.blob());
}

View File

@@ -0,0 +1,13 @@
import { saveUrl } from '../../utils/helpers/files';
import type { HttpClient } from './HttpClient';
export class ImageDownloader {
public constructor(private readonly httpClient: HttpClient, private readonly window: Window) {}
public async saveImage(imgUrl: string, filename: string): Promise<void> {
const data = await this.httpClient.fetchBlob(imgUrl);
const url = URL.createObjectURL(data);
saveUrl(this.window, url, filename);
}
}

View File

@@ -0,0 +1,29 @@
import type { ExportableShortUrl } from '../../short-urls/data';
import type { JsonToCsv } from '../../utils/helpers/csvjson';
import { saveCsv } from '../../utils/helpers/files';
import type { NormalizedVisit } from '../../visits/types';
export class ReportExporter {
public constructor(private readonly window: Window, private readonly jsonToCsv: JsonToCsv) {}
public readonly exportVisits = (filename: string, visits: NormalizedVisit[]) => {
if (!visits.length) {
return;
}
this.exportCsv(filename, visits);
};
public readonly exportShortUrls = (shortUrls: ExportableShortUrl[]) => {
if (!shortUrls.length) {
return;
}
this.exportCsv('short_urls.csv', shortUrls);
};
private readonly exportCsv = (filename: string, rows: object[]) => {
const csv = this.jsonToCsv(rows);
saveCsv(this.window, csv, filename);
};
}

View File

@@ -1,45 +0,0 @@
import ScrollToTop from '../ScrollToTop';
import MainHeader from '../MainHeader';
import Home from '../Home';
import MenuLayout from '../MenuLayout';
import AsideMenu from '../AsideMenu';
import ErrorHandler from '../ErrorHandler';
import ShlinkVersions from '../ShlinkVersions';
const provideServices = (bottle, connect, withRouter) => {
bottle.constant('window', global.window);
bottle.constant('console', global.console);
bottle.serviceFactory('ScrollToTop', ScrollToTop, 'window');
bottle.decorator('ScrollToTop', withRouter);
bottle.serviceFactory('MainHeader', MainHeader, 'ServersDropdown');
bottle.decorator('MainHeader', withRouter);
bottle.serviceFactory('Home', () => Home);
bottle.decorator('Home', connect([ 'servers' ], [ 'resetSelectedServer' ]));
bottle.serviceFactory(
'MenuLayout',
MenuLayout,
'TagsList',
'ShortUrls',
'AsideMenu',
'CreateShortUrl',
'ShortUrlVisits',
'TagVisits',
'ShlinkVersions',
'ServerError'
);
bottle.decorator('MenuLayout', connect([ 'selectedServer', 'shortUrlsListParams' ], [ 'selectServer' ]));
bottle.decorator('MenuLayout', withRouter);
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
bottle.serviceFactory('ShlinkVersions', () => ShlinkVersions);
bottle.decorator('ShlinkVersions', connect([ 'selectedServer' ]));
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window', 'console');
};
export default provideServices;

View File

@@ -0,0 +1,64 @@
import type Bottle from 'bottlejs';
import type { ConnectDecorator } from '../../container/types';
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
import { AsideMenu } from '../AsideMenu';
import { ErrorHandler } from '../ErrorHandler';
import { Home } from '../Home';
import { MainHeader } from '../MainHeader';
import { MenuLayout } from '../MenuLayout';
import { sidebarNotPresent, sidebarPresent } from '../reducers/sidebar';
import { ScrollToTop } from '../ScrollToTop';
import { ShlinkVersionsContainer } from '../ShlinkVersionsContainer';
import { HttpClient } from './HttpClient';
import { ImageDownloader } from './ImageDownloader';
import { ReportExporter } from './ReportExporter';
export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
// Services
bottle.constant('window', window);
bottle.constant('console', console);
bottle.constant('fetch', window.fetch.bind(window));
bottle.service('HttpClient', HttpClient, 'fetch');
bottle.service('ImageDownloader', ImageDownloader, 'HttpClient', 'window');
bottle.service('ReportExporter', ReportExporter, 'window', 'jsonToCsv');
// Components
bottle.serviceFactory('ScrollToTop', () => ScrollToTop);
bottle.serviceFactory('MainHeader', MainHeader, 'ServersDropdown');
bottle.serviceFactory('Home', () => Home);
bottle.decorator('Home', withoutSelectedServer);
bottle.decorator('Home', connect(['servers'], ['resetSelectedServer']));
bottle.serviceFactory(
'MenuLayout',
MenuLayout,
'TagsList',
'ShortUrlsList',
'AsideMenu',
'CreateShortUrl',
'ShortUrlVisits',
'TagVisits',
'DomainVisits',
'OrphanVisits',
'NonOrphanVisits',
'ServerError',
'Overview',
'EditShortUrl',
'ManageDomains',
);
bottle.decorator('MenuLayout', connect(['selectedServer'], ['selectServer', 'sidebarPresent', 'sidebarNotPresent']));
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
bottle.serviceFactory('ShlinkVersionsContainer', () => ShlinkVersionsContainer);
bottle.decorator('ShlinkVersionsContainer', connect(['selectedServer', 'sidebar']));
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window', 'console');
// Actions
bottle.serviceFactory('sidebarPresent', () => sidebarPresent);
bottle.serviceFactory('sidebarNotPresent', () => sidebarNotPresent);
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Some files were not shown because too many files have changed in this diff Show More