mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-05 15:57:24 +03:00
Created SimpleCard component to reduce duplicated code when rendering cards
This commit is contained in:
parent
e60d241fcf
commit
2017ee7456
4 changed files with 126 additions and 93 deletions
|
@ -1,6 +1,7 @@
|
||||||
import { Card, CardBody, CardHeader, FormGroup, Input } from 'reactstrap';
|
import { FormGroup, Input } from 'reactstrap';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ToggleSwitch from '../utils/ToggleSwitch';
|
import ToggleSwitch from '../utils/ToggleSwitch';
|
||||||
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import { Settings } from './reducers/settings';
|
import { Settings } from './reducers/settings';
|
||||||
|
|
||||||
interface RealTimeUpdatesProps {
|
interface RealTimeUpdatesProps {
|
||||||
|
@ -14,9 +15,7 @@ const intervalValue = (interval?: number) => !interval ? '' : `${interval}`;
|
||||||
const RealTimeUpdates = (
|
const RealTimeUpdates = (
|
||||||
{ settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps,
|
{ settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps,
|
||||||
) => (
|
) => (
|
||||||
<Card>
|
<SimpleCard title="Real-time updates">
|
||||||
<CardHeader>Real-time updates</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<ToggleSwitch checked={realTimeUpdates.enabled} onChange={toggleRealTimeUpdates}>
|
<ToggleSwitch checked={realTimeUpdates.enabled} onChange={toggleRealTimeUpdates}>
|
||||||
Enable or disable real-time updates, when using Shlink v2.2.0 or newer.
|
Enable or disable real-time updates, when using Shlink v2.2.0 or newer.
|
||||||
|
@ -45,8 +44,7 @@ const RealTimeUpdates = (
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</CardBody>
|
</SimpleCard>
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export default RealTimeUpdates;
|
export default RealTimeUpdates;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { isEmpty, pipe, replace, trim } from 'ramda';
|
import { isEmpty, pipe, replace, trim } from 'ramda';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { Button, Card, CardBody, CardHeader, FormGroup, Input } from 'reactstrap';
|
import { Button, FormGroup, Input } from 'reactstrap';
|
||||||
import { InputType } from 'reactstrap/lib/Input';
|
import { InputType } from 'reactstrap/lib/Input';
|
||||||
import * as m from 'moment';
|
import * as m from 'moment';
|
||||||
import DateInput, { DateInputProps } from '../utils/DateInput';
|
import DateInput, { DateInputProps } from '../utils/DateInput';
|
||||||
|
@ -11,6 +11,7 @@ import { isReachableServer, SelectedServer } from '../servers/data';
|
||||||
import { formatIsoDate } from '../utils/helpers/date';
|
import { formatIsoDate } from '../utils/helpers/date';
|
||||||
import { TagsSelectorProps } from '../tags/helpers/TagsSelector';
|
import { TagsSelectorProps } from '../tags/helpers/TagsSelector';
|
||||||
import { DomainSelectorProps } from '../domains/DomainSelector';
|
import { DomainSelectorProps } from '../domains/DomainSelector';
|
||||||
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import { ShortUrlData } from './data';
|
import { ShortUrlData } from './data';
|
||||||
import { ShortUrlCreation } from './reducers/shortUrlCreation';
|
import { ShortUrlCreation } from './reducers/shortUrlCreation';
|
||||||
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
|
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
|
||||||
|
@ -121,9 +122,7 @@ const CreateShortUrl = (
|
||||||
<>
|
<>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-6 mb-3">
|
<div className="col-sm-6 mb-3">
|
||||||
<Card>
|
<SimpleCard title="Customize the short URL">
|
||||||
<CardHeader>Customize the short URL</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
<p>
|
<p>
|
||||||
Use a custom slug for your marketing campaigns, change the domain or set a specific length for
|
Use a custom slug for your marketing campaigns, change the domain or set a specific length for
|
||||||
the auto-generated short code.
|
the auto-generated short code.
|
||||||
|
@ -150,26 +149,21 @@ const CreateShortUrl = (
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</SimpleCard>
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-sm-6 mb-3">
|
<div className="col-sm-6 mb-3">
|
||||||
<Card>
|
<SimpleCard title="Limit access to the short URL">
|
||||||
<CardHeader>Limit access to the short URL</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
<p>Determine when and how many times your short URL can be accessed.</p>
|
<p>Determine when and how many times your short URL can be accessed.</p>
|
||||||
{renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
|
{renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
|
||||||
{renderDateInput('validSince', 'Enabled since...', { maxDate: shortUrlCreation.validUntil as m.Moment | undefined })}
|
{renderDateInput('validSince', 'Enabled since...', { maxDate: shortUrlCreation.validUntil as m.Moment | undefined })}
|
||||||
{renderDateInput('validUntil', 'Enabled until...', { minDate: shortUrlCreation.validSince as m.Moment | undefined })}
|
{renderDateInput('validUntil', 'Enabled until...', { minDate: shortUrlCreation.validSince as m.Moment | undefined })}
|
||||||
</CardBody>
|
</SimpleCard>
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="mb-3">
|
<ForServerVersion minVersion="1.16.0">
|
||||||
<CardHeader>Extra validations</CardHeader>
|
<SimpleCard title="Extra validations" className="mb-3">
|
||||||
<CardBody>
|
|
||||||
<p>
|
<p>
|
||||||
Make sure the long URL is valid, or ensure an existing short URL is returned if it matches all
|
Make sure the long URL is valid, or ensure an existing short URL is returned if it matches all
|
||||||
provided data.
|
provided data.
|
||||||
|
@ -185,7 +179,6 @@ const CreateShortUrl = (
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</p>
|
</p>
|
||||||
</ForServerVersion>
|
</ForServerVersion>
|
||||||
<ForServerVersion minVersion="1.16.0">
|
|
||||||
<p>
|
<p>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
inline
|
inline
|
||||||
|
@ -197,9 +190,8 @@ const CreateShortUrl = (
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
<UseExistingIfFoundInfoIcon />
|
<UseExistingIfFoundInfoIcon />
|
||||||
</p>
|
</p>
|
||||||
|
</SimpleCard>
|
||||||
</ForServerVersion>
|
</ForServerVersion>
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
13
src/utils/SimpleCard.tsx
Normal file
13
src/utils/SimpleCard.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { CardProps } from 'reactstrap/lib/Card';
|
||||||
|
import { Card, CardBody, CardHeader } from 'reactstrap';
|
||||||
|
|
||||||
|
interface SimpleCardProps extends CardProps {
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SimpleCard = ({ title, children, ...rest }: SimpleCardProps) => (
|
||||||
|
<Card {...rest}>
|
||||||
|
{title && <CardHeader>{title}</CardHeader>}
|
||||||
|
<CardBody>{children}</CardBody>
|
||||||
|
</Card>
|
||||||
|
);
|
30
test/utils/SimpleCard.test.tsx
Normal file
30
test/utils/SimpleCard.test.tsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { Card, CardBody, CardHeader } from 'reactstrap';
|
||||||
|
import { SimpleCard } from '../../src/utils/SimpleCard';
|
||||||
|
|
||||||
|
describe('<SimpleCard />', () => {
|
||||||
|
it.each([
|
||||||
|
[{}, 0 ],
|
||||||
|
[{ title: 'Cool title' }, 1 ],
|
||||||
|
])('renders header only if title is provided', (props, expectedAmountOfHeaders) => {
|
||||||
|
const wrapper = shallow(<SimpleCard {...props} />);
|
||||||
|
|
||||||
|
expect(wrapper.find(CardHeader)).toHaveLength(expectedAmountOfHeaders);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders children inside body', () => {
|
||||||
|
const wrapper = shallow(<SimpleCard>Hello world</SimpleCard>);
|
||||||
|
const body = wrapper.find(CardBody);
|
||||||
|
|
||||||
|
expect(body).toHaveLength(1);
|
||||||
|
expect(body.html()).toContain('Hello world');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes extra props to nested card', () => {
|
||||||
|
const wrapper = shallow(<SimpleCard className="foo" color="primary">Hello world</SimpleCard>);
|
||||||
|
const card = wrapper.find(Card);
|
||||||
|
|
||||||
|
expect(card.prop('className')).toEqual('foo');
|
||||||
|
expect(card.prop('color')).toEqual('primary');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue