Fixed coding styles

This commit is contained in:
Alejandro Celaya 2020-08-22 08:10:31 +02:00
parent 343a93b984
commit a91f1b3bd4
60 changed files with 133 additions and 125 deletions

View file

@ -41,6 +41,7 @@
"no-magic-numbers": "off", "no-magic-numbers": "off",
"react/no-array-index-key": "off", "react/no-array-index-key": "off",
"react/no-did-update-set-state": "off", "react/no-did-update-set-state": "off",
"react/display-name": "off",
"react/jsx-curly-spacing": ["error", "never"], "react/jsx-curly-spacing": ["error", "never"],
"react/jsx-indent-props": ["error", 2], "react/jsx-indent-props": ["error", 2],
"react/jsx-first-prop-new-line": ["error", "multiline-multiprop"], "react/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
@ -52,7 +53,10 @@
"files": ["**/*.ts", "**/*.tsx"], "files": ["**/*.ts", "**/*.tsx"],
"extends": [ "extends": [
"@shlinkio/js-coding-standard" "@shlinkio/js-coding-standard"
] ],
"rules": {
"react/display-name": "off"
}
} }
] ]
} }

View file

@ -10,7 +10,7 @@ const { NODE_ENV } = process.env;
if (!NODE_ENV) { if (!NODE_ENV) {
throw new Error( throw new Error(
'The NODE_ENV environment variable is required but was not specified.' 'The NODE_ENV environment variable is required but was not specified.',
); );
} }
@ -36,7 +36,7 @@ dotenvFiles.forEach((dotenvFile) => {
require('dotenv-expand')( require('dotenv-expand')(
require('dotenv').config({ require('dotenv').config({
path: dotenvFile, path: dotenvFile,
}) }),
); );
} }
}); });
@ -82,7 +82,7 @@ function getClientEnvironment(publicUrl) {
// This should only be used as an escape hatch. Normally you would put // This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths. // images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl, PUBLIC_URL: publicUrl,
} },
); );
// Stringify all values so we can feed into Webpack DefinePlugin // Stringify all values so we can feed into Webpack DefinePlugin

View file

@ -75,7 +75,7 @@ module.exports = (webpackEnv) => {
loader: MiniCssExtractPlugin.loader, loader: MiniCssExtractPlugin.loader,
options: Object.assign( options: Object.assign(
{}, {},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined,
), ),
}, },
{ {
@ -281,7 +281,7 @@ module.exports = (webpackEnv) => {
modules: [ 'node_modules' ].concat( modules: [ 'node_modules' ].concat(
// It is guaranteed to exist because we tweak it in `env.js` // It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean) process.env.NODE_PATH.split(path.delimiter).filter(Boolean),
), ),
// These are the reasonable defaults supported by the Node ecosystem. // These are the reasonable defaults supported by the Node ecosystem.
@ -372,7 +372,7 @@ module.exports = (webpackEnv) => {
loader: require.resolve('babel-loader'), loader: require.resolve('babel-loader'),
options: { options: {
customize: require.resolve( customize: require.resolve(
'babel-preset-react-app/webpack-overrides' 'babel-preset-react-app/webpack-overrides',
), ),
plugins: [ plugins: [
@ -470,7 +470,7 @@ module.exports = (webpackEnv) => {
importLoaders: 2, importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
}, },
'sass-loader' 'sass-loader',
), ),
// Don't consider CSS imports dead code even if the // Don't consider CSS imports dead code even if the
@ -491,7 +491,7 @@ module.exports = (webpackEnv) => {
modules: true, modules: true,
getLocalIdent: getCSSModuleLocalIdent, getLocalIdent: getCSSModuleLocalIdent,
}, },
'sass-loader' 'sass-loader',
), ),
}, },
@ -544,8 +544,8 @@ module.exports = (webpackEnv) => {
minifyURLs: true, minifyURLs: true,
}, },
} }
: undefined : undefined,
) ),
), ),
// Inlines the webpack runtime script. This script is too small to warrant // Inlines the webpack runtime script. This script is too small to warrant

View file

