mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-04-21 14:06:19 +00:00
Moved logic to dynamically render components based on server version to a separated component
This commit is contained in:
@@ -20,7 +20,7 @@ const mapActionService = (map, actionName) => ({
|
||||
// Wrap actual action service in a function so that it is lazily created the first time it is called
|
||||
[actionName]: lazyService(container, actionName),
|
||||
});
|
||||
const connect = (propsFromState, actionServiceNames) =>
|
||||
const connect = (propsFromState, actionServiceNames = []) =>
|
||||
reduxConnect(
|
||||
propsFromState ? pick(propsFromState) : null,
|
||||
actionServiceNames.reduce(mapActionService, {})
|
||||
|
||||
31
src/servers/helpers/ForServerVersion.js
Normal file
31
src/servers/helpers/ForServerVersion.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { compareVersions } from '../../utils/utils';
|
||||
import { serverType } from '../prop-types';
|
||||
|
||||
const propTypes = {
|
||||
minVersion: PropTypes.string,
|
||||
maxVersion: PropTypes.string,
|
||||
selectedServer: serverType,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
const ForServerVersion = ({ minVersion, maxVersion, selectedServer, children }) => {
|
||||
if (!selectedServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { version } = selectedServer;
|
||||
const matchesMinVersion = !minVersion || compareVersions(version, '>=', minVersion);
|
||||
const matchesMaxVersion = !maxVersion || compareVersions(version, '<=', maxVersion);
|
||||
|
||||
if (!matchesMinVersion || !matchesMaxVersion) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <React.Fragment>{children}</React.Fragment>;
|
||||
};
|
||||
|
||||
ForServerVersion.propTypes = propTypes;
|
||||
|
||||
export default ForServerVersion;
|
||||
@@ -5,4 +5,5 @@ export const serverType = PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
apiKey: PropTypes.string,
|
||||
version: PropTypes.string,
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import DeleteServerButton from '../DeleteServerButton';
|
||||
import ImportServersBtn from '../helpers/ImportServersBtn';
|
||||
import { resetSelectedServer, selectServer } from '../reducers/selectedServer';
|
||||
import { createServer, createServers, deleteServer, listServers } from '../reducers/server';
|
||||
import ForServerVersion from '../helpers/ForServerVersion';
|
||||
import ServersImporter from './ServersImporter';
|
||||
import ServersService from './ServersService';
|
||||
import ServersExporter from './ServersExporter';
|
||||
@@ -28,6 +29,9 @@ const provideServices = (bottle, connect, withRouter) => {
|
||||
bottle.serviceFactory('ImportServersBtn', ImportServersBtn, 'ServersImporter');
|
||||
bottle.decorator('ImportServersBtn', connect(null, [ 'createServers' ]));
|
||||
|
||||
bottle.serviceFactory('ForServerVersion', () => ForServerVersion);
|
||||
bottle.decorator('ForServerVersion', connect([ 'selectedServer' ]));
|
||||
|
||||
// Services
|
||||
bottle.constant('csvjson', csvjson);
|
||||
bottle.service('ServersImporter', ServersImporter, 'csvjson');
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Collapse, FormGroup, Input } from 'reactstrap';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import DateInput from '../utils/DateInput';
|
||||
import Checkbox from '../utils/Checkbox';
|
||||
import ForVersion from '../utils/ForVersion';
|
||||
import { serverType } from '../servers/prop-types';
|
||||
import { compareVersions } from '../utils/utils';
|
||||
import { createShortUrlResultType } from './reducers/shortUrlCreation';
|
||||
@@ -15,7 +14,11 @@ import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
|
||||
const normalizeTag = pipe(trim, replace(/ /g, '-'));
|
||||
const formatDate = (date) => isNil(date) ? date : date.format();
|
||||
|
||||
const CreateShortUrl = (TagsSelector, CreateShortUrlResult) => class CreateShortUrl extends React.Component {
|
||||
const CreateShortUrl = (
|
||||
TagsSelector,
|
||||
CreateShortUrlResult,
|
||||
ForServerVersion
|
||||
) => class CreateShortUrl extends React.Component {
|
||||
static propTypes = {
|
||||
createShortUrl: PropTypes.func,
|
||||
shortUrlCreationResult: createShortUrlResultType,
|
||||
@@ -116,7 +119,7 @@ const CreateShortUrl = (TagsSelector, CreateShortUrlResult) => class CreateShort
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ForVersion minVersion="1.16.0" currentServerVersion={currentServerVersion}>
|
||||
<ForServerVersion minVersion="1.16.0">
|
||||
<div className="mb-4 text-right">
|
||||
<Checkbox
|
||||
className="mr-2"
|
||||
@@ -127,7 +130,7 @@ const CreateShortUrl = (TagsSelector, CreateShortUrlResult) => class CreateShort
|
||||
</Checkbox>
|
||||
<UseExistingIfFoundInfoIcon />
|
||||
</div>
|
||||
</ForVersion>
|
||||
</ForServerVersion>
|
||||
</Collapse>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -7,23 +7,19 @@ import moment from 'moment';
|
||||
import SearchField from '../utils/SearchField';
|
||||
import Tag from '../tags/helpers/Tag';
|
||||
import DateRangeRow from '../utils/DateRangeRow';
|
||||
import { compareVersions, formatDate } from '../utils/utils';
|
||||
import { serverType } from '../servers/prop-types';
|
||||
import { formatDate } from '../utils/utils';
|
||||
import { shortUrlsListParamsType } from './reducers/shortUrlsListParams';
|
||||
import './SearchBar.scss';
|
||||
|
||||
const propTypes = {
|
||||
listShortUrls: PropTypes.func,
|
||||
shortUrlsListParams: shortUrlsListParamsType,
|
||||
selectedServer: serverType,
|
||||
};
|
||||
|
||||
const dateOrUndefined = (date) => date ? moment(date) : undefined;
|
||||
|
||||
const SearchBar = (colorGenerator) => {
|
||||
const SearchBar = ({ listShortUrls, shortUrlsListParams, selectedServer }) => {
|
||||
const currentServerVersion = selectedServer ? selectedServer.version : '';
|
||||
const enableDateFiltering = !isEmpty(currentServerVersion) && compareVersions(currentServerVersion, '>=', '1.21.0');
|
||||
const SearchBar = (colorGenerator, ForServerVersion) => {
|
||||
const SearchBar = ({ listShortUrls, shortUrlsListParams }) => {
|
||||
const selectedTags = shortUrlsListParams.tags || [];
|
||||
const setDate = (dateName) => pipe(
|
||||
formatDate(),
|
||||
@@ -38,7 +34,7 @@ const SearchBar = (colorGenerator) => {
|
||||
}
|
||||
/>
|
||||
|
||||
{enableDateFiltering && (
|
||||
<ForServerVersion minVersion="1.21.0">
|
||||
<div className="mt-3">
|
||||
<DateRangeRow
|
||||
startDate={dateOrUndefined(shortUrlsListParams.startDate)}
|
||||
@@ -47,7 +43,7 @@ const SearchBar = (colorGenerator) => {
|
||||
onEndDateChange={setDate('endDate')}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</ForServerVersion>
|
||||
|
||||
{!isEmpty(selectedTags) && (
|
||||
<h4 className="search-bar__selected-tag mt-3">
|
||||
|
||||
@@ -13,9 +13,7 @@ import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ButtonDropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEmpty } from 'ramda';
|
||||
import { serverType } from '../../servers/prop-types';
|
||||
import { compareVersions } from '../../utils/utils';
|
||||
import { shortUrlType } from '../reducers/shortUrlsList';
|
||||
import PreviewModal from './PreviewModal';
|
||||
import QrCodeModal from './QrCodeModal';
|
||||
@@ -24,7 +22,8 @@ import './ShortUrlsRowMenu.scss';
|
||||
const ShortUrlsRowMenu = (
|
||||
DeleteShortUrlModal,
|
||||
EditTagsModal,
|
||||
EditMetaModal
|
||||
EditMetaModal,
|
||||
ForServerVersion
|
||||
) => class ShortUrlsRowMenu extends React.Component {
|
||||
static propTypes = {
|
||||
onCopyToClipboard: PropTypes.func,
|
||||
@@ -45,9 +44,6 @@ const ShortUrlsRowMenu = (
|
||||
render() {
|
||||
const { onCopyToClipboard, shortUrl, selectedServer } = this.props;
|
||||
const completeShortUrl = shortUrl && shortUrl.shortUrl ? shortUrl.shortUrl : '';
|
||||
const currentServerVersion = selectedServer ? selectedServer.version : '';
|
||||
const showEditMetaBtn = !isEmpty(currentServerVersion) && compareVersions(currentServerVersion, '>=', '1.18.0');
|
||||
const showPreviewBtn = !isEmpty(currentServerVersion) && compareVersions(currentServerVersion, '<', '2.0.0');
|
||||
const toggleModal = (prop) => () => this.setState((prevState) => ({ [prop]: !prevState[prop] }));
|
||||
const toggleQrCode = toggleModal('isQrModalOpen');
|
||||
const togglePreview = toggleModal('isPreviewModalOpen');
|
||||
@@ -70,14 +66,12 @@ const ShortUrlsRowMenu = (
|
||||
</DropdownItem>
|
||||
<EditTagsModal shortUrl={shortUrl} isOpen={this.state.isTagsModalOpen} toggle={toggleTags} />
|
||||
|
||||
{showEditMetaBtn && (
|
||||
<React.Fragment>
|
||||
<DropdownItem onClick={toggleMeta}>
|
||||
<FontAwesomeIcon icon={editIcon} fixedWidth /> Edit metadata
|
||||
</DropdownItem>
|
||||
<EditMetaModal shortUrl={shortUrl} isOpen={this.state.isMetaModalOpen} toggle={toggleMeta} />
|
||||
</React.Fragment>
|
||||
)}
|
||||
<ForServerVersion minVersion="1.18.0">
|
||||
<DropdownItem onClick={toggleMeta}>
|
||||
<FontAwesomeIcon icon={editIcon} fixedWidth /> Edit metadata
|
||||
</DropdownItem>
|
||||
<EditMetaModal shortUrl={shortUrl} isOpen={this.state.isMetaModalOpen} toggle={toggleMeta} />
|
||||
</ForServerVersion>
|
||||
|
||||
<DropdownItem className="short-urls-row-menu__dropdown-item--danger" onClick={toggleDelete}>
|
||||
<FontAwesomeIcon icon={deleteIcon} fixedWidth /> Delete short URL
|
||||
@@ -86,21 +80,21 @@ const ShortUrlsRowMenu = (
|
||||
|
||||
<DropdownItem divider />
|
||||
|
||||
{showPreviewBtn && (
|
||||
<React.Fragment>
|
||||
<DropdownItem onClick={togglePreview}>
|
||||
<FontAwesomeIcon icon={pictureIcon} fixedWidth /> Preview
|
||||
</DropdownItem>
|
||||
<PreviewModal url={completeShortUrl} isOpen={this.state.isPreviewModalOpen} toggle={togglePreview} />
|
||||
</React.Fragment>
|
||||
)}
|
||||
<ForServerVersion maxVersion="1.x">
|
||||
<DropdownItem onClick={togglePreview}>
|
||||
<FontAwesomeIcon icon={pictureIcon} fixedWidth /> Preview
|
||||
</DropdownItem>
|
||||
<PreviewModal url={completeShortUrl} isOpen={this.state.isPreviewModalOpen} toggle={togglePreview} />
|
||||
</ForServerVersion>
|
||||
|
||||
<DropdownItem onClick={toggleQrCode}>
|
||||
<FontAwesomeIcon icon={qrIcon} fixedWidth /> QR code
|
||||
</DropdownItem>
|
||||
<QrCodeModal url={completeShortUrl} isOpen={this.state.isQrModalOpen} toggle={toggleQrCode} />
|
||||
|
||||
{showPreviewBtn && <DropdownItem divider />}
|
||||
<ForServerVersion maxVersion="1.x">
|
||||
<DropdownItem divider />
|
||||
</ForServerVersion>
|
||||
|
||||
<CopyToClipboard text={completeShortUrl} onCopy={onCopyToClipboard}>
|
||||
<DropdownItem>
|
||||
|
||||
@@ -24,8 +24,8 @@ const provideServices = (bottle, connect) => {
|
||||
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList)
|
||||
));
|
||||
|
||||
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator');
|
||||
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams', 'selectedServer' ], [ 'listShortUrls' ]));
|
||||
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator', 'ForServerVersion');
|
||||
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], [ 'listShortUrls' ]));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
|
||||
bottle.decorator('ShortUrlsList', connect(
|
||||
@@ -35,10 +35,17 @@ const provideServices = (bottle, connect) => {
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'stateFlagTimeout');
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'EditTagsModal', 'EditMetaModal');
|
||||
bottle.serviceFactory(
|
||||
'ShortUrlsRowMenu',
|
||||
ShortUrlsRowMenu,
|
||||
'DeleteShortUrlModal',
|
||||
'EditTagsModal',
|
||||
'EditMetaModal',
|
||||
'ForServerVersion'
|
||||
);
|
||||
bottle.serviceFactory('CreateShortUrlResult', CreateShortUrlResult, 'stateFlagTimeout');
|
||||
|
||||
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector', 'CreateShortUrlResult');
|
||||
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector', 'CreateShortUrlResult', 'ForServerVersion');
|
||||
bottle.decorator(
|
||||
'CreateShortUrl',
|
||||
connect([ 'shortUrlCreationResult', 'selectedServer' ], [ 'createShortUrl', 'resetCreateShortUrl' ])
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEmpty } from 'ramda';
|
||||
import { compareVersions } from './utils';
|
||||
|
||||
const propTypes = {
|
||||
minVersion: PropTypes.string.isRequired,
|
||||
currentServerVersion: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
const ForVersion = ({ minVersion, currentServerVersion, children }) =>
|
||||
isEmpty(currentServerVersion) || compareVersions(currentServerVersion, '<', minVersion)
|
||||
? null
|
||||
: <React.Fragment>{children}</React.Fragment>;
|
||||
|
||||
ForVersion.propTypes = propTypes;
|
||||
|
||||
export default ForVersion;
|
||||
Reference in New Issue
Block a user