mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-14 03:23:49 +00:00
Added short code length field to form to create short URLs
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { serverType } from '../prop-types';
|
import { serverType } from '../prop-types';
|
||||||
import { compareVersions } from '../../utils/helpers/version';
|
import { versionMatch } from '../../utils/helpers/version';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
minVersion: PropTypes.string,
|
minVersion: PropTypes.string,
|
||||||
@@ -16,10 +16,9 @@ const ForServerVersion = ({ minVersion, maxVersion, selectedServer, children })
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { version } = selectedServer;
|
const { version } = selectedServer;
|
||||||
const matchesMinVersion = !minVersion || compareVersions(version, '>=', minVersion);
|
const matchesVersion = versionMatch(version, { maxVersion, minVersion });
|
||||||
const matchesMaxVersion = !maxVersion || compareVersions(version, '<=', maxVersion);
|
|
||||||
|
|
||||||
if (!matchesMinVersion || !matchesMaxVersion) {
|
if (!matchesVersion) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import * as PropTypes from 'prop-types';
|
|||||||
import DateInput from '../utils/DateInput';
|
import DateInput from '../utils/DateInput';
|
||||||
import Checkbox from '../utils/Checkbox';
|
import Checkbox from '../utils/Checkbox';
|
||||||
import { serverType } from '../servers/prop-types';
|
import { serverType } from '../servers/prop-types';
|
||||||
import { compareVersions } from '../utils/helpers/version';
|
import { versionMatch } from '../utils/helpers/version';
|
||||||
|
import { hasValue } from '../utils/utils';
|
||||||
import { createShortUrlResultType } from './reducers/shortUrlCreation';
|
import { createShortUrlResultType } from './reducers/shortUrlCreation';
|
||||||
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
|
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ const CreateShortUrl = (
|
|||||||
longUrl: '',
|
longUrl: '',
|
||||||
tags: [],
|
tags: [],
|
||||||
customSlug: undefined,
|
customSlug: undefined,
|
||||||
|
shortCodeLength: undefined,
|
||||||
domain: undefined,
|
domain: undefined,
|
||||||
validSince: undefined,
|
validSince: undefined,
|
||||||
validUntil: undefined,
|
validUntil: undefined,
|
||||||
@@ -73,8 +75,9 @@ const CreateShortUrl = (
|
|||||||
assoc('validUntil', formatDate(this.state.validUntil))
|
assoc('validUntil', formatDate(this.state.validUntil))
|
||||||
)(this.state));
|
)(this.state));
|
||||||
};
|
};
|
||||||
const currentServerVersion = this.props.selectedServer ? this.props.selectedServer.version : '';
|
const currentServerVersion = this.props.selectedServer && this.props.selectedServer.version;
|
||||||
const disableDomain = isEmpty(currentServerVersion) || compareVersions(currentServerVersion, '<', '1.19.0-beta.1');
|
const disableDomain = !versionMatch(currentServerVersion, { minVersion: '1.19.0-beta.1' });
|
||||||
|
const disableShortCodeLength = !versionMatch(currentServerVersion, { minVersion: '2.1.0' });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={save}>
|
<form onSubmit={save}>
|
||||||
@@ -95,10 +98,19 @@ const CreateShortUrl = (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-4">
|
||||||
{renderOptionalInput('customSlug', 'Custom slug')}
|
{renderOptionalInput('customSlug', 'Custom slug')}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-4">
|
||||||
|
{renderOptionalInput('shortCodeLength', 'Short code length', 'number', {
|
||||||
|
min: 4,
|
||||||
|
disabled: disableShortCodeLength || hasValue(this.state.customSlug),
|
||||||
|
...disableShortCodeLength && {
|
||||||
|
title: 'Shlink 2.1.0 or higher is required to be able to provide the short code length',
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="col-sm-4">
|
||||||
{renderOptionalInput('domain', 'Domain', 'text', {
|
{renderOptionalInput('domain', 'Domain', 'text', {
|
||||||
disabled: disableDomain,
|
disabled: disableDomain,
|
||||||
...disableDomain && { title: 'Shlink 1.19.0 or higher is required to be able to provide the domain' },
|
...disableDomain && { title: 'Shlink 1.19.0 or higher is required to be able to provide the domain' },
|
||||||
@@ -107,13 +119,13 @@ const CreateShortUrl = (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-4">
|
||||||
{renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
|
{renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-3">
|
<div className="col-sm-4">
|
||||||
{renderDateInput('validSince', 'Enabled since...', { maxDate: this.state.validUntil })}
|
{renderDateInput('validSince', 'Enabled since...', { maxDate: this.state.validUntil })}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-3">
|
<div className="col-sm-4">
|
||||||
{renderDateInput('validUntil', 'Enabled until...', { minDate: this.state.validSince })}
|
{renderDateInput('validUntil', 'Enabled until...', { minDate: this.state.validSince })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
import { compare } from 'compare-versions';
|
import { compare } from 'compare-versions';
|
||||||
import { identity, memoizeWith } from 'ramda';
|
import { identity, memoizeWith } from 'ramda';
|
||||||
|
import { hasValue } from '../utils';
|
||||||
|
|
||||||
export const compareVersions = (firstVersion, operator, secondVersion) => compare(
|
export const versionMatch = (versionToMatch, { maxVersion, minVersion }) => {
|
||||||
firstVersion,
|
if (!hasValue(versionToMatch)) {
|
||||||
secondVersion,
|
return false;
|
||||||
operator,
|
}
|
||||||
);
|
|
||||||
|
const matchesMinVersion = !minVersion || compare(versionToMatch, minVersion, '>=');
|
||||||
|
const matchesMaxVersion = !maxVersion || compare(versionToMatch, maxVersion, '<=');
|
||||||
|
|
||||||
|
return !!(matchesMaxVersion && matchesMinVersion);
|
||||||
|
};
|
||||||
|
|
||||||
const versionIsValidSemVer = memoizeWith(identity, (version) => {
|
const versionIsValidSemVer = memoizeWith(identity, (version) => {
|
||||||
try {
|
try {
|
||||||
return compareVersions(version, '=', version);
|
return compare(version, version, '=');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import L from 'leaflet';
|
|||||||
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
||||||
import marker from 'leaflet/dist/images/marker-icon.png';
|
import marker from 'leaflet/dist/images/marker-icon.png';
|
||||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||||
import { range } from 'ramda';
|
import { isEmpty, isNil, range } from 'ramda';
|
||||||
|
|
||||||
const TEN_ROUNDING_NUMBER = 10;
|
const TEN_ROUNDING_NUMBER = 10;
|
||||||
const DEFAULT_TIMEOUT_DELAY = 2000;
|
const DEFAULT_TIMEOUT_DELAY = 2000;
|
||||||
@@ -45,3 +45,4 @@ export const rangeOf = (size, mappingFn, startAt = 1) => range(startAt, size + 1
|
|||||||
|
|
||||||
export const roundTen = (number) => ceil(number / TEN_ROUNDING_NUMBER) * TEN_ROUNDING_NUMBER;
|
export const roundTen = (number) => ceil(number / TEN_ROUNDING_NUMBER) * TEN_ROUNDING_NUMBER;
|
||||||
|
|
||||||
|
export const hasValue = (value) => !isNil(value) && !isEmpty(value);
|
||||||
|
|||||||
23
test/utils/helpers/version.test.js
Normal file
23
test/utils/helpers/version.test.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { versionMatch } from '../../../src/utils/helpers/version';
|
||||||
|
|
||||||
|
describe('version', () => {
|
||||||
|
describe('versionMatch', () => {
|
||||||
|
it.each([
|
||||||
|
[ undefined, {}, false ],
|
||||||
|
[ null, {}, false ],
|
||||||
|
[ '', {}, false ],
|
||||||
|
[[], {}, false ],
|
||||||
|
[ '2.8.3', {}, true ],
|
||||||
|
[ '2.8.3', { minVersion: '2.0.0' }, true ],
|
||||||
|
[ '2.0.0', { minVersion: '2.0.0' }, true ],
|
||||||
|
[ '1.8.0', { maxVersion: '1.8.0' }, true ],
|
||||||
|
[ '1.7.1', { maxVersion: '1.8.0' }, true ],
|
||||||
|
[ '1.7.3', { minVersion: '1.7.0', maxVersion: '1.8.0' }, true ],
|
||||||
|
[ '1.8.3', { minVersion: '2.0.0' }, false ],
|
||||||
|
[ '1.8.3', { maxVersion: '1.8.0' }, false ],
|
||||||
|
[ '1.8.3', { minVersion: '1.7.0', maxVersion: '1.8.0' }, false ],
|
||||||
|
])('properly matches versions based on what is provided', (version, versionConstraints, expected) => {
|
||||||
|
expect(versionMatch(version, versionConstraints)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user