@ -75,12 +75,12 @@ checkBrowsers(paths.appPath, isInteractive)
console.log( console.log(
`\nSearch for the ${ `\nSearch for the ${
chalk.underline(chalk.yellow('keywords')) chalk.underline(chalk.yellow('keywords'))
} to learn more about each warning.` } to learn more about each warning.`,
); );
console.log( console.log(
`To ignore, add ${ `To ignore, add ${
chalk.cyan('// eslint-disable-next-line') chalk.cyan('// eslint-disable-next-line')
} to the line before.\n` } to the line before.\n`,
); );
} else { } else {
console.log(chalk.green('Compiled successfully.\n')); console.log(chalk.green('Compiled successfully.\n'));
@ -93,7 +93,7 @@ checkBrowsers(paths.appPath, isInteractive)
previousFileSizes, previousFileSizes,
paths.appBuild, paths.appBuild,
WARN_AFTER_BUNDLE_GZIP_SIZE, WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE WARN_AFTER_CHUNK_GZIP_SIZE,
); );
console.log(); console.log();
}, },
@ -101,7 +101,7 @@ checkBrowsers(paths.appPath, isInteractive)
console.log(chalk.red('Failed to compile.\n')); console.log(chalk.red('Failed to compile.\n'));
printBuildError(err); printBuildError(err);
process.exit(1); process.exit(1);
} },
) )
.then(() => hasVersion && !withoutDist && zipDist(version)) .then(() => hasVersion && !withoutDist && zipDist(version))
.catch((err) => { .catch((err) => {
@ -133,7 +133,7 @@ function build(previousFileSizes) {
}); });
} else { } else {
messages = formatWebpackMessages( messages = formatWebpackMessages(
stats.toJson({ all: false, warnings: true, errors: true }) stats.toJson({ all: false, warnings: true, errors: true }),
); );
} }
if (messages.errors.length) { if (messages.errors.length) {
@ -154,8 +154,8 @@ function build(previousFileSizes) {
console.log( console.log(
chalk.yellow( chalk.yellow(
'\nTreating warnings as errors because process.env.CI = true.\n' + '\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n' 'Most CI servers set it automatically.\n',
) ),
); );
return reject(new Error(messages.warnings.join('\n\n'))); return reject(new Error(messages.warnings.join('\n\n')));

View file

@ -49,15 +49,15 @@ if (process.env.HOST) {
console.log( console.log(
chalk.cyan( chalk.cyan(
`Attempting to bind to HOST environment variable: ${chalk.yellow( `Attempting to bind to HOST environment variable: ${chalk.yellow(
chalk.bold(process.env.HOST) chalk.bold(process.env.HOST),
)}` )}`,
) ),
); );
console.log( console.log(
'If this was unintentional, check that you haven\'t mistakenly set it in your shell.' 'If this was unintentional, check that you haven\'t mistakenly set it in your shell.',
); );
console.log( console.log(
`Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}` `Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`,
); );
console.log(); console.log();
} }
@ -91,7 +91,7 @@ checkBrowsers(paths.appPath, isInteractive)
// Serve webpack assets generated by the compiler over a web server. // Serve webpack assets generated by the compiler over a web server.
const serverConfig = createDevServerConfig( const serverConfig = createDevServerConfig(
proxyConfig, proxyConfig,
urls.lanUrlForConfig urls.lanUrlForConfig,
); );
const devServer = new WebpackDevServer(compiler, serverConfig); const devServer = new WebpackDevServer(compiler, serverConfig);

View file

@ -9,32 +9,36 @@ const propTypes = {
servers: PropTypes.object, servers: PropTypes.object,
}; };
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer, Settings) => ({ fetchServers, servers }) => { const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer, Settings) => {
// On first load, try to fetch the remote servers if the list is empty const AppComp = ({ fetchServers, servers }) => {
useEffect(() => { // On first load, try to fetch the remote servers if the list is empty
if (Object.keys(servers).length === 0) { useEffect(() => {
fetchServers(); if (Object.keys(servers).length === 0) {
} fetchServers();
}, []); }
}, []);
return ( return (
<div className="container-fluid app-container"> <div className="container-fluid app-container">
<MainHeader /> <MainHeader />
<div className="app"> <div className="app">
<Switch> <Switch>
<Route exact path="/" component={Home} /> <Route exact path="/" component={Home} />
<Route exact path="/settings" component={Settings} /> <Route exact path="/settings" component={Settings} />
<Route exact path="/server/create" component={CreateServer} /> <Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} /> <Route exact path="/server/:serverId/edit" component={EditServer} />
<Route path="/server/:serverId" component={MenuLayout} /> <Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} /> <Route component={NotFound} />
</Switch> </Switch>
</div>
</div> </div>
</div> );
); };
AppComp.propTypes = propTypes;
return AppComp;
}; };
App.propTypes = propTypes;
export default App; export default App;

View file

@ -26,7 +26,7 @@ const MenuLayout = (
ShortUrlVisits, ShortUrlVisits,
TagVisits, TagVisits,
ShlinkVersions, ShlinkVersions,
ServerError ServerError,
) => { ) => {
const MenuLayoutComp = ({ match, location, selectedServer }) => { const MenuLayoutComp = ({ match, location, selectedServer }) => {
const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle(); const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle();
@ -44,7 +44,7 @@ const MenuLayout = (
}); });
const swipeMenuIfNoModalExists = (callback) => (e) => { const swipeMenuIfNoModalExists = (callback) => (e) => {
const swippedOnVisitsTable = e.event.path.some( const swippedOnVisitsTable = e.event.path.some(
({ classList }) => classList && classList.contains('visits-table') ({ classList }) => classList && classList.contains('visits-table'),
); );
if (swippedOnVisitsTable || document.querySelector('.modal')) { if (swippedOnVisitsTable || document.querySelector('.modal')) {

View file

@ -29,7 +29,7 @@ const provideServices = (bottle, connect, withRouter) => {
'ShortUrlVisits', 'ShortUrlVisits',
'TagVisits', 'TagVisits',
'ShlinkVersions', 'ShlinkVersions',
'ServerError' 'ServerError',
); );
bottle.decorator('MenuLayout', connect([ 'selectedServer', 'shortUrlsListParams' ], [ 'selectServer' ])); bottle.decorator('MenuLayout', connect([ 'selectedServer', 'shortUrlsListParams' ], [ 'selectServer' ]));
bottle.decorator('MenuLayout', withRouter); bottle.decorator('MenuLayout', withRouter);

View file

@ -25,7 +25,7 @@ const mapActionService = (map, actionName) => ({
const connect = (propsFromState, actionServiceNames = []) => const connect = (propsFromState, actionServiceNames = []) =>
reduxConnect( reduxConnect(
propsFromState ? pick(propsFromState) : null, propsFromState ? pick(propsFromState) : null,
actionServiceNames.reduce(mapActionService, {}) actionServiceNames.reduce(mapActionService, {}),
); );
bottle.serviceFactory('App', App, 'MainHeader', 'Home', 'MenuLayout', 'CreateServer', 'EditServer', 'Settings'); bottle.serviceFactory('App', App, 'MainHeader', 'Home', 'MenuLayout', 'CreateServer', 'EditServer', 'Settings');

View file

@ -15,7 +15,7 @@ const localStorageConfig = {
}; };
const store = createStore(reducers, load(localStorageConfig), composeEnhancers( const store = createStore(reducers, load(localStorageConfig), composeEnhancers(
applyMiddleware(save(localStorageConfig), ReduxThunk) applyMiddleware(save(localStorageConfig), ReduxThunk),
)); ));
export default store; export default store;

View file

@ -28,6 +28,6 @@ render(
</ErrorHandler> </ErrorHandler>
</BrowserRouter> </BrowserRouter>
</Provider>, </Provider>,
document.getElementById('root') document.getElementById('root'),
); );
registerServiceWorker(); registerServiceWorker();

View file

@ -18,8 +18,8 @@ const isLocalhost = Boolean(
// 127.0.0.1/8 is considered localhost for IPv4. // 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match( window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
) ),
); );
export default function register() { export default function register() {
@ -46,7 +46,7 @@ export default function register() {
return navigator.serviceWorker.ready.then(() => { return navigator.serviceWorker.ready.then(() => {
console.log( console.log(
'This web app is being served cache-first by a service ' + 'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ' 'worker. To learn more, visit https://goo.gl/SC7cgQ',
); );
}); });
} }
@ -110,7 +110,7 @@ function checkValidServiceWorker(swUrl) {
}) })
.catch(() => { .catch(() => {
console.log( console.log(
'No internet connection found. App is running in offline mode.' 'No internet connection found. App is running in offline mode.',
); );
}); });
} }

