mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-12 02:23:49 +00:00
Converted ShortUrlsRow component into a functional component
This commit is contained in:
@@ -13,40 +13,36 @@ import Tag from '../../tags/helpers/Tag';
|
|||||||
import ShortUrlVisitsCount from './ShortUrlVisitsCount';
|
import ShortUrlVisitsCount from './ShortUrlVisitsCount';
|
||||||
import './ShortUrlsRow.scss';
|
import './ShortUrlsRow.scss';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
refreshList: PropTypes.func,
|
||||||
|
shortUrlsListParams: shortUrlsListParamsType,
|
||||||
|
selectedServer: serverType,
|
||||||
|
shortUrl: shortUrlType,
|
||||||
|
};
|
||||||
|
|
||||||
const ShortUrlsRow = (
|
const ShortUrlsRow = (
|
||||||
ShortUrlsRowMenu,
|
ShortUrlsRowMenu,
|
||||||
colorGenerator,
|
colorGenerator,
|
||||||
stateFlagTimeout
|
useStateFlagTimeout
|
||||||
) => class ShortUrlsRow extends React.Component {
|
) => {
|
||||||
static propTypes = {
|
const ShortUrlsRowComp = ({ shortUrl, selectedServer, refreshList, shortUrlsListParams }) => {
|
||||||
refreshList: PropTypes.func,
|
const [ copiedToClipboard, setCopiedToClipboard ] = useStateFlagTimeout(false);
|
||||||
shortUrlsListParams: shortUrlsListParamsType,
|
const renderTags = (tags) => {
|
||||||
selectedServer: serverType,
|
if (isEmpty(tags)) {
|
||||||
shortUrl: shortUrlType,
|
return <i className="indivisible"><small>No tags</small></i>;
|
||||||
};
|
}
|
||||||
|
|
||||||
state = { copiedToClipboard: false };
|
const selectedTags = shortUrlsListParams.tags || [];
|
||||||
|
|
||||||
renderTags(tags) {
|
return tags.map((tag) => (
|
||||||
if (isEmpty(tags)) {
|
<Tag
|
||||||
return <i className="indivisible"><small>No tags</small></i>;
|
colorGenerator={colorGenerator}
|
||||||
}
|
key={tag}
|
||||||
|
text={tag}
|
||||||
const { refreshList, shortUrlsListParams } = this.props;
|
onClick={() => refreshList({ tags: [ ...selectedTags, tag ] })}
|
||||||
const selectedTags = shortUrlsListParams.tags || [];
|
/>
|
||||||
|
));
|
||||||
return tags.map((tag) => (
|
};
|
||||||
<Tag
|
|
||||||
colorGenerator={colorGenerator}
|
|
||||||
key={tag}
|
|
||||||
text={tag}
|
|
||||||
onClick={() => refreshList({ tags: [ ...selectedTags, tag ] })}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { shortUrl, selectedServer } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="short-urls-row">
|
<tr className="short-urls-row">
|
||||||
@@ -56,16 +52,10 @@ const ShortUrlsRow = (
|
|||||||
<td className="short-urls-row__cell" data-th="Short URL: ">
|
<td className="short-urls-row__cell" data-th="Short URL: ">
|
||||||
<span className="indivisible short-urls-row__cell--relative">
|
<span className="indivisible short-urls-row__cell--relative">
|
||||||
<ExternalLink href={shortUrl.shortUrl} />
|
<ExternalLink href={shortUrl.shortUrl} />
|
||||||
<CopyToClipboard
|
<CopyToClipboard text={shortUrl.shortUrl} onCopy={setCopiedToClipboard}>
|
||||||
text={shortUrl.shortUrl}
|
|
||||||
onCopy={() => stateFlagTimeout(this.setState.bind(this), 'copiedToClipboard')}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon icon={copyIcon} className="ml-2 short-urls-row__copy-btn" />
|
<FontAwesomeIcon icon={copyIcon} className="ml-2 short-urls-row__copy-btn" />
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
<span
|
<span className="badge badge-warning short-urls-row__copy-hint" hidden={!copiedToClipboard}>
|
||||||
className="badge badge-warning short-urls-row__copy-hint"
|
|
||||||
hidden={!this.state.copiedToClipboard}
|
|
||||||
>
|
|
||||||
Copied short URL!
|
Copied short URL!
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -73,7 +63,7 @@ const ShortUrlsRow = (
|
|||||||
<td className="short-urls-row__cell short-urls-row__cell--break" data-th="Long URL: ">
|
<td className="short-urls-row__cell short-urls-row__cell--break" data-th="Long URL: ">
|
||||||
<ExternalLink href={shortUrl.longUrl} />
|
<ExternalLink href={shortUrl.longUrl} />
|
||||||
</td>
|
</td>
|
||||||
<td className="short-urls-row__cell" data-th="Tags: ">{this.renderTags(shortUrl.tags)}</td>
|
<td className="short-urls-row__cell" data-th="Tags: ">{renderTags(shortUrl.tags)}</td>
|
||||||
<td className="short-urls-row__cell text-md-right" data-th="Visits: ">
|
<td className="short-urls-row__cell text-md-right" data-th="Visits: ">
|
||||||
<ShortUrlVisitsCount
|
<ShortUrlVisitsCount
|
||||||
visitsCount={shortUrl.visitsCount}
|
visitsCount={shortUrl.visitsCount}
|
||||||
@@ -86,7 +76,11 @@ const ShortUrlsRow = (
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
ShortUrlsRowComp.propTypes = propTypes;
|
||||||
|
|
||||||
|
return ShortUrlsRowComp;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlsRow;
|
export default ShortUrlsRow;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const provideServices = (bottle, connect) => {
|
|||||||
[ 'listShortUrls', 'resetShortUrlParams' ]
|
[ 'listShortUrls', 'resetShortUrlParams' ]
|
||||||
));
|
));
|
||||||
|
|
||||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'stateFlagTimeout');
|
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useStateFlagTimeout');
|
||||||
|
|
||||||
bottle.serviceFactory(
|
bottle.serviceFactory(
|
||||||
'ShortUrlsRowMenu',
|
'ShortUrlsRowMenu',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { stateFlagTimeout } from '../utils';
|
import { stateFlagTimeout, useStateFlagTimeout } from '../utils';
|
||||||
import Storage from './Storage';
|
import Storage from './Storage';
|
||||||
import ColorGenerator from './ColorGenerator';
|
import ColorGenerator from './ColorGenerator';
|
||||||
import buildShlinkApiClient from './ShlinkApiClientBuilder';
|
import buildShlinkApiClient from './ShlinkApiClientBuilder';
|
||||||
@@ -14,6 +14,7 @@ const provideServices = (bottle) => {
|
|||||||
|
|
||||||
bottle.constant('setTimeout', global.setTimeout);
|
bottle.constant('setTimeout', global.setTimeout);
|
||||||
bottle.serviceFactory('stateFlagTimeout', stateFlagTimeout, 'setTimeout');
|
bottle.serviceFactory('stateFlagTimeout', stateFlagTimeout, 'setTimeout');
|
||||||
|
bottle.serviceFactory('useStateFlagTimeout', useStateFlagTimeout, 'setTimeout');
|
||||||
};
|
};
|
||||||
|
|
||||||
export default provideServices;
|
export default provideServices;
|
||||||
|
|||||||
@@ -19,6 +19,16 @@ export const stateFlagTimeout = (setTimeout) => (
|
|||||||
setTimeout(() => setState({ [flagName]: !initialValue }), delay);
|
setTimeout(() => setState({ [flagName]: !initialValue }), delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useStateFlagTimeout = (setTimeout) => (initialValue = true, delay = DEFAULT_TIMEOUT_DELAY) => {
|
||||||
|
const [ flag, setFlag ] = useState(initialValue);
|
||||||
|
const callback = () => {
|
||||||
|
setFlag(!initialValue);
|
||||||
|
setTimeout(() => setFlag(initialValue), delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
return [ flag, callback ];
|
||||||
|
};
|
||||||
|
|
||||||
export const determineOrderDir = (clickedField, currentOrderField, currentOrderDir) => {
|
export const determineOrderDir = (clickedField, currentOrderField, currentOrderDir) => {
|
||||||
if (currentOrderField !== clickedField) {
|
if (currentOrderField !== clickedField) {
|
||||||
return 'ASC';
|
return 'ASC';
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ describe('<ShortUrlsRow />', () => {
|
|||||||
let wrapper;
|
let wrapper;
|
||||||
const mockFunction = () => '';
|
const mockFunction = () => '';
|
||||||
const ShortUrlsRowMenu = mockFunction;
|
const ShortUrlsRowMenu = mockFunction;
|
||||||
const stateFlagTimeout = jest.fn();
|
const stateFlagTimeout = jest.fn(() => true);
|
||||||
|
const useStateFlagTimeout = jest.fn(() => [ false, stateFlagTimeout ]);
|
||||||
const colorGenerator = {
|
const colorGenerator = {
|
||||||
getColorForKey: mockFunction,
|
getColorForKey: mockFunction,
|
||||||
setColorForKey: mockFunction,
|
setColorForKey: mockFunction,
|
||||||
@@ -30,7 +31,7 @@ describe('<ShortUrlsRow />', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, stateFlagTimeout);
|
const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, useStateFlagTimeout);
|
||||||
|
|
||||||
wrapper = shallow(
|
wrapper = shallow(
|
||||||
<ShortUrlsRow shortUrlsListParams={{}} refreshList={mockFunction} selecrtedServer={server} shortUrl={shortUrl} />
|
<ShortUrlsRow shortUrlsListParams={{}} refreshList={mockFunction} selecrtedServer={server} shortUrl={shortUrl} />
|
||||||
@@ -96,12 +97,4 @@ describe('<ShortUrlsRow />', () => {
|
|||||||
menu.simulate('copy');
|
menu.simulate('copy');
|
||||||
expect(stateFlagTimeout).toHaveBeenCalledTimes(1);
|
expect(stateFlagTimeout).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows copy hint when state prop is true', () => {
|
|
||||||
const isHidden = () => wrapper.find('td').at(1).find('.short-urls-row__copy-hint').prop('hidden');
|
|
||||||
|
|
||||||
expect(isHidden()).toEqual(true);
|
|
||||||
wrapper.setState({ copiedToClipboard: true });
|
|
||||||
expect(isHidden()).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user