Updated to airbnb coding styles

This commit is contained in:
Alejandro Celaya
2022-03-26 12:17:42 +01:00
parent 4e9b19afd1
commit a2df486280
239 changed files with 2210 additions and 3549 deletions

View File

@@ -32,10 +32,10 @@ const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagT
const navigate = useNavigate();
const goBack = useGoBack();
const hasServers = !!Object.keys(servers).length;
const [ serversImported, setServersImported ] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
const [ errorImporting, setErrorImporting ] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
const [ isConfirmModalOpen, toggleConfirmModal ] = useToggle();
const [ serverData, setServerData ] = useState<ServerData | undefined>();
const [serversImported, setServersImported] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
const [errorImporting, setErrorImporting] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
const [isConfirmModalOpen, toggleConfirmModal] = useToggle();
const [serverData, setServerData] = useState<ServerData | undefined>();
const save = () => {
if (!serverData) {
return;
@@ -53,13 +53,14 @@ const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagT
);
serverExists ? toggleConfirmModal() : save();
}, [ serverData ]);
}, [serverData]);
return (
<NoMenuLayout>
<ServerForm title={<h5 className="mb-0">Add new server</h5>} onSubmit={setServerData}>
{!hasServers &&
<ImportServersBtn tooltipPlacement="top" onImport={setServersImported} onImportError={setErrorImporting} />}
{!hasServers && (
<ImportServersBtn tooltipPlacement="top" onImport={setServersImported} onImportError={setErrorImporting} />
)}
{hasServers && <Button outline onClick={goBack}>Cancel</Button>}
<Button outline color="primary" className="ms-2">Create server</Button>
</ServerForm>
@@ -69,7 +70,7 @@ const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagT
<DuplicatedServersModal
isOpen={isConfirmModalOpen}
duplicatedServers={serverData ? [ serverData ] : []}
duplicatedServers={serverData ? [serverData] : []}
onDiscard={goBack}
onSave={save}
/>

View File

@@ -14,7 +14,7 @@ export interface DeleteServerButtonProps {
const DeleteServerButton = (DeleteServerModal: FC<DeleteServerModalProps>): FC<DeleteServerButtonProps> => (
{ server, className, children, textClassName },
) => {
const [ isModalOpen, , showModal, hideModal ] = useToggle();
const [isModalOpen, , showModal, hideModal] = useToggle();
return (
<>

View File

@@ -1,5 +1,5 @@
import { FC } from 'react';
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import { useNavigate } from 'react-router-dom';
import { ServerWithId } from './data';
@@ -37,8 +37,8 @@ const DeleteServerModal: FC<DeleteServerModalConnectProps> = (
</p>
</ModalBody>
<ModalFooter>
<button className="btn btn-link" onClick={toggle}>Cancel</button>
<button className="btn btn-danger" onClick={() => closeModal()}>Delete</button>
<Button color="link" onClick={toggle}>Cancel</Button>
<Button color="danger" onClick={() => closeModal()}>Delete</Button>
</ModalFooter>
</Modal>
);

View File

@@ -26,16 +26,16 @@ export const ManageServers = (
ManageServersRow: FC<ManageServersRowProps>,
): FC<ManageServersProps> => ({ servers }) => {
const allServers = Object.values(servers);
const [ serversList, setServersList ] = useState(allServers);
const [serversList, setServersList] = useState(allServers);
const filterServers = (searchTerm: string) => setServersList(
allServers.filter(({ name, url }) => `${name} ${url}`.match(searchTerm)),
);
const hasAutoConnect = serversList.some(({ autoConnect }) => !!autoConnect);
const [ errorImporting, setErrorImporting ] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
const [errorImporting, setErrorImporting] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME);
useEffect(() => {
setServersList(Object.values(servers));
}, [ servers ]);
}, [servers]);
return (
<NoMenuLayout>
@@ -61,17 +61,17 @@ export const ManageServers = (
<table className="table table-hover responsive-table mb-0">
<thead className="responsive-table__header">
<tr>
{hasAutoConnect && <th style={{ width: '50px' }} />}
{hasAutoConnect && <th aria-label="Auto-connect" style={{ width: '50px' }} />}
<th>Name</th>
<th>Base URL</th>
<th />
<th aria-label="Options" />
</tr>
</thead>
<tbody>
{!serversList.length && <tr className="text-center"><td colSpan={4}>No servers found.</td></tr>}
{serversList.map((server) =>
<ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} />)
}
{serversList.map((server) => (
<ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} />
))}
</tbody>
</table>
</SimpleCard>

View File

@@ -25,8 +25,8 @@ interface ManageServersRowDropdownConnectProps extends ManageServersRowDropdownP
export const ManageServersRowDropdown = (
DeleteServerModal: FC<DeleteServerModalProps>,
): FC<ManageServersRowDropdownConnectProps> => ({ server, setAutoConnect }) => {
const [ isMenuOpen, toggleMenu ] = useToggle();
const [ isModalOpen,, showModal, hideModal ] = useToggle();
const [isMenuOpen, toggleMenu] = useToggle();
const [isModalOpen,, showModal, hideModal] = useToggle();
const serverUrl = `/server/${server.id}`;
const { autoConnect: isAutoConnect } = server;
const autoConnectIcon = isAutoConnect ? toggleOffIcon : toggleOnIcon;

View File

@@ -109,4 +109,4 @@ export const Overview = (
</Card>
</>
);
}, () => [ Topics.visits, Topics.orphanVisits ]);
}, () => [Topics.visits, Topics.orphanVisits]);