View file

@ -15,7 +15,7 @@ export const LATEST_VERSION_CONSTRAINT = 'latest';
const initialState = null; const initialState = null;
const versionToSemVer = pipe( const versionToSemVer = pipe(
(version) => version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version, (version) => version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version,
toSemVer(MIN_FALLBACK_VERSION) toSemVer(MIN_FALLBACK_VERSION),
); );
const getServerVersion = memoizeWith(identity, (serverId, health) => health().then(({ version }) => ({ const getServerVersion = memoizeWith(identity, (serverId, health) => health().then(({ version }) => ({
@ -27,7 +27,7 @@ export const resetSelectedServer = createAction(RESET_SELECTED_SERVER);
export const selectServer = (buildShlinkApiClient, loadMercureInfo) => (serverId) => async ( export const selectServer = (buildShlinkApiClient, loadMercureInfo) => (serverId) => async (
dispatch, dispatch,
getState getState,
) => { ) => {
dispatch(resetSelectedServer()); dispatch(resetSelectedServer());
dispatch(resetShortUrlParams()); dispatch(resetShortUrlParams());

View file

@ -27,7 +27,7 @@ const serversListToMap = reduce((acc, server) => assoc(server.id, server, acc),
export const createServers = pipe( export const createServers = pipe(
map(assocId), map(assocId),
serversListToMap, serversListToMap,
(newServers) => ({ type: CREATE_SERVERS, newServers }) (newServers) => ({ type: CREATE_SERVERS, newServers }),
); );
export const editServer = (serverId, serverData) => ({ type: EDIT_SERVER, serverId, serverData }); export const editServer = (serverId, serverData) => ({ type: EDIT_SERVER, serverId, serverData });

View file

@ -23,7 +23,7 @@ const SearchBar = (colorGenerator, ForServerVersion) => {
const selectedTags = shortUrlsListParams.tags || []; const selectedTags = shortUrlsListParams.tags || [];
const setDate = (dateName) => pipe( const setDate = (dateName) => pipe(
formatDate(), formatDate(),
(date) => listShortUrls({ ...shortUrlsListParams, [dateName]: date }) (date) => listShortUrls({ ...shortUrlsListParams, [dateName]: date }),
); );
return ( return (
@ -63,7 +63,7 @@ const SearchBar = (colorGenerator, ForServerVersion) => {
{ {
...shortUrlsListParams, ...shortUrlsListParams,
tags: selectedTags.filter((selectedTag) => selectedTag !== tag), tags: selectedTags.filter((selectedTag) => selectedTag !== tag),
} },
)} )}
/> />
))} ))}

View file

@ -23,7 +23,7 @@ const propTypes = {
const ShortUrlsRow = ( const ShortUrlsRow = (
ShortUrlsRowMenu, ShortUrlsRowMenu,
colorGenerator, colorGenerator,
useStateFlagTimeout useStateFlagTimeout,
) => { ) => {
const ShortUrlsRowComp = ({ shortUrl, selectedServer, refreshList, shortUrlsListParams }) => { const ShortUrlsRowComp = ({ shortUrl, selectedServer, refreshList, shortUrlsListParams }) => {
const [ copiedToClipboard, setCopiedToClipboard ] = useStateFlagTimeout(); const [ copiedToClipboard, setCopiedToClipboard ] = useStateFlagTimeout();

View file

@ -33,9 +33,9 @@ const initialState = {
const setPropFromActionOnMatchingShortUrl = (prop) => (state, { shortCode, domain, [prop]: propValue }) => assocPath( const setPropFromActionOnMatchingShortUrl = (prop) => (state, { shortCode, domain, [prop]: propValue }) => assocPath(
[ 'shortUrls', 'data' ], [ 'shortUrls', 'data' ],
state.shortUrls.data.map( state.shortUrls.data.map(
(shortUrl) => shortUrlMatches(shortUrl, shortCode, domain) ? assoc(prop, propValue, shortUrl) : shortUrl (shortUrl) => shortUrlMatches(shortUrl, shortCode, domain) ? assoc(prop, propValue, shortUrl) : shortUrl,
), ),
state state,
); );
export default handleActions({ export default handleActions({
@ -55,9 +55,9 @@ export default handleActions({
state.shortUrls && state.shortUrls.data && state.shortUrls.data.map( state.shortUrls && state.shortUrls.data && state.shortUrls.data.map(
(shortUrl) => shortUrlMatches(shortUrl, shortCode, domain) (shortUrl) => shortUrlMatches(shortUrl, shortCode, domain)
? assoc('visitsCount', visitsCount, shortUrl) ? assoc('visitsCount', visitsCount, shortUrl)
: shortUrl : shortUrl,
), ),
state state,
), ),
}, initialState); }, initialState);

View file

@ -23,7 +23,7 @@ const provideServices = (bottle, connect) => {
// Components // Components
bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList'); bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList');
bottle.decorator('ShortUrls', reduxConnect( bottle.decorator('ShortUrls', reduxConnect(
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList) (state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList),
)); ));
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator', 'ForServerVersion'); bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator', 'ForServerVersion');
@ -32,7 +32,7 @@ const provideServices = (bottle, connect) => {
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow'); bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
bottle.decorator('ShortUrlsList', connect( bottle.decorator('ShortUrlsList', connect(
[ 'selectedServer', 'shortUrlsListParams', 'mercureInfo' ], [ 'selectedServer', 'shortUrlsListParams', 'mercureInfo' ],
[ 'listShortUrls', 'resetShortUrlParams', 'createNewVisit', 'loadMercureInfo' ] [ 'listShortUrls', 'resetShortUrlParams', 'createNewVisit', 'loadMercureInfo' ],
)); ));
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useStateFlagTimeout'); bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useStateFlagTimeout');
@ -44,14 +44,14 @@ const provideServices = (bottle, connect) => {
'EditTagsModal', 'EditTagsModal',
'EditMetaModal', 'EditMetaModal',
'EditShortUrlModal', 'EditShortUrlModal',
'ForServerVersion' 'ForServerVersion',
); );
bottle.serviceFactory('CreateShortUrlResult', CreateShortUrlResult, 'useStateFlagTimeout'); bottle.serviceFactory('CreateShortUrlResult', CreateShortUrlResult, 'useStateFlagTimeout');
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector', 'CreateShortUrlResult', 'ForServerVersion'); bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector', 'CreateShortUrlResult', 'ForServerVersion');
bottle.decorator( bottle.decorator(
'CreateShortUrl', 'CreateShortUrl',
connect([ 'shortUrlCreationResult', 'selectedServer' ], [ 'createShortUrl', 'resetCreateShortUrl' ]) connect([ 'shortUrlCreationResult', 'selectedServer' ], [ 'createShortUrl', 'resetCreateShortUrl' ]),
); );
bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal); bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal);

View file

@ -23,7 +23,7 @@ const propTypes = {
const TagsList = (TagCard) => { const TagsList = (TagCard) => {
const TagListComp = ( const TagListComp = (
{ filterTags, forceListTags, tagsList, selectedServer, createNewVisit, loadMercureInfo, mercureInfo } { filterTags, forceListTags, tagsList, selectedServer, createNewVisit, loadMercureInfo, mercureInfo },
) => { ) => {
const [ displayedTag, setDisplayedTag ] = useState(); const [ displayedTag, setDisplayedTag ] = useState();

View file

@ -28,7 +28,7 @@ export default handleActions({
export const editTag = (buildShlinkApiClient, colorGenerator) => (oldName, newName, color) => async ( export const editTag = (buildShlinkApiClient, colorGenerator) => (oldName, newName, color) => async (
dispatch, dispatch,
getState getState,
) => { ) => {
dispatch({ type: EDIT_TAG_START }); dispatch({ type: EDIT_TAG_START });
const { editTag } = buildShlinkApiClient(getState); const { editTag } = buildShlinkApiClient(getState);

View file

@ -18,7 +18,7 @@ const provideServices = (bottle, connect) => {
'DeleteTagConfirmModal', 'DeleteTagConfirmModal',
'EditTagModal', 'EditTagModal',
'ForServerVersion', 'ForServerVersion',
'ColorGenerator' 'ColorGenerator',
); );
bottle.serviceFactory('DeleteTagConfirmModal', () => DeleteTagConfirmModal); bottle.serviceFactory('DeleteTagConfirmModal', () => DeleteTagConfirmModal);
@ -30,7 +30,7 @@ const provideServices = (bottle, connect) => {
bottle.serviceFactory('TagsList', TagsList, 'TagCard'); bottle.serviceFactory('TagsList', TagsList, 'TagCard');
bottle.decorator('TagsList', connect( bottle.decorator('TagsList', connect(
[ 'tagsList', 'selectedServer', 'mercureInfo' ], [ 'tagsList', 'selectedServer', 'mercureInfo' ],
[ 'forceListTags', 'filterTags', 'createNewVisit', 'loadMercureInfo' ] [ 'forceListTags', 'filterTags', 'createNewVisit', 'loadMercureInfo' ],
)); ));
// Actions // Actions

View file

@ -68,7 +68,7 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]); const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo( const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
() => processStatsFromVisits(normalizedVisits), () => processStatsFromVisits(normalizedVisits),
[ normalizedVisits ] [ normalizedVisits ],
); );
const mapLocations = values(citiesForMap); const mapLocations = values(citiesForMap);

View file

@ -96,7 +96,7 @@ const VisitsTable = ({
'visits-table__sticky': isSticky, 'visits-table__sticky': isSticky,
})} })}
onClick={() => setSelectedVisits( onClick={() => setSelectedVisits(
selectedVisits.length < resultSet.total ? resultSet.visitsGroups.flat() : [] selectedVisits.length < resultSet.total ? resultSet.visitsGroups.flat() : [],
)} )}
> >
<FontAwesomeIcon icon={checkIcon} className={classNames({ 'text-primary': selectedVisits.length > 0 })} /> <FontAwesomeIcon icon={checkIcon} className={classNames({ 'text-primary': selectedVisits.length > 0 })} />
@ -149,7 +149,7 @@ const VisitsTable = ({
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
className={classNames({ 'table-primary': isSelected })} className={classNames({ 'table-primary': isSelected })}
onClick={() => setSelectedVisits( onClick={() => setSelectedVisits(
isSelected ? selectedVisits.filter((v) => v !== visit) : [ ...selectedVisits, visit ] isSelected ? selectedVisits.filter((v) => v !== visit) : [ ...selectedVisits, visit ],
)} )}
> >
<td className="text-center"> <td className="text-center">

View file

@ -117,7 +117,7 @@ const LineChartCard = ({ title, visits, highlightedVisits, highlightedLabel = 'S
); );
const groupedHighlighted = useMemo( const groupedHighlighted = useMemo(
() => fillTheGaps(groupVisitsByStep(step, reverse(highlightedVisits)), labels), () => fillTheGaps(groupVisitsByStep(step, reverse(highlightedVisits)), labels),
[ highlightedVisits, step, labels ] [ highlightedVisits, step, labels ],
); );
const data = { const data = {

View file

@ -44,9 +44,9 @@ const SortableBarGraph = ({
const sortedPairs = !order.orderField ? pairs : sortBy( const sortedPairs = !order.orderField ? pairs : sortBy(
pipe( pipe(
prop(order.orderField === head(keys(sortingItems)) ? 0 : 1), prop(order.orderField === head(keys(sortingItems)) ? 0 : 1),
toLowerIfString toLowerIfString,
), ),
pairs pairs,
); );
return !order.orderDir || order.orderDir === 'ASC' ? sortedPairs : reverse(sortedPairs); return !order.orderDir || order.orderDir === 'ASC' ? sortedPairs : reverse(sortedPairs);
@ -56,7 +56,7 @@ const SortableBarGraph = ({
const sortedKeys = sortedPairs.map(pickKeyFromPair); const sortedKeys = sortedPairs.map(pickKeyFromPair);
// The highlighted stats have to be ordered based on the regular stats, not on its own values // The highlighted stats have to be ordered based on the regular stats, not on its own values
const sortedHighlightedPairs = highlightedStats && toPairs( const sortedHighlightedPairs = highlightedStats && toPairs(
{ ...zipObj(sortedKeys, sortedKeys.map(() => 0)), ...highlightedStats } { ...zipObj(sortedKeys, sortedKeys.map(() => 0)), ...highlightedStats },
); );
if (sortedPairs.length <= itemsPerPage) { if (sortedPairs.length <= itemsPerPage) {
@ -94,7 +94,7 @@ const SortableBarGraph = ({
const { currentPageStats, currentPageHighlightedStats, pagination, max } = determineStats( const { currentPageStats, currentPageHighlightedStats, pagination, max } = determineStats(
stats, stats,
highlightedStats && keys(highlightedStats).length > 0 ? highlightedStats : undefined, highlightedStats && keys(highlightedStats).length > 0 ? highlightedStats : undefined,
sortingItems sortingItems,
); );
const activeCities = keys(currentPageStats); const activeCities = keys(currentPageStats);
const computeTitle = () => ( const computeTitle = () => (

View file

@ -56,7 +56,7 @@ export const processStatsFromVisits = (normalizedVisits) =>
return stats; return stats;
}, },
{ os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} } { os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} },
); );
export const normalizeVisits = map(({ userAgent, date, referer, visitLocation }) => { export const normalizeVisits = map(({ userAgent, date, referer, visitLocation }) => {

View file

@ -17,12 +17,12 @@ const provideServices = (bottle, connect) => {
bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'VisitsStats'); bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'VisitsStats');
bottle.decorator('ShortUrlVisits', connect( bottle.decorator('ShortUrlVisits', connect(
[ 'shortUrlVisits', 'shortUrlDetail', 'mercureInfo' ], [ 'shortUrlVisits', 'shortUrlDetail', 'mercureInfo' ],
[ 'getShortUrlVisits', 'getShortUrlDetail', 'cancelGetShortUrlVisits', 'createNewVisit', 'loadMercureInfo' ] [ 'getShortUrlVisits', 'getShortUrlDetail', 'cancelGetShortUrlVisits', 'createNewVisit', 'loadMercureInfo' ],
)); ));
bottle.serviceFactory('TagVisits', TagVisits, 'VisitsStats', 'ColorGenerator'); bottle.serviceFactory('TagVisits', TagVisits, 'VisitsStats', 'ColorGenerator');
bottle.decorator('TagVisits', connect( bottle.decorator('TagVisits', connect(
[ 'tagVisits', 'mercureInfo' ], [ 'tagVisits', 'mercureInfo' ],
[ 'getTagVisits', 'cancelGetTagVisits', 'createNewVisit', 'loadMercureInfo' ] [ 'getTagVisits', 'cancelGetTagVisits', 'createNewVisit', 'loadMercureInfo' ],
)); ));
// Services // Services

View file

@ -30,7 +30,7 @@ describe('<ErrorHandler />', () => {
expect(wrapper.text()).toContain('Oops! This is awkward :S'); expect(wrapper.text()).toContain('Oops! This is awkward :S');
expect(wrapper.text()).toContain( expect(wrapper.text()).toContain(
'It seems that something went wrong. Try refreshing the page or just click this button.' 'It seems that something went wrong. Try refreshing the page or just click this button.',
); );
expect(wrapper.find(Button)).toHaveLength(1); expect(wrapper.find(Button)).toHaveLength(1);
}); });

View file

@ -24,7 +24,7 @@ describe('<NotFound />', () => {
const { content } = createWrapper(); const { content } = createWrapper();
expect(content).toContain( expect(content).toContain(
'Use your browser\'s back button to navigate to the page you have previously come from, or just press this button.' 'Use your browser\'s back button to navigate to the page you have previously come from, or just press this button.',
); );
}); });

View file

@ -15,7 +15,7 @@ describe('<CreateServer />', () => {
const CreateServer = createServerConstruct(ImportServersBtn, () => [ serversImported, () => '' ]); const CreateServer = createServerConstruct(ImportServersBtn, () => [ serversImported, () => '' ]);
wrapper = shallow( wrapper = shallow(
<CreateServer createServer={createServerMock} resetSelectedServer={identity} history={historyMock} /> <CreateServer createServer={createServerMock} resetSelectedServer={identity} history={historyMock} />,
); );
return wrapper; return wrapper;

View file

@ -22,7 +22,7 @@ describe('<DeleteServerModal />', () => {
isOpen={true} isOpen={true}
deleteServer={deleteServerMock} deleteServer={deleteServerMock}
history={historyMock} history={historyMock}
/> />,
); );
}); });
afterEach(() => wrapper.unmount()); afterEach(() => wrapper.unmount());
@ -38,7 +38,7 @@ describe('<DeleteServerModal />', () => {
const modalBody = wrapper.find(ModalBody); const modalBody = wrapper.find(ModalBody);
expect(modalBody.find('p').first().text()).toEqual( expect(modalBody.find('p').first().text()).toEqual(
`Are you sure you want to remove ${serverName}?` `Are you sure you want to remove ${serverName}?`,
); );
}); });

View file

@ -28,7 +28,7 @@ describe('<EditServer />', () => {
match={match} match={match}
selectedServer={selectedServer} selectedServer={selectedServer}
selectServer={jest.fn()} selectServer={jest.fn()}
/> />,
); );
}); });

View file

@ -37,7 +37,7 @@ describe('<ServersDropdown />', () => {
it('shows a message when no servers exist yet', () => { it('shows a message when no servers exist yet', () => {
wrapped = shallow( wrapped = shallow(
<ServersDropdown servers={{}} listServers={identity} history={history} /> <ServersDropdown servers={{}} listServers={identity} history={history} />,
); );
const item = wrapped.find(DropdownItem); const item = wrapped.find(DropdownItem);

View file

@ -9,7 +9,7 @@ describe('<ForServerVersion />', () => {
wrapped = mount( wrapped = mount(
<ForServerVersion minVersion={minVersion} maxVersion={maxVersion} selectedServer={selectedServer}> <ForServerVersion minVersion={minVersion} maxVersion={maxVersion} selectedServer={selectedServer}>
<span>Hello</span> <span>Hello</span>
</ForServerVersion> </ForServerVersion>,
); );
return wrapped; return wrapped;

View file

@ -23,7 +23,7 @@ describe('<ImportServersBtn />', () => {
const ImportServersBtn = importServersBtnConstruct(serversImporterMock); const ImportServersBtn = importServersBtnConstruct(serversImporterMock);
wrapper = shallow( wrapper = shallow(
<ImportServersBtn createServers={createServersMock} fileRef={fileRef} onImport={onImportMock} /> <ImportServersBtn createServers={createServersMock} fileRef={fileRef} onImport={onImportMock} />,
); );
}); });
afterEach(() => wrapper.unmount()); afterEach(() => wrapper.unmount());

View file

@ -33,7 +33,7 @@ describe('<ServerError />', () => {
wrapper = shallow( wrapper = shallow(
<BrowserRouter> <BrowserRouter>
<ServerError type={type} servers={{}} selectedServer={selectedServer} /> <ServerError type={type} servers={{}} selectedServer={selectedServer} />
</BrowserRouter> </BrowserRouter>,
); );
const wrapperText = wrapper.html(); const wrapperText = wrapper.html();
const textPairs = Object.entries(textsToFind); const textPairs = Object.entries(textsToFind);

View file

@ -17,7 +17,7 @@ describe('<CreateShortUrl />', () => {
const CreateShortUrl = createShortUrlsCreator(TagsSelector, () => '', () => ''); const CreateShortUrl = createShortUrlsCreator(TagsSelector, () => '', () => '');
wrapper = shallow( wrapper = shallow(
<CreateShortUrl shortUrlCreationResult={shortUrlCreationResult} createShortUrl={createShortUrl} /> <CreateShortUrl shortUrlCreationResult={shortUrlCreationResult} createShortUrl={createShortUrl} />,
); );
}); });
afterEach(() => { afterEach(() => {

View file

@ -52,7 +52,7 @@ describe('<SearchBar />', () => {
it('updates short URLs list when a tag is removed', () => { it('updates short URLs list when a tag is removed', () => {
wrapper = shallow( wrapper = shallow(
<SearchBar shortUrlsListParams={{ tags: [ 'foo' ] }} listShortUrls={listShortUrlsMock} /> <SearchBar shortUrlsListParams={{ tags: [ 'foo' ] }} listShortUrls={listShortUrlsMock} />,
); );
const tag = wrapper.find(Tag).first(); const tag = wrapper.find(Tag).first();
@ -63,7 +63,7 @@ describe('<SearchBar />', () => {
it.each([ 'startDateChange', 'endDateChange' ])('updates short URLs list when date range changes', (event) => { it.each([ 'startDateChange', 'endDateChange' ])('updates short URLs list when date range changes', (event) => {
wrapper = shallow( wrapper = shallow(
<SearchBar shortUrlsListParams={{}} listShortUrls={listShortUrlsMock} /> <SearchBar shortUrlsListParams={{}} listShortUrls={listShortUrlsMock} />,
); );
const dateRange = wrapper.find(DateRangeRow); const dateRange = wrapper.find(DateRangeRow);

View file

@ -37,7 +37,7 @@ describe('<ShortUrlsList />', () => {
] ]
} }
mercureInfo={{ loading: true }} mercureInfo={{ loading: true }}
/> />,
); );
}); });

View file

@ -20,7 +20,7 @@ describe('<DeleteShortUrlModal />', () => {
toggle={identity} toggle={identity}
deleteShortUrl={deleteShortUrl} deleteShortUrl={deleteShortUrl}
resetDeleteShortUrl={identity} resetDeleteShortUrl={identity}
/> />,
); );
return wrapper; return wrapper;

View file

@ -17,7 +17,7 @@ describe('<EditMetaModal />', () => {
toggle={toggle} toggle={toggle}
editShortUrlMeta={editShortUrlMeta} editShortUrlMeta={editShortUrlMeta}
resetShortUrlMeta={resetShortUrlMeta} resetShortUrlMeta={resetShortUrlMeta}
/> />,
); );
return wrapper; return wrapper;

View file

@ -15,7 +15,7 @@ describe('<EditShortUrlModal />', () => {
shortUrlEdition={shortUrlEdition} shortUrlEdition={shortUrlEdition}
toggle={toggle} toggle={toggle}
editShortUrl={editShortUrl} editShortUrl={editShortUrl}
/> />,
); );
return wrapper; return wrapper;

View file

@ -26,7 +26,7 @@ describe('<EditTagsModal />', () => {
toggle={toggle} toggle={toggle}
editShortUrlTags={editShortUrlTags} editShortUrlTags={editShortUrlTags}
resetShortUrlsTags={resetShortUrlsTags} resetShortUrlsTags={resetShortUrlsTags}
/> />,
); );
return wrapper; return wrapper;

View file

@ -21,7 +21,7 @@ describe('<ShortUrlVisitsCount />', () => {
const maxVisitsTooltip = wrapper.find(UncontrolledTooltip); const maxVisitsTooltip = wrapper.find(UncontrolledTooltip);
expect(wrapper.html()).toEqual( expect(wrapper.html()).toEqual(
`<span><strong class="short-url-visits-count__amount">${visitsCount}</strong></span>` `<span><strong class="short-url-visits-count__amount">${visitsCount}</strong></span>`,
); );
expect(maxVisitsHelper).toHaveLength(0); expect(maxVisitsHelper).toHaveLength(0);
expect(maxVisitsTooltip).toHaveLength(0); expect(maxVisitsTooltip).toHaveLength(0);

View file

@ -34,7 +34,7 @@ describe('<ShortUrlsRow />', () => {
const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, useStateFlagTimeout); 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} />,
); );
}); });
afterEach(() => wrapper.unmount()); afterEach(() => wrapper.unmount());

View file

@ -23,7 +23,7 @@ describe('<ShortUrlsRowMenu />', () => {
EditTagsModal, EditTagsModal,
EditMetaModal, EditMetaModal,
EditShortUrlModal, EditShortUrlModal,
() => '' () => '',
); );
wrapper = shallow( wrapper = shallow(
@ -31,7 +31,7 @@ describe('<ShortUrlsRowMenu />', () => {
selectedServer={selectedServer} selectedServer={selectedServer}
shortUrl={shortUrl} shortUrl={shortUrl}
onCopyToClipboard={onCopyToClipboard} onCopyToClipboard={onCopyToClipboard}
/> />,
); );
return wrapper; return wrapper;

View file

@ -60,7 +60,7 @@ describe('shortUrlDeletionReducer', () => {
}); });
it.each( it.each(
[[ undefined ], [ null ], [ 'example.com' ]] [[ undefined ], [ null ], [ 'example.com' ]],
)('dispatches proper actions if API client request succeeds', async (domain) => { )('dispatches proper actions if API client request succeeds', async (domain) => {
const apiClientMock = { const apiClientMock = {
deleteShortUrl: jest.fn(() => ''), deleteShortUrl: jest.fn(() => ''),

View file

@ -70,7 +70,7 @@ describe('shortUrlTagsReducer', () => {
expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_TAGS_START }); expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_TAGS_START });
expect(dispatch).toHaveBeenNthCalledWith( expect(dispatch).toHaveBeenNthCalledWith(
2, 2,
{ type: SHORT_URL_TAGS_EDITED, tags: normalizedTags, shortCode, domain } { type: SHORT_URL_TAGS_EDITED, tags: normalizedTags, shortCode, domain },
); );
}); });

View file

@ -15,7 +15,7 @@ describe('<TagsList />', () => {
const TagsList = createTagsList(TagCard); const TagsList = createTagsList(TagCard);
wrapper = shallow( wrapper = shallow(
<TagsList forceListTags={identity} filterTags={filterTags} match={{ params }} tagsList={tagsList} /> <TagsList forceListTags={identity} filterTags={filterTags} match={{ params }} tagsList={tagsList} />,
); );
return wrapper; return wrapper;

View file

@ -17,7 +17,7 @@ describe('<DeleteTagConfirmModal />', () => {
deleteTag={deleteTag} deleteTag={deleteTag}
tagDeleted={tagDeleted} tagDeleted={tagDeleted}
tagDelete={tagDelete} tagDelete={tagDelete}
/> />,
); );
return wrapper; return wrapper;

View file

@ -42,7 +42,7 @@ describe('ShlinkApiClient', () => {
const { createShortUrl } = new ShlinkApiClient(axiosSpy); const { createShortUrl } = new ShlinkApiClient(axiosSpy);
await createShortUrl( await createShortUrl(
{ foo: 'bar', empty: undefined, anotherEmpty: null } { foo: 'bar', empty: undefined, anotherEmpty: null },
); );
expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ data: { foo: 'bar' } })); expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ data: { foo: 'bar' } }));

View file

@ -30,7 +30,7 @@ describe('<ShortUrlVisits />', () => {
shortUrlDetail={{}} shortUrlDetail={{}}
cancelGetShortUrlVisits={identity} cancelGetShortUrlVisits={identity}
matchMedia={() => ({ matches: false })} matchMedia={() => ({ matches: false })}
/> />,
); );
}); });

View file

@ -21,7 +21,7 @@ describe('<ShortUrlVisitsHeader />', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallow(
<ShortUrlVisitsHeader shortUrlDetail={shortUrlDetail} shortUrlVisits={shortUrlVisits} goBack={goBack} /> <ShortUrlVisitsHeader shortUrlDetail={shortUrlDetail} shortUrlVisits={shortUrlVisits} goBack={goBack} />,
); );
}); });
afterEach(() => wrapper.unmount()); afterEach(() => wrapper.unmount());

View file

@ -25,7 +25,7 @@ describe('<TagVisits />', () => {
history={history} history={history}
tagVisits={{ loading: true, visits: [] }} tagVisits={{ loading: true, visits: [] }}
cancelGetTagVisits={identity} cancelGetTagVisits={identity}
/> />,
); );
}); });

View file

@ -13,7 +13,7 @@ describe('<TagVisitsHeader />', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallow(
<TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={{}} /> <TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={{}} />,
); );
}); });
afterEach(() => wrapper.unmount()); afterEach(() => wrapper.unmount());

