Skip to content

Commit

Permalink
Merge pull request #1044 from acelaya-forks/feature/swc-0.5
Browse files Browse the repository at this point in the history
Update to latest shlink-web-component
  • Loading branch information
acelaya committed Jan 29, 2024
2 parents f8d2084 + 71735e0 commit b12bb6c
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 96 deletions.
18 changes: 14 additions & 4 deletions CHANGELOG.md
Expand Up @@ -4,24 +4,34 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).

## [Unreleased]
## [4.0.0] - 2024-01-29
### Added
* *Nothing*
* [shlink-web-component #7](https://github.com/shlinkio/shlink-web-component/issues/7) Allow comparing visits for multiple short URLs, tags or domains.

When in the tags, domains or short URLs tables, you can now pick up to 5 items to compare their visits. Once selected, you are taken to a section displaying a comparative line chart, which supports all regular visits filtering capabilities.

* [shlink-web-component #9](https://github.com/shlinkio/shlink-web-component/issues/9) Allow comparing visits with the previous period.
* [shlink-web-component #12](https://github.com/shlinkio/shlink-web-component/issues/12) and [#13](https://github.com/shlinkio/shlink-web-component/issues/13) Add new "Visits options" section for arbitrary visit stats options. Add section to delete short URL and orphan visits there.

This section is only visible if short URL visits deletion or orphan visits deletion are supported by connected Shlink server.

* [shlink-web-component #10](https://github.com/shlinkio/shlink-web-component/issues/10) Improve general accessibility: Add accessibility tests, fix accessibility issues and enable accessibility linting rules.

### Changed
* [#338](https://github.com/shlinkio/shlink-web-client/issues/338) Extract `@shlinkio/shlink-web-component` and `@shlinkio/shlink-frontend-kit` as external libs.
* [#978](https://github.com/shlinkio/shlink-web-client/issues/978) Use system preferred theme as default theme.
* Use API client from `@shlinkio/shlink-js-sdk` to consume Shlink servers.
* [#902](https://github.com/shlinkio/shlink-web-client/pull/902) Docker image is no longer running as root. As a side effect, exposed port is `8080`, not `80` anymore.
* [shlink-web-component #117](https://github.com/shlinkio/shlink-web-component/issues/117) Migrate charts from Chart.JS to Recharts.

### Deprecated
* *Nothing*

### Removed
* *Nothing*
* Drop support for Shlink older than v3.0.0

### Fixed
* [#910](https://github.com/shlinkio/shlink-web-client/issues/910) Fix warnings related with missing `act`in tests and refs in `AppUpdateBanner`.
* [#910](https://github.com/shlinkio/shlink-web-client/issues/910) Fix warnings related with missing `act` in tests and refs in `AppUpdateBanner`.


## [3.10.2] - 2023-07-09
Expand Down
105 changes: 40 additions & 65 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -35,7 +35,7 @@
"@shlinkio/data-manipulation": "^1.0.3",
"@shlinkio/shlink-frontend-kit": "^0.4.2",
"@shlinkio/shlink-js-sdk": "^0.2.2",
"@shlinkio/shlink-web-component": "^0.4.1",
"@shlinkio/shlink-web-component": "^0.5.0",
"bootstrap": "5.2.3",
"bottlejs": "^2.0.1",
"clsx": "^2.1.0",
Expand Down
73 changes: 47 additions & 26 deletions src/settings/VisitsSettings.tsx
@@ -1,39 +1,60 @@
import { LabeledFormGroup, SimpleCard, ToggleSwitch } from '@shlinkio/shlink-frontend-kit';
import type { Settings, VisitsSettings as VisitsSettingsConfig } from '@shlinkio/shlink-web-component';
import type { FC } from 'react';
import { useCallback } from 'react';
import { FormGroup } from 'reactstrap';
import type { DateInterval } from '../utils/dates/DateIntervalSelector';
import { DateIntervalSelector } from '../utils/dates/DateIntervalSelector';
import { FormText } from '../utils/forms/FormText';

interface VisitsProps {
type VisitsProps = {
settings: Settings;
setVisitsSettings: (settings: VisitsSettingsConfig) => void;
}
};

const currentDefaultInterval = (settings: Settings): DateInterval => settings.visits?.defaultInterval ?? 'last30Days';

export const VisitsSettings: FC<VisitsProps> = ({ settings, setVisitsSettings }) => (
<SimpleCard title="Visits" className="h-100">
<FormGroup>
<ToggleSwitch
checked={!!settings.visits?.excludeBots}
onChange={(excludeBots) => setVisitsSettings(
{ defaultInterval: currentDefaultInterval(settings), excludeBots },
)}
>
Exclude bots wherever possible (this option&lsquo;s effect might depend on Shlink server&lsquo;s version).
<FormText>
The visits coming from potential bots will be <b>{settings.visits?.excludeBots ? 'excluded' : 'included'}</b>.
</FormText>
</ToggleSwitch>
</FormGroup>
<LabeledFormGroup noMargin label="Default interval to load on visits sections:">
<DateIntervalSelector
allText="All visits"
active={currentDefaultInterval(settings)}
onChange={(defaultInterval) => setVisitsSettings({ defaultInterval })}
/>
</LabeledFormGroup>
</SimpleCard>
);
export const VisitsSettings: FC<VisitsProps> = ({ settings, setVisitsSettings }) => {
const updateSettings = useCallback(
({ defaultInterval, ...rest }: Partial<VisitsSettingsConfig>) => setVisitsSettings(
{ defaultInterval: defaultInterval ?? currentDefaultInterval(settings), ...rest },
),
[setVisitsSettings, settings],
);

return (
<SimpleCard title="Visits" className="h-100">
<FormGroup>
<ToggleSwitch
checked={!!settings.visits?.excludeBots}
onChange={(excludeBots) => updateSettings({ excludeBots })}
>
Exclude bots wherever possible (this option&lsquo;s effect might depend on Shlink server&lsquo;s version).
<FormText>
The visits coming from potential bots will
be <b>{settings.visits?.excludeBots ? 'excluded' : 'included'}</b>.
</FormText>
</ToggleSwitch>
</FormGroup>
<FormGroup>
<ToggleSwitch
checked={!!settings.visits?.loadPrevInterval}
onChange={(loadPrevInterval) => updateSettings({ loadPrevInterval })}
>
Compare visits with previous period.
<FormText>
When loading visits, previous period <b>{settings.visits?.loadPrevInterval ? 'will' : 'won\'t'}</b> be
loaded by default.
</FormText>
</ToggleSwitch>
</FormGroup>
<LabeledFormGroup noMargin label="Default interval to load on visits sections:">
<DateIntervalSelector
allText="All visits"
active={currentDefaultInterval(settings)}
onChange={(defaultInterval) => updateSettings({ defaultInterval })}
/>
</LabeledFormGroup>
</SimpleCard>
);
};
33 changes: 33 additions & 0 deletions test/settings/VisitsSettings.test.tsx
Expand Up @@ -19,6 +19,7 @@ describe('<VisitsSettings />', () => {
expect(screen.getByRole('heading')).toHaveTextContent('Visits');
expect(screen.getByText('Default interval to load on visits sections:')).toBeInTheDocument();
expect(screen.getByText(/^Exclude bots wherever possible/)).toBeInTheDocument();
expect(screen.getByText('Compare visits with previous period.')).toBeInTheDocument();
});

it.each([
Expand Down Expand Up @@ -93,4 +94,36 @@ describe('<VisitsSettings />', () => {
await user.click(screen.getByText(/^Exclude bots wherever possible/));
expect(setVisitsSettings).toHaveBeenCalledWith(expect.objectContaining({ excludeBots: true }));
});

it.each([
[
fromPartial<Settings>({}),
/When loading visits, previous period won't be loaded by default.$/,
/When loading visits, previous period will be loaded by default.$/,
],
[
fromPartial<Settings>({ visits: { loadPrevInterval: false } }),
/When loading visits, previous period won't be loaded by default.$/,
/When loading visits, previous period will be loaded by default.$/,
],
[
fromPartial<Settings>({ visits: { loadPrevInterval: true } }),
/When loading visits, previous period will be loaded by default.$/,
/When loading visits, previous period won't be loaded by default.$/,
],
])('displays expected helper text for prev interval control', (settings, expectedText, notExpectedText) => {
setUp(settings);

const visitsComponent = screen.getByText('Compare visits with previous period.');

expect(visitsComponent).toHaveTextContent(expectedText);
expect(visitsComponent).not.toHaveTextContent(notExpectedText);
});

it('invokes setVisitsSettings when loading prev visits is toggled', async () => {
const { user } = setUp();

await user.click(screen.getByText('Compare visits with previous period.'));
expect(setVisitsSettings).toHaveBeenCalledWith(expect.objectContaining({ loadPrevInterval: true }));
});
});

0 comments on commit b12bb6c

Please sign in to comment.