View File

@@ -35,15 +35,15 @@ export const hasServerData = (server: SelectedServer | ServerData): server is Se
!!(server as ServerData)?.url && !!(server as ServerData)?.apiKey;
export const isServerWithId = (server: SelectedServer | ServerWithId): server is ServerWithId =>
!!server?.hasOwnProperty('id');
!!(server as ServerWithId)?.id;
export const isReachableServer = (server: SelectedServer): server is ReachableServer =>
!!server?.hasOwnProperty('version');
!!(server as ReachableServer)?.version;
export const isNotFoundServer = (server: SelectedServer): server is NotFoundServer =>
!!server?.hasOwnProperty('serverNotFound');
!!(server as NotFoundServer)?.serverNotFound;
export const getServerId = (server: SelectedServer) => isServerWithId(server) ? server.id : '';
export const getServerId = (server: SelectedServer) => (isServerWithId(server) ? server.id : '');
export const serverWithIdToServerData = (server: ServerWithId): ServerData =>
omit<ServerWithId, 'id' | 'autoConnect'>([ 'id', 'autoConnect' ], server);
omit<ServerWithId, 'id' | 'autoConnect'>(['id', 'autoConnect'], server);

View File

@@ -20,12 +20,12 @@ export const DuplicatedServersModal: FC<DuplicatedServersModalProps> = (
<ModalBody>
<p>{hasMultipleServers ? 'The next servers already exist:' : 'There is already a server with:'}</p>
<ul>
{duplicatedServers.map(({ url, apiKey }, index) => !hasMultipleServers ? (
{duplicatedServers.map(({ url, apiKey }, index) => (!hasMultipleServers ? (
<Fragment key={index}>
<li>URL: <b>{url}</b></li>
<li>API key: <b>{apiKey}</b></li>
</Fragment>
) : <li key={index}><b>{url}</b> - <b>{apiKey}</b></li>)}
) : <li key={index}><b>{url}</b> - <b>{apiKey}</b></li>))}
</ul>
<span>
{hasMultipleServers ? 'Do you want to ignore duplicated servers' : 'Do you want to save this server anyway'}?

View File

@@ -10,7 +10,7 @@ export interface HighlightCardProps {
link?: string | false;
}
const buildExtraProps = (link?: string | false) => !link ? {} : { tag: Link, to: link };
const buildExtraProps = (link?: string | false) => (!link ? {} : { tag: Link, to: link });
export const HighlightCard: FC<HighlightCardProps> = ({ children, title, link }) => (
<Card className="highlight-card" body {...buildExtraProps(link)}>

View File

@@ -1,4 +1,4 @@
import { useRef, RefObject, ChangeEvent, MutableRefObject, FC, useState, useEffect } from 'react';
import { useRef, RefObject, ChangeEvent, MutableRefObject, useState, useEffect, FC } from 'react';
import { Button, UncontrolledTooltip } from 'reactstrap';
import { complement, pipe } from 'ramda';
import { faFileUpload as importIcon } from '@fortawesome/free-solid-svg-icons';
@@ -38,9 +38,9 @@ const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<Import
className = '',
}) => {
const ref = fileRef ?? useRef<HTMLInputElement>();
const [ serversToCreate, setServersToCreate ] = useState<ServerData[] | undefined>();
const [ duplicatedServers, setDuplicatedServers ] = useState<ServerData[]>([]);
const [ isModalOpen,, showModal, hideModal ] = useToggle();
const [serversToCreate, setServersToCreate] = useState<ServerData[] | undefined>();
const [duplicatedServers, setDuplicatedServers] = useState<ServerData[]>([]);
const [isModalOpen,, showModal, hideModal] = useToggle();
const create = pipe(createServers, onImport);
const createAllServers = pipe(() => create(serversToCreate ?? []), hideModal);
const createNonDuplicatedServers = pipe(
@@ -52,7 +52,7 @@ const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<Import
.then(setServersToCreate)
.then(() => {
// Reset input after processing file
(target as { value: string | null }).value = null;
(target as { value: string | null }).value = null; // eslint-disable-line no-param-reassign
})
.catch(onImportError);
@@ -62,12 +62,12 @@ const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<Import
}
const existingServers = Object.values(servers);
const duplicatedServers = serversToCreate.filter(serversFiltering(existingServers));
const hasDuplicatedServers = !!duplicatedServers.length;
const dupServers = serversToCreate.filter(serversFiltering(existingServers));
const hasDuplicatedServers = !!dupServers.length;
!hasDuplicatedServers ? create(serversToCreate) : setDuplicatedServers(duplicatedServers);
!hasDuplicatedServers ? create(serversToCreate) : setDuplicatedServers(dupServers);
hasDuplicatedServers && showModal();
}, [ serversToCreate ]);
}, [serversToCreate]);
return (
<>

View File

@@ -11,16 +11,16 @@ interface ServerFormProps {
}
export const ServerForm: FC<ServerFormProps> = ({ onSubmit, initialValues, children, title }) => {
const [ name, setName ] = useState('');
const [ url, setUrl ] = useState('');
const [ apiKey, setApiKey ] = useState('');
const [name, setName] = useState('');
const [url, setUrl] = useState('');
const [apiKey, setApiKey] = useState('');
const handleSubmit = handleEventPreventingDefault(() => onSubmit({ name, url, apiKey }));
useEffect(() => {
initialValues && setName(initialValues.name);
initialValues && setUrl(initialValues.url);
initialValues && setApiKey(initialValues.apiKey);
}, [ initialValues ]);
}, [initialValues]);
return (
<form className="server-form" onSubmit={handleSubmit}>

View File

@@ -16,7 +16,7 @@ export function withSelectedServer<T = {}>(WrappedComponent: FC<WithSelectedServ
useEffect(() => {
params.serverId && selectServer(params.serverId);
}, [ params.serverId ]);
}, [params.serverId]);
if (!selectedServer) {
return (

View File

@@ -6,8 +6,9 @@ interface WithoutSelectedServerProps {
export function withoutSelectedServer<T = {}>(WrappedComponent: FC<WithoutSelectedServerProps & T>) {
return (props: WithoutSelectedServerProps & T) => {
const { resetSelectedServer } = props;
useEffect(() => {
props.resetSelectedServer();
resetSelectedServer();
}, []);
return <WrappedComponent {...props} />;

View File

@@ -7,7 +7,7 @@ import { createServers } from './servers';
const responseToServersList = pipe(
prop<any, any>('data'),
(data: any): ServerData[] => Array.isArray(data) ? data.filter(hasServerData) : [],
(data: any): ServerData[] => (Array.isArray(data) ? data.filter(hasServerData) : []),
);
export const fetchServers = ({ get }: AxiosInstance) => () => async (dispatch: Dispatch) => {

View File

@@ -7,21 +7,19 @@ import { ShlinkHealth } from '../../api/types';
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
/* eslint-disable padding-line-between-statements */
export const SELECT_SERVER = 'shlink/selectedServer/SELECT_SERVER';
export const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER';
export const MIN_FALLBACK_VERSION = '1.0.0';
export const MAX_FALLBACK_VERSION = '999.999.999';
export const LATEST_VERSION_CONSTRAINT = 'latest';
/* eslint-enable padding-line-between-statements */
export interface SelectServerAction extends Action<string> {
selectedServer: SelectedServer;
}
const versionToSemVer = pipe(
(version: string) => version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version,
(version: string) => (version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version),
toSemVer(MIN_FALLBACK_VERSION),
);

View File

@@ -4,12 +4,10 @@ import { Action } from 'redux';
import { ServerData, ServersMap, ServerWithId } from '../data';
import { buildReducer } from '../../utils/helpers/redux';
/* eslint-disable padding-line-between-statements */
export const EDIT_SERVER = 'shlink/servers/EDIT_SERVER';
export const DELETE_SERVER = 'shlink/servers/DELETE_SERVER';
export const CREATE_SERVERS = 'shlink/servers/CREATE_SERVERS';
export const SET_AUTO_CONNECT = 'shlink/servers/SET_AUTO_CONNECT';
/* eslint-enable padding-line-between-statements */
export interface CreateServersAction extends Action<string> {
newServers: ServersMap;
@@ -37,9 +35,9 @@ const serverWithId = (server: ServerWithId | ServerData): ServerWithId => {
export default buildReducer<ServersMap, CreateServersAction & DeleteServerAction & SetAutoConnectAction>({
[CREATE_SERVERS]: (state, { newServers }) => ({ ...state, ...newServers }),
[DELETE_SERVER]: (state, { serverId }) => dissoc(serverId, state),
[EDIT_SERVER]: (state, { serverId, serverData }: any) => !state[serverId]
? state
: assoc(serverId, { ...state[serverId], ...serverData }, state),
[EDIT_SERVER]: (state, { serverId, serverData }: any) => (
!state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state)
),
[SET_AUTO_CONNECT]: (state, { serverId, autoConnect }) => {
if (!state[serverId]) {
return state;
@@ -50,7 +48,7 @@ export default buildReducer<ServersMap, CreateServersAction & DeleteServerAction
}
return fromPairs(
toPairs(state).map(([ evaluatedServerId, server ]) => [
toPairs(state).map(([evaluatedServerId, server]) => [
evaluatedServerId,
{ ...server, autoConnect: evaluatedServerId === serverId },
]),
@@ -66,7 +64,7 @@ export const createServers = pipe(
(newServers: ServersMap) => ({ type: CREATE_SERVERS, newServers }),
);
export const createServer = (server: ServerWithId) => createServers([ server ]);
export const createServer = (server: ServerWithId) => createServers([server]);
export const editServer = (serverId: string, serverData: Partial<ServerData>) => ({
type: EDIT_SERVER,

View File

@@ -29,8 +29,8 @@ export class ServersImporter {
}
resolve(servers);
} catch (e) {
reject(e);
} catch (error) {
reject(error);
}
});
reader.readAsText(file);

View File

@@ -31,41 +31,41 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
'ManageServersRow',
);
bottle.decorator('ManageServers', withoutSelectedServer);
bottle.decorator('ManageServers', connect([ 'selectedServer', 'servers' ], [ 'resetSelectedServer' ]));
bottle.decorator('ManageServers', connect(['selectedServer', 'servers'], ['resetSelectedServer']));
bottle.serviceFactory('ManageServersRow', ManageServersRow, 'ManageServersRowDropdown');
bottle.serviceFactory('ManageServersRowDropdown', ManageServersRowDropdown, 'DeleteServerModal');
bottle.decorator('ManageServersRowDropdown', connect(null, [ 'setAutoConnect' ]));
bottle.decorator('ManageServersRowDropdown', connect(null, ['setAutoConnect']));
bottle.serviceFactory('CreateServer', CreateServer, 'ImportServersBtn', 'useStateFlagTimeout');
bottle.decorator('CreateServer', withoutSelectedServer);
bottle.decorator('CreateServer', connect([ 'selectedServer', 'servers' ], [ 'createServer', 'resetSelectedServer' ]));
bottle.decorator('CreateServer', connect(['selectedServer', 'servers'], ['createServer', 'resetSelectedServer']));
bottle.serviceFactory('EditServer', EditServer, 'ServerError');
bottle.decorator('EditServer', connect([ 'selectedServer' ], [ 'editServer', 'selectServer', 'resetSelectedServer' ]));
bottle.decorator('EditServer', connect(['selectedServer'], ['editServer', 'selectServer', 'resetSelectedServer']));
bottle.serviceFactory('ServersDropdown', () => ServersDropdown);
bottle.decorator('ServersDropdown', connect([ 'servers', 'selectedServer' ]));
bottle.decorator('ServersDropdown', connect(['servers', 'selectedServer']));
bottle.serviceFactory('DeleteServerModal', () => DeleteServerModal);
bottle.decorator('DeleteServerModal', connect(null, [ 'deleteServer' ]));
bottle.decorator('DeleteServerModal', connect(null, ['deleteServer']));
bottle.serviceFactory('DeleteServerButton', DeleteServerButton, 'DeleteServerModal');
bottle.serviceFactory('ImportServersBtn', ImportServersBtn, 'ServersImporter');
bottle.decorator('ImportServersBtn', connect([ 'servers' ], [ 'createServers' ]));
bottle.decorator('ImportServersBtn', connect(['servers'], ['createServers']));
bottle.serviceFactory('ForServerVersion', () => ForServerVersion);
bottle.decorator('ForServerVersion', connect([ 'selectedServer' ]));
bottle.decorator('ForServerVersion', connect(['selectedServer']));
bottle.serviceFactory('ServerError', ServerError, 'DeleteServerButton');
bottle.decorator('ServerError', connect([ 'servers', 'selectedServer' ]));
bottle.decorator('ServerError', connect(['servers', 'selectedServer']));
bottle.serviceFactory('Overview', Overview, 'ShortUrlsTable', 'CreateShortUrl', 'ForServerVersion');
bottle.decorator('Overview', connect(
[ 'shortUrlsList', 'tagsList', 'selectedServer', 'mercureInfo', 'visitsOverview' ],
[ 'listShortUrls', 'listTags', 'createNewVisits', 'loadMercureInfo', 'loadVisitsOverview' ],
['shortUrlsList', 'tagsList', 'selectedServer', 'mercureInfo', 'visitsOverview'],
['listShortUrls', 'listTags', 'createNewVisits', 'loadMercureInfo', 'loadVisitsOverview'],
));
// Services