View file

@ -10,7 +10,7 @@ describe('<VisitsHeader />', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallow(
<VisitsHeader visits={visits} goBack={goBack} title={title} /> <VisitsHeader visits={visits} goBack={goBack} title={title} />,
); );
}); });
@ -21,7 +21,7 @@ describe('<VisitsHeader />', () => {
const visitsBadge = wrapper.find('.badge'); const visitsBadge = wrapper.find('.badge');
expect(visitsBadge.html()).toContain( expect(visitsBadge.html()).toContain(
`Visits: <span><strong class="short-url-visits-count__amount">${visits.length}</strong></span>` `Visits: <span><strong class="short-url-visits-count__amount">${visits.length}</strong></span>`,
); );
}); });

View file

@ -24,7 +24,7 @@ describe('<VisitStats />', () => {
visitsInfo={visitsInfo} visitsInfo={visitsInfo}
cancelGetVisits={identity} cancelGetVisits={identity}
matchMedia={() => ({ matches: false })} matchMedia={() => ({ matches: false })}
/> />,
); );
return wrapper; return wrapper;

View file

@ -16,7 +16,7 @@ describe('<VisitsTable />', () => {
selectedVisits={selectedVisits} selectedVisits={selectedVisits}
setSelectedVisits={setSelectedVisits} setSelectedVisits={setSelectedVisits}
matchMedia={matchMedia} matchMedia={matchMedia}
/> />,
); );
return wrapper; return wrapper;
@ -64,7 +64,7 @@ describe('<VisitsTable />', () => {
}); });
it.each( it.each(
rangeOf(20, (value) => [ value ]) rangeOf(20, (value) => [ value ]),
)('does not render footer when there is only one page to render', (visitsCount) => { )('does not render footer when there is only one page to render', (visitsCount) => {
const wrapper = createWrapper(rangeOf(visitsCount, () => ({ browser: '', date: '', referer: '' }))); const wrapper = createWrapper(rangeOf(visitsCount, () => ({ browser: '', date: '', referer: '' })));
const tr = wrapper.find('tbody').find('tr'); const tr = wrapper.find('tbody').find('tr');

View file

@ -24,7 +24,7 @@ describe('<SortableBarGraph />', () => {
stats={{ ...stats, ...extraStats }} stats={{ ...stats, ...extraStats }}
sortingItems={sortingItems} sortingItems={sortingItems}
withPagination={withPagination} withPagination={withPagination}
/> />,
); );
return wrapper; return wrapper;
@ -108,7 +108,7 @@ describe('<SortableBarGraph />', () => {
</span> </span>
)} )}
/> />
</span> </span>,
).find(SortableBarGraph); ).find(SortableBarGraph);
const header = wrapper.renderProp('extraHeaderContent')(); const header = wrapper.renderProp('extraHeaderContent')();

View file

@ -4,7 +4,7 @@ describe('visitCreationReducer', () => {
describe('createNewVisit', () => { describe('createNewVisit', () => {
it('just returns the action with proper type', () => it('just returns the action with proper type', () =>
expect(createNewVisit({ shortUrl: {}, visit: {} })).toEqual( expect(createNewVisit({ shortUrl: {}, visit: {} })).toEqual(
{ type: CREATE_VISIT, shortUrl: {}, visit: {} } { type: CREATE_VISIT, shortUrl: {}, visit: {} },
)); ));
}); });
